数据集
继上次的图像聚类后,这次准备对比有监督学习的分类和无监督学习的聚类,以及无监督学习聚类中,对比在低维度且简单分布的数据中,各个模型的聚类效果。
首先附上数据集:
链接:https://pan.baidu.com/s/1LNu8toOmGXVz9b7t2Ah-6A
提取码:6fwb
这次数据集很简单,就是1500个二维坐标点,分为3类。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
data = pd.read_csv('D:/桌面/data.csv')
print(data.head())
X_df = data.iloc[0:,:2] # 方便后续可视化对比
X = data.iloc[0:,:2].values # 数组形式
[V1, V2]代表了一组二维数据点,而对应的label就是该组点的分类。数组形式的数据方便训练,dataframe形式方便后面可视化对比效果。
看看我们的y标签。
y = data.loc[:,'labels']
print(pd.value_counts(y))
数据总共被分为3类,其中0标签890组,1标签954组,2标签1156组。
对我们的真实数据标签进行可视化。
plt.figure(figsize=(6,5), dpi=100)
plt.scatter(X_df.loc[:,'V1'][y==0], X_df.loc[:,'V2'][y==0], label='0')
plt.scatter(X_df.loc[:,'V1'][y==1], X_df.loc[:,'V2'][y==1], label='1')
plt.scatter(X_df.loc[:,'V1'][y==2], X_df.loc[:,'V2'][y==2], label='2')
plt.title('true data')
plt.legend()
plt.savefig('D:/桌面/true data.png')
人眼可以很明显的看出,这1500组数据被分为3组,每一组都集中分布在一块区域。还是很容易区分的。接下来就可以看看无监督学习和有监督学习在这份数据集上的表现了。
无监督学习
Meanshift
Mean-shift 聚类是一个基于滑窗的算法,尝试找到数据点密集的区域。它是一个基于质心的算法,也就是说他的目标是通过更新中心点候选者定位每个组或类的中心点,将中心点候选者更新为滑窗内点的均值。这些候选滑窗之后会在后处理阶段被过滤,来减少临近的重复点,最后形成了中心点的集合和他们对应的组。
他有个很明显的优点是,meanshift不怕噪声点,会自动过滤然后检测出来。缺点也很明显,因为是基于滑窗的,也就是下面代码中要确定的bandwidth,这一选择导致meanshift往往运行较慢。
好在sklearn给我们estimate_bandwidth方法能够自动计算出带宽。这点倒是非常的省心。减轻我们调参的痛苦。
from sklearn.cluster import MeanShift, estimate_bandwidth
# 自动获取meanshift带宽
bw = estimate_bandwidth(X,n_samples=151)
print(bw)
# 设置模型
ms = MeanShift(bandwidth=bw)
ms.fit(X)
# 预测
y_predict_ms = ms.predict(X)
print(y_predict_ms)
from collections import Counter
print(Counter(y_predict_ms)) # 预测结果统计
from sklearn.metrics import accuracy_score
accuracy_score(y,y_predict_ms)
很多小伙伴肯定会诧异,为什么正确率才31%?这是因为我们meanshift是无监督学习,它不知道每组数据的原始标签。观察上方代码,我们也确实没有把y标签输入给meanshift模型。因此我们还需要校正结果。
观察数据的数量,我们可以得出由meanshift得出的标签和真实标签对应的结果。然后就可以进行校正。
# 校正结果
y_corrected_ms = []
for i in y_predict_ms:
if i==0:
y_corrected_ms.append(2)
elif i==1:
y_corrected_ms.append(1)
else:
y_corrected_ms.append(0)
print(pd.value_counts(y_corrected_ms),'\n\n',pd.value_counts(y))
from sklearn.metrics import accuracy_score
print('meanshift:',accuracy_score(y,y_corrected_ms))
看到我们的meanshift模型很不错,正确率达到了99.7%
但是这是以时间为代价的。耗时较长。
对meanshift模型预测后并校正的结果和我们真实数据放在同一张图进行可视化对比。
# meanshift可视化
y_corrected_ms = np.array(y_corrected_ms)
plt.figure(figsize=(11,5), dpi=100)
plt.subplot(121)
plt.scatter(X_df.loc[:,'V1'][y==0], X_df.loc[:,'V2'][y==0], label='0')
plt.scatter(X_df.loc[:,'V1'][y==1], X_df.loc[:,'V2'][y==1], label='1')
plt.scatter(X_df.loc[:,'V1'][y==2], X_df.loc[:,'V2'][y==2], label='2')
plt.title('true data')
plt.legend()
plt.subplot(122)
plt.scatter(X_df.loc[:,'V1'][y_corrected_ms==0],
X_df.loc[:,'V2'][y_corrected_ms==0], label='0')
plt.scatter(X_df.loc