1. 程式人生 > >【Python資料探勘課程】三.Kmeans聚類程式碼實現、作業及優化

【Python資料探勘課程】三.Kmeans聚類程式碼實現、作業及優化

        這篇文章直接給出上次關於Kmeans聚類的籃球遠動員資料分析案例,同時介紹這次作業同學們完成的圖例,最後介紹Matplotlib包繪圖的優化知識。        希望這篇文章對你有所幫助,尤其是剛剛接觸資料探勘以及大資料的同學,同時準備嘗試以案例為主的方式進行講解。如果文章中存在不足或錯誤的地方,還請海涵~

一. 案例實現

        這裡不再贅述,詳見第二篇文章,直接上程式碼,這是我的學生完成的作業。
        資料集:
        下載地址:KEEL-dataset - Basketball data set
        籃球運動員資料,每分鐘助攻和每分鐘得分數。通過該資料集判斷一個籃球運動員屬於什麼位置(控位、分位、中鋒等)。

完整資料集包括5個特徵,每分鐘助攻數、運動員身高、運動員出場時間、運動員年齡和每分鐘得分數。

assists_per_minute  height  time_played  age  points_per_minute  
0               0.0888     201        36.02   28             0.5885  
1               0.1399     198        39.32   30             0.8291  
2               0.0747     198        38.80   26             0.4974  
3               0.0983     191        40.71   30             0.5772  
4               0.1276     196        38.40   28             0.5703  
5               0.1671     201        34.10   31             0.5835  
6               0.1906     193        36.20   30             0.5276  
7               0.1061     191        36.75   27             0.5523  
8               0.2446     185        38.43   29             0.4007  
9               0.1670     203        33.54   24             0.4770  
10              0.2485     188        35.01   27             0.4313  
11              0.1227     198        36.67   29             0.4909  
12              0.1240     185        33.88   24             0.5668  
13              0.1461     191        35.59   30             0.5113  
14              0.2315     191        38.01   28             0.3788  
15              0.0494     193        32.38   32             0.5590  
16              0.1107     196        35.22   25             0.4799  
17              0.2521     183        31.73   29             0.5735  
18              0.1007     193        28.81   34             0.6318  
19              0.1067     196        35.60   23             0.4326  
20              0.1956     188        35.28   32             0.4280  
        完整程式碼:
# -*- coding: utf-8 -*-
  
from sklearn.cluster import Birch  
from sklearn.cluster import KMeans  
  
X = [[0.0888, 0.5885],  
     [0.1399, 0.8291],  
     [0.0747, 0.4974],  
     [0.0983, 0.5772],  
     [0.1276, 0.5703],  
     [0.1671, 0.5835],  
     [0.1906, 0.5276],  
     [0.1061, 0.5523],  
     [0.2446, 0.4007],  
     [0.1670, 0.4770],  
     [0.2485, 0.4313],  
     [0.1227, 0.4909],  
     [0.1240, 0.5668],  
     [0.1461, 0.5113],  
     [0.2315, 0.3788],  
     [0.0494, 0.5590],  
     [0.1107, 0.4799],  
     [0.2521, 0.5735],  
     [0.1007, 0.6318],  
     [0.1067, 0.4326],  
     [0.1956, 0.4280]     
    ]  
print X  

# Kmeans聚類
clf = KMeans(n_clusters=3)  
y_pred = clf.fit_predict(X)  
print(clf)   
print(y_pred)  


import numpy as np  
import matplotlib.pyplot as plt  
  
x = [n[0] for n in X]  
print x  
y = [n[1] for n in X]  
print y  

# 視覺化操作
plt.scatter(x, y, c=y_pred, marker='x')   
plt.title("Kmeans-Basketball Data")   
plt.xlabel("assists_per_minute")  
plt.ylabel("points_per_minute")  
plt.legend(["Rank"])   
plt.show()  

        執行結果:
        從圖中可以看到聚整合三類,紅色比較厲害,得分很高;中間藍色是一類,普通球員;右小角綠色是一類,助攻高得分低,是控位。

        程式碼分析:

from sklearn.cluster import KMeans
        表示在sklearn中處理kmeans聚類問題,用到 sklearn.cluster.KMeans 這個類。
X = [[164,62],[156,50],...]
X是資料集,包括2列20行,即20個球員的助攻數和得分數。
clf = KMeans(n_clusters=3)
        表示輸出完整Kmeans函式,包括很多省略引數,將資料集分成類簇數為3的聚類。
