KNN算法实现约会对象分类
import numpy as np
import matplotlib.pyplot as plt
import day1.KNN.封装KNN函数 as K
#第一步,读取数据集,需要将数据分为特征矩阵和对应的分类标签向量
#定义一个函数:打开并解析文件,对数据进行分类,1代表不喜欢,2代表魅力一般,3代表极具魅力
#filename-文件名
#returnMat-特征矩阵
#classLabelVector 分类标签向量
def file2matrix(filename):
fr=open(filename)
numberOfLines=len(fr.readlines()) #获取数据一共有多少行
returnMat=np.zeros((numberOfLines,3)) #创建一个1000行,3列的矩阵 具体看百度
classLabelVector=[] #创建标签向量
fr=open(filename)
index=0 #定位到第0行,开始for循环
for line in fr.readlines(): #for循环,读取所有行
line=line.strip() #清理空格,头尾对齐
listFromLine=line.split('\t') #根据指定的字符(空格)将数据进行切分
returnMat[index,:]=listFromLine[0:3] #切出0、1、2列 左闭右开,从第0行开始
if listFromLine[-1]=='didntLike': #将输出结果分类成标签1、2、3
classLabelVector.append(1) #append() 向列表的尾部添加一个新的元素
elif listFromLine[-1]=='smallDoses':
classLabelVector.append(2)
elif listFromLine[-1]=='largeDoses':
classLabelVector.append(3)
index+=1
return returnMat,classLabelVector #返回数据矩阵和标签
#测试函数 检查数据内容
datingDataMat,datingLables=file2matrix(r'C:\Users\63096\Desktop\datingTestSet.txt')
print(datingLables)
#(2)分析数据
#plt.scatter(datingDataMat[:,0],datingDataMat[:,1],c=datingLables)# 先看看里程数和游戏时间的坐标图 c是颜色
#plt.scatter(datingDataMat[:,1],datingDataMat[:,2],c=datingLables)# 比较游戏时间和吃冰激凌的时间 c是颜色
plt.scatter(datingDataMat[:,0],datingDataMat[:,2],c=datingLables)# 比较里程数和吃冰激凌的时间 c是颜色
#plt.show()
plt.close()
#(3)数据归一化 0-1标准化,Z-score标准化 sigmoid压缩法等
def autoNorm(dataSet):
minVals=dataSet.min(0) #取列的最小值 这里的0代表的是列 然后构成一个1*n的向量
maxVals=dataSet.max(0) #取列的最大值
normDataSet=np.zeros(dataSet.shape) #.shape返回的是行和列的数量
normDataSet=(dataSet-minVals)/(maxVals-minVals) #使用0-1归一化
return normDataSet
print(datingDataMat)
print(datingLables)
dataSet=autoNorm(datingDataMat) #归一化后的数据集
print(dataSet)
#(4)测试KNN分类器模型
m=0.8 #训练集 测试集的比例
dataSize=dataSet.shape[0] #获得总行数
print('数据集总行数:',dataSize)
trainSize=int(m*dataSize)
testSize=int((1-m)*dataSize)
k=5
results=[]
error=0
for i in range(testSize):
results=K.knn(dataSet[trainSize+i,:],dataSet[0:trainSize,:] #第一个切的是测试集,第二个切的是训练集
,datingLables[0:trainSize],k)
if results!=datingLables[trainSize+i-1]: #比较的是结果与测试集的结果
error=error+1
print('错误率',error/trainSize)
KNN封装函数
#inX-未知样本 测试集
#dataSet 训练集
#labels 训练集分类标签向量
#k 选择距离最小的k个点
def knn(inX,dataSet,labels,k):
dist=(((dataSet-inX)**2).sum(1))**0.5
sortedDist=dist.argsort()
classCount={}
for i in range(k):
voteLabel=labels[sortedDist[i]]
classCount[voteLabel]=classCount.get(voteLabel,0)+1
maxType=0
maxCount=-1
for key,value in classCount.items():
if value>maxCount:
maxType=key
maxCount=value
return maxType