**个人的学习笔记,欢迎大佬指点**
链接: [link](https://www.imooc.com/video/22254).
k-means算法背景:
无监督、聚类、将给定的数据分为k个簇并找到每个簇的中心
k-means算法举例:见代码
k-means算法理论介绍:
第一步:数据预处理,剔除离群点、数据归一化、数据标准化等操作。
第二步:初始化中心点,随机选择k个中心点,作为初始的聚类中心。
第三步:定义损失函数,即每个样本点到相应聚类中心的距离的和。
第四步:选择迭代次数,直到函数收敛。
k-means函数缺点:
一、 需要人工选择k值
二、 受初始值和离群点影响比较严重
三、 结果是局部的最优解,不是全局的最优解
k-means函数优点:
一、 计算时间复杂度是线性的
二、 局部最优解完全够用
k-means算法改进:
对8个样本点进行分类,并找出每个簇的中心点
# -*- coding: utf-8 -*- 防止中文注释报错
from numpy import *
import pandas as pd
import matplotlib.pyplot as plt
#距离度量函数
def calc_distance(vec1 , vec2):
return sqrt(sum(power((vec1 - vec2) , 2)))
#创建初始聚类中心
def creat_centroid(data , k):
centroids = zeros((k , n))
centroids[0 , 0] = 2
centroids[0 , 1] = 10
centroids[1 , 0] = 5
centroids[1 , 1] = 8
centroids[2 , 0] = 1
centroids[2 , 1] = 2
return centroids
#k-means聚类函数
def kMeans(data , k , dist=calc_distance , creat_center=creat_centroid):#data:需要传入的数据,k:设置的聚类个数,dist:距离,creat_center:初始聚类中心
# 初始化一个矩阵cluster_assment,用于存储中间结果
# 矩阵的第一列存储索引,第二列存储距离
m = shape(data)[0]#样本个数
init = zeros((m , 2))
cluster_assment = mat(init)#把init转为矩阵
#初始化聚类中心矩阵
centroids = creat_centroid(data , k)
for epoch in range(100):
#完成一次聚类
for i in range(m):#对数据集中每个样本点进行计算
min_dist = inf#设置距离初始值为无穷大
min_index= -1#设置初始索引为-1
for j in range(k):#对每个样本点到每个中心的距离进行计算
dist_ij = calc_distance(centroids[j,:] , data[i,:])
if dist_ij < min_dist:#找到距离最近的中心的距离和索引
min_dist = dist_ij
min_index = j #j代表相应的中心点
cluster_assment[i,:] = min_index , min_dist #一个中间矩阵,存储每个样本点所对应的中心点,和与中心点的距离
#对所有节点聚类之后,重新更新中心
for i in range(k):
pts_in_cluster = data[nonzero(cluster_assment[:,0].A==i)[0]]#返回相应簇的每个样本,为什么要用nonzero函数?
centroids[i,:] = mean(pts_in_cluster , axis=0)#计算这些点的平均值来更新簇的中心点
return centroids , cluster_assment #返回新的中心,和新的分类
if __name__ == '__main__':#定义主函数
#创建数据
data = array([[2 , 10] , [2 , 5] , [8 , 4] , [5 , 8] ,
[7 , 5] , [6 , 4] , [1 , 2] , [4 , 9]])
k = 3#k为聚类个数
n = 2#数据包含2个特征
centroids, cluster_assment = kMeans(data , k , dist=calc_distance , creat_center=creat_centroid)
predict_label = cluster_assment[:,0]#展示分类标签
data_and_pred = column_stack((data , predict_label))#按列堆叠显示,这里共有三列数据
#将data_and_pred转换为DataFrame数据结构
df = pd.DataFrame(data_and_pred , columns=['data1','data2','pred'])
df0 = df[df.pred == 0].values#将样本拆分成3类
df1 = df[df.pred == 1].values
df2 = df[df.pred == 2].values
#画图
plt.scatter(df0[:,0] , df0[:,1] , c='blue' ,marker='o' , label='label0')
plt.scatter(df1[:,0] , df1[:,1] , c='green' ,marker='*' , label='label1')
plt.scatter(df2[:,0] , df2[:,1] , c='orange' ,marker='+' , label='label2')
plt.scatter(centroids[:,0].tolist() , centroids[:,1].tolist() , c='red')
plt.legend(loc=2)
plt.show()
KMeans算法为数据挖掘中常用的算法,可以直接从机器学习库函数sklearn中调入使用。
以下便是利用“手肘法”,寻找8个样本点的最佳分类方案
from numpy import *
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
if __name__ == '__main__':
#创建数据集
data = array([[2,10] , [2,5] , [8,4] , [5,8] ,[7,5] , [6,4] ,[1,2] , [4,9]])
sse = []
for i in range(1,9):#寻找最合适的分类方案
mid = KMeans(n_clusters=i , init='random' , n_init=10 , max_iter=200)#n_clusters=i:分类个数,init='random':随机选择分类点,n_init=10:例如i=3,即分为三类,则随机挑选三个簇的中心,挑选10次,max_iter=200:循环计算200次
mid.fit(data)
sse.append(mid.inertia_)# mid.inertia:每次分类后,每个样本点到各自中心点距离的和
plt.plot(range(1,9) , sse ,marker='o')
plt.xlabel('k')
plt.ylabel('SSE')
plt.show()