天天看點

機器學習-K-means-2020-5-7

​一:聚類的目的

使同一類對象近可能的大,不同對象之間的相似度盡可能的小

二:聚類的分類:

1 : 基于劃分 

K-Means ,K-Medoids,CLarans

2: 基于層次

BIRCH , CURE ,CHAMELEON

3: 基于密度

DBscan ,Optics , DenClue

推薦網站可視化:

https://www.naftaliharris.com/blog/visualizing-k-means-clustering/

比較好玩,形象化!!!

機器學習-K-means-2020-5-7

三:K -mans:  基于劃分的聚類,無監督學習算法(硬聚類)

适用資料集:球狀分布的資料,沒有标簽

K-Means works best in datasets that have with clusters that are roughly equally-sized and shaped roughly regularly.(每個類數量大緻相等,形狀規則)

資料集X: 

機器學習-K-means-2020-5-7

基本思想: 

The k-means algorithm captures the insight that each point in a cluster should be near to the center of that cluster. (所有樣本點到中心點的距離最小)

政策:采用歐式距離平方和最小 squared Euclidean distance

The k-means algorithm divides a set of N samples X into K disjoint clusters C(資料集n個樣本,劃分成C個族,每個族中心為uj)

(簡單了解: 每個樣本點到它的所分類中心的距離之和)

機器學習-K-means-2020-5-7

李航<<統計學習方法>>:

X = {x1, x2,x3 .....xn} , xi 是m維特征,無标簽資料集

K均值聚類的目标是将n個資料集劃分到k個不同的簇(cu) cluster, 或者叫類中k < n 。

定義樣本之間距離歐式距離: 

機器學習-K-means-2020-5-7

損失函數:

機器學習-K-means-2020-5-7

優化問題:        C*  = arg min W(C)

算法流程:

(1)随機選取K個樣本點,作為初始化聚類 中心。

(2)資料集中每個樣本點測量其到每個聚類中心的距離,并把它劃分到最近的中心。

(3)重新計算,每個類中所有點的均值作為這個類的聚類中心。

(4)疊代(2)~(3)步直至新的中心與原中心相等或小于指定門檻值,算法結束。

注意一下幾個問題?

1:初始化K個聚類中心(centroids) 的選擇? 

  • 随機選擇空間中任意k個位置作為距離中心
  • 随機從資料集 中選擇k個聚類中心
  • 最遠中心(1:資料集随機選擇一個點作為聚類中心。然後在剩下資料中選擇距離第一個聚類中心最遠的點,作為第二個聚類中心, 循環以上,直到選擇k個聚類中心)

初始聚類中心: 不同的方法對收斂速度,聚類結果都有很大影響

k-means++ 最好的初始化聚類中心(基本思想就是:初始的聚類中心之間的互相距離要盡可能的遠)

2: 距離

  • 歐式距離
  • 餘弦相似度(文本資料)

3:k值選擇

事先不知道資料集能劃分多少聚類,K是試探性 的,然後比較損失函數選出合适的k值

4: 優缺點

優點:

原理比較簡單,實作也是很容易,收斂速度快

 主要需要調參的參數僅僅是k

缺點:

  • K值的選取不好把握
  • 對于不是凸的資料集比較難收斂(改進:基于密度的聚類算法更加适合,比如DESCAN算法)
  • 如果各隐含類别的資料不平衡,比如各隐含類别的資料量嚴重失衡,或者各隐含類别的方差不同,則聚類效果不佳。
  • 采用疊代方法,得到的結果隻是局部最優。
  •  對噪音和異常點比較的敏感(改進1:離群點檢測的LOF算法,通過去除離群點後再聚類,可以減少離群點和孤立點對于聚類效果的影響;改進2:改成求點的中位數,這種聚類方式即K-Mediods聚類(K中值))
  • 初始聚類中心的選擇(改進1:k-means++; 改進2:二分K-means)

四:代碼實作:

一:初聚類中心初始化最遠

