1.算法概述(略)
2.从文件中解析数据
伪代码如下:
对未知类别属性的数据集中的每个点依次执行以下操作
(1)计算已知类别数据集中的点与当前点之间的距离;
(2)按照距离递增次序排序;
(3)选取与当前点距离最小的k个点;
(4)确定前K个点所在类别出现的频率;
(5)返回前k个点出现频率最高的类别作为当前点的预测分类。
def knn(inx,dataset,labels,k):#inx输入向量,dataset输入的训练样本集,labels标签向量,k为最近邻数
#距离计算
dataset_size = dataset.shape[0]
diffmat = tile(inx,(dataset.size,1))-dataset
sqdiffmat = dffmat**2
sqdistances = sqdiffmat.sum(axis=1)
distances = sqdistances**0.5
sorted_distances = distances.argsort()
class_count = {}
for i in range(k):
vote_label = labels[sorted_distances[i]]
#选择距离最小的k个点
calss_count[vote_label] = class_count.get(vote_label,0)+1
#排序
sorted_class_count = sorted(class_count.items(),key = operator.itemgetter(1),reverse = True)
return sorted_class_count[0][0]
#距离公式为欧氏距离
3.实例:使用K近邻算法改进约会网站配对效果
过程
(1)收集数据:提供文本文件
(2)准备数据:使用python解析文本文件
(3)分析数据:使用matplotlib画二维扩散图
(4)训练算法:此步骤不适用于KNN
(5)测试算法:测试样本是已经完成分类的数据,如果预测与实际类别不同,则标记为一个错误
(6)使用算法:产生简单的命令行程序,然后输入一些特征数据来判断对方的类型
代码如下:
def file2matrix(filename):
fr = open(filename)
array_lines = fr.readlines()
lines_num = len(array_lines)#得到文件行数
mat = zeros((lines_num,3))#创建以零填充的矩阵,为了简化处理,将矩阵的另一维度设置为固定值3
class_label = []
index = 0
for line in array_lines:
line = line.strip()#截取掉所有的回车字符
line_list = line.split('\t')#将上一步得到的整行数据分割成一个元素列表
mat[index,:] = line_list[0:3]#选取前3个元素,将他们存储到特征矩阵中。
class_label.append(int(line_list[-1]))#将列表的最后一列存储到向量class_label,列表中存储的元素值为整型,否则会将这些元素作为字符串处理
index +=1
return mat,class_label
import numpy as np # 科学计算包Numpy
import operator # 运算符模块
import os
import matplotlib as mpl
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
datingdatamat,datinglabels = file2matrix('datingTestSet.txt')
ax.scatter(datingdatamat[:,1],datingdatamat[:,2])
plt.show()
ax.scatter(datingdatamat[:.1],datingdatamat[:,2],15.0*array(datinglabels),15.0*array(datinglabels))
#归一化
def norm(dataset):
minvals = dataset.min(0)
maxvals = dataset.max(0)
ranges = maxvals - minvals
norm_dataset = zeros(shape(dataset))
m = dataset.shape[0]
norm_dataset = dataset-tile(minvals,(m,1))
norm_dataset = normdataset/tile(ranges,(m,1))
return norm_dataset,ranges,minvals
#将最小值放在minvals中,最大值放在maxvals,函数计算取值范围,创建新的返回矩阵,
#(当前值-最小值)/取值范围。需要注意的是,特征值矩阵1000*3,而minvals,ranges都是1*3,
#因此使用tile()函数将变量内容复制成输入矩阵同样大小的矩阵。
def datingClassTest():
hoRatio = 0.10 # 测试集比例
datingDataMat, datingLabels = file2matrix('datas/datingTestSet.txt') # 读取数据
normMat = norma(datingDataMat) # 归一化处理
m = normMat.shape[0] # 样本数目
numTestVecs = int(m * hoRatio) # 用于测试的数据
errorCount = 0
for i in range(numTestVecs):
# normMat[i, :]待分类的输入数据,normMat[numTestVecs:m, :]训练数据,datingLabels[numTestVecs:m]标签数据,k=3
classifierResult = knn(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3) # 分类函数
print("预测结果为 : %d, 真实值为 : %d" % (classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]):
errorCount += 1
print("错误率为 : %f" % (errorCount / float(numTestVecs)))
# 针对新数据的预测
def classifyPerson():
resultList = ['不喜欢的人', '魅力一般的人', '极具魅力的人']
percentTats = float(input("玩视频游戏所耗时间百分比:"))
ffMiles = float(input("每年获得的飞行常客里程数:"))
iceCream = float(input("每年消费冰淇淋公升数:"))
datingDataMat, datingLabels = file2matrix("datas/datingTestSet.txt")
normMat, ranges, minVals = normal(datingDataMat)
inArr = np.array([ffMiles, percentTats, iceCream])
classifierResult = knn((inArr - minVals) / ranges, normMat, datingLabels, 3)
print("你对这个人的印象是:", resultList[classifierResult - 1])
# 测试
classifyPerson()