使用k-近邻算法改进约会网站的配对效果
一、 准备数据:从文本中解析
1.数据:datingTestSet2.txt :一个数据一行,共1000行
三种特征:飞行里程数 视频游戏耗时 冰淇淋数
2.函数:file2matrix(filename):
使用:datingDataMat, datingLabels = file2matrix(‘datingTestSet2.txt’)
用于处理文本格式文件的函数,将文本格式的数据变为可用于输入模型的数据
如果不是都放在KNN.py里面或者是在命令提示符里面使用用KNN.file2matrix()
# 文本转矩阵
def file2matrix(filename):
fr = open(filename) # 打开文件
arrayOLines = fr.readlines() # readlines()自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for... in ... 结构进行处理
# readline()每次只读取一行
numberOfLines = len(arrayOLines) # 得到文件行数
returnMat = zeros((numberOfLines,3)) # 创建返回的numpy矩阵 3是三个属性 里程数 百分比和冰淇淋公升数
classLabelVector = [] # 创建标签向量 类型为列表
fr = open(filename) # 没写这行就一直报could not convert string to float的错囧 也不知道为啥
index = 0
for line in arrayOLines: # 从文件所得的行列表的第一行开始
line = line.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
listFromLine = line.split('\t') # split()通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串 split(str=" ", num = 2)
# \t 水平制表(HT) (跳到下一个TAB位置)
returnMat[index,:] = listFromLine[0:3] # 选取前三个元素,存储在特征矩阵的第i行中
classLabelVector.append(int(listFromLine[-1])) # list[-1]取从最后一个元素往前第几个 -1就是取最后一个
# 此处最后一个味属性 所以将属性标签放到标签类别的vector里
index += 1 # 下一行的转换
return returnMat,classLabelVector
二、分析数据
三、准备数据:归一化数值
函数:autoNorm(dataSet)
#归一化数据处理
def autoNorm(dataSet):
minVals = dataSet.min(0) # 得到每一列的最小值 min() 参数为0表示从列中选最小值,1位从行中选最小值
maxVals = dataSet.max(0) # 得到每一列的最大值
ranges = maxVals - minVals # 得到每一列最大值-最小值的差
normDataSet = zeros(shape(dataSet)) # dataSet形状的全0矩阵
m = dataSet.shape[0] # shape[0]为行数
normDataSet = dataSet - tile(minVals,(m,1)) # tile(minVals,(m,1))得到一个每列都为min的和dataSet形状相同的矩阵 每个数都减去了最小值
normDataSet = normDataSet / tile(ranges,(m,1)) # 每个数都除以ranges
return normDataSet,ranges,minVals
四、测试算法
函数:datingClassTest()
def datingClassTest():
hoRatio = 0.10 # 使用真实数据的多大部分来作为测试集
datingDataMat,datingLables = file2matrix('datingTestSet2.txt') # 将datingTestSet2.txt中的内容转化为数据矩阵和标签矩阵
normMat,ranges,minVals = autoNorm(datingDataMat) # 对数据进行归一化
m = normMat.shape[0] # m为数据矩阵的行数 即有多少个数据
numTestVecs = int(m*hoRatio) # 测试集数量为 数据总数* 百分比
errorCount = 0.0 # 初始错误个数为0
for i in range(numTestVecs): # 对1 - 测试个数 的每一个样本
# 输入归一化数据的第i行,输出,标签向量,k
# 用于分类的输入向量(未知样本)——normMat[i,:] dataSet——normMat[numTestVecs:m,:] normMat中从numTestVecs到m行的所有列
# lables——datingLables[numTestVecs:m] k——3
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLables[numTestVecs:m],3)
print("the classifier came back with:%d, the real anser is: %d" % (classifierResult,datingLables[i]))
if (classifierResult!=datingLables[i]):
errorCount += 1
print("the total error rate is : %f" % (errorCount/float(numTestVecs)))
五、使用算法
函数:classifyPerson()
def classifyPerson():
resultList = ['not at all','in small doses','in large doses']
percentTats = float(input("percentage of time spent playing video games?\n")) # python3中将 raw_input() 重命名为 input()
ffmiles = float(input("frequent flier miles earned per year?\n"))
iceCream = float(input("liters of ice cream consumed per year\n")) # 得到三个属性的输入
datingDataMat,datingLabels = file2matrix("datingTestSet2.txt") # 将文本数据转化为数据矩阵
normMat, ranges, minVals = autoNorm(datingDataMat) # 对数据进行归一化处理
inArr = array([ffmiles,percentTats,iceCream]) # 将输入转化为列表 以便输入到分类算法中
classifierResult = classify0((inArr-minVals)/ranges,normMat,datingLabels,3) # 将输入也进行归一化 进行输入
print("you will probably like this person:",resultList[classifierResult - 1]) # 训练集中喜欢不喜欢的分类是1 2 3 但是在结果标签中下标为0 1 2 因此要-1