y_pred =clf.fit_predict(X)
        輸出聚類預測結果,對X聚類,20行資料,每個y_pred對應X的一行或一個孩子,聚成3類,類標為0、1、2。
print(y_pred)
        輸出結果:[0 2 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 1]
import matplotlib.pyplot as plt
        matplotlib.pyplot是用來畫圖的方法,matplotlib是視覺化包。
x = [n[0] for n in X]
y = [n[1] for n in X]
        獲取第1列的值, 使用for迴圈獲取 ,n[0]表示X第一列。
        獲取第2列的值,使用for迴圈獲取 ,n[1]表示X第2列。

plt.scatter(x, y, c=y_pred, marker='o')
        繪製散點圖(scatter),橫軸為x,獲取的第1列資料;縱軸為y,獲取的第2列資料;c=y_pred對聚類的預測結果畫出散點圖,marker='o'說明用點表示圖形。
plt.title("Kmeans-Basketball Data")
        表示圖形的標題為Kmeans-heightweight Data。
plt.xlabel("assists_per_minute")
        表示圖形x軸的標題。
plt.ylabel("points_per_minute")
        表示圖形y軸的標題。
plt.legend(["Rank"])
        設定右上角圖例。
plt.show()
        表示顯示圖形。

二. 學生圖例 

        下面簡單展示學生做的作業及分析,感覺還是不錯,畢竟才上幾節課而且第一次作業,希望後面的作業更加精彩吧。因為學生的專業分佈不同,所以儘量讓學生設計他們專業的內容。
        eg 遺傳學身高體重資料
        第一列表示孩子的身高,單位cm;第二列表示孩子的體重,單位kg。從上圖可以看出,資料集被分為了三類。綠色為一類、藍色為一類,紅色為一類。

         
        eg 微博資料集
        第一列代表微博中某條資訊的轉發量,第二列代表微博中某條資訊的評論數。從上圖可以看出,總共分為3類,共三種顏色,綠色一層說明該資訊轉發量與評論數都很高。

        eg 上市公司財務報表
        第一列表示公司利潤率;第二列表示公司資產規模。從上圖可以看出,總共分為4類,共四種顏色。暗紅色為資產規模最大,依次至藍色資產規模減小。


        eg 世界各國家人均面積與土地面積
        第一列表示各國家的人均面積(人/ 平方公里);第二列表示各國家的土地面積(萬平方公里)。從上圖可以看出,總共分為3類,共三種顏色。紅色表示的國家相對來說最擁擠,可能是孟加拉這樣土地面積少且人口眾多的國家;藍色就是地廣人稀的代表,比如俄羅斯、美國、、墨西哥、巴西;綠色表示人口密度分佈比較平均的國家。


        eg employee  salaries資料集
        第一列表示員工工資;第二列表示員工年齡數。從上圖可以看出,總共分為5類,共5種顏色。總體呈現正相關性,年齡越大,工資越高;除個別外,總體正線性關係。

        eg 學生英語成績資料集
        第一列表示學生英語平時成績;第二列表示學生英語期末成績。從上圖可以看出,總共分為4類,共四種顏色。黃色一層,平時成績和末考成績都很高,屬於“學霸”級別的人物;其次,藍色一層和紅色一層;最後,天藍色一層,暫且稱之為“學渣”。



三. Matplotlib繪圖優化

        Matplotlib程式碼的優化:
        1.第一部分程式碼是定義X陣列,實際中是讀取檔案進行的,如何實現讀取檔案中資料再轉換為矩陣進行聚類呢?
        2.第二部分是繪製圖形,希望繪製不同的顏色及型別,使用legend()繪製圖標。
        假設存在資料集如下圖所示:data.txt



        資料集包括96個運動員的資料,源自:KEEL-dataset - Basketball data set
        現需要獲取第一列每分鐘助攻數、第五列每分鐘得分數存於矩陣中。

