前篇:K-近邻算法开篇之电影
数据下载链接:https://pan.baidu.com/s/1qDPBH_E2lnq-_gWjTH4xSA
提取码:0vsp
Hellen经常使用约会网站寻找猎物用于解决自己的终身大事。时光流逝,Hellen还是single dog。她遇见了很多人,有好有坏,Hellen将约会网站上的人分为三类:不喜欢的人,魅力一般的人和极具魅力的人。为了以后的约会能尽可能与极具魅力的人在一起,Hellen需要对约会对象进行分类。
Hellen收集了一堆数据,每个样本包含三个特征:每年获得的飞行常客里程数,玩视频游戏所耗时间百分比和每周消费的冰淇淋公升数。
部分数据如下所示:

数据的录入
import numpy as np
def load_data(filename):
with open(filename) as file:
lines = file.readlines()
dataSize = len(lines)
dataSet = np.zeros((dataSize,3))
labels = []
index = 0
for line in lines:
line = line.strip()
items = line.split("\t")
dataSet[index,:] = items[0:3]
labels.append(int(items[-1]))
index+=1
return dataSet,labels
data,labels = load_data("datingTestSet.txt")
print(data[:5,:])
print(labels[:5])

数据的展示
数据中总共有三个特征值,进行两两配对画图。
import matplotlib.lines as mlines
def draw_image(data,labels):
fig, axs = plt.subplots(nrows=2, ncols=2, sharex=False, sharey=False, figsize=(13, 8))
LabelsColors = []
for i in labels:
if i == 1:
LabelsColors.append('black')
if i == 2:
LabelsColors.append('green')
if i == 3:
LabelsColors.append('red')
axs[0][0].scatter(x=data[:, 0], y=data[:, 1], color=LabelsColors, s=15, alpha=.5)
axs[0][1].scatter(x=data[:, 0], y=data[:, 2], color=LabelsColors, s=15, alpha=.5)
axs[1][0].scatter(x=data[:, 1], y=data[:, 2], color=LabelsColors, s=15, alpha=.5)
didntLike = mlines.Line2D([], [], color='black', marker='.', markersize=6, label='didntLike')
smallDoses = mlines.Line2D([], [], color='green', marker='.', markersize=6, label='smallDoses')
largeDoses = mlines.Line2D([], [], color='red', marker='.', markersize=6, label='largeDoses')
axs[0][0].legend(handles=[didntLike, smallDoses, largeDoses])
axs[0][1].legend(handles=[didntLike, smallDoses, largeDoses])
axs[1][0].legend(handles=[didntLike, smallDoses, largeDoses])
plt.savefig("data.png")
plt.show()

数据处理
观察数据我们会发现飞行常客里程数远大于另外两个特征值,并且飞行常客里程数往往相差比较大,这意味着在计算距离时这一特征的差值特别大,从而会严重影响预测结果。Hellen任务这三个特征的权重是一样的,所以我们需要对数据进行归一化操作。我们可以使用公式:newValue=maxminoldValuemin 实现归一化操作。
max:对应特征特征值的最大值;
min:对应特征特征值的最小值。
def norm(data):
minvalues = data.min(axis=0)
maxvalues = data.max(axis=0)
rangevalues = maxvalues - minvalues
normData = np.zeros(data.shape)
dataSize = data.shape[0]
normData = data - np.tile(minvalues,(dataSize,1))
normData = normData / np.tile(rangevalues,(dataSize,1))
return normData,rangevalues,minvalues

初步实现,计算错误率
KNN实现的方法请查看前篇:K-近邻算法开篇之电影
选择100条数据用于做测试集,计算KNN算法对好感度预测的错误率如何。
if __name__ == '__main__':
k=3
errorCount=0.0
rate = 0.1
data,labels = load_data("datingTestSet.txt")
normdata = norm(data)
allNum = normdata.shape[0]
testNum = int(rate*allNum)
for i in range(testNum):
result = classify(normdata[i,:],normdata[testNum:allNum,:],labels[testNum:allNum],k)
print('第{}条数据,预测为:{}==>实际为:{}'.format(i+1,result,labels[i]))
if result != labels[i]:
errorCount+=1.0
print('错误率为:',errorCount/testNum)

错误率为5%,预测的效果还不错。现在我们可以手动输入测试集,使用这个算法来进行预测了。
完成,形成可用系统
def main(case):
k = 3
data, labels = load_data("datingTestSet.txt")
normdata,rangevalues,minvalues = norm(data)
result = classify((case-minvalues)/rangevalues, normdata, labels, k)
return result
if __name__ == '__main__':
resultLabel = ['不喜欢','魅力一般','极具魅力']
meters = float(input("请输入飞行常客里程数:"))
gamerate = float(input("玩游戏所占实际比:"))
icecream = float(input("每周冰淇淋消费数:"))
input_case = np.array([meters,gamerate,icecream])
result = main(input_case)
print("预测结果为:",resultLabel[result-1])

|