K-Means聚类算法

  • 引:K-Means算法作为经典且简单的聚类算法,在很多目标检测算法中使用(如YOLOv3)
  • 相关参考
  • K-Means目标:对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大
  • K-Means目标公式化:
    E = Σ i = 1 k Σ x ϵ C i ∣ ∣ x − u i ∣ ∣ 2 2 E=\Sigma_{i=1}^k\Sigma_{x\epsilon C_i}||x-u_i||_2^2 E=Σi=1kΣxϵCixui22
    其中E为总平方误差,k为k个簇,C_i为第i个簇的样本集,x为某个样本,u_i为第i个簇的样本均值。
    最小化上面的公式并不容易,找到它的最优解需考察样本集D内所有可能的簇划分,这是一个NP难问题。因此,k-means算法采用了贪心策略,通过迭代优化来近似求解上面的公式。
  • K-Means算法流程
    K-Means聚类算法_第1张图片
  • python实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
dataset = pd.read_csv('watermelon_4.csv', delimiter=",")
data = dataset.values

print(dataset)

import random
def distance(x1, x2):  # 计算距离
    return sum((x1-x2)**2)
def Kmeans(D,K,maxIter):
    m, n = np.shape(D)
    if K >= m:
        return D
    initSet = set()
    curK = K
    while(curK>0):  # 随机选取k个样本
        randomInt = random.randint(0, m-1)
        if randomInt not in initSet:
            curK -= 1
            initSet.add(randomInt)
    U = D[list(initSet), :]  # 均值向量,即质心
    C = np.zeros(m)
    curIter = maxIter  # 最大的迭代次数
    while curIter > 0:
        curIter -= 1
        # 计算样本到各均值向量的距离
        for i in range(m):
            p = 0
            minDistance = distance(D[i], U[0])
            for j in range(1, K):
                if distance(D[i], U[j]) < minDistance:
                    p = j
                    minDistance = distance(D[i], U[j])
            C[i] = p
        newU = np.zeros((K, n))
        cnt = np.zeros(K)

        for i in range(m):
            newU[int(C[i])] += D[i]
            cnt[int(C[i])] += 1
        changed = 0
        # 判断质心是否发生变化,如果发生变化则继续迭代,否则结束
        for i in range(K):
            newU[i] /= cnt[i]
            for j in range(n):
                if U[i, j] != newU[i, j]:
                    changed = 1
                    U[i, j] = newU[i, j]
        if changed == 0:
            return U, C, maxIter-curIter
    return U, C, maxIter-curIter

U, C, iter = Kmeans(data,3,10)

f1 = plt.figure(1)
plt.title('watermelon_4')
plt.xlabel('density')
plt.ylabel('ratio')
plt.scatter(data[:, 0], data[:, 1], marker='o', color='g', s=50)
plt.scatter(U[:, 0], U[:, 1], marker='o', color='r', s=100)
# plt.xlim(0,1)
# plt.ylim(0,1)
m, n = np.shape(data)
for i in range(m):
    plt.plot([data[i, 0], U[int(C[i]), 0]], [data[i, 1], U[int(C[i]), 1]], "c--", linewidth=0.3)
plt.show()

你可能感兴趣的:(机器学习与深度学习理论1)