手寫演算法-python程式碼實現Kmeans
原理解析
今天,我們來講一下Kmeans,一種無監督聚類演算法,也是最為經典的基於劃分的聚類方法,它的思想是:對於給定的樣本集,按照樣本之間的距離大小,將樣本集劃分為K個簇。讓簇內的點儘量緊密的連在一起,而讓簇間的距離儘量的大。
實現流程如下:
1、先確定資料集聚類個數k;
2、在資料集中隨機選取k個資料,作為初始質心;
3、計算資料集中每個樣本到每個質心的距離,把樣本劃分到
距離最小的質心所屬的類別;
4、根據聚類結果,重新計算質心,當本次計算的質心與上一次質心完全一樣(或者收斂)時,停止迭代;
否則更新質心,繼續執行步驟2、3、4。
流程比較簡單,這裡要說的是注意幾個問題:
1、步驟1確定資料集聚類個數k,很顯然,當資料集D是高維資料時,沒辦法很快確定合適的k;
2、步驟2隨機選取資料作為初始質心,可以想象,當質心之間距離很近的時候,將需要迭代很多次,會影響收斂速度,甚至不能收斂;
3、步驟3中計算距離,我們應該想到,距離受到量綱的影響,在使用時,需要考慮一下標準化;
然後就是基於所有樣本,因此會對異常資料比較敏感;
4、當資料集很大時,計算的時間複雜度很高。
可見優化的點很多(優化部分我們明天再寫,今天只實現最基礎的Kmeans)。
程式碼實現
基於上面描述的過程,我們來寫python實現程式碼:
import numpy as np
from sklearn.datasets import make_blobs
from matplotlib import pyplot as plt
#無監督演算法,學習過程就是訓練質心的位置,進行聚類
class Kmeans:
def __init__(self,k):
self.k = k
def calc_distance(self,x1,x2):
diff = x1 - x2
distances = np.sqrt(np.square(diff).sum(axis=1))
return distances
def fit(self,x):
self.x = x
m,n = self.x.shape
#隨機選定k個資料作為初始質心,不重複選取
self.original_ = np.random.choice(m,self.k,replace=False)
#預設類別是從0到k-1
self.original_center = x[self.original_]
while True:
#初始化一個字典,以類別作為key,賦值一個空陣列
dict_y = {}
for j in range(self.k):
dict_y[j] = np.empty((0,n))
for i in range(m):
distances =self.calc_distance(x[i],self.original_center)
#把第i個資料分配到距離最近的質心,存放在字典中
label = np.argsort(distances)[0]
dict_y[label] = np.r_[dict_y[label],x[i].reshape(1,-1)]
centers = np.empty((0,n))
#對每個類別的樣本重新求質心
for i in range(self.k):
center = np.mean(dict_y[i],axis=0).reshape(1,-1)
centers = np.r_[centers,center]
#與上一次迭代的質心比較,如果沒有發生變化,則停止迭代(也可考慮收斂時停止)
result = np.all(centers == self.original_center)
if result == True:
break
else:
#繼續更新質心
self.original_center = centers
def predict(self,x):
y_preds = []
m,n = x.shape
for i in range(m):
distances =self.calc_distance(x[i],self.original_center)
y_pred = np.argsort(distances)[0]
y_preds.append(y_pred)
return y_preds
例項演示
下面我們來生成一些資料集,來看看我們寫的Kmeans聚類效果:
#下面是我今天找到的一個很有代表性的資料集,哈哈,為什麼這麼說,後面會用到
x,y = make_blobs(centers=5,random_state=20,cluster_std=1)
plt.scatter(x[:,0],x[:,1])
plt.show()
從影像上看,我們適合把這些資料分成5個類別,跑一下程式碼看一下結果:
model = Kmeans(k=5)
model.fit(x)
y_preds = model.predict(x)
plt.scatter(x[:,0],x[:,1],c=y_preds)
plt.show()
,聚類得挺完美的,等一下,有人跑出不一樣的結果:
哈哈,要的就是這個效果(大家多重複執行一下上面這段程式碼,就會發現結果各種各樣),為什麼呢?
答案就在我們剛才說的幾個問題上,也就是步驟的問題,
具體怎麼優化我們明天寫。
sklearn對比
上面的問題,sklearn中的Kmeans演算法,會不會也出現呢?
我們來驗證一下:
from sklearn.cluster import KMeans
model_1 = KMeans(n_clusters=5)
y_pred_1 = model_1.fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=y_pred_1)
plt.show()
可以發現,不管執行多少次,聚類效果都很穩定,都很好。
總結
初步實現了Kmeans演算法,但是有待優化,下一篇,我們來介紹優化的Kmeans。
相關文章
- 利用python的KMeans和PCA包實現聚類演算法PythonPCA聚類演算法
- python Kmeans演算法解析Python演算法
- 幾道JS程式碼手寫題以及一些程式碼實現JS
- 小程式實現手寫簽名
- Python-遺傳演算法君主交叉程式碼實現Python演算法
- 可能這裡有你想要的js手寫程式碼實現JS
- JS手寫Promise程式碼ES6方式實現JSPromise
- 基於Apache Zookeeper手寫實現動態配置中心(純程式碼實踐)Apache
- Python課程程式碼實現Python
- 用6行Python程式碼實現選擇性排序演算法Python排序演算法
- 生產消費實現-寫程式碼
- 【微信小程式canvas】實現小程式手寫板使用者簽名(附程式碼)微信小程式Canvas
- Kmeans演算法優缺點演算法
- js手寫程式碼合集JS
- 手寫程式語言-實現運算子過載
- 感知機演算法(PLA)程式碼實現演算法
- 圖解Dijkstra演算法+程式碼實現圖解演算法
- 【演算法】手撕紅黑樹(上)—— 基本性質以及插入實現(附帶程式碼實現)演算法
- 面試題目:手寫一個LRU演算法實現面試題演算法
- 勞動節快樂!手寫個核心價值觀編碼工具 - Python實現Python
- 七個不一樣的Python程式碼寫法,讓你寫出一手漂亮的程式碼Python
- python加法程式碼如何寫Python
- 吳恩達《Machine Learning》精煉筆記 8:聚類 KMeans 及其 Python實現吳恩達Mac筆記聚類Python
- Python程式碼實現“FlappyBird”小遊戲PythonAPP遊戲
- JS面試手寫程式碼JS面試
- JS 筆試手寫程式碼JS筆試
- android 利用path 實現手寫板的手寫效果Android
- 用Python寫演算法 | 蓄水池演算法實現隨機抽樣Python演算法隨機
- 動手實現程式碼虛擬機器虛擬機
- python讀寫Excel表格程式碼PythonExcel
- 手寫IOC實現過程
- 手寫AOP實現過程
- 如何手寫實現 JSON ParserJSON
- 求職之手寫程式碼-手寫原始碼大雜燴求職原始碼
- 從 0 開始實現程式語言(一):手寫 jsonParserJSON
- 🐒編寫高質量程式碼(手撕程式碼)
- 一行 Python 程式碼實現並行Python並行
- 20 行 Python 程式碼實現加密通訊Python加密