1) 导入IRIS数据集;
2) 使用K-means算法进行聚类方法分析,K=3;
3) 使用Matplotlib进行结果的可视化(不同类用不同颜色表示,给出3个聚类中心);
4)给出聚类的正确率(检查)。
Matplotlib是一个非常好用的可视化绘图库,我们将创建两个散点图:
分别使用两种不同的作图思路进行绘画。蓝色的小点代表不喜欢,黄色的中等点代表魅力一般,红色的大点代表极具魅力。
将用来画图的dataShow函数添加到我们的代码中:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from KNN import kNN
def file2matrix(filename):
"""
将文件转换为特征矩阵和对应的标签
:param filename:
:return:
"""
# 打开文件
fr = open(filename)
# 按照行进行读取
arrayOLines = fr.readlines()
# 计算出总行数,为1000行
numbserOfLines = len(arrayOLines)
# 创建一个1000行的0矩阵
returnMat = np.zeros((numbserOfLines, 3))
classLabelVector = []
index = 0
for line in arrayOLines:
# 去除前后空格
line = line.strip()
# 按照\t将每行内容分割开来
listFormLine = line.split('\t')
# 将得到前三项的内容填充到对应的行数矩阵上
returnMat[index, :] = listFormLine[0:3]
# 按照喜欢程度进行添加标签
# classLabelVector.append(int(listFormLine[-1]))
if listFormLine[-1] == 'largeDoses':
classLabelVector.append(3)
if listFormLine[-1] == 'smallDoses':
classLabelVector.append(2)
if listFormLine[-1] == 'didntLike':
classLabelVector.append(1)
# 行数索引加一
index += 1
return returnMat, classLabelVector
def dataShow(datingDataMat, datingLabels):
"""
将矩阵可视化,画出每年获得的飞行常客里程数和玩视频游戏所消耗时间百分比的图示
:param datingDataMat:矩阵
:param datingLabels:矩阵标签
:return:
"""
# 将对应的标签转换为颜色
LabelsColors = []
for i in datingLabels:
if i == 1:
LabelsColors.append("b") # 黑色不喜欢
if i == 2:
LabelsColors.append("y") # 黄色一般喜欢
if i == 3:
LabelsColors.append("r") # 红色很喜欢
# 能够显示中文
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['font.serif'] = ['SimHei']
# matplotlib的图像都位于Figure对象中,设置大小和分辨率
fig = plt.figure(figsize=(12, 7), dpi=80)
# 第一个图,用来显示每年获得的飞行常客里程数和玩视频游戏所消耗时间百分比
ax1 = fig.add_subplot(1, 2, 1)
# 设置x标签
ax1.set_xlabel('每年获得飞行常客里程数')
# 设置y标签
ax1.set_ylabel('玩视频游戏所消耗时间百分比')
# 添加数据,第一列就是飞行里程数,第二列是玩视频游戏的时间
ax1.scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 1], color=LabelsColors,
s=(15.0 * np.array(datingLabels), 15.0 * np.array(datingLabels)), marker='o')
didnt_Like = ax1.scatter([], [], c='b', s=15)
smallDoses = ax1.scatter([], [], c='y', s=30)
largeDoses = ax1.scatter([], [], c='r', s=45)
# 添加标签
ax1.legend((didnt_Like, smallDoses, largeDoses), ('不喜欢', '魅力一般', '极具魅力'), loc='best')
# 另一种作图思路,作出玩视频游戏所消耗百分比(x)和每周消耗冰淇淋公斤数(y)的图
ax2 = fig.add_subplot(1, 2, 2)
# 设置x标签
ax2.set_xlabel('玩视频游戏所消耗百分比')
# 设置y标签
ax2.set_ylabel('每周消耗冰淇淋公斤数')
# 遍历标签,划分出三种类别的坐标
ice_didntLike = [] # 不喜欢类型的冰淇淋公斤数
game_didntLike = [] # 不喜欢类型的玩游戏时间
ice_smallDoses = [] # 一般魅力的冰淇淋公斤数
game_smallDoses = [] # 一般魅力你的玩游戏时间
ice_largeDoses = [] # 极大魅力的冰淇淋公斤数
game_largeDoses = [] # 极大魅力的玩游戏时间
num = 0 # 索引
for i in datingLabels:
if i == 1: # 不喜欢
ice_didntLike.append(datingDataMat[num, 2])
game_didntLike.append(datingDataMat[num, 1])
if i == 2: # 一般魅力
ice_smallDoses.append(datingDataMat[num, 2])
game_smallDoses.append(datingDataMat[num, 1])
if i == 3: # 极大魅力
ice_largeDoses.append(datingDataMat[num, 2])
game_largeDoses.append(datingDataMat[num, 1])
num += 1
# 极大魅力绘制
largeDoses = ax2.scatter(x=game_largeDoses, y=ice_largeDoses, s=45, c='r')
# 一般魅力绘制
smallDoses = ax2.scatter(x=game_smallDoses, y=ice_smallDoses, s=30, c='y')
# 不喜欢绘制
didntLike = ax2.scatter(x=game_didntLike, y=ice_didntLike, s=15, c='b')
# 添加标签
ax2.legend((didntLike, smallDoses, largeDoses), ('不喜欢', '魅力一般', '极具魅力'), loc='best')
# 自动调整间距防止标签超过范围
plt.tight_layout()
plt.show()
if __name__ == '__main__':
# 拿到数据
datingDataMat, datingLabels = file2matrix('datingTestSet.txt')
# print(datingDataMat)
# print(datingLabels)
# 数据可视化
dataShow(datingDataMat, datingLabels)
运行结果,将散点图显示出来:
为什么要绘图呢?
因为我们可以从图中大概的看出不同类别的人对应的特征值的分布范围,比如说从第一张图就能够看出魅力一般的人每年飞行客场里程数大概分布在0到20000这个范围内。而从第二张图又能够看出,极具魅力的人玩视频游戏所消耗时间百分比大概分布在10左右。同样也能够从第二张图看出,貌似每周所消耗的冰淇淋公斤数三种类别的人分布都没有固定的聚集范围,都是比较分散的,这样就能够大概猜出其实喜欢不喜欢和每周所消耗的冰淇淋公斤数没有多大关系。
而且绘图的时候需要注意,不同的类别的点用不同颜色和大小进行绘制,这样绘制出来的图比较直观明了。不然绘画出来都是一样的黑点也看不出来什么东西。
1.如何导入IRIS数据集?
使用sklearn库中的load_iris函数导入IRIS数据集,并将其存储为pandas中的DataFrame格式。
from sklearn.datasets import load_iris
import pandas as pd
iris = load_iris()
data = pd.DataFrame(iris['data'], columns=iris['feature_names'])
label = pd.DataFrame(iris['target'], columns=['label'])
df = pd.concat([data,label],axis=1)
print(df.head())
2.如何使用K-means算法对数据集进行聚类分析,其中K=3?
使用sklearn库中的KMeans函数进行聚类分析。将数据集分为3类时,设置n_clusters=3。
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=3)
kmeans.fit(data)
predict = kmeans.predict(data)
df['predict'] = predict
print(df.head())
3.如何使用Matplotlib展示聚类结果?可视化时不同类别需要用不同颜色表示,并标注三个聚类中心。
使用Matplotlib的scatter函数绘制散点图。使用不同颜色显示不同的聚类标签及聚类中心。
import matplotlib.pyplot as plt
plt.scatter(df.iloc[:, 0], df.iloc[:, 1], c=df['predict'])
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=100, marker='*', c='red', label='Centers')
plt.legend()
plt.show()
4.如何检验聚类结果准确性,如何计算聚类的正确率?
由于IRIS数据集存在真实标签,可以使用ARI指标来评估聚类结果准确性。利用sklearn库中的metrics包中的adjusted_rand_score函数计算ARI指标。
from sklearn import metrics
ARI = metrics.adjusted_rand_score(label['label'], predict)
print("ARI: ", ARI)
以下回答参考GPT并且由妙妙大帅整理:
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 导入IRIS数据集
iris = load_iris()
X = iris.data[:, :2] # 取前两个特征
y = iris.target
# 使用K-means算法进行聚类,K=3
kmeans = KMeans(n_clusters=3, random_state=0).fit(X)
# 绘制结果的可视化图像
plt.scatter(X[:, 0], X[:, 1], c=kmeans.labels_)
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], marker='*', s=200, c='#050505')
plt.title('K-means Clustering')
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.show()
# 计算聚类的正确率
correct = 0
for i in range(len(y)):
if kmeans.labels_[i] == y[i]:
correct += 1
accuracy = correct / len(y)
print('Clustering accuracy: {:.2f}%'.format(accuracy*100))