05_無監督學習--聚類模型--K 均值

無監督學習--聚類模型--K 均值0.引入依賴1.數據的加載和預處理2.算法實現3.測試python


無監督學習--聚類模型--K 均值

0.引入依賴

import numpy as np
import matplotlib.pyplot as plt

# 這裏直接 sklearn 裏的數據集
from sklearn.datasets.samples_generator import make_blobs

1.數據的加載和預處理

x, y = make_blobs(n_samples=100, centers=6, random_state=1234, cluster_std=0.6)
# x # array([[-0.02708305,  5.0215929 ], ..., [-4.7583093 ,  5.85803377]])
# x.shape # (100, 2)
# y.shape # (100,)

plt.figure(figsize=(99))
plt.scatter(x[:,0], x[:,1], c=y)
plt.show()

做圖以下:算法

2.算法實現

# 引入 scipy 庫中的距離函數,默認實現是歐式距離
from scipy.spatial.distance import cdist

class K_Means(object):
    # 初始化,參數 n_clusters(K)、max_iter(迭代次數)、centroids(初始質心)
    def __init__(self, n_clusters=6, max_iter=300, centroids=[]):
        self.n_clusters = n_clusters
        self.max_iter = max_iter
        self.centroids = np.array(centroids, dtype=np.float)

    # 定義訓練模型方法,實現 K-means 聚類過程
    def fit(self, data):
        # 假如沒有指定初始質心,就隨機選取 data 中的點做爲質心
        if (self.centroids.shape == (0,)):
            # 從 data 中隨機生成 0 到 data 行數的 6 個整數,做爲索引值
            self.centroids = data[np.random.randint(0, data.shape[0], self.n_clusters) ,:]

        # 開始迭代
        for i in range(self.max_iter):
            # 1.計算距離,獲得的是一個 100x6 的矩陣,該矩陣的每一行含義是:一個樣本點跟全部質心的距離
            distances = cdist(data, self.centroids)

            # 2.對距離按由近到遠排序,選取最近的質心點的類別,做爲當前點的分類
            c_index = np.argmin(distances, axis=1# 獲得 100x1 的矩陣

            # 3.對每一類數據進行均值計算,更新質心點的座標
            for i in range(self.n_clusters): # 遍歷每一類
                # 排除掉沒有出如今 c_index 裏的類別
                if i in c_index:
                    # 選擇全部類別是 i 的點,取 data 裏面座標的均值,更新第 i 個質心
                    self.centroids[i] = np.mean(data[c_index==i], axis=0# 獲得一行數據,使用了布爾索引

    # 定義預測模型方法
    def predict(self, samples):
        # 跟上面同樣,先計算距離,而後讀取距離最近的那個質心的類別
        distances = cdist(samples, self.centroids)
        c_index = np.argmin(distances, axis=1# 獲得 100x1 的矩陣

        return c_index

# 測試
distances = np.array([[1212213243],
                      [12133216652],
                      [9641156158],
                      [45235542156],
                      [1405463255],
                     ], dtype=np.float)
c_index = np.argmin(distances, axis=1)
print(c_index)

x_new =x[0:5]
print(x_new)
print(c_index==2)
print(x_new[c_index==2])
np.mean(x_new[c_index==2], axis=0)

輸出結果以下:app

[2 3 2 0 1]
[[-0.02708305  5.0215929 ]
 [-5.49252256  6.27366991]
 [-5.37691608  1.51403209]
 [-5.37872006  2.16059225]
 [ 9.58333171  8.10916554]]
True False  True False False]
[[-0.02708305  5.0215929 ]
 [-5.37691608  1.51403209]]

array([-2.70199956,  3.26781249])

3.測試

# 定義一個繪製子圖的函數
def plotKMeans(x, y, centroids, subplot, title):
    # 分配子圖,121 表示 1 行 2 列的子圖中的第一個
    plt.subplot(subplot)
    plt.scatter(x[:,0], x[:,1], c='r')
    # 畫出質心點
    plt.scatter(centroids[:,0], centroids[:,1], c=np.array(range(6)), s=100)
    plt.title(title)

kmeans = K_Means(max_iter=300, centroids=np.array([[21],[22],[23],[24],[25],[26]]))

plt.figure(figsize=(189))
plotKMeans(x, y, kmeans.centroids, 121'Initial State')

# 開始聚類
kmeans.fit(x)
plotKMeans(x, y, kmeans.centroids, 122'Final State')

# 開始預測
x_new = np.array([[00],[107]])
y_pred = kmeans.predict(x_new)

print(kmeans.centroids)
print(y_pred)

plt.scatter(x_new[:,0], x_new[:,1], c='black', s=100)

輸出結果以下:dom

[[ 5.76444812 -4.67941789]
 [-2.89174024 -0.22808556]
 [-5.89115978  2.33887408]
 [-4.53406813  6.11523454]
 [-1.15698106  5.63230377]
 [ 9.20551979  7.56124841]]
[1 5]

<matplotlib.collections.PathCollection at 0x1543350c518>

做圖以下:函數

相關文章
相關標籤/搜索