1、使用python导入数据
from numpy import * def createDataSet(): group=array([[1.1,1.1],[1.0,1.0],[0,0],[0,0.1]]) labels=['A','A','B','B'] return group,labels
kNN分类算法:
from numpy import * import operator def classify0(inX,dataSet,labels,k): dataSetSize=dataSet.shape[0] #shape[0]表示dataSet的行数 diffMat=tile(inX,(dataSetSize,1))-dataSet sqDiffMat=diffMat**2 sqDistances=sqDiffMat.sum(axis=1) distances=sqDistances**0.5 sortedDistIndicies=distances.argsort() classCount={} for i in range(k): voteIlabel=labels[sortedDistIndicies[i]] classCount[voteIlabel]=classCount.get(voteIlabel,0)+1 sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) return sortedClassCount[0][0]
distances是1*4的矩阵,分别表示待分类的点与所有已知点的距离;
sortedDistIndicies是distances从小到大的索引值;
voteIlabel相当于临时变量,用来取得标签值;
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1 如果在字典classCount中找到key=voteIlabel的value,就加1,找不到的话classCount.get(voteIlabel,0)返回0然后加1
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) 先把字典classCount变成列表,再按照第二维降序排列,返回的仍是列表
执行算法:
import kNN from classify_kNN import * g,l=kNN.createDataSet() result=classify0([0,0],g,l,3) print(result)
输出:
B
items():将字典中的项按照列表返回,无序:
get():返回字典对应key的value值,不存在key时返回第二个参数:
dic={'a':1,'b':2,'c':3}
print(dic.items())
print(dic.get('c','no'))
输出:
dict_items([('b', 2), ('c', 3), ('a', 1)])
3
shape:返回矩阵的维数;
from numpy import * c=array([[1,1],[2,3,],[5,6]]) print(c) print(c.shape) print(c.shape[0]) print(c.shape[1]) 输出: [[1 1] [2 3] [5 6]] (3, 2) 3 2
operator.itemgetter():返回对象特定维的数据,结合sorted()方法使用:
import operator students=[['刚田武',20,'gangtw'],['朱二娃',25,'zhuerw'],['咪咪two',30,'miomitwo']] print(sorted(students,key=operator.itemgetter(1),reverse=True)) 输出: [['咪咪two', 30, 'miomitwo'], ['朱二娃', 25, 'zhuerw'], ['刚田武', 20, 'gangtw']]
argsort():返回数组值从小到大的索引值
归一化数值:在计算欧氏距离的过程中,数值较大的属性对结果的贡献大,如果认为不同属性权重应该相同的话,就需要将数值归一化处理。
from numpy import *
def autoNorm(dataset):
minVals=dataset.min(0) #取每列的最小值,返回数组
print(minVals)
maxVals=dataset.max(0)
print(maxVals)
ranges=maxVals-minVals #ranges是每列的最大值与最小值之差组成的数组
print(ranges)
normDataset=zeros(shape(dataset))
print(normDataset)
m=dataset.shape[0] #取dataset的行数
normDataset=dataset-tile(minVals,(m,1))
print(normDataset)
normDataset=normDataset/tile(ranges,(m,1))
print(ranges)
return normDataset
minVals=dataset.min(0) #取数据集每列的最小值,返回数组
from numpy import *
dataset=array(([6,5],
[3,1000],
[10,300]))
print(dataset.min()) #返回所有元素中的最小值
print(dataset.min(0)) #返回每列的最小值组成的数组
print(dataset.min(1)) #返回每行的最小值组成的数组
输出:
3
[3 5]
[ 5 3 10]
m=dataset.shape[0] #取dataset的行数
from numpy import *
dataset=array(([6,5],
[3,1000],
[10,300]))
print(dataset.shape) #返回数据集的“形状”,行数和列数
print(dataset.shape[0]) #返回行数
print(dataset.shape[1]) #返回列数
输出:
(3, 2)
3
2
测试分类器:
def datingClassTest():
hoRatio=0.1
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
normMat,ranges,minVals=autoNorm(datingDataMat)
m=normMat.shape[0]
numTestVecs=int(m*hoRatio)
errorCount=0
for i in range(numTestVecs):
classifyerResult=classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print('classify result is %s ,the real answer is %s'%(classifyerResult,datingLabels[i]))
if classifyerResult!=datingLabels[i]:
errorCount+=1
print('the total error rate is %f'%(errorCount/float(numTestVecs)))
hoRatio=0.1 测试数据占数据集的10%
使用:输入各参数,输出分类结果:
def classifyPerson():
resultList=['not at all','in small doses','in largr doses']
timeOnGames=float(input('请输入游戏时间百分比:'))
flyMiles=float(input('请输入每年飞行里程数:'))
iceCream=float(input('请输入每周消耗的冰淇淋升数:'))
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
normMat,ranges,minVals=autoNorm(datingDataMat)
person2test=array([flyMiles,timeOnGames,iceCream])
classifierResult=classify0((person2test-minVals)/ranges,normMat,datingLabels,5)
print('you may like thie one:',resultList[classifierResult-1])
通过调节k值可以调整分类器的正确率。
使用k近邻算法识别手写数字:
def handwritingClassTest():
hwLabels=[]
trainingFileList=listdir('digits/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('digits/trainingDigits/%s'%fileNameStr)
testFileList=listdir('digits/testDigits')
errorCount=0
mTest=len(testFileList)
for i in range(mTest):
fileNameStr=testFileList[i]
fileStr=fileNameStr.split('.')[0]
classNumStr=int(fileStr.split('_')[0])
vectorUnderTest=img2vector('digits/testDigits/%s'%fileNameStr)
classifierResult=classify0(vectorUnderTest,trainingMat,hwLabels,3)
#print('分类结果:%s,实际结果:%s'%(classifierResult,classNumStr))
if(classifierResult!=classNumStr):
errorCount+=1
print('分类错误总计:',errorCount)
print('分类错误率:',errorCount/float(mTest))
注释:
trainingMat用来存储数据集,每个待测记录都要计算与此数据集之间的距离
hwLabels用来存储trainingMat对应的标签
fileNameStr存储文件名
fileStr存储不含后缀的文件名
classNumStr存储每条记录实际标签
vectorUnderTest表示待分类记录
计算分类错误率时,使用float()将int型数据变成浮点型