声明:本文集的所有文章都只讨论Python如何使用sklearn
进行机器学习。且学习的部分截图来自中国大学MOOC上的Python机器学习应用课程以及EduCoder,侵权删。
2020.3.2
新的学期是真的开始了,就是需要早起有点脑壳疼。而机器学习这边的算法补全也会陆陆续续进行,加油ヾ(◍°∇°◍)ノ゙。
K-means
一、距离
在一个N维的空间中,每一个点在当前空间建立的坐标系中,都有一个唯一标识的 坐标向量 ,例如在三维空间中就有一个点 P(x, y, z)。而两个点之间的距离,就是在一定规则下,两个坐标向量的计算。以下将会讲述
欧氏距离
和曼哈顿距离
。
-
欧氏距离:
欧氏距离是指空间中两个坐标向量的 直线距离 ,所求的是两个点的最短距离。公式如下:
欧氏距离
-
曼哈顿距离:
曼哈顿距离就像是把两个坐标向量当成两间房子,而它们之间隔着很多的十字路口(图片中左右上下这些箭头),计算方法是向量中 各维的差值的绝对值 的 和。
曼哈顿距离
代码示范 (点击可以查看完整代码)
import numpy as np
def distance(x, y, p=2):
'''
input:x(ndarray):第一个样本的坐标
y(ndarray):第二个样本的坐标
p(int):等于1时为曼哈顿距离,等于2时为欧氏距离
output:distance(float):x到y的距离
'''
if p == 1:
distances = np.abs(x - y)
dis = 0.0
for dist in distances:
dis += dist
distances = dis
else:
distances = np.power(x - y, 2)
dis = 0.0
for dist in distances:
dis += dist
distances = np.sqrt(dis)
return distances
两种距离
二、质心
质心 是指在样本空间中的所有样本的均值点,可以想象为见缝插针的形式。
见缝插针
它是所有样本的均衡点,也就是说,所有样本离这一点的距离都是一样的。 K-means算法就是通过不同的质心来给样本聚类的,每个样本都被归类到离它最近的样本。
代码示范 (点击可以查看完整代码)
def cal_Cmass(data):
'''
input:data(ndarray):数据样本
output:mass(ndarray):数据样本质心
'''
# ********* Begin *********#
Cmass = [0] * data.shape[1]
for d in data:
Cmass += d
Cmass /= data.shape[0]
# ********* End *********#
return Cmass
这里有一点需要特别说明: 被归一化之后的数据, 每一行为一个样本,而列就是所有样本点都具有的特征(属性),也就是样本们的维数。 比如说,有3列,就是有三个特征点,也就是说他们处于一个三维的空间,质心也应该是三维的。还有就是, 质心的每一维的值是样本每维的均值,不需要等于某个样本。
质心
三、K-means算法思想
K-means算法旨在于使用迭代的方法,通过设定好的几个质心来对数据进行聚类。以下是K-means算法的大致步骤:
- 设定分类的数量与最大迭代数,并随机生成相应数量的质心: 第一次的质心是随机的,因为K-means是非监督学习,所以很依赖给出的分类数,分多了分少了都会出现没那么好的结果。而最大迭代数用于防止死循环。
- 计算样本点与各质心的距离,分类,生成标签:将所有样本点依次跟每个质心计算距离,将其归类到离它最近的质心的一类中,生成一个 标签数组 (一个一维数组,长度为数据源的行数,因为源数据一行为一个样本,所以这个标签数组每一个元素就记录着该样本对应的类别)。
- 更新每一类的质心,并再次分类和生成新标签 : 分类计算,求出每一类样本的均值,更新质心。之后每一类都再进行样本跟每一个质心的距离计算,生成新标签。
- 如果达到最大迭代数,或者所有质心都基本不再变化,聚类完毕 : 否则,循环2、3两步,直到满足这些条件,退出循环,完成聚类。
代码示范 (点击可以查看完整代码)
# 对整个数据集X进行Kmeans聚类,返回其聚类的标签
def predict(self, X):
# 从所有样本中随机选取self.k样本作为初始的聚类中心
# 迭代,直到算法收敛(上一次的聚类中心和这一次的聚类中心几乎重合)或者达到最大迭代次数
# 将所有进行归类,归类规则就是将该样本归类到与其最近的中心
# 计算新的聚类中心
# 如果聚类中心几乎没有变化,说明算法已经收敛,退出迭代
self.init_random_centroids(X)
self.create_clusters(self.centroids_list, X)
for i in range(self.max_iterations):
new_centroid = self.update_centroids(self.clusters, X)
if 0.98 < np.sum((new_centroid / self.centroids_list)) < 1.02:
break
self.centroids_list = new_centroid
self.create_clusters(self.centroids_list, X)
return self.clusters
在这里说明一下,我设置只要两次的所有质心只差小于正负0.02,就可以结束循环了。
K-means
四、Scikit-learn中的K-means
sklearn 中的 K-means 简化了步骤,只需要先使用 fit() 函数来训练,再使用 predict() 来预测生成标签即可。
代码示范 (点击可以查看完整代码)
def kmeans_cluster(data):
'''
input:data(ndarray):样本数据
output:result(ndarray):聚类结果
'''
km = KMeans(n_clusters=3, random_state=8)
km.fit(data)
result = km.predict(data)
return result
K-means