机器学习-kmeans(实现步骤、sklearn实现、python自实现、优缺点)

机器学习-kmeans

KMeans(K均值)是典型的基于距离的排他划分方法:给定一个n个对象的数据集,它可以构建数据的k个划分,每个划分就是一个聚类,并且k<=n,同时还满足两个要求:

1.每个组至少包含一个对象

2.每个对象必须属于且仅属于一个组

优点:

  擅长处理球状分布的数据,当结果聚类是密集的,而且类和类之间的区别比较明显时,K均值的效果比较好

  对于处理大数据及,这个算法是相对可伸缩的和高效的,它的复杂度是O(nkt),n是对象的个数,k是簇的数目,t是迭代的次数。

缺点:

  算法的初始中心点选择与算法的运行效率密切相关,而随机选取中心点有可能导致迭代次数很大或者限于某个局部最优状态;通常k<

  K均值的最大问题是要求用户必须事先给出k的个数,k的选择一般都基于经验值和多次实验的结果,对于不同的数据集,k的取值没有可借鉴性。

  对异常偏离的数据敏感--离群点;K均值对噪声和孤立点数据是敏感的,少量的这类数据就能对平均值造成极大的影响。

步骤:

1.首先创建一个初始化分,随机的选择k个对象,每个对象初始的代表一个聚类中心。对于其他对象,根据其与各个聚类中心的距离,将它们赋给最近的聚类。

递归重定位,尝试通过对象在划分间移动来改进划分。重定位即:当有新的对象加入聚类或者已有对象离开聚类的时候,重新计算聚类的平均值,然后对对象进行重新分配。这个过程不断重复,直到聚类中的数据不再变化为止。

sklearn代码如下

from numpy import *
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

def file2matrix(filePath, lineSplit):
    dataSet = []
    fr = open(filePath, 'r')
    content = fr.read()
    for line in content.splitlines():
        dataSet.append([line.split('\t')[0], line.split('\t')[1]])
    fr.close()
    return dataSet


def drawScatter(plt, dataMat, size, color, mrkr):
    X = dataMat[:,0]
    Y = dataMat[:,-1]
    plt.scatter(X.tolist(), Y.tolist(), c=color, marker=mrkr, s=size)
    plt.xlabel("x")
    plt.ylabel("y")
    plt.title("Kmeans")
    plt.legend()


k = 4
dataSet = file2matrix("/Users/FengZhen/Desktop/accumulate/机器学习/推荐系统/kmeans聚类测试集.txt", "\t")
dataMat = mat(dataSet)
print(dataMat)
# 执行kmeans算法
kmeans = KMeans(init='k-means++', n_clusters=k)
kmeans.fit(dataMat)
print(kmeans.cluster_centers_)

#绘制计算结果
drawScatter(plt, dataMat, size=20, color='b', mrkr='.')
drawScatter(plt, kmeans.cluster_centers_, size=20, color='red', mrkr='D')
plt.show()

 机器学习-kmeans(实现步骤、sklearn实现、python自实现、优缺点)_第1张图片

python自实现

import matplotlib.pyplot as plt
from numpy import *
import numpy as np

# 数据文件转矩阵
def file2matrix(filePath):
dataSet = []
fr = open(filePath, 'r')
content = fr.read()
for line in content.splitlines():
dataSet.append([line.split('\t')[0], line.split('\t')[1]])
fr.close()
return dataSet

# 根据聚类中心绘制散点图,以及绘制聚类中心
def color_cluster(dataindx, dataSet, plt, k=4):
# print(dataindx)
plt.scatter(dataSet[:, 0].tolist(), dataSet[:, 1].tolist(), c='blue', marker='o')
# index = 0
# datalen = len(dataindx)
# for indx in range(datalen):
# if int(dataindx[index]) == 0:
# plt.scatter(dataSet[index, 0].tolist(),dataSet[index, 1].tolist(), c='blue', marker='o')
# elif int(dataindx[index]) == 1:
# plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='green', marker='o')
# elif int(dataindx[index]) == 2:
# plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='red', marker='o')
# elif int(dataindx[index]) == 3:
# plt.scatter(dataSet[index, 0].tolist(), dataSet[index, 1].tolist(), c='cyan', marker='o')
# index += 1

# 绘制散点图
def drawScatter(plt, mydata, size=20, color='blue', mrkr='o'):
# print(mydata.T[0][0].tolist())
# print(mydata.T[1][0].tolist())
plt.scatter(mydata.T[0][0].tolist(), mydata.T[1][0].tolist(), s=size, c=color, marker=mrkr)


# 欧氏距离公式
def distEclud(vecA, vecB):
return linalg.norm(vecA.astype(float) - vecB.astype(float))


# 随机生成聚类中心
def randCenters(dataSet, k):
n = shape(dataSet)[1] # 列数
clustercents = mat(zeros((k, n))) # 初始化聚类中心矩阵:k*n
for col in range(n):
mincol = min(dataSet[:, col]).astype(float); maxcol = max(dataSet[:, col]).astype(float)
# random.rand(k,1)):产生一个0-1之间的随机数向量:k,1表示产生k行1列的随机数
clustercents[:, col] = mat(mincol + float(maxcol - mincol) * random.rand(k, 1))
return clustercents

def kMeans(dataSet, k):
m = dataSet.shape[0]
ClustDist = mat(zeros((m, 2)))
clustercents = randCenters(dataSet, k) # 随机生成聚类中心
flag = True # 迭代标记
counter = [] # 初始化计数器

while flag:
flag = False # 默认设置退出标志
# 算法停止条件:ClustDist[i, 0] == minIndex
for i in range(m):
# 遍历k个聚类中心,获取最短距离
distlist = [distEclud(clustercents[j, :], dataSet[i, :]) for j in range(k)]
minDist = min(distlist) # 获取最小距离
minIndex = distlist.index(minDist) # 获取最小距离所属的簇
if ClustDist[i, 0] != minIndex: # 找到了一个新聚类中心
flag = True # 重置标志位为True,继续迭代
# 更新聚类中心
ClustDist[i, :] = minIndex, minDist
for cent in range(k):
# 从ClustDist的第一列中筛选出等于cent值的行下标
ptsInClust = dataSet[nonzero(ClustDist[:, 0].A == cent)[0]]
# 计算ptsInClust各列的均值
clustercents[cent, :] = mean(ptsInClust.astype(float), axis=0)
return clustercents, ClustDist

dataMat = file2matrix("/Users/FengZhen/Desktop/accumulate/机器学习/推荐系统/kmeans聚类测试集.txt") # 从文件构建的数据集
dataSet = mat(dataMat) # 转换为矩阵形式
k = 4 # 外部指定的聚类中心
clustercents,ClustDist = kMeans(dataSet, k)
# print("clustercents:\n", clustercents)

# color_cluster(ClustDist[:, 0:1], dataSet, plt)
# drawScatter(plt, clustercents, size=20, color='red', mrkr='D')
# plt.show()

机器学习-kmeans(实现步骤、sklearn实现、python自实现、优缺点)_第2张图片

你可能感兴趣的:(python,机器学习,sklearn,kmeans,聚类)