今天我们来看一个非常常见和使用的无监督机器学习算法——K-均值聚类(K-means)
首先我们先了解一下这个算法的大致背景:
首先要知道什么是聚类
聚是一个将数据集中在某些方面相似的数据成员进行分类组织的过程,聚类就是一种发现这种内在结构的技术,聚类技术经常被称为无监督学习。
通俗的说,就是比如我们去海南种水稻,水稻田里面有各种各样的水稻,每株水稻的高低颜色还有其他很多特征都不一样,我们更具这些特征对水稻进行分类,相似的聚为一类。
K-均值聚类的定义
给定一个数据点集合和需要的聚类数目k,k由用户指定,k均值算法根据某个距离函数反复把数据分入k个聚类中
具体什么含义呢?就是我把每个样本点的数据搜集好,形成了一个数据集,然后我人为地定义一个K,就是我想聚成K类,那么K-means算法就会根据我定义的K进行反复迭代和计算,最后,我的所有样本就会被分成K类
K-means算法的实现
摘自百度百科,我觉的百度百科已经说得很清楚了
先随机选取K个对象作为初始的聚类中心。然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。一旦全部对象都被分配了,每个聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是以下任何一个:
Step 1 没有(或最小数目)对象被重新分配给不同的聚类
Step 2 没有(或最小数目)聚类中心再发生变化
Step 3 误差平方和局部最小。
伪代码
选择k个点作为初始质心。
repeat 将每个点指派到最近的质心,形成k个簇 重新计算每个簇的质心
until 质心不发生变化
既然是学习最简单的K-means,就先不讲太多的复杂内容,直接上代码来实战一下。
Scikit-learn - K-means 实战
首先我先定义一些数据,假设我在海南种水稻的时候,测量的水稻的株高和剑叶长(数据纯属乱扯的哈)。
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
X = np.array([[1, 2], [1, 4], [1, 1],
[6, 2], [2, 3], [4, 2],
[8, 1], [4, 5], [5, 3],
[3, 0], [5, 0], [6, 4],
[4, 9], [6, 4], [3, 6],
[5, 4], [9, 7], [2, 4],
[6, 2], [4, 5], [8, 3]])
X
我们将数据输入这个矩阵中
然后我们大致看一下数据的情况
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
X = np.array([[1, 2], [1, 4], [1, 1],
[6, 2], [2, 3], [4, 2],
[8, 1], [4, 5], [5, 3],
[3, 0], [5, 0], [6, 4],
[4, 9], [6, 4], [3, 6],
[5, 4], [9, 7], [2, 4],
[6, 2], [4, 5], [8, 3]])
plt.scatter(X[:, 0], X[:, 1], c = "red", marker='o', label='see')
plt.show()
然后直接用scikit的函数训练,这里我们可以设置 K, 我先设置成 K=2 的情况
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
X = np.array([[1, 2], [1, 4], [1, 1],
[6, 2], [2, 3], [4, 2],
[8, 1], [4, 5], [5, 3],
[3, 0], [5, 0], [6, 4],
[4, 9], [6, 4], [3, 6],
[5, 4], [9, 7], [2, 4],
[6, 2], [4, 5], [8, 3]])
rice_cluster = KMeans(n_clusters=2) #设置一个你想分的类别,定义一个聚类器
rice_cluster.fit(X) # 使用这个数据进行训练
rice_cluster.labels_ # 我们可以看到每个样本点的聚类标签
我们画图来看一下结果
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
X = np.array([[1, 2], [1, 4], [1, 1],
[6, 2], [2, 3], [4, 2],
[8, 1], [4, 5], [5, 3],
[3, 0], [5, 0], [6, 4],
[4, 9], [6, 4], [3, 6],
[5, 4], [9, 7], [2, 4],
[6, 2], [4, 5], [8, 3]])
rice_cluster = KMeans(n_clusters=2) #设置一个你想分的类别,定义一个聚类器
rice_cluster.fit(X) # 使用这个数据进行训练
label = rice_cluster.labels_
x0 = X[label == 0]
x1 = X[label == 1]
plt.scatter(x0[:, 0], x0[:, 1], c = "red", marker='o', label='label0')
plt.scatter(x1[:, 0], x1[:, 1], c = "blue", marker='*', label='label1')
plt.show()
使用轮子的好处就是你主要调参就行了,接下来我们调整成3类试试看
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
X = np.array([[1, 2], [1, 4], [1, 1],
[6, 2], [2, 3], [4, 2],
[8, 1], [4, 5], [5, 3],
[3, 0], [5, 0], [6, 4],
[4, 9], [6, 4], [3, 6],
[5, 4], [9, 7], [2, 4],
[6, 2], [4, 5], [8, 3]])
rice_cluster = KMeans(n_clusters=3) #设置一个你想分的类别,定义一个聚类器
rice_cluster.fit(X) # 使用这个数据进行训练
label = rice_cluster.labels_
x0 = X[label == 0]
x1 = X[label == 1]
x2 = X[label == 2]
plt.scatter(x0[:, 0], x0[:, 1], c = "red", marker='o', label='label0')
plt.scatter(x1[:, 0], x1[:, 1], c = "blue", marker='*', label='label1')
plt.scatter(x2[:, 0], x2[:, 1], c = "green", marker='+', label='label2')
plt.show()
用起来不是很难,关键是我们要懂其内在的原理,同时清楚自己要解决的问题是什么。
评价模型好坏
我们先来看看模型的中心点
rice_cluster.cluster_centers_
然后可以用已经训练好的模型,去预测新的值
rice_cluster.predict([[1, 1], [5, 3],[5, 6]])
还有一个评价体系,评价模型好坏,结果与1越接近,样本聚类越合理
from sklearn import metrics
score=metrics.silhouette_score(X,label)
score
K-means 优缺点介绍
优点:简单 快捷 如果簇是密集的,分类效果特别好
缺点:处理符号属性的数据不适用、必须实现给出K值、对初始值有一定的要求,初始值设定不当,聚类结果可能不同、如果有极端值,会影响平均值
K-means 算法升级
这里就不做多的介绍,可以自行搜索scikit-learn聚类
里面有详细的介绍,我们要根据自己实际的数据情况选择相应的聚类方法。