本文基於教材《大數據挖掘與應用》王振武,出於期末複習目的,對部分算法利用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值 | 簇個數須要做爲參數指定 | 自動地肯定簇個數 |
模型 | 優化問題,即最小化每一個點到最近質心的偏差平方和 | 不基於任何形式化模型 |