#coding=utf-8
from os import listdir
import operator
def createDataSet():
#创建数据集
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels=['A','A','B','B']
return group,labels
def classify(inX,dataSet,labels,k):
"""
@author:liyafei
@parameter:inX,待测数据,k选择的k个点个数
分类
"""
dataSetSize=dataSet.shape[0] #计算多少组数据,4
diffMat=tile(inX,(dataSetSize,1))-dataSet
"""
diffMat=将inX 重复写 dataSetSize行1列 ,然后与dataSet相减
[[ 0. -0.1]
[ 0. 0. ]
[ 1. 1. ]
[ 1. 0.9]]
"""
sqDiffMat=diffMat**2 #数组平方,全部转化为正
"""
sqDiffMat=
[[ 0. 0.01]
[ 0. 0. ]
[ 1. 1. ]
[ 1. 0.81]]
"""
sqDistances=sqDiffMat.sum(axis=1)
#sqDistances=[ 0.01 0. 2. 1.81],sqdistances每行平方相加
distances=sqDistances**0.5 #开方
sortedDistIndicies=distances.argsort() #对距离进行排序
#sortedDistIndicies=[1 0 3 2] #给每个距离相对应大小的角标,第3个元素最大
print(sortedDistIndicies)
#sortedDistIndicies=sorted(sortedDistIndicies) #这个语句不能用,因为用了之后,总是选择标签前面几个固定值,类别判定总是相同。
print(sortedDistIndicies)
classCount={}
for i in range(k): #选取k个近邻点,kNN
voteIlabel=labels[sortedDistIndicies[i]]
print(voteIlabel)
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
print(classCount)# {'B': 1, 'A': 2}
sortedClassCount=sorted(classCount.items(),
key=operator.itemgetter(1),reverse=True)
#按值进行排序。
"""
>>> d['a']=3
>>> d['b']=5
>>> sortedClassCount=sorted(d.items(),
key=operator.itemgetter(1),reverse=True)
>>> sortedClassCount
[('b', 5), ('a', 3)]
>>> sortedClassCount[0][0]
'b'
>>>
"""
print(sortedClassCount[0][0])
return sortedClassCount[0][0]
#返回最大值对应的键,也就是类别
group,labels=createDataSet()
x=classify([1,1],group,labels,3)
def file2matrix(filename):
#将文件数据转化为矩阵
fr=open(filename)
arrayOLines=fr.readlines()
numberOfLines=len(arrayOLines) #获取文件行数
returnMat=zeros((numberOfLines,3))#创建行为numberOfLines,列为3的0矩阵
classLabelVector=[] #创建一个类标签向量空列表
index=0 #角标为0
for line in arrayOLines:
#遍历文件中所有的行
line=line.strip()
# print(line) #3 2 5 0 字符串类型。
listFromLine=line.split('\t') #以\t进行分割每行数据。
#print(listFromLine,'he') #['3', '2', '5', '0'] 转换前
listFromLineToList=[]
for i in range(len(listFromLine)):
#listFromLineToList.append(int(listFromLine[i])) #文本数据中的一行数据是字符串,将其转换为int放入到list中
listFromLineToList.append((listFromLine[i]))
# print(listFromLineToList,'change') #[3, 2, 5, 0] 转换后
returnMat[index,:]=listFromLineToList[0:3] #复制每行数据到returnMat矩阵中
classLabelVector.append(int(listFromLine[-1]))#将每行数据的最后一个类别属性放入到类标签向量中
index+=1
return returnMat,classLabelVector #返回文件对应的属性矩阵和类别标签向量。
#filename="d:point.txt"
def autoNorm(dataSet):
"""
归一化处理,将任意特征的特征值转化为0到1区间内的值.
数学公式:
newValue=(oldValue-min)/(max-min)
"""
print(dataSet)
print(type(dataSet))
minVals=dataSet.min(0)
maxVals=dataSet.max(0)
ranges=maxVals-minVals
normDataSet=zeros(shape(dataSet)) #创建一个与dataSet形状一样的0矩阵
m=dataSet.shape[0] #计算dataSet中的元素个数
normDataSet=dataSet-tile(minVals,(m,1)) #将每列的minVals组成的向量,重复写m行1列,(oldValue-min)
normDataSet=normDataSet/tile(ranges,(m,1))#(oldValue-min)/(max-min)
return normDataSet,ranges,minVals
"""
d:point.txt中的数据
3 2 5 0
7 5 3 1
2 3 6 0
3 4 6 1
9 8 5 1
"""
"""
mat,lab=file2matrix(filename)
import matplotlib
import matplotlib.pyplot as plt
fig=plt.figure() #创建一个图片fig
ax=fig.add_subplot(111) #将大图分割成1*1的图片,选取第一个
ax.scatter(mat[:,1],mat[:,2]) #选取mat的角标为1,2的列,画图。
ax.scatter(mat[:,1],mat[:,2],15.0*array(lab),15.0*array(lab)) #用彩色或其它的记号不同的类,
#plt.show()
"""
#print("归一化处理 autoNorm")
#normDataSet,ranges,minVals=autoNorm(mat)
#print(normDataSet,ranges,minVals)
def datingClassTest():
"""
测试分类器,根据测试集,将会计算分类器的错误率,
"""
hoRatio=0.10 #比例,测试数据所占的比例。
datingDataMat,datingLabels=file2matrix('d:point.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) #分类,用k近邻方法进行分类。训练集为除测试集之外的数据,normMat[numTestVecs:m,:]
print("the classifier came back with : %d,the real real answer is : %d" %(classifierResult,datingLabels[i]))
if (classifierResult != datingLabels[i]):
errorCount+=1.0 #计算错误个数
print("the total error rate is :%f"%(errorCount/float(numTestVecs))) #错误率。
#datingClassTest()
def classifyPerson():
"""
约会网站预测函数
"""
resultList=['not at all','in small doses','in large dases'] #结果集,相当于类别标签
percentTats=float(input("percentage of time spent playing video games?"))#输入花费在打电子游戏上面的时间百分比
#需用input,input需要输入一个合法的表达式。不能用raw_input.raw_input将所有输入作为字符串
ffMiles=float(input("frequent flier miles earned per year?")) #输入每年旅行公里
iceCream=float(input("liters of ice cream consumed per year?"))#每年在冰激凌上面花费的时间
datingDataMat,datingLabels=file2matrix('d:datingTestSet2.txt') #训练数据集
normMat,ranges,minVals=autoNorm(datingDataMat) #归一化
inArr=array([ffMiles,percentTats,iceCream]) #将要被预测的数据封装到一个数组里
classifierResult=classify((inArr-minVals)/ranges,normMat,datingLabels,3) #分类
print("you will probably like this person:",resultList[classifierResult-1]) #结果,类别标签中用1,2,3,现在转化为字符串
#classifyPerson()
def img2vector(filename):
returnVect=zeros((1,1024))
fr=open(filename) #打开文件,里面是32乘32的图像像素,0,1
for i in range(32):
lineStr=fr.readline() #读取一行,32个0,1.
for j in range(32):
returnVect[0,32*i+j]=int(lineStr[j]) #将读取到的像素存储到returnVect中
return returnVect
def hand():
hwLabels=[] #标签
trainingFileList=listdir('D:/test/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('D:/test/trainingDigits/%s'% fileNameStr) #将像素存放到矩阵中
testFileList=listdir('D:/test/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('D:/test/testDigits/%s'%fileNameStr) #转化为1*1024向量
classifierResult=classify(vectorUnderTest,trainingMat,hwLabels,3) #用kNN方法进行分类
print("the classifier came back with:%d,the real answer is :%d"%(classifierResult,classNumStr))
if(classifierResult!=classNumStr):
errorCount+=1.0
print("the total number of errors is :%d"%errorCount)
print(mTest)
print("the rate is %d" % float(errorCount/mTest))
hand()
"""
k-近邻算法
优点:精度高,对异常值不敏感,无数据输入假定。
缺点:计算复杂度高,空间复杂度高
适用数据范围:数值型和标称型
"""
from numpy import *from os import listdir
import operator
def createDataSet():
#创建数据集
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels=['A','A','B','B']
return group,labels
def classify(inX,dataSet,labels,k):
"""
@author:liyafei
@parameter:inX,待测数据,k选择的k个点个数
分类
"""
dataSetSize=dataSet.shape[0] #计算多少组数据,4
diffMat=tile(inX,(dataSetSize,1))-dataSet
"""
diffMat=将inX 重复写 dataSetSize行1列 ,然后与dataSet相减
[[ 0. -0.1]
[ 0. 0. ]
[ 1. 1. ]
[ 1. 0.9]]
"""
sqDiffMat=diffMat**2 #数组平方,全部转化为正
"""
sqDiffMat=
[[ 0. 0.01]
[ 0. 0. ]
[ 1. 1. ]
[ 1. 0.81]]
"""
sqDistances=sqDiffMat.sum(axis=1)
#sqDistances=[ 0.01 0. 2. 1.81],sqdistances每行平方相加
distances=sqDistances**0.5 #开方
sortedDistIndicies=distances.argsort() #对距离进行排序
#sortedDistIndicies=[1 0 3 2] #给每个距离相对应大小的角标,第3个元素最大
print(sortedDistIndicies)
#sortedDistIndicies=sorted(sortedDistIndicies) #这个语句不能用,因为用了之后,总是选择标签前面几个固定值,类别判定总是相同。
print(sortedDistIndicies)
classCount={}
for i in range(k): #选取k个近邻点,kNN
voteIlabel=labels[sortedDistIndicies[i]]
print(voteIlabel)
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
print(classCount)# {'B': 1, 'A': 2}
sortedClassCount=sorted(classCount.items(),
key=operator.itemgetter(1),reverse=True)
#按值进行排序。
"""
>>> d['a']=3
>>> d['b']=5
>>> sortedClassCount=sorted(d.items(),
key=operator.itemgetter(1),reverse=True)
>>> sortedClassCount
[('b', 5), ('a', 3)]
>>> sortedClassCount[0][0]
'b'
>>>
"""
print(sortedClassCount[0][0])
return sortedClassCount[0][0]
#返回最大值对应的键,也就是类别
group,labels=createDataSet()
x=classify([1,1],group,labels,3)
def file2matrix(filename):
#将文件数据转化为矩阵
fr=open(filename)
arrayOLines=fr.readlines()
numberOfLines=len(arrayOLines) #获取文件行数
returnMat=zeros((numberOfLines,3))#创建行为numberOfLines,列为3的0矩阵
classLabelVector=[] #创建一个类标签向量空列表
index=0 #角标为0
for line in arrayOLines:
#遍历文件中所有的行
line=line.strip()
# print(line) #3 2 5 0 字符串类型。
listFromLine=line.split('\t') #以\t进行分割每行数据。
#print(listFromLine,'he') #['3', '2', '5', '0'] 转换前
listFromLineToList=[]
for i in range(len(listFromLine)):
#listFromLineToList.append(int(listFromLine[i])) #文本数据中的一行数据是字符串,将其转换为int放入到list中
listFromLineToList.append((listFromLine[i]))
# print(listFromLineToList,'change') #[3, 2, 5, 0] 转换后
returnMat[index,:]=listFromLineToList[0:3] #复制每行数据到returnMat矩阵中
classLabelVector.append(int(listFromLine[-1]))#将每行数据的最后一个类别属性放入到类标签向量中
index+=1
return returnMat,classLabelVector #返回文件对应的属性矩阵和类别标签向量。
#filename="d:point.txt"
def autoNorm(dataSet):
"""
归一化处理,将任意特征的特征值转化为0到1区间内的值.
数学公式:
newValue=(oldValue-min)/(max-min)
"""
print(dataSet)
print(type(dataSet))
minVals=dataSet.min(0)
maxVals=dataSet.max(0)
ranges=maxVals-minVals
normDataSet=zeros(shape(dataSet)) #创建一个与dataSet形状一样的0矩阵
m=dataSet.shape[0] #计算dataSet中的元素个数
normDataSet=dataSet-tile(minVals,(m,1)) #将每列的minVals组成的向量,重复写m行1列,(oldValue-min)
normDataSet=normDataSet/tile(ranges,(m,1))#(oldValue-min)/(max-min)
return normDataSet,ranges,minVals
"""
d:point.txt中的数据
3 2 5 0
7 5 3 1
2 3 6 0
3 4 6 1
9 8 5 1
"""
"""
mat,lab=file2matrix(filename)
import matplotlib
import matplotlib.pyplot as plt
fig=plt.figure() #创建一个图片fig
ax=fig.add_subplot(111) #将大图分割成1*1的图片,选取第一个
ax.scatter(mat[:,1],mat[:,2]) #选取mat的角标为1,2的列,画图。
ax.scatter(mat[:,1],mat[:,2],15.0*array(lab),15.0*array(lab)) #用彩色或其它的记号不同的类,
#plt.show()
"""
#print("归一化处理 autoNorm")
#normDataSet,ranges,minVals=autoNorm(mat)
#print(normDataSet,ranges,minVals)
def datingClassTest():
"""
测试分类器,根据测试集,将会计算分类器的错误率,
"""
hoRatio=0.10 #比例,测试数据所占的比例。
datingDataMat,datingLabels=file2matrix('d:point.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) #分类,用k近邻方法进行分类。训练集为除测试集之外的数据,normMat[numTestVecs:m,:]
print("the classifier came back with : %d,the real real answer is : %d" %(classifierResult,datingLabels[i]))
if (classifierResult != datingLabels[i]):
errorCount+=1.0 #计算错误个数
print("the total error rate is :%f"%(errorCount/float(numTestVecs))) #错误率。
#datingClassTest()
def classifyPerson():
"""
约会网站预测函数
"""
resultList=['not at all','in small doses','in large dases'] #结果集,相当于类别标签
percentTats=float(input("percentage of time spent playing video games?"))#输入花费在打电子游戏上面的时间百分比
#需用input,input需要输入一个合法的表达式。不能用raw_input.raw_input将所有输入作为字符串
ffMiles=float(input("frequent flier miles earned per year?")) #输入每年旅行公里
iceCream=float(input("liters of ice cream consumed per year?"))#每年在冰激凌上面花费的时间
datingDataMat,datingLabels=file2matrix('d:datingTestSet2.txt') #训练数据集
normMat,ranges,minVals=autoNorm(datingDataMat) #归一化
inArr=array([ffMiles,percentTats,iceCream]) #将要被预测的数据封装到一个数组里
classifierResult=classify((inArr-minVals)/ranges,normMat,datingLabels,3) #分类
print("you will probably like this person:",resultList[classifierResult-1]) #结果,类别标签中用1,2,3,现在转化为字符串
#classifyPerson()
def img2vector(filename):
returnVect=zeros((1,1024))
fr=open(filename) #打开文件,里面是32乘32的图像像素,0,1
for i in range(32):
lineStr=fr.readline() #读取一行,32个0,1.
for j in range(32):
returnVect[0,32*i+j]=int(lineStr[j]) #将读取到的像素存储到returnVect中
return returnVect
def hand():
hwLabels=[] #标签
trainingFileList=listdir('D:/test/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('D:/test/trainingDigits/%s'% fileNameStr) #将像素存放到矩阵中
testFileList=listdir('D:/test/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('D:/test/testDigits/%s'%fileNameStr) #转化为1*1024向量
classifierResult=classify(vectorUnderTest,trainingMat,hwLabels,3) #用kNN方法进行分类
print("the classifier came back with:%d,the real answer is :%d"%(classifierResult,classNumStr))
if(classifierResult!=classNumStr):
errorCount+=1.0
print("the total number of errors is :%d"%errorCount)
print(mTest)
print("the rate is %d" % float(errorCount/mTest))
hand()