本文實例為大家分享了python K均值聚類的具體代碼,供大家參考,具體內容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
#-*- coding:utf-8 -*- #!/usr/bin/python ''''' k Means K均值聚類 ''' # 測試 # K均值聚類 import kMeans as KM KM.kMeansTest() # 二分K均值聚類 import kMeans as KM KM.biKMeansTest() # 地理位置 二分K均值聚類 import kMeans as KM KM.clusterClubs() from numpy import * # 導入數據集 def loadDataSet(fileName): # dataMat = [] # fr = open (fileName) for line in fr.readlines(): # 每一行 curLine = line.strip().split( '\t' ) # 按 Tab鍵 分割成 列表 fltLine = map ( float ,curLine) # 映射成 浮點型 dataMat.append(fltLine) # 放入數據集里 return dataMat # 計算歐幾里的距離 def distEclud(vecA, vecB): return sqrt( sum (power(vecA - vecB, 2 ))) #la.norm(vecA-vecB) # 初始構建質心(隨機) 數據集 質心個數 def randCent(dataSet, k): n = shape(dataSet)[ 1 ] # 樣本特征維度 centroids = mat(zeros((k,n))) # 初始化 k個 質心 for j in range (n): # 每種樣本特征 minJ = min (dataSet[:,j]) # 每種樣本特征最小值 需要轉換成 numpy 的mat rangeJ = float ( max (dataSet[:,j]) - minJ) #每種樣本特征的幅值范圍 centroids[:,j] = mat(minJ + rangeJ * random.rand(k, 1 )) # 在每種樣本的最大值和最小值間隨機生成K個樣本特征值 return centroids # 簡單k均值聚類算法 # 數據集 中心數量 距離算法 初始聚類中心算法 def kMeans(dataSet, k, distMeas = distEclud, createCent = randCent): m = shape(dataSet)[ 0 ] # 樣本個數 clusterAssment = mat(zeros((m, 2 ))) # 樣本標記 分配結果 第一列索引 第二列誤差 centroids = createCent(dataSet, k) # 初始聚類中心 clusterChanged = True # 設置質心是否仍然發送變化 while clusterChanged: clusterChanged = False for i in range (m): #對每個樣本 計算最近的中心 # 更新 樣本所屬關系 minDist = inf; minIndex = - 1 # 距離變量 以及 最近的中心索引 for j in range (k): # 對每個中心 distJI = distMeas(centroids[j,:],dataSet[i,:]) # 計算距離 if distJI < minDist: minDist = distJI; minIndex = j # 得到最近的 中心 索引 if clusterAssment[i, 0 ] ! = minIndex: clusterChanged = True # 所屬索引發生了變化 即質心還在變化,還可以優化 clusterAssment[i,:] = minIndex,minDist * * 2 # 保存 所屬索引 以及距離平方 用以計算誤差平方和 SSE # 更新質心 print centroids # 每次迭代打印質心 for cent in range (k): # ptsInClust = dataSet[nonzero(clusterAssment[:, 0 ].A = = cent)[ 0 ]] # 數組過濾 得到各個中心所屬的樣本 centroids[cent,:] = mean(ptsInClust, axis = 0 ) # 按列求平均 得到新的中心 return centroids, clusterAssment # 返回質心 和各個樣本分配結果 def kMeansTest(k = 5 ): MyDatMat = mat(loadDataSet( "testSet.txt" )) MyCenters, ClustAssing = kMeans(MyDatMat, k) # bisecting K-means 二分K均值算法 克服局部最優值 def biKmeans(dataSet, k, distMeas = distEclud): m = shape(dataSet)[ 0 ] # 樣本個數 clusterAssment = mat(zeros((m, 2 ))) # 樣本標記 分配結果 第一列索引 第二列誤差 centroid0 = mean(dataSet, axis = 0 ).tolist()[ 0 ] # 創建一個初始質心 centList = [centroid0] # 一個中心的 列表 for j in range (m): # 計算初始誤差 clusterAssment[j, 1 ] = distMeas(mat(centroid0), dataSet[j,:]) * * 2 #每個樣本與中心的距離平方 while ( len (centList) < k): # 中心數倆個未達到指定中心數量 繼續迭代 lowestSSE = inf # 最小的 誤差平方和 SSE for i in range ( len (centList)): # 對于每一個中心 ptsInCurrCluster = dataSet[nonzero(clusterAssment[:, 0 ].A = = i)[ 0 ],:] # 處于當前中心的樣本點 centroidMat, splitClustAss = kMeans(ptsInCurrCluster, 2 , distMeas) # 對此中心內的點進行二分類 # 該樣本中心 二分類之后的 誤差平方和 SSE sseSplit = sum (splitClustAss[:, 1 ]) # 其他未劃分數據集的誤差平方和 SSE sseNotSplit = sum (clusterAssment[nonzero(clusterAssment[:, 0 ].A! = i)[ 0 ], 1 ]) print "sseSplit, and notSplit: " ,sseSplit,sseNotSplit # 劃分后的誤差和沒有進行劃分的數據集的誤差為本次誤差 if (sseSplit + sseNotSplit) < lowestSSE: # 小于上次 的 誤差 bestCentToSplit = i # 記錄應該被劃分的中心 的索引 bestNewCents = centroidMat # 最好的新劃分出來的中心 bestClustAss = splitClustAss.copy() # 新中心 對于的 劃分記錄 索引(0或1)以及 誤差平方 lowestSSE = sseSplit + sseNotSplit # 更新總的 誤差平方和 # 記錄中心 劃分 數據 bestClustAss[nonzero(bestClustAss[:, 0 ].A = = 1 )[ 0 ], 0 ] = len (centList) # 現有中心數量 bestClustAss[nonzero(bestClustAss[:, 0 ].A = = 0 )[ 0 ], 0 ] = bestCentToSplit # 最應該被劃分的中心 print 'the bestCentToSplit is: ' ,bestCentToSplit print 'the len of bestClustAss is: ' , len (bestClustAss) # 將最應該被劃分的中心 替換為 劃分后的 兩個 中心(一個替換,另一個 append在最后添加) centList[bestCentToSplit] = bestNewCents[ 0 ,:].tolist()[ 0 ] # 替換 centList.append(bestNewCents[ 1 ,:].tolist()[ 0 ]) # 添加 # 更新 樣本標記 分配結果 替換 被劃分中心的記錄 clusterAssment[nonzero(clusterAssment[:, 0 ].A = = bestCentToSplit)[ 0 ],:] = bestClustAss return mat(centList), clusterAssment def biKMeansTest(k = 5 ): MyDatMat = mat(loadDataSet( "testSet.txt" )) MyCenters, ClustAssing = biKmeans(MyDatMat, k) ####位置數據聚類測試##### # 利用雅虎的服務器將地址轉換為 經度和緯度 import urllib import json def geoGrab(stAddress, city): apiStem = 'http://where.yahooapis.com/geocode?' # params = {} params[ 'flags' ] = 'J' # 設置返回類型為JSON字符串 params[ 'appid' ] = 'aaa0VN6k' # 注冊 帳號后獲得 http://developer.yahoo.com params[ 'location' ] = '%s %s' % (stAddress, city) # 位置信息 url_params = urllib.urlencode(params) # 將字典轉換成可以通過URL進行傳遞的字符串格式 yahooApi = apiStem + url_params # 加入網絡地址 print yahooApi # 打印 URL c = urllib.urlopen(yahooApi) # 打開 URL return json.loads(c.read()) # 讀取返回的jason字符串 對位置進行了編碼 得到經度和緯度 from time import sleep def massPlaceFind(fileName): fw = open ( 'places.txt' , 'w' ) # 打開位置信息文件 for line in open (fileName).readlines(): # 每一行 line = line.strip() lineArr = line.split( '\t' ) # 得到列表 retDict = geoGrab(lineArr[ 1 ], lineArr[ 2 ]) # 第二列為號牌 第三列為城市 進行地址解碼 if retDict[ 'ResultSet' ][ 'Error' ] = = 0 : lat = float (retDict[ 'ResultSet' ][ 'Results' ][ 0 ][ 'latitude' ]) #經度 lng = float (retDict[ 'ResultSet' ][ 'Results' ][ 0 ][ 'longitude' ]) #緯度 print "%s\t%f\t%f" % (lineArr[ 0 ], lat, lng) fw.write( '%s\t%f\t%f\n' % (line, lat, lng)) #再寫入到文件 else : print "error fetching" sleep( 1 ) #延遲1s fw.close() # 返回地球表面兩點之間的距離 單位英里 輸入經緯度(度) 球面余弦定理 def distSLC(vecA, vecB): #Spherical Law of Cosines a = sin(vecA[ 0 , 1 ] * pi / 180 ) * sin(vecB[ 0 , 1 ] * pi / 180 ) b = cos(vecA[ 0 , 1 ] * pi / 180 ) * cos(vecB[ 0 , 1 ] * pi / 180 ) * \ cos(pi * (vecB[ 0 , 0 ] - vecA[ 0 , 0 ]) / 180 ) return arccos(a + b) * 6371.0 #pi in numpy # 位置聚類測試 畫圖可視化顯示 import matplotlib import matplotlib.pyplot as plt def clusterClubs(numClust = 5 ): datList = [] # 樣本 for line in open ( 'places.txt' ).readlines(): lineArr = line.split( '\t' ) datList.append([ float (lineArr[ 4 ]), float (lineArr[ 3 ])]) # 保存經緯度 datMat = mat(datList) # 數據集 numpy的mat類型 # 進行二分K均值算法聚類 myCentroids, clustAssing = biKmeans(datMat, numClust, distMeas = distSLC) fig = plt.figure() # 窗口 rect = [ 0.1 , 0.1 , 0.8 , 0.8 ] scatterMarkers = [ 's' , 'o' , '^' , '8' , 'p' , \ 'd' , 'v' , 'h' , '>' , '<' ] axprops = dict (xticks = [], yticks = []) ax0 = fig.add_axes(rect, label = 'ax0' , * * axprops) #軸 imgP = plt.imread( 'Portland.png' ) # 標注在實際的圖片上 ax0.imshow(imgP) ax1 = fig.add_axes(rect, label = 'ax1' , frameon = False ) for i in range (numClust): #每一個中心 ptsInCurrCluster = datMat[nonzero(clustAssing[:, 0 ].A = = i)[ 0 ],:] # 屬于每個中心的樣本點 markerStyle = scatterMarkers[i % len (scatterMarkers)] # 點的類型 畫圖 # 散點圖 每個中心的樣本點 ax1.scatter(ptsInCurrCluster[:, 0 ].flatten().A[ 0 ], ptsInCurrCluster[:, 1 ].flatten().A[ 0 ], marker = markerStyle, s = 90 ) # 散 點圖 每個中心 ax1.scatter(myCentroids[:, 0 ].flatten().A[ 0 ], myCentroids[:, 1 ].flatten().A[ 0 ], marker = '+' , s = 300 ) plt.show() # 顯示 |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/xiaoxiaowenqiang/article/details/78076896