本文基于教材《大数据挖掘与应用》王振武,出于期末复习目的,对部分算法利用python进行实现,顺便学习numpy构建思惟导图,帮助理解。
全部代码、结果都以jupyter的形式放在了github上。
题型
选择题和判断题可能从里面出,题目与答案的word版一样放入了github中。html
本章主要考填空题:python
混淆矩阵:运用于二分类问题git
(真实)/(预测) | 0 | 1 | 总计 |
---|---|---|---|
0 | 预测0正确(TN) | 预测0错误(FP) | P(YES) |
1 | 预测1错误(FN) | 预测1正确(TP) | N(NO) |
总计 | P' | N' | P+N |
定义:合并多个数据源中的数据,存放在一个一致的数据储存(如数据仓库)中。github
定义:将数据转换或统一成适合于挖掘的形式。算法
修正系数=\(w_{nr}=w_d * {\frac N {n_r}}={\frac N n}*{\frac n {n_r}}\)bootstrap
统计表:
数组
修正后统计表:
网络
修正后比例:
app
利用np.split对数组分割
dom
平均值平滑
对每一行设为其行平均值
边界平滑
对每一行设为其round(\({\frac {索引} {每行元素个数}}\))向上取整的值
d = np.array([200,300,400,600,1000])
令\(min=0,max=1\),
(d.max() - d) / (d.min() - d) * (1.0 - 0.0)
\({\frac {{原值}-{均值}} {标准差}}\)
(d - np.average(d)) / np.std(d)
\({\frac {{原值}-{均值}} {平均绝对误差}}\)
(d - np.average(d)) / np.mean(np.absolute(d - np.mean(d)))
\({\frac {原值}{数组绝对值后的最大值对10求导向上取整再对10求幂}}\)
import math d / math.pow(10, math.ceil(math.log(np.max(np.abs(d)), 10)))
主要考名词解释
数据压缩是指使用数据编码或变换以便将原始数据集合成一个较小的数据集合。
数值规约是指选择替代的、“较小的”数据表示形式减小数据量。
原理书上说的很明白了,直接经过例题理解。
利用Apriori算法计算频繁项集能够有效下降计算频繁集的时间复杂度。在如下的购物篮中产生支持度不小于3的候选3-项集,在候选2-项集中须要剪枝的是()
ID 项集
1 面包、牛奶
2 面包、尿布、啤酒、鸡蛋
3 牛奶、尿布、啤酒、可乐
4 面包、牛奶、尿布、啤酒
5 面包、牛奶、尿布、可乐
A、啤酒、尿布
B、啤酒、面包
C、面包、尿布
D、啤酒、牛奶
import numpy as np data = np.array([['面包','牛奶'], ['面包','尿布','啤酒','鸡蛋'], ['牛奶','尿布','啤酒','可乐'], ['面包','牛奶','尿布','啤酒'], ['面包','牛奶','尿布','可乐']]) min_support = 3 data
C1 = set() for t in data: for item in t: item_set = frozenset([item]) C1.add(item_set) C1
* 计算支持度计数:
item_count = {} for t in data: for item in C1: if item.issubset(t): if item not in item_count: item_count[item] = 1 else: item_count[item] += 1 for item in item_count: print(item,item_count[item])
* 根据支持度计数生成频繁1-项集
for item in item_count: if(item_count[item]<min_support): C1.remove(item) C1
Clist = list(C1) C2 = set() for i in range(len(Clist)): for j in range(i+1,len(Clist)): Ctmp = Clist[i]|Clist[j] # 检查是不是频繁项集 check = 1 for item in Ctmp: sub_Ck = Ctmp - frozenset([item]) if sub_Ck not in Clist: check = 0 if check: C2.add(Ctmp) C2
- 根据支持度计数生成频繁2-项集
item_count = {} for t in data: for item in C2: if item.issubset(t): if item not in item_count: item_count[item] = 1 else: item_count[item] += 1 for item in item_count: print(item,item_count[item]) for item in item_count: if(item_count[item]<min_support): C2.remove(item) C2
减去的是BD。
说到逻辑回归,昨天刷V2的时候才看到一个帖子工做两年的同事不知道逻辑回归是什么,这个正常吗?
因为本章不考应用题,仅罗列概念。
注意:分类和回归均可用于预测,分类的输出是离散的类别值,而回归的输出是连续数值。
回归是指研究一组随机变量和另外一组变量之间关系的统计方法,又称多重回归分析。
线性回归是指利用称为线性回归方程的最小平方函数对一个或多个自变量与因变量之间关系进行建模的一种回归分析。
KNN算法又称K-最近邻算法,根据距离函数计算待分类样本X和每一个训练样本之间的距离(做为类似度),选择与待分类样本距离最小的K个样本做为X的K个最近邻,最后以X的K个最近邻中的大多数样本所属的类别做为X的类别。
注意:
有下列数据集,对于测试样本\(T=\{18,8\}\),求所属类别
序号 | 特征1 | 特征2 | 类别 |
---|---|---|---|
T1 | 2 | 4 | L1 |
T1 | 4 | 3 | L2 |
T1 | 10 | 6 | L3 |
T1 | 12 | 9 | L2 |
T1 | 3 | 11 | L3 |
T1 | 20 | 7 | L2 |
T1 | 22 | 5 | L2 |
T1 | 21 | 10 | L1 |
T1 | 11 | 2 | L3 |
T1 | 24 | 1 | L1 |
import numpy as np data = np.array([[2,4],[4,3],[10,6],[12,9],[3,11],[20,7],[22,5],[21,10],[11,2],[24,1]]) f = np.array([1,2,3,2,3,2,2,1,3,1]) T = np.array([18,8]) np.linalg.norm(T-data,ord=2,axis=1)
k = 4 s = np.argsort(np.linalg.norm(T-data,ord=2,axis=1))[:k] s
f[s]
np.argmax(np.bincount(f[s]))
k=5,数据集以下,对\(x=(1,2)\)分类
经过np.random()随机生成数据: n = 40 x = np.random.rand(n, 2) * 2 y = np.random.randint(1,4,size=n) for i in range(len(x)): print("| $T_{"+str(i+1)+"}$ |",x[i][0],"|",x[i][1],"|",y[i],"|")
实例 | 横坐标 | 纵坐标 | 类别 |
---|---|---|---|
\(T_{1}\) | 1.6786053339467983 | 0.15487473902042592 | 3 |
\(T_{2}\) | 1.903750045541173 | 1.6775903335564164 | 2 |
\(T_{3}\) | 0.15144619402840243 | 1.543485488927614 | 1 |
\(T_{4}\) | 1.7015965993474789 | 1.552612092889784 | 3 |
\(T_{5}\) | 1.9723048073918905 | 1.8052157775896671 | 3 |
\(T_{6}\) | 0.7477259494384572 | 1.433438461194146 | 1 |
\(T_{7}\) | 1.9302135013005466 | 1.9269776190658305 | 1 |
\(T_{8}\) | 0.24207606669714932 | 1.894010458348885 | 2 |
\(T_{9}\) | 0.21842554513045265 | 1.9478022428563655 | 1 |
\(T_{10}\) | 1.7494723363303561 | 0.7672192141953507 | 3 |
\(T_{11}\) | 1.9906629300385918 | 1.0869545317058076 | 1 |
\(T_{12}\) | 1.63510361868541 | 0.8617001535631279 | 3 |
\(T_{13}\) | 0.6459535122987747 | 1.0827522985620026 | 2 |
\(T_{14}\) | 0.3144944541356516 | 1.9091634904941777 | 1 |
\(T_{15}\) | 1.5689608732625806 | 0.39157113233171503 | 2 |
\(T_{16}\) | 1.8363603823958718 | 1.2276694755874005 | 2 |
\(T_{17}\) | 1.4337847229694787 | 1.8034165435084824 | 1 |
\(T_{18}\) | 0.45600475381462724 | 0.3148736825002354 | 1 |
\(T_{19}\) | 0.42574632497710296 | 0.5997987868811052 | 2 |
\(T_{20}\) | 1.1773573959790524 | 1.748304458676117 | 2 |
\(T_{21}\) | 1.6423369352181407 | 0.37773395675275623 | 1 |
\(T_{22}\) | 1.7097476306439856 | 1.9885829599019398 | 3 |
\(T_{23}\) | 0.24618239172597223 | 0.07728932157603396 | 2 |
\(T_{24}\) | 1.7603811296081917 | 1.748070452804373 | 2 |
\(T_{25}\) | 0.002840121920356653 | 1.2658785281393257 | 3 |
\(T_{26}\) | 1.8250450796924662 | 0.9212481743931855 | 3 |
\(T_{27}\) | 0.27403996814324993 | 1.5629091001024709 | 1 |
\(T_{28}\) | 0.4159278127296058 | 0.8888387282888994 | 2 |
\(T_{29}\) | 1.7620478294700856 | 1.2516409761386298 | 3 |
\(T_{30}\) | 0.4351390216463453 | 0.03836283116041028 | 3 |
\(T_{31}\) | 1.1043330594244645 | 0.8946100006511641 | 1 |
\(T_{32}\) | 1.2059961685894143 | 1.891497200080938 | 3 |
\(T_{33}\) | 0.6245753790375235 | 1.6229014671236641 | 2 |
\(T_{34}\) | 0.7155919663569039 | 0.7721262392930481 | 1 |
\(T_{35}\) | 0.9074113329307563 | 0.12869596969464703 | 1 |
\(T_{36}\) | 0.85636723383494 | 0.8891063898237037 | 1 |
\(T_{37}\) | 0.375263657366401 | 0.3075941820847998 | 1 |
\(T_{38}\) | 1.2824196407500417 | 0.8380355595664228 | 2 |
\(T_{39}\) | 0.9577673955193708 | 1.4249046312912836 | 3 |
\(T_{40}\) | 0.14893382442377834 | 1.783124207544456 | 1 |
k = 5 T = (1,2) s = np.argsort(np.linalg.norm(T-x,ord=2,axis=1))[:k] np.bincount(y[s])
贝叶斯方法是一种研究不肯定性的推理方法,不肯定性经常使用贝叶斯几率表示,它是一种主观几率
朴素贝叶斯能够被认为几率统计中事件A发生的前提下B发生的几率,即\(P(B|A)={\frac {P(A)∗P(B|A)} {P(B)}}\)
序号 | 家庭经济情况 | 月收入 | 购买汽车 |
---|---|---|---|
1 | 通常 | 优秀 | 10 |
2 | 好 | 优秀 | 12 |
3 | 通常 | 优秀 | 6 |
4 | 通常 | 良好 | 8.5 |
5 | 通常 | 良好 | 9 |
6 | 通常 | 优秀 | 7.5 |
7 | 好 | 通常 | 22 |
8 | 通常 | 通常 | 9.5 |
9 | 通常 | 良好 | 7 |
10 | 好 | 良好 | 12.5 |
import numpy as np data = np.array([['通常', '优秀', 10, 1], ['好', '优秀', 12, '1'], ['通常', '优秀', 6, '1'], ['通常', '良好', 8.5, '0'], ['通常', '良好', 9, '0'], ['通常', '优秀', 7.5, '1'], ['好', '通常', 22, '1'], ['通常', '通常', 9.5, '0'], ['通常', '良好', 7, '1'], ['好', '良好', 12.5, '1']]) data
p_1 = np.sum(data=='1')/len(data) p_0 = np.sum(data=='0')/len(data) p_1,p_0
X = np.array(['通常','优秀','12']) p_1_s = 1 p_0_s = 1 data_1 = data[data[:,3]=='1'] # 购买汽车的训练数据 data_0 = data[data[:,3]=='0'] # 不买汽车的训练数据 for i,x in enumerate(X): print(x, np.sum(data_1==x),np.sum(data_0==x)) p_1_s *= np.sum(data_1==x)/len(data) p_0_s *= np.sum(data_0==x)/len(data) p_1_s*p_1,p_0_s*p_0
认为该测试样本的预测结果为1。
7酱昨天没上场
随机森林方法是一种统计学习理论,它利用bootstrap重抽样方法从原始样本中抽取多个样本,对每一个bootstrap样本进行决策树建模,而后组合多棵决策树的预测,经过投票得出最终预测结果。
考完补足随机森林算法可视化例子
看到名字就想到AC自动机
支持向量机根据有限的样本信息在模型的复杂性和学习能力间寻求最佳折中,以期得到最好的推广能力。
wiki上的解释比书上好懂多了。
人工神经网络是一种模仿生物神经网络的结构和功能的数学模型或计算模型,用于对函数进行估计或近似。这里仅对反向传播算法(BP)进行说明
算法分为两个阶段
\(x_1\) | \(x_2\) | \(x_31\) | \(x_{14}\) | \(x_{15}\) | \(x_{24}\) | \(x_{25}\) | \(x_{34}\) | \(x_{35}\) | \(x_{46}\) | \(x_{56}\) | \(\theta_4\) | \(\theta_5\) | \(\theta_6\) |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 1 | 0.2 | -0.3 | 0.4 | 0.1 | -0.5 | 0.2 | -0.3 | -0.2 | -0.4 | 0.2 | 0.1 |
结点 | 网格输入值 | 输出值 |
---|---|---|
4 | \(x_1*x_{14}+x_2*x_{24}+x_3*x_{34}+\theta_4=1*0.2+0*0.4+1*-0.5-0.4=-0.7\) | $\frac {1} {1+e^{0.7}}=0.332 $ |
5 | \(x_1*x_{15}+x_2*x_{25}+x_3*x_{35}+\theta_5=1*-0.3+0*0.1+1*0.2+0.2=0.1\) | $\frac {1} {1+e^{-0.1}}=0.1 $ |
6 | \(o_4*x_{46}+o_5*x_{56}+\theta_6=-0.3*0.332+-0.2*0.525+0.1=-0.105\) | \(\frac {1} {1+e^{0.105}}\) |
结点 | 系数修正 | 权系数变化值 |
---|---|---|
6 | \(\eta=f'(net_6)*E=O_6*(1-O_6)*(1-O_6)\) | 0.1311 |
5 | \(\varDelta 5=\eta f'(net_5)*x_{56}=\eta O_5*(1-O_5)*{w_56}\) | -0.0065 |
4 | \(\varDelta 4=\eta f'(net_4)*x_{46}=\eta O_4*(1-O_4)*{w_46}\) | -0.0087 |
输入样本\(x_1=1,x_2=0\) 输出结点的指望输出为1,对于第k次学习获得的权值为\(w_{11}(k)=0,w_{12}(k)=2,w_{21}(k)=1,w_{22}=1,T_1(k)=1,T_2(k)=1\),求\(z(k),z(k+1)\)
求正向传导
隐含层:\(net_i = \sum_{(j=1)}^k w_{ji} x_j+θ_i\)
输出层:\(net_z = ∑_{(j=1)}^2 w_{jz} y_j^1+θ_z\)
\(y_1(k)=x_1*w_{11}(k)+x_2*w_{21}(k)=1*0+0*2=0<1\ f(net_1)=1\)
\(y_2(k)=x_1*w_{12}(k)+x_2*w_{22}(k)=1*2+0*2=2>=1\ f(net_2)=2\)
\(z(k)=T_1(k)*f(net_1)+T_2(k)*f(net_2)=1*1+2*1=3\)
反向求修正系数
输出层:\(δ_z^k=y_z^k (d_z^1-y_z^k)(1-y_z^k)\)
隐含层:\(δ_i^k=δ_z^k w_iz (k)y_i^k (1-y_i^k)\)
\(\delta_{k} =\triangle z(k) = f'(net_3)*(E-z(k))=(1-3)*3*(1-3)=2*3*2=12\)
\(\varDelta y_1 = f\prime(net_1) *\delta_{k} * net_1 = 1*(1-1)*12*1 =0\)
\(\varDelta y_2 = f\prime(net_2) *\delta_{k} * net_2 = 2*(1-2)*12*2 =-24\)
经过修正系数求修正值
\(w_{iz}(k+1)=w_{iz} (k)+ηδ_z^k y_i^k\)
\(T_1(k+1) = T_1(k) + \delta_{k} * \eta * f(net_1)_k =1+12*1*1 = 13\)
\(T_2(k+1) = T_2(k) + \delta_{k} * \eta * f(net_2)_k=1+12*1*2 = 25\)
\(w_{11}(k+1) = w_{11}(k) +\varDelta y_1*\eta*x_{1} =0 + 12*1*0 = 0\)
\(w_{12}(k+1) = w_{12}(k) +\varDelta y_2*\eta*x_{1} =2 -24*1*1 = -22\)
\(w_{21}(k+1) = w_{21}(k) +\varDelta y_1*\eta*x_{2} =2 + 12*1*0 = 2\)
\(w_{22}(k+1) = w_{22}(k) +\varDelta y_2*\eta*x_{2} =1 -24*1*0 = 1\)
求第k+1次的正向传导输出值
\(y_1(k+1)=x_1*w_{11}(k+1)+x_2*w_{21}(k+1)=1*0+0*2=0<1\ f(net_1)=1\)
\(y_2(k+1)=x_1*w_{12}(k+1)+x_2*w_{22}(k+1)=1*(-22)+0*2=-22<=1\ f(net_2)=1\)
\(z(k+1)=T_1(k+1)*f(net_1)+T_2(k+1)*f(net_2)=1*13+1*25=38\)
从数据中生成分类器的一个特别有效的方法是生成一棵决策树。决策树表示方法是应用最普遍的逻辑方法之一,它从一组无次序、无规则的事例中推理出决策树表示形式的分类准则。
import numpy as np import random outlook = [ 'sunny', 'overcast', 'rainy' ] temperature = [ 'hot', 'mild', 'cool' ] humidity = [ 'high', 'normal', ] windy = [ 'false', 'true' ] play = [ 'no', 'Yes' ] data = [] for i in range(20): data.append([outlook[random.randint(0,len(outlook)-1)], temperature[random.randint(0,len(temperature)-1)], humidity[random.randint(0,len(humidity)-1)], windy[random.randint(0,len(windy)-1)], play[random.randint(0,len(play)-1)]]) data = np.array(data) data
编号 | outlook | temperature | humidity | windy | play |
---|---|---|---|---|---|
1 | rainy | mild | high | true | Yes |
2 | overcast | hot | normal | false | no |
3 | sunny | hot | normal | true | no |
4 | sunny | cool | normal | false | no |
5 | rainy | hot | high | false | no |
6 | sunny | mild | high | true | no |
7 | overcast | mild | high | true | Yes |
8 | rainy | cool | normal | false | Yes |
9 | sunny | cool | normal | true | no |
10 | sunny | mild | high | true | Yes |
11 | overcast | cool | high | false | Yes |
12 | rainy | cool | high | false | Yes |
13 | sunny | mild | high | false | Yes |
14 | overcast | cool | normal | true | Yes |
15 | rainy | hot | normal | false | Yes |
16 | overcast | mild | normal | false | Yes |
17 | sunny | hot | normal | false | Yes |
18 | sunny | cool | normal | true | no |
19 | rainy | mild | normal | false | no |
20 | rainy | cool | normal | true | no |
import math def entropy(a,b): return 0.0-a/(a+b)*math.log(a/(a+b),2)-b/(a+b)*math.log(b/(a+b),2) entropy(np.sum(data=='Yes'),np.sum(data=='no'))
\(entropy(S)=-\sum_{i=0}^{n}{p_i log_2 p_i}=0.9927744539878084\)
ans = 0 for o in outlook: pos = np.sum(np.where(data[np.where(data=='Yes')[0]]==o)) neg = np.sum(np.where(data[np.where(data=='no')[0]]==o)) print('| $entropy(S_{'+o+'})$ | $-\\frac {'+ str(pos)+"} {"+str(neg+pos)+"} \\log_2\\frac {"+ str(pos)+"} {"+str(neg+pos)+"} -\\frac {"+ str(neg)+"} {"+str(neg+pos)+"} \\log_2\\frac {"+ str(neg)+"} {"+str(neg+pos)+"} $ | " ,str(entropy(pos,neg))," |" ) ans = ans + len(np.where(data == o)[0])/ len(data) *entropy(pos,neg) ans
指望信息 | 公式 | 结果 |
---|---|---|
\(entropy(S_{sunny})\) | $-\frac {3} {8} \log_2\frac {3} {8} -\frac {5} {8} \log_2\frac {5} {8} $ | 0.9544340029249649 |
\(entropy(S_{overcast})\) | $-\frac {4} {5} \log_2\frac {4} {5} -\frac {1} {5} \log_2\frac {1} {5} $ | 0.7219280948873623 |
\(entropy(S_{rainy})\) | $-\frac {4} {7} \log_2\frac {4} {7} -\frac {3} {7} \log_2\frac {3} {7} $ | 0.9852281360342516 |
\(gain(S,outlook)=0.08568898148399373\)
同理可得,\(gain(S,temperature)=0.0008495469303535508\),\(gain(S,humidity)=0.3658730455992085\),\(gain(S,windy)=0.3654369784855406\)
属性humidity的信息增量更大,选取humidity做为根结点的测试属性。
from sklearn import tree clf = tree.DecisionTreeClassifier(criterion="entropy",class_weight="balanced",min_samples_split=2) from sklearn import preprocessing feature = ['outlook','temperature','humdity','windy'] le = preprocessing.LabelEncoder() data_sk = data.copy() for i in range(5): data_sk[:,i] = le.fit_transform(data_sk[:,i]) clf = clf.fit(data_sk[:,:4],data_sk[:,4]) import graphviz dot_data = tree.export_graphviz(clf, out_file=None,feature_names=feature,class_names=np.array(['Yes','no']),filled=True, rounded=True, special_characters=True) graph = graphviz.Source(dot_data) graph
sklearn运用的是cart算法,只能生成二叉树:
from sklearn.datasets import load_breast_cancer from id3 import Id3Estimator from id3 import export_graphviz bunch = load_breast_cancer() estimator = Id3Estimator() data = [] for i in range(20): data.append([outlook[random.randint(0,len(outlook)-1)], temperature[random.randint(0,len(temperature)-1)], humidity[random.randint(0,len(humidity)-1)], windy[random.randint(0,len(windy)-1)], play[random.randint(0,len(play)-1)]]) data = np.array(data) estimator.fit(data[:,:4],data[:,4], check_input=True) export_graphviz(estimator.tree_, 'tree.dot', feature) from subprocess import check_call check_call(['dot', '-Tpng', 'tree.dot', '-o', 'tree.png'])
C4.5是ID3的一种改进算法,用信息增益比代替了信息增熵进行分支。
ans = 0 for o in outlook: pos = np.sum(np.where(data[np.where(data=='Yes')[0]]==o)) neg = np.sum(np.where(data[np.where(data=='no')[0]]==o)) ans = ans + len(np.where(data == o)[0])/ len(data) *entropy(pos,neg) ans2 = 0 def entropy2(a,b): return 0.0-a/b*math.log(a/b,2) for o in outlook: ans2 = ans + entropy2(len(np.where(data==o)[0]),len(data)) ans/ans2
指望信息 | 公式 | 结果 |
---|---|---|
\(entropy(S_{sunny})\) | $-\frac {3} {8} \log_2\frac {3} {8} -\frac {5} {8} \log_2\frac {5} {8} $ | 0.9544340029249649 |
\(entropy(S_{overcast})\) | $-\frac {4} {5} \log_2\frac {4} {5} -\frac {1} {5} \log_2\frac {1} {5} $ | 0.7219280948873623 |
\(entropy(S_{rainy})\) | $-\frac {4} {7} \log_2\frac {4} {7} -\frac {3} {7} \log_2\frac {3} {7} $ | 0.9852281360342516 |
$entropy(overlook)= 0.9070854725038147 \( \)gain(overlook) =entropy(play)-entropy(overlook)= 0.08568898148399373 \( \)splitInfo(overlook)=-\frac{8} {20}\log_2(\frac{8} {20})-\frac{5} {20}\log_2(\frac{5} {20})-\frac{7} {20}*\log_2(\frac{7} {20})\(=1.4371860829942302 \)gainratio(overlook)= \frac {gain(overlook)}{splitInfo(overlook)}= 0.6311538103778426 \( \)gainratio(windy)= \frac {gain(windy)}{splitInfo(windy)}= 0.6457015657437329 \( \)gainratio(humidity)= \frac {gain(humidity)}{splitInfo(humidity)}= 0.6325210109574498 \( \)gainratio(temperature)= \frac {gain(temperature)}{splitInfo(temperature)}=0.6405928106112709 $
显然windy最大,根据windy构建决策树。
k-means把n个点(能够是样本的一次观察或一个实例)划分到k个聚类中,使得每一个点都属于离他最近的均值(此即聚类中心)对应的聚类,以之做为聚类的标准。
k-means | KNN |
---|---|
聚类问题 | 分类问题 |
训练集无特征 | 训练集有特征 |
具备先验过程 | 没有先验过程 |
以做业第三题为例:
分别取k=2和3,利用K-means聚类算法对如下的点聚类,(2, 1), (1, 2), (2, 2), (3, 2), (2, 3), (3, 3), (2, 4), (3, 5), (4, 4), (5, 3),并讨论k值以及初始聚类中心对聚类结果的影响。
import numpy as np import matplotlib.pyplot as plt X = np.array([[2, 1], [1, 2], [2, 2], [3, 2], [2, 3], [3, 3], [2, 4], [3, 5], [4, 4], [5, 3]]) plt.scatter(X[:, 0], X[:, 1], marker='o') plt.show() print(X)
使用题中数据,画出散点图
import numpy as np import matplotlib.pyplot as plt X = np.array([[2, 1], [1, 2], [2, 2], [3, 2], [2, 3], [3, 3], [2, 4], [3, 5], [4, 4], [5, 3]]) from sklearn.cluster import KMeans x_init = np.array([[2, 1], [1, 2]]) # 将前2个点设为初始聚类中心,迭代次数为1次 y_pred = KMeans(n_clusters=2, max_iter=1, init=x_init).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()
第一次迭代结果
使用第一次迭代结果的质心做为聚类中心
x_init = np.array([[3.16, 2.5], [2, 3.5]]) # 将第一次分类结果的质心设为初始聚类中心,迭代次数为1次 y_pred = KMeans(n_clusters=2, max_iter=1, init=x_init).fit_predict(X) print(y_pred) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()
结果与第一次同样
计算矩阵:
import math m1_x = 0.0 m1_y = 0.0 m2_x = 0.0 m2_y = 0.0 for i, y in enumerate(y_pred): if not y: m1_x += X[i][0] m1_y += X[i][1] else: m2_x += X[i][0] m2_y += X[i][1] m1_x = m1_x / y_pred[y_pred == 0].size m1_y = m1_y / y_pred[y_pred == 0].size m2_x = m2_x / y_pred[y_pred == 1].size m2_y = m2_y / y_pred[y_pred == 1].size print("M1':" , m1_x, m1_y, "M2':" , m2_x, m2_y) for i, x in enumerate(X): print(math.sqrt(math.pow(x[0] - m1_x, 2) + math.pow(x[1] - m1_y, 2)), math.sqrt(math.pow(x[0] - m2_x, 2) + math.pow(x[1] - m2_y, 2)))
结果:
# 当k=3时 x_init = np.array([[2, 1], [1, 2], [2, 2]]) # 将前3个点设为初始聚类中心,迭代次数为1次 y_pred = KMeans(n_clusters=3, max_iter=1, init=x_init).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show() print(y_pred) m1 = np.mean(X[np.where(y_pred == 0)], axis=0) # axis==0 计算每一列均值 m2 = np.mean(X[np.where(y_pred == 1)], axis=0) m3 = np.mean(X[np.where(y_pred == 2)], axis=0) print("M1':", m1, "M2':", m2, "M3':", m3)
结果:
y_pred = KMeans(n_clusters=3, max_iter=2, init=x_init).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show() m1 = np.mean(X[np.where(y_pred == 0)], axis=0) # axis==0 计算每一列均值 m2 = np.mean(X[np.where(y_pred == 1)], axis=0) m3 = np.mean(X[np.where(y_pred == 2)], axis=0) print("M1':", m1, "M2':", m2, "M3':", m3)
结果:
y_pred = KMeans(n_clusters=3, max_iter=3, init=x_init).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show() m1 = np.mean(X[np.where(y_pred == 0)], axis=0) # axis==0 计算每一列均值 m2 = np.mean(X[np.where(y_pred == 1)], axis=0) m3 = np.mean(X[np.where(y_pred == 2)], axis=0) print("M1':", m1, "M2':", m2, "M3':", m3)
与第二次同样:
在 K-means 算法中 K 是事先给定的,这个 K 值的选定是很是难以估计的。不少时候,事先并不知道给定的数据集应该分红多少个类别才最合适。K值太小,类内类似性变小,聚类结果将没法知足应用须要;K值过大,类间间距变小,意味着应用中将会增长成本。这也是 K-means 算法的一个不足。
初始聚类中心的选择对聚类结果有较大的影响,一旦初始值选择的很差,可能没法获得有效的聚类结果,甚至若是选到噪声数据和孤立点,将使算法的迭代次数增多,算法的时间性能变差,另外,受噪声数据和孤立点的影响算法还容易陷入局部极值。若是这也成为 K-means算法的一个主要问题。
除了中心点选取算法与k-means不一致外,其余算法过程一致。
【例12.1】,当初始中心点为{D,E}时,试运用K-中心点聚类算法给出第一次迭代后生成的两个簇。
sklearn中彷佛没有该算法,不过wiki中讲的很详细。
% matplotlib inline import numpy as np import matplotlib.pyplot as plt X = np.array([[0, 1, 2, 2, 3], [1, 0, 2, 4, 3], [2, 2, 0, 1, 5], [2, 4, 1, 0, 3], [3, 3, 5, 3, 0]]) k = [3, 4] y = [] for i, x in enumerate(X): if x[k[0]] <= x[k[1]]: print(x[k[0]], x[k[1]], "0") y.append(0) else: print(x[k[0]], x[k[1]], "1") y.append(1) y = np.array(y) print("COST:", np.sum(X[np.where(y == 0)], axis=0)[k[0]], np.sum(X[np.where(y == 1)], axis=0)[k[1]])
结果:
k = [0, 4] y = [] for i, x in enumerate(X): if x[k[0]] <= x[k[1]]: print(x[k[0]], x[k[1]], "0") y.append(0) else: print(x[k[0]], x[k[1]], "1") y.append(1) y = np.array(y) print("COST:", np.sum(X[np.where(y == 0)], axis=0)[k[0]], np.sum(X[np.where(y == 1)], axis=0)[k[1]]) ans_da = np.sum(X[np.where(y == 0)], axis=0)[k[0]] + np.sum(X[np.where(y == 1)], axis=0)[k[1]] print(ans_da - ans)
结果:
- 替换k中的值,得出不一样结果,选择第一个代价最小的结果,即用A替换D。
一个神经网络接受外界输入模式时,将会分为不一样的对应区域,各区域对输入模式具备不一样的响应特征,并且这个过程是自动完成的。SOM经过自动寻找样本中的内在规律和本质属性,自组织、自适应地改变网络参数与结构。
DBSCAN是一个基于高密度链接区域地密度聚类算法,该算法将簇定义为密度相连的点的最大集,将具备高密度的区域划分为簇。
k-means | DBSCAN | |
---|---|---|
划分聚类 | 聚类全部对象 | 丢弃被它识别为噪声的对象 |
基准 | 原型 | 密度 |
处理数据 | 难处理非球形的簇和不一样大小的簇 | 能够处理不一样大小或形状的簇 |
处理数据 | 只能用于具备明肯定义的质心(好比均值或中位数)的数据 | 要求密度定义(基于传统的欧几里得密度概念) |
处理数据 | 能够用于稀疏的高维数据,如文档数据 | 对于高维数据,传统的欧几里得密度定义不能很好处理它们 |
架设 | 假定全部的簇都来自球形高斯分布,具备不一样的均值,但具备相同的协方差矩阵 | 不对数据的分布作任何假定 |
合并 | 能够发现不是明显分离的簇,即使簇有重叠也能够发现 | 合并有重叠的簇 |
时间复杂度 | \(O(m)\) | \(O(m^2)\) |
屡次运行 | 使用随机初始化质心,不会产生相同的结果 | 会产生相同结果 |
K值 | 簇个数须要做为参数指定 | 自动地肯定簇个数 |
模型 | 优化问题,即最小化每一个点到最近质心的偏差平方和 | 不基于任何形式化模型 |