集體智慧程式設計-K均值聚類程式碼理解
阿新 • • 發佈:2019-01-03
K均值聚類,先人工製造幾個中心點,根據資料尋找距離每個中心點最近的所有例項點,用所有例項點的均值代替中心點,如此反覆,直到所有的例項點都被歸類到正確的中心點。
例子
對於下面的例項點
人工構造兩個中心點,對於每個中心點尋找距離其最近的所有例項點,用距離其最近的所有例項點的均值代替中心點
通過A與B所構造的中心點到C的距離比通過C、D、E所構造的中心點到C的距離近,因此A與B的中心點繼續變化,而C與D的中心點不動
對於中心點1來說最近的例項點是A、B、C,因此即使再繼續找中心點仍和原來一樣,中心點2也是一樣,即使繼續找,位置也不會變化。
這樣就完成了聚類,A、B、C為一類,D、E為一類。
程式碼詳解
對於每一個例項看起來就像下面的表格那樣
Blog | app | Android | … |
---|---|---|---|
person1 | 100 | 50 | … |
person2 | 200 | 300 | … |
… | … | … | … |
但是表格程式是讀不出來的,不過只需要資料的二維列表就行了。
計算每一個單詞使用次數的最大值和最小值,計算時可以把二維列表想象成下面這樣
ranges = [(min([row[i] for row in rows]), max([row[i] for row in rows]))
建立中心點,中心點不是隻有一個數據,它相當於我們自己建立的博主,併為其隨機生成單詞使用次數的資料
clusters = [[random.random() * (ranges[i][1] - ranges[i][0]) + ranges[i][0]
for i in range(rows[0])] for j in range(k)]
建立一個for
迴圈來進行聚類:
for t in range(20):
print('Interation %d' % t)
'''
儲存與中心點最近的例項點的下標
'''
bestmatches = [[] for i in range(k)]
for j in range(len(rows)):
row = rows[j]
bestmatch = 0
for i in range(k):
d = distance(clusters[i], row)
if d < distance(clusters[bestmatch], row):
bestmatch = i
bestmatches[bestmatch].append(j)
'''
判斷這一輪迴圈得到的距離每個中心點最近的例項點與上一輪得到的距離每個中心點最近的例項點是否相同,如果相同停止迴圈,否則繼續
'''
if bestmatches == lastmatches:
break
舉個例子,如圖
假設距離中心點1最近的例項點為A、B、C,距離中心點2最近的例項點為D、E,那麼第一次迴圈bestmatches
為:
[['0', '1'], ['2', '3', '4']]
找到距離每個中心點最近的例項點後,中心點中的單詞使用次數為距離每個中心點最近的一組例項點的均值
if bestmatches == lastmatches:
break
lastmatches = bestmatches
for i in range(k):
avgs = [0.0] * len(rows[0])
if len(bestmatches[i]) > 0:
for rowid in bestmatches[i]:
'''
先求和
'''
for m in range(len(rows[rowid])):
avgs[m] += rows[rowid][m]
'''
再除以例項點的個數
'''
for j in range(len(avgs)):
avgs[j] /= len(bestmatches[i])
clusters[i] = avgs
那麼經過處理後,上面的圖片就會變成這樣
然後開始第二次迴圈,假設此時距離中心點1最近的點是C,那麼中心點1的數值繼續改變,而中心點2的數值不變:
中心點1每個單詞使用次數的計算公式為
第二次迴圈
bestmatches = [['0', '1', '2'], ['3', '4']]
lastmatches = bestmatches
第三次迴圈
bestmatches = [['0', '1', '2'], ['3', '4']]
此時,對於此次迴圈來說
lastmatches = bestmatches
即所有的例項點都被成功地聚類,迴圈結束。