无监督学习——K均值聚类的Python实现
目錄
概要
一、K均值算法
二、K值的選取:手肘法
三、用聚類實現(xiàn)鳶尾花數(shù)據(jù)分類
四、應(yīng)用案例
1. 讀取數(shù)據(jù)
2. 繪制手肘圖
3. 找到最佳K值
4. 分類結(jié)果可視化
機器學習類型和算法的分類
無監(jiān)督學習的數(shù)據(jù)集中沒有輸出標簽y,常用的無監(jiān)督學習算法有聚類和降維。
概要
聚類人有歸納和總結(jié)的能力,機器也有。聚類就是讓機器把數(shù)據(jù)集中的樣本按照特征的性質(zhì)分組,這個過程中沒有標簽的存在。
聚類和監(jiān)督學習中的分類問題有些類似,其主要區(qū)別在于:傳統(tǒng)分類問題也就是說,在對貓狗圖像分類之前,我們心里面已經(jīng)對貓、狗圖像形成了概念。這些概念指導(dǎo)著我們?yōu)橛?xùn)練集設(shè)定好標簽。機器首先是學習概念,然后才能夠做分類、做判斷。分類的結(jié)果,還要接受標簽,也就是已有概念的檢驗。
而聚類不同,雖然本質(zhì)上也是“分類”,但是“譬如,漫天繁星,彼此之間并沒有關(guān)聯(lián),也 沒有星座的概念,當人們看到它們,是先根據(jù)星星在廣袤蒼穹中的位置將其一組一組地“聚集"起來,然后才逐漸形成星座的概念。人們說,這一-組星星是“大熊座",那一組星星是“北斗七星”。這個先根據(jù)特征進行分組,之后再概念化的過程就是聚類。聚類算法有好幾種,K均值(K-means)是其中最常見的一種。
一、K均值算法
K均值算法是最容易理解的無監(jiān)督學習算法。算法簡單,速度也不差,但需要人工指定K值,也就是分成幾個聚類。
具體算法流程:
(1)首先確定K的數(shù)值,比如5個聚類,也叫5個簇。
(2)然后再一大堆數(shù)據(jù)中隨機挑選K個數(shù)據(jù)點,作為簇的質(zhì)心(centroid)。這些隨機質(zhì)心當然不完美,別著急,它們會慢慢變得完美。
(3)遍歷集合中每一個數(shù)據(jù)點,計算它們與每一個質(zhì)心的距離(比如歐式距離)。數(shù)據(jù)點離哪個質(zhì)心近,就屬于哪一類。此時初始的K個類別開始形成。
(4)這時每一個質(zhì)心中都聚集了很多數(shù)據(jù)點,于是質(zhì)心說,你們來了,我就要“退役”了(這是個偉大的“禪讓制度”啊!),選取一個新的質(zhì)心吧。然后計算出每一類中最靠近中心的點,作為新的質(zhì)心。此時新的質(zhì)心會比原來隨機選來的靠譜一些(等會兒用圖展示質(zhì)心的移動)
(5)重新進行步驟(3),計算所有數(shù)據(jù)點和新的質(zhì)心的距離,在新的質(zhì)心周圍形成新的簇分配(“吃瓜群眾”隨風飄搖,離誰進就跟誰)。
(6)重新進行步驟(4),繼續(xù)選擇更好的質(zhì)心(一代一代的“禪讓”下去)。
(7)一直重復(fù)進行步驟(5)和(6),不斷更新簇中的數(shù)據(jù)點,不斷找到新的質(zhì)心,直至收斂。
二、K值的選取:手肘法
聚類問題的關(guān)鍵在于K值的選取。也就是說,把一批數(shù)據(jù)劃分為多少個簇是最合理的呢?當數(shù)據(jù)特征維度較少、數(shù)據(jù)分布較為分散時,可通過數(shù)據(jù)可視化的方法來人工確定K值。但當數(shù)據(jù)特征維度較多、數(shù)據(jù)分布較為混亂時,數(shù)據(jù)可視化幫助不大。
當然,也可以經(jīng)過多次實驗,逐步調(diào)整,使簇的數(shù)目逐漸達到最優(yōu),以符合數(shù)據(jù)集的特點。
這里我介紹一種直觀的手肘法( elbow method)進行簇的數(shù)量的確定。手肘法是基于 對聚類效果的一一個度量指標來實現(xiàn)的,這個指標也可以視為一一種損失。 在K值很小的時候,整體損失很大,而隨著K值的增大,損失函數(shù)的值會在逐漸收斂之前出現(xiàn)一個拐點。此時的K值就是比較好的值。
大家看下面的圖,損失隨著簇的個數(shù)而收斂的曲線有點像只手臂,最佳K值的點像是手肘,因此取名為手肘法。
三、用聚類實現(xiàn)鳶尾花數(shù)據(jù)分類
1. 數(shù)據(jù)讀取
import numpy as np import pandas as pd dataset = pd.read_csv('D:/NoteBook/Iris.txt') dataset.head() #只對兩個特征進行聚類,以便二維展示 X = dataset.iloc[:,[0,3]].values下面嘗試用不同的K值進行聚類的擬合
#聚類的集合,下面嘗試用不同的K值進行聚類的擬合 from sklearn.cluster import KMeans#導(dǎo)入聚類模型 cost = []#初始化損失(距離)值 for i in range(1,11):#嘗試不同的K值kmeans = KMeans(n_clusters= i ,init='k-means++', random_state = 0)kmeans.fit(X)cost.append(kmeans.inertia_)#inerita_是我們選擇的方法,其作用相當于損失函數(shù) #繪制手肘圖找到最佳K值 import matplotlib.pyplot as plt import seaborn as sns hist,ax = plt.subplots() plt.plot(range(1,11),cost) # plt.title('The Elbow Method') ax.set_title('The Elbow Method') ax.set_ylabel('Cost') plt.show() kmeansmodel = KMeans(n_clusters=3, init='k-means++') y_kmeans = kmeansmodel.fit_predict(X) #把分類好的聚類可視化 hist,ax = plt.subplots() plt.scatter(X[y_kmeans == 0,0], X[y_kmeans == 0,1],s = 100, c = 'cyan', label = 'Cluster 1')#聚類1 plt.scatter(X[y_kmeans == 1,0], X[y_kmeans == 1,1],s = 100, c = 'blue', label = 'Cluster 2')#聚類2 plt.scatter(X[y_kmeans == 2,0], X[y_kmeans == 2,1],s = 100, c = 'green', label = 'Cluster 3')#聚類3 plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],s = 200, c = 'yellow', label = 'Centroids')#質(zhì)心 ax.set_title('鳶尾花花萼形成的聚類')#鳶尾花花萼形成的聚類 ax.set_xlabel('花萼長度')# ax.set_ylabel('花萼寬度')# plt.legend() plt.show()打印聚類結(jié)果圖:?
四、應(yīng)用案例
本案例主要是基于企業(yè)注冊資金和參保人數(shù)的企業(yè)聚類分析
1. 讀取數(shù)據(jù)
import numpy as np import pandas as pd data = pd.read_excel('C:/新評分及數(shù)據(jù)補全合并.xlsx') data.head()注冊資金數(shù)據(jù)去單位
import re io = 'C:/新評分及數(shù)據(jù)補全合并.xlsx' registered_capital = data['注冊資本'] capital = [] for i in registered_capital:m = str(i).replace('-','0') #匹配到“-”并替換為“0”now = re.match("\d*", m).group() #group(0) 同 group() 就是匹配正則表達式整體結(jié)果capital.append(now) data['注冊資本新'] = pd.DataFrame(capital) #數(shù)據(jù)存入Excel列 data['注冊資本新'].head() data.to_excel(io) #此行代碼為數(shù)據(jù)存入Excel列,上面已存儲,可注釋數(shù)據(jù)歸一化處理
from sklearn.preprocessing import MinMaxScaler io = 'C:/新評分及數(shù)據(jù)補全合并.xlsx' x1 = data[['注冊資本新']] x2 = data[['參保人數(shù)']] # x2 = (x1 - np.min(x1))/(np.max(x1) - np.min(x1)) #注冊資本歸一化后的結(jié)果 min_max_scaler = MinMaxScaler() X_train_minmax1 = min_max_scaler.fit_transform(x1)#注冊資本歸一化后的結(jié)果 X_train_minmax2 = min_max_scaler.fit_transform(x2)#參保人數(shù)歸一化后的結(jié)果 data['注冊資本歸一化'] = pd.DataFrame(X_train_minmax1) #數(shù)據(jù)存入Excel列 data['參保人數(shù)一化'] = pd.DataFrame(X_train_minmax2) #數(shù)據(jù)存入Excel列 # pd.DataFrame(X_train_minmax1.tolist()).describe() # pd.DataFrame(X_train_minmax2.tolist()).describe() # data.to_excel(io)歸一化結(jié)果
X2 = data.loc[:,['注冊資本歸一化','參保人數(shù)一化']].values print(X2)?
2. 繪制手肘圖
#繪制手肘圖 from sklearn.cluster import KMeans cost = [] for i in range(1,11):kmeans = KMeans(n_clusters= i ,init='k-means++', random_state = 0)kmeans.fit(X2)cost.append(kmeans.inertia_)3. 找到最佳K值
#繪制手肘圖找到最佳K值 import matplotlib.pyplot as plt import seaborn as sns hist,ax = plt.subplots() plt.plot(range(1,11),cost) # plt.title('The Elbow Method') ax.set_title('The Elbow Method') ax.set_ylabel('Cost') plt.show()由手肘圖可判斷,最佳K值大概為4,我們選擇4作為聚類個數(shù)
kmeansmodel = KMeans(n_clusters=4, init='k-means++') y_kmeans = kmeansmodel.fit_predict(X2)4. 分類結(jié)果可視化
#把分類好的聚類可視化 hist,ax = plt.subplots() #解決中文顯示問題 plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus'] = False plt.scatter(X2[y_kmeans == 0,0], X2[y_kmeans == 0,1],s = 100, c = 'cyan', label = 'Cluster 1')#聚類1 plt.scatter(X2[y_kmeans == 1,0], X2[y_kmeans == 1,1],s = 100, c = 'blue', label = 'Cluster 2')#聚類2 plt.scatter(X2[y_kmeans == 2,0], X2[y_kmeans == 2,1],s = 100, c = 'green', label = 'Cluster 3')#聚類3 plt.scatter(X2[y_kmeans == 3,0], X2[y_kmeans == 3,1],s = 100, c = 'red', label = 'Cluster 4')#聚類3 plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],s = 200, c = 'yellow', label = 'Centroids')#質(zhì)心 ax.set_title('企業(yè)聚類')#客戶形成的聚類 ax.set_xlabel('注冊資本')# ax.set_ylabel('參保人數(shù)')# plt.legend() plt.show()企業(yè)聚類結(jié)果
?
?由于我們的數(shù)據(jù)比較隨機,并不是很規(guī)整,所以結(jié)果來看,聚類結(jié)果并不是十分美觀。
總結(jié)
以上是生活随笔為你收集整理的无监督学习——K均值聚类的Python实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用Python写了一个水果忍者小游戏
- 下一篇: 20182316胡泊 第2,3周学习总