如果觉得本篇文章对您的学习起到帮助作用,请 点赞 + 关注 + 评论 ,留下您的足迹💪💪💪
本篇文章为我对机器学习实战-K-MEANS聚类的理解与我在学习时所做笔记,一是为了日后查找方便并加深对代码的理解,二是希望能帮助到使用这本书遇到困难的人。
代码可在python3.7跑通
因此代码相对原书做了一些修改,增加了可读性,同时也解决了一些问题。
代码k_means.py及详细注释如下:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
def loadDataset(filename):
'''
# 加载数据,并转化为 numpy.ndarray 类型
:param filename: 文档路径及名字
:return: 返回数据为 numpy.ndarray 类型
'''
dataMat = []
with open(filename) as fr:
for line in fr.readlines():
curline = line.strip().split('\t')
dataMat.append([float(curline[0]), float(curline[1])])
dataMat = np.array(dataMat)
return dataMat
def draw(dataset):
# 显示汉字
mpl.rcParams['font.sans-serif'] = [u'SimHei']
# 解决负号错误问题
mpl.rcParams['axes.unicode_minus'] = False
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111)
ax.plot(dataset[:,0], dataset[:,1],'bo')
plt.show()
def distEclud(vecA, vecB):
'''
# 计算 vecA 和 vecB 两个向量的欧式距离
:param vecA: 向量A
:param vecB: 向量B
:return:
'''
return np.sqrt(np.sum(np.power(vecA - vecB, 2)))
def randCent(dataset, k):
'''
# 该函数为给定数据集生成包含 k 个随机质心的集合。
# 随机质心必须在整个数据集的边界之内,需要通过数据集每一维的最小最大值来确定。
:param dataset:数据集
:param k:聚类算法簇的个数
:return:
'''
n = np.shape(dataset)[1]
centroids = np.zeros((k, n))
for j in range(n):
minJ = np.min(dataset[:,j])
rangeJ = float(np.max(dataset[:,j]) - minJ)
# 最小值 + 最小最大范围 * [0, 1]
centroids[:,j] = np.squeeze(minJ + rangeJ * np.random.rand(k, 1)) # 去掉一个维度,与centroids[:,j]同维
return centroids
def KMeans(dataset, k, distMeas=distEclud, creatCent=randCent):
m = np.shape(dataset)[0]
# 簇分类结果矩阵,分为两列
# 第一列记录:簇索引值
# 第二列记录:存储误差(当前点到簇质心的距离)
clusterAssment = np.zeros((m, 2))
centroids = creatCent(dataset, k)
clusterChanged = True # 判断是否继续迭代的标志位,所有数据点不在重新分配则为Flase
while clusterChanged:
clusterChanged = False
for i in range(m):
minDist = np.inf # np.inf 表示一个无穷大的正数
minIndex = -1
for j in range(k):
distJI = distMeas(dataset[i,:], centroids[j,:]) # 数据点和质心的距离
if distJI < minDist: # 比较数据点到第k个质心的距离,取数据点到质心距离最小的质心
minDist = distJI
minIndex = j
if clusterAssment[i,0] != minIndex: clusterChanged = True # 所有数据分类簇的索引值不再变化则停止迭代
clusterAssment[i,:] = minIndex,minDist**2 # 距离取平方,对应于损失函数
for cent in range(k): # 重新计算质心
# ptsInClust = dataset[np.nonzero(clusterAssment[:, 0] == cent)[0]] # 在这个群集中找到对应簇的所有点
ptsInClust = dataset[clusterAssment[:, 0] == cent] # 很简单代码就可以解决
centroids[cent, :] = np.mean(ptsInClust, axis=0) # 质心取平均值
return centroids, clusterAssment
if __name__ == '__main__':
filename = 'dataset//testSet.txt'
dataMat = loadDataset(filename)
centroids, clusterAssment = KMeans(dataMat, 4, distMeas=distEclud, creatCent=randCent)
print(centroids)
print(clusterAssment)
希望文章内容可以帮助到你,快来动手敲代码吧!!