<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
K-means(K均值)演演算法是最簡單的一種聚類演演算法,它期望最小化平方誤差
注:為避免執行時間過長,通常設定一個最大執行輪數或最小調整幅度閾值,若到達最大輪數或調整幅度小於閾值,則停止執行。
下面我們用python來實現一下K-means演演算法:我們先嚐試手動實現這個演演算法,再用sklearn
庫中的KMeans
類來實現。資料我們採用《機器學習》的西瓜資料(P202表9.1):
# 下面的內容儲存在 melons.txt 中 # 第一列為西瓜的密度;第二列為西瓜的含糖率。我們要把這30個西瓜分為3類 0.697 0.460 0.774 0.376 0.634 0.264 0.608 0.318 0.556 0.215 0.403 0.237 0.481 0.149 0.437 0.211 0.666 0.091 0.243 0.267 0.245 0.057 0.343 0.099 0.639 0.161 0.657 0.198 0.360 0.370 0.593 0.042 0.719 0.103 0.359 0.188 0.339 0.241 0.282 0.257 0.748 0.232 0.714 0.346 0.483 0.312 0.478 0.437 0.525 0.369 0.751 0.489 0.532 0.472 0.473 0.376 0.725 0.445 0.446 0.459
我們用到的庫有matplotlib
和numpy
,如果沒有需要先用pip安裝一下。
import random import numpy as np import matplotlib.pyplot as plt
下面定義一些資料:
k = 3 # 要分的簇數 rnd = 0 # 輪次,用於控制迭代次數(見上文) ROUND_LIMIT = 100 # 輪次的上限 THRESHOLD = 1e-10 # 單輪改變距離的閾值,若改變幅度小於該閾值,演演算法終止 melons = [] # 西瓜的列表 clusters = [] # 簇的列表,clusters[i]表示第i簇包含的西瓜
從melons.txt讀取資料,儲存在列表中:
f = open('melons.txt', 'r') for line in f: # 把字串轉化為numpy中的float64型別 melons.append(np.array(line.split(' '), dtype = np.string_).astype(np.float64))
從 m m m個資料中隨機挑選出 k k k個,對應上面演演算法的第 1 1 1行:
# random的sample函數從列表中隨機挑選出k個樣本(不重複)。我們在這裡把這些樣本作為均值向量 mean_vectors = random.sample(melons, k)
下面是演演算法的主要部分。
# 這個while對應上面演演算法的2-17行 while True: rnd += 1 # 輪次增加 change = 0 # 把改變幅度重置為0 # 清空對簇的劃分,對應上面演演算法的第3行 clusters = [] for i in range(k): clusters.append([]) # 這個for對應上面演演算法的4-8行 for melon in melons: ''' argmin 函數找出容器中最小的下標,在這裡這個目標容器是 list(map(lambda vec: np.linalg.norm(melon - vec, ord = 2), mean_vectors)), 它表示melon與mean_vectors中所有向量的距離列表。 (numpy.linalg.norm計算向量的範數,ord = 2即歐幾里得範數,或模長) ''' c = np.argmin( list(map( lambda vec: np.linalg.norm(melon - vec, ord = 2), mean_vectors)) ) clusters[c].append(melon) # 這個for對應上面演演算法的9-16行 for i in range(k): # 求每個簇的新均值向量 new_vector = np.zeros((1,2)) for melon in clusters[i]: new_vector += melon new_vector /= len(clusters[i]) # 累加改變幅度並更新均值向量 change += np.linalg.norm(mean_vectors[i] - new_vector, ord = 2) mean_vectors[i] = new_vector # 若超過設定的輪次或者變化幅度<預先設定的閾值,結束演演算法 if rnd > ROUND_LIMIT or change < THRESHOLD: break print('最終迭代%d輪'%rnd)
最後我們繪圖來觀察一下劃分的結果:
colors = ['red', 'green', 'blue'] # 每個簇換一下顏色,同時迭代簇和顏色兩個列表 for i, col in zip(range(k), colors): for melon in clusters[i]: # 繪製散點圖 plt.scatter(melon[0], melon[1], color = col) plt.show()
劃分結果(由於最開始的 k k k個均值向量隨機選取,每次劃分的結果可能會不同):
完整程式碼:
import random import numpy as np import matplotlib.pyplot as plt k = 3 rnd = 0 ROUND_LIMIT = 10 THRESHOLD = 1e-10 melons = [] clusters = [] f = open('melons.txt', 'r') for line in f: melons.append(np.array(line.split(' '), dtype = np.string_).astype(np.float64)) mean_vectors = random.sample(melons, k) while True: rnd += 1 change = 0 clusters = [] for i in range(k): clusters.append([]) for melon in melons: c = np.argmin( list(map( lambda vec: np.linalg.norm(melon - vec, ord = 2), mean_vectors)) ) clusters[c].append(melon) for i in range(k): new_vector = np.zeros((1,2)) for melon in clusters[i]: new_vector += melon new_vector /= len(clusters[i]) change += np.linalg.norm(mean_vectors[i] - new_vector, ord = 2) mean_vectors[i] = new_vector if rnd > ROUND_LIMIT or change < THRESHOLD: break print('最終迭代%d輪'%rnd) colors = ['red', 'green', 'blue'] for i, col in zip(range(k), colors): for melon in clusters[i]: plt.scatter(melon[0], melon[1], color = col) plt.show()
這種經典演演算法顯然不需要我們反覆地造輪子,被廣泛使用的python機器學習庫sklearn
已經提供了該演演算法的實現。sklearn
的官方檔案中給了我們一個範例:
>>> from sklearn.cluster import KMeans >>> import numpy as np >>> X = np.array([[1, 2], [1, 4], [1, 0], ... [10, 2], [10, 4], [10, 0]]) >>> kmeans = KMeans(n_clusters=2, random_state=0).fit(X) >>> kmeans.labels_ array([1, 1, 1, 0, 0, 0], dtype=int32) >>> kmeans.predict([[0, 0], [12, 3]]) array([1, 0], dtype=int32) >>> kmeans.cluster_centers_ array([[10., 2.], [ 1., 2.]])
可以看出,X
即要聚類的資料(1,2),(1,4),(1,0)
等。KMeans
類的初始化引數n_clusters
即簇數 k k k;random_state
是用於初始化選取 k k k個向量的亂數種子;kmeans.labels_
即每個點所屬的簇;kmeans.predict
方法預測新的資料屬於哪個簇;kmeans.cluster_centers_
返回每個簇的中心。
我們就改造一下這個簡單的範例,完成對上面西瓜的聚類。
import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans X = [] f = open('melons.txt', 'r') for line in f: X.append(np.array(line.split(' '), dtype = np.string_).astype(np.float64)) kmeans = KMeans(n_clusters = 3, random_state = 0).fit(X) colors = ['red', 'green', 'blue'] for i, cluster in enumerate(kmeans.labels_): plt.scatter(X[i][0], X[i][1], color = colors[cluster]) plt.show()
執行結果如下,可以看到和我們手寫的聚類結果基本一致:
到此這篇關於Python實現聚類K-means演演算法詳解的文章就介紹到這了,更多相關Python K-means演演算法內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45