聚類中心的選擇,第一個中心: centrod1,資料集中随機選擇一個

第二個中心: centrod2,為資料集中到第centrod1最遠的點

第三個中心 :centrod3 ,為資料集中到 centrod1,centrod2 距離之和最大的點

'''

第k個中心:centrodk ,資料集中到(centrod1,centrod2,...centrodk-1)距離之和最大的點

import numpy as np              import matplotlib.pyplot as plt              import random              from sklearn import datasets              #兩點之間的距離歐式距離              def distance(point1,point2):              """              e1: 資料1  向量              e2: 資料2              return : distance(point2,point2)              """              e1 = np.array(point1)              e2 = np.array(point2)              return np.sqrt(np.sum((point1-point2)**2))              #聚類中心              def meanCenter(class_one):              """              class_one: 一個聚類的所有樣本點              return : 這個聚類所有樣本點的均值              """              arr = np.array(class_one)              mean = arr.mean(axis=0)              return mean              #最遠中心法,用于初始化聚類中心              def farCenter(centrods,data_set):              """              centrods: k個聚類中心數組              data_set: 整個資料集              return: 一個樣本點: 離已經有的聚類中心距離求和,最遠的點              """              m = np.shape(data_set)[1]  #特征次元              temp_point =np.zeros([m]) # 臨時儲存樣本點資料              max_dist = 0              for point in data_set:              dist =0               for i in range(len(centrods)):              dist += np.sqrt(distance(centrods[i],point)) #到已經有的聚類中心求和,開平方為了簡化計算              if dist >max_dist:              max_dist = dist              temp_point =point              return temp_point              data_set = datasets.load_iris().data              k= 3  # 聚類中心的個數,人為設定              # 随機選項一個點,初始化聚類中心              rand_point = random.choice(data_set)              clusterCenter_K =np.array([rand_point])              class_arr = [[]]                 #儲存每個聚類的最近樣本點 例:cla[1][...] 第1 個類中的樣本點              # 初始化聚類中心,資料集中選擇距離最大的k個點              for i in range(k-1):              far_point = farCenter(clusterCenter_K,data_set)              clusterCenter_K =np.concatenate([clusterCenter_K,np.array([far_point])])              class_arr.append([])              #可視化初始化資料              col = ['HotPink', 'Aqua', 'Chartreuse', 'yellow', 'LightSalmon']              plt.scatter(data_set[:,0],data_set[:,1],label='origin data',c='g')              plt.legend(loc = 'upper left')               for i in range(k):              plt.scatter(clusterCenter_K[i][0],clusterCenter_K[i][1],linewidth=10, color=col[i])              plt.show()              #疊代              epochs = 50              for epoch in range(epochs):              #1:更新樣本點所屬類,離聚類中心最近,則劃分到這個聚類中              for point in data_set:              ki = 0              mid_dist =distance(point,clusterCenter_K[ki])   # 找出離聚類中心最近的聚類              for j in range(1,len(clusterCenter_K)):              dist =distance(point,clusterCenter_K[j])              if dist <mid_dist:              mid_dist = dist              ki = j              class_arr[ki].append(point) #将樣本點劃入 最近Ki類中              #2更新聚類中心              for i in range(len(clusterCenter_K)):              if epochs-1 == epoch:# 最後一次不更新              break               clusterCenter_K[i]= meanCenter(class_arr[i])              class_arr[i] = []              ## 可視化展示              col = ['HotPink', 'Aqua', 'red', 'yellow', 'LightSalmon']              for i in range(k):              plt.scatter(clusterCenter_K[i][0], clusterCenter_K[i][1], linewidth=10, color=col[i])              plt.scatter([e[0] for e in class_arr[i]], [e[1] for e in class_arr[i]], color=col[i])              plt.show()
           
機器學習-K-means-2020-5-7

二: k-means ++ 

k-means++算法選擇初始seeds的基本思想就是:初始的聚類中心之間的互相距離要盡可能的遠。

算法步驟:

(1)從輸入的資料點集合中随機選擇一個點作為第一個聚類中心

(2)對于資料集中的每一個點x,計算它與最近聚類中心(指已選擇的聚類中心)的距離D(x)

(3)選擇一個新的資料點作為新的聚類中心,選擇的原則是:D(x)較大的點,被選取作為聚類中心的機率較大

(4)重複2和3直到k個聚類中心被選出來

   (5) 與K-means一樣,聚類中心更新,和在劃分類。

從上面的算法描述上可以看到,算法的關鍵是第3步,如何将D(x)反映到點被選擇的機率上,一種算法如下:

  1. 資料集中随機選擇一個樣本點,作為種子點
  2. 對于資料集中每個樣本點,我們都計算其和最近的一個“種子點”的距離D(x)并儲存在一個數組裡,然後把這些距離加起來得到Sum(D(x))。
  3. 再取一個機率随機值P, 屬于[0,1],用權重的方式來取計算下一個“種子點”。這個算法的實作是,total =Sum(D(x))*P ,然後用total -= D(x),直到其<=0,此時的點就是下一個“種子點”。
import math              import random              from sklearn import datasets              import numpy as np              import matplotlib.pyplot as plt              def distance(point1,point2)->float:              """              point1: 樣本點1               point2: 樣本點2              return:distance(point1,point2) 歐式距離              """              dist = 0.0              for e1,e2 in zip(point1,point2):              dist += (e1-e2)**2              return math.sqrt(dist)              def closest_distance(point,centroids):              """              計算樣本點到所有聚類中心最短距離              """              min_dist = math.inf #初始設定成無窮大              for _, centroid in enumerate(centroids):              dist = distance(centroid,point)              if dist < min_dist:              min_dist = dist              return min_dist              #初始化聚類中心              def k_Centers(data_set:list ,k : int)->list:              """              從資料集 中傳回k個對象作為質心              """              cluster_centers = []              cluster_centers.append(random.choice(data_set)) # 第一個聚類中心在資料集中随機選擇一個              d =[0 for  i in range(len(data_set))]     # 初始化為0              for _ in range(1,k):              total = 0              for i ,point in enumerate(data_set):              d[i] = closest_distance(point,cluster_centers)#樣本點到所有聚類中心最近的點              total +=d[i]              total *=random.random() # total * [0,1]的機率              for i ,di in enumerate(d):              total -= di              if total > 0:              continue              cluster_centers.append(data_set[i])              break               return cluster_centers              #更新聚類中心              def meanCenter_updata(subsetData:list):              """              subsetData: 一個聚類中所有的樣本              return : 這個聚類中所有樣本的平均值              """              data = np.array(subsetData)              mean = data.mean(axis=0)              return mean              data_set = datasets.load_iris().data # 加載資料              epochs = 50              class_arr = [[]] #儲存每個類的樣本資料              k= 3  # 聚類個數              cluster_centers = k_Centers(data_set,k) #初始化聚類中心 initial cluster center              for _ in range(len(cluster_centers)):              class_arr.append([])              #繪制初始聚類中心分布圖              col = ['HotPink', 'red', 'Chartreuse', 'yellow', 'LightSalmon']              for i in range(len(cluster_centers)):              plt.scatter(cluster_centers[i][0],cluster_centers[i][1],linewidth=10, color=col[i])              plt.scatter(data_set[:,0],data_set[:,1],c="g",marker='o',label='origin data')              plt.xlabel('sepal length')              plt.ylabel('sepal width')              plt.legend(loc=2)              plt.show()              for epoch in range(epochs):              for point in data_set:  #1将資料劃分到最近聚類中心              index = 0              min_dist = distance(point,cluster_centers[0])              for i in range(1,len(cluster_centers)):              dist = distance(point,cluster_centers[i])              if dist < min_dist:              min_dist =dist              index = i              class_arr[index].append(point)              for j in range(len(cluster_centers)): #2:更新聚類中心              if epoch == epochs -1 :              break              cluster_centers[j] = meanCenter_updata(class_arr[j])              class_arr[j] = []              #結果可視化              for i in range(k):              plt.scatter(cluster_centers[i][0], cluster_centers[i][1], linewidth=10, color=col[i])              plt.scatter([e[0] for e in class_arr[i]], [e[1] for e in class_arr[i]], color=col[i])              plt.show()
           
機器學習-K-means-2020-5-7

3: scikit-learn

官網手冊:https://scikit-learn.org/stable/modules/clustering.html#k-means

使用:

導包 : from sklearn.cluster import KMeans

KMeans() 

參數: paramters 

  • n_clusters  = 8 default 
  • max_iter:  300  最大疊代數
  • n_init : 10  用不同質心初始化運算比較次數,選擇一個損失函數最小的 inertia
  • init:始化方法k-means++ , random , ndarray向量(n_cluster,n_features)自定義
  • precopute_distance: 預計算距離,計算速度快,但占記憶體。auto ,True ,False
  • tol: float default 1e-4 
  • n_jobs : -1 cpu計算  +1 ,不進行并行運算
  • copy_x: True default 當我們precomputing distances時,将資料中心化會得到更準确的結果。如果把此參數值設為True,則原始資料不會被改變。如果是False,則會直接在原始資料

屬性: attributes

  • cluster_centers_:
  • Labels_ : 每個點的分類
  • inertia_ 

方法: methods

  • fit()
  • fit_predictt()
  • fit_transform()
  • get_params()
  • predict()
  • score()
  • set_params()
  • transform()

iris資料集k-means聚類

import matplotlib.pyplot as plt              import numpy as np              from sklearn.cluster import KMeans              from sklearn import datasets              from  sklearn.metrics import confusion_matrix              iris = datasets.load_iris()              data = iris.data              #繪制資料分布圖              plt.scatter(data[:,0],data[:,1],c="red",marker='o',label='see')              plt.xlabel('sepal length')              plt.ylabel('sepal width')              plt.legend(loc=2)              plt.show()              estimator = KMeans(n_clusters=3,max_iter=400,n_init=11,init="k-means++") # 構造聚類器              estimator.fit(data)              label_pred = estimator.labels_ # 擷取聚類标簽 每個點的分類              cluster_center = estimator.cluster_centers_ # 擷取聚類中心              color =['r','g','b']              i = 0              for e in cluster_center:              plt.scatter(e[0],e[1],linewidth=10,c=color[i])              i+=1              # 繪制聚類結果              X0 = data[label_pred ==0]              X1 = data[label_pred ==1]              X2 = data[label_pred ==2]              plt.scatter(X0[:,0],X0[:,1],c='r',marker='o',label='label0')              plt.scatter(X1[:,0],X1[:,1],c='g',marker='+',label='label1')              plt.scatter(X2[:,0],X2[:,1],c='b',marker='*',label='label2')              plt.xlabel('sepal length')              plt.ylabel('sepal width')              plt.legend(loc=2)              print('聚類結果,混淆矩陣')              print(confusion_matrix(iris.target,label_pred))              #print(estimator.predict(data))              print(estimator.score(data))              print(estimator.get_params())              #print(estimator.fit_transform(data))
           
機器學習-K-means-2020-5-7
機器學習-K-means-2020-5-7

Reference:

[1]:https://towardsdatascience.com/the-5-clustering-algorithms-data-scientists-need-to-know-a36d136ef68

[2]:https://medium.com/m/global-identity?redirectUrl=https%3A%2F%2Ftowardsdatascience.com%2Fthe-5-clustering-algorithms-data-scientists-need-to-know-a36d136ef68

[3] https://blog.csdn.net/github_39261590/article/details/76910689

[4] https://blog.csdn.net/loadstar_kun/article/details/39450615

[5] https://blog.csdn.net/itplus/article/details/10088429