K邻近算法
由于《机器学习实战》中用的是python2+,而我用的是python3+,所以在学习中产生了很多bug
又因为对各种函数不是太了解,每个都要具体查,很麻烦。
这里对每个函数都做了大致的注释,Bug也都改了。
拿来直接运行
话不多说,直接上代码,注释肯不好(望谅解)
KNN.py文件
from numpy import *
import operator
#功能****
##读取文件获得训练样本和标签##
def readfile(filename):
#1读取文件,此时文件指针指向文件尾部
#2获得样本数目/维度 以便建立矩阵
#3建立样本数目*3的零矩阵 和 标签向量组
#4重定向文件指针指向文件头
#5循环遍历文件每行并储存到矩阵中
fr=open(filename)
train_num=len(fr.readlines())
returnMat=zeros((train_num,3))
class_label=[]
fr=open(filename)
index=0
for line in fr.readlines():
line=line.strip()
line_list=line.split('\t')
returnMat[index,:]=line_list[0:3]
class_label.append(int(line_list[-1]))
index+=1
return returnMat,class_label
#功能****
#输入样本,训练样本,样本标签,选取最邻近值个数
#输出标签
def classify(train_object,train_example,train_labels,k):
#1先求出训练样本的维度
#2再建立一个特征值数量行*1列的 矩阵保存输入样本
#3把该样本与训练样本相减并平方,并用sum(axis=1)使行向量相加,再^1/2
#如下公式根号下((x-y)^2)
#4对求差后的向量进行排序,从小到大,以标签的所在列形式显示argsort()
#5申明一个分类字典
#6循环前k个距离差值,确定各个标签出现的频率
#7使用get匹配,如果匹配且出现过则+1
#9返回匹配率最高的一个
train_dem=train_example.shape[0]
diff_mat=tile(train_object,(train_dem,1))
diff_mat=(diff_mat-train_example)**2
distance=diff_mat.sum(axis=1)**0.5
dist_values=distance.argsort()
label_class={}
for i in range(k):
votelabel=labels[dist_values[i]]
label_class[votelabel]=label_class.get(votelabel,0)+1
sortedClassCount=sorted(label_class.items(),
key=operator.itemgetter(1),
reverse=True)
return sortedClassCount[0][0]
#功能***
#约会测试
def classifyPerson():
#定义返回值列表
#定义输入样本
#用readfile读取文件,返回训练样本和标签
#归一化训练样本
#归一化输入样本*****输入样本-训练样本最小值)/训练样本范围
#分类classify(归一化输入样本,训练样本,训练标签,k值)
resultList=['一点也不喜欢','喜欢一点点','非常喜欢']
percentTats=float(input("花费在游戏上的百分比"))
ffMiles=float(input("每年的飞行里程数"))
iceCream=float(input("每年吃的冰淇淋公升数"))
datingDataMat,dataingLabels=readfile('datingTestSet2.txt')
normMat,ranges,minVals=autoNorm(datingDataMat)
inArr=array([ffMiles,percentTats,iceCream])
classifierResult=classify((inArr-minVals)/ranges
,normMat,dataingLabels,3)
print("你可能:",resultList[classifierResult-1])
#功能****
#归一化特征值
#newVlaue=(oldValue-min)/(max-min)
#返回归一化矩阵,矩阵差值,矩阵每列最小值
def autoNorm(dataSet):
#1获得每列最小值
#2获得每列的范围
#3建立一个数据集大小的零矩阵
#4获取样本个数
#5数据集减去每列最小的值(求出差)并保存到归一化矩阵
#6归一化矩阵每个元素除以范围 得出真.归一化矩阵
minVals=dataSet.min(0)
maxVals=dataSet.max(0)
ranges=maxVals-minVals
normDataSet=zeros(shape(dataSet))
m=dataSet.shape[0]
normDataSet=dataSet-tile(minVals,(m,1))
normDataSet=normDataSet/tile(ranges,(m,1))
return normDataSet,ranges,minVals
#功能******
#把图片变成一组样本
#把32*32变成1*1024
def img2vector(filename):
returnVect=zeros((1,1024))
fr=open(filename)
for i in range(32):
lineStr=fr.readline()
for j in range(32):
returnVect[0,32*i+j]=int(lineStr[j])
return returnVect
#功能******
#正确率测试
def datingClassTest():
#定义挑选数据 这里定义挑选10%的数据
#1readfile读取文件返回训练样本和训练标签
#2归一化训练样本
#3shape[0]取得样本数目后*0.1 定义挑选的数据量
#4for遍历数据量
#5取得测试数据与真实数据对比
#6输出错误率
hoRatio = 0.10
datingDataMat,datingLabels =readfile('datingTestSet2.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify(normMat[i,:],
normMat[numTestVecs:m,:],
datingLabels[numTestVecs:m],3)
print("the classifier came back with:\
%d, the real answer is: %d"%(classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]):
errorCount += 1.0
print("the total error rate is:%f"%(errorCount/float(numTestVecs)))
print(errorCount)
#功能*****
#手写识别
def handwritingClassTest():
#定义样本标签
#1读取文件夹内文件列表,并获取列表长度m(文件个数)
#2声明一个m*1024的训练样本的0矩阵
#3遍历样本
#4{从文件名上分离出样本标签,并添加到样本标签列表中
#5加载处理后1*1024的单个训练样本}
#6读入输入样本文件夹内文件列表
#7对每个输入样本做如下处理
#8{取出输入样本标签值
#9对每个输入样本classify后对比正确数
#10输出错误率
hwLabels=[]
trainingFileList=listdir('trainingDigits')
m=len(trainingFileList)
trainingMat=zeros((m,1024))
for i in range(m):
fileNameStr=trainingFileList[i]
fileStr=fileNameStr.split('.')[0]
classNumStr=int(fileStr.split('_')[0])
hwLabels.append(classNumStr)
trainingMat[i,:]=img2vector('trainingDigits/%s'
%fileNameStr)
testFileList=listdir('testDigits')
errorCount=0.0
mTest=len(testFileList)
for i in range(mTest):
fileNameStr=testFileList[i]
fileStr=fileNameStr.split('.')[0]
classNumStr=int(fileStr.split('_')[0])
vectorUnderTest=img2vector('trainingDigits/%s'
%fileNameStr)
classifierResult=classify(vectorUnderTest,trainingMat,
hwLabels,3)
print("the classifier came back with:%d,\
the real answer is:%d"%(classifierResult,
classNumStr))
if(classifierResult!=classNumStr):
errorCount+=1.0
print("\n错误总数是:%d"%errorCount)
print("\n错误率是:%f"%(errorCount/float(mTest)))