0.0888     201     36.02     28     0.5885
0.1399     198     39.32     30     0.8291
0.0747     198     38.8     26     0.4974
0.0983     191     40.71     30     0.5772
0.1276     196     38.4     28     0.5703
0.1671     201     34.1     31     0.5835
0.1906     193     36.2     30     0.5276
0.1061     191     36.75     27     0.5523
0.2446     185     38.43     29     0.4007
0.167     203     33.54     24     0.477
0.2485     188     35.01     27     0.4313
0.1227     198     36.67     29     0.4909
0.124     185     33.88     24     0.5668
0.1461     191     35.59     30     0.5113
0.2315     191     38.01     28     0.3788
0.0494     193     32.38     32     0.559
0.1107     196     35.22     25     0.4799
0.2521     183     31.73     29     0.5735
0.1007     193     28.81     34     0.6318
0.1067     196     35.6     23     0.4326
0.1956     188     35.28     32     0.428
0.1828     191     29.54     28     0.4401
0.1627     196     31.35     28     0.5581
0.1403     198     33.5     23     0.4866
0.1563     193     34.56     32     0.5267
0.2681     183     39.53     27     0.5439
0.1236     196     26.7     34     0.4419
0.13     188     30.77     26     0.3998
0.0896     198     25.67     30     0.4325
0.2071     178     36.22     30     0.4086
0.2244     185     36.55     23     0.4624
0.3437     185     34.91     31     0.4325
0.1058     191     28.35     28     0.4903
0.2326     185     33.53     27     0.4802
0.1577     193     31.07     25     0.4345
0.2327     185     36.52     32     0.4819
0.1256     196     27.87     29     0.6244
0.107     198     24.31     34     0.3991
0.1343     193     31.26     28     0.4414
0.0586     196     22.18     23     0.4013
0.2383     185     35.25     26     0.3801
0.1006     198     22.87     30     0.3498
0.2164     193     24.49     32     0.3185
0.1485     198     23.57     27     0.3097
0.227     191     31.72     27     0.4319
0.1649     188     27.9     25     0.3799
0.1188     191     22.74     24     0.4091
0.194     193     20.62     27     0.3588
0.2495     185     30.46     25     0.4727
0.2378     185     32.38     27     0.3212
0.1592     191     25.75     31     0.3418
0.2069     170     33.84     30     0.4285
0.2084     185     27.83     25     0.3917
0.0877     193     21.67     26     0.5769
0.101     193     21.79     24     0.4773
0.0942     201     20.17     26     0.4512
0.055     193     29.07     31     0.3096
0.1071     196     24.28     24     0.3089
0.0728     193     19.24     27     0.4573
0.2771     180     27.07     28     0.3214
0.0528     196     18.95     22     0.5437
0.213     188     21.59     30     0.4121
0.1356     193     13.27     31     0.2185
0.1043     196     16.3     23     0.3313
0.113     191     23.01     25     0.3302
0.1477     196     20.31     31     0.4677
0.1317     188     17.46     33     0.2406
0.2187     191     21.95     28     0.3007
0.2127     188     14.57     37     0.2471
0.2547     160     34.55     28     0.2894
0.1591     191     22.0     24     0.3682
0.0898     196     13.37     34     0.389
0.2146     188     20.51     24     0.512
0.1871     183     19.78     28     0.4449
0.1528     191     16.36     33     0.4035
0.156     191     16.03     23     0.2683
0.2348     188     24.27     26     0.2719
0.1623     180     18.49     28     0.3408
0.1239     180     17.76     26     0.4393
0.2178     185     13.31     25     0.3004
0.1608     185     17.41     26     0.3503
0.0805     193     13.67     25     0.4388
0.1776     193     17.46     27     0.2578
0.1668     185     14.38     35     0.2989
0.1072     188     12.12     31     0.4455
0.1821     185     12.63     25     0.3087
0.188     180     12.24     30     0.3678
0.1167     196     12.0     24     0.3667
0.2617     185     24.46     27     0.3189
0.1994     188     20.06     27     0.4187
0.1706     170     17.0     25     0.5059
0.1554     183     11.58     24     0.3195
0.2282     185     10.08     24     0.2381
0.1778     185     18.56     23     0.2802
0.1863     185     11.81     23     0.381
0.1014     193     13.81     32     0.1593
        程式碼如下:
# -*- coding: utf-8 -*-

"""
By: Eastmount CSDN 2016-10-12
該部分講資料集讀取,然後賦值給X變數
讀取檔案data.txt 儲存結果為X
"""

import os

data = []
for line in open("data.txt", "r").readlines():
    line = line.rstrip()    #刪除換行
    #刪除多餘空格,儲存一個空格連線
    result = ' '.join(line.split())
    #獲取每行五個值 '0 0.0888 201 36.02 28 0.5885' 注意:字串轉換為浮點型數
    s = [float(x) for x in result.strip().split(' ')]
    #輸出結果:['0', '0.0888', '201', '36.02', '28', '0.5885']
    print s
    #資料儲存至data
    data.append(s)

#輸出完整資料集
print u'完整資料集'
print data
print type(data)

'''
現在輸出資料集:
['0 0.0888 201 36.02 28 0.5885', 
 '1 0.1399 198 39.32 30 0.8291', 
 '2 0.0747 198 38.80 26 0.4974', 
 '3 0.0983 191 40.71 30 0.5772', 
 '4 0.1276 196 38.40 28 0.5703'
]
'''

print u'第一列 第五列資料'
L2 = [n[0] for n in data]
print L2
L5 = [n[4] for n in data]
print L5

'''
X表示二維矩陣資料,籃球運動員比賽資料
總共96行,每行獲取兩列資料
第一列表示球員每分鐘助攻數:assists_per_minute
第五列表示球員每分鐘得分數:points_per_minute
'''

#兩列資料生成二維資料
print u'兩列資料合併成二維矩陣'
T = dict(zip(L2,L5))
type(T)

#dict型別轉換為list
print u'List'
X = list(map(lambda x,y: (x,y), T.keys(),T.values()))
print X
print type(X)


"""
KMeans聚類
clf = KMeans(n_clusters=3) 表示類簇數為3,聚成3類資料,clf即賦值為KMeans
y_pred = clf.fit_predict(X) 載入資料集X,並且將聚類的結果賦值給y_pred
"""

from sklearn.cluster import Birch
from sklearn.cluster import KMeans

clf = KMeans(n_clusters=3)
y_pred = clf.fit_predict(X)
print(clf)
#輸出聚類預測結果,96行資料,每個y_pred對應X一行或一個球員,聚成3類,類標為0、1、2
print(y_pred)


"""
視覺化繪圖
Python匯入Matplotlib包,專門用於繪圖
import matplotlib.pyplot as plt 此處as相當於重新命名,plt用於顯示影象
"""

import numpy as np
import matplotlib.pyplot as plt


#獲取第一列和第二列資料 使用for迴圈獲取 n[0]表示X第一列
x = [n[0] for n in X]
print x
y = [n[1] for n in X]
print y 

#繪製散點圖 引數:x橫軸 y縱軸 c=y_pred聚類預測結果 marker型別 o表示圓點 *表示星型 x表示點
#plt.scatter(x, y, c=y_pred, marker='x')


#座標
x1 = []
y1 = []

x2 = []
y2 = []

x3 = []
y3 = []

#分佈獲取類標為0、1、2的資料 賦值給(x1,y1) (x2,y2) (x3,y3)
i = 0
while i < len(X):
    if y_pred[i]==0:
        x1.append(X[i][0])
        y1.append(X[i][1])
    elif y_pred[i]==1:
        x2.append(X[i][0])
        y2.append(X[i][1])
    elif y_pred[i]==2:
        x3.append(X[i][0])
        y3.append(X[i][1])
    
    i = i + 1


#四種顏色 紅 綠 藍 黑  
plot1, = plt.plot(x1, y1, 'or', marker="x")  
plot2, = plt.plot(x2, y2, 'og', marker="o")  
plot3, = plt.plot(x3, y3, 'ob', marker="*")  

#繪製標題
plt.title("Kmeans-Basketball Data")

#繪製x軸和y軸座標
plt.xlabel("assists_per_minute")
plt.ylabel("points_per_minute")

#設定右上角圖例
plt.legend((plot1, plot2, plot3), ('A', 'B', 'C'), fontsize=10)

plt.show()  
        輸出結果如下圖所示:三個層次很明顯,而且右上角也標註。

四. Spyder常見問題


        下面是常見遇到的幾個問題:
        1.Spyder軟體如果Editor編輯框不在,如何調出來。

        2.會缺少一些第三方包,如lda,如何匯入。使用cd ..去到C盤根目錄,cd去到Anaconda的Scripts目錄下,輸入"pip install selenium"安裝selenium相應的包,"pip install lda"安裝lda包。

        學生告訴我另一個更方便的方法:





        3.執行時報錯,缺少Console,點選如下。



        4.如果Spyder安裝點選沒有反應,重新安裝也沒有反應,建議在執行下試試。


        實在不行解除安裝再重灌:pip uninstall spyder  
                                          pip install spyder


        5.Spyder如何顯示繪製Matplotlib中文。

from matplotlib.font_manager import FontProperties
font = FontProperties(fname="C:\Windows\Fonts/msyh.ttf", size=10)
#繪製標題 fontproperties表示字型型別,用於顯示中文字元,下同
plt.title(u'世界各國家人均面積與土地面積',fontproperties=font)
#繪製x軸和y軸座標
plt.ylabel(u'人均面積(人/ 平方公里)',fontproperties=font)
plt.xlabel(u'面積(萬平方公里)',fontproperties=font)