学后面几张的时候卡住了,然后突然想回头再自己写一遍课后习题,毕竟第一遍有点对着书敲的意味。果不其然,自己回头重写总会有的地方有问题。
第二章是用的KNN算法,优点是精度高(结果看来的确很高),对异常值不敏感(我觉得是因为KNN算法要选出与当前距离最小的k个点,异常值肯定在很后面,所以根本排不上号),无数据输入假定(没能理解这个),缺点是计算复杂度高,空间复杂度高,这两点好理解。
from numpy import array
from os import listdir
import operator
def GetData(String):
fl = open(String,'r')
NumberName = String.split('.')[0].split('_')[0][-1] #先以'.'为分界,再以'_'分界,这样最后一位就是图片的数字
NumberList = []
lines = fl.readlines()
for line in lines:
for i in range(len(line)-1): #字符串最后一位是'\n',所以要减去一
NumberList.append(int(line[i]))
return NumberList, int(NumberName)
def GetDistances(x,y): #传进来的时候,x,y都是list,公式是欧式公式
x = array(x)
y = array(y)
d = x-y
sqd = d**2
sqdistances = sqd.sum()
distances = sqdistances**0.5
return distances
def KNN(dataSet, NumberNameSet, testdata, k):
l = len(dataSet)
Distances = []
for i in range(l):
Distances.append(GetDistances(dataSet[i],testdata))
sortedDistances = array(Distances).argsort() #argsort()返回array(Distances)排序后的值的索引值
NumberNameDict = {} #key是数字名字,value是出现的次数
for i in range(k):
if NumberNameSet[sortedDistances[i]] not in NumberNameDict:
NumberNameDict[NumberNameSet[sortedDistances[i]]] = 0
else:
NumberNameDict[NumberNameSet[sortedDistances[i]]] += 1
sortedNumberNameDict = sorted(NumberNameDict.items(),key=operator.itemgetter(1),reverse = True)
return sortedNumberNameDict[0][0]
def HeadWriteDiscriminate():
TrainFileList = listdir('PythonTest/机器学习/machinelearninginaction-master/Ch02/digits/trainingDigits')
l = len(TrainFileList)
DataSet = []
NumberNameSet = []
for i in range(l):
String ='PythonTest/机器学习/machinelearninginaction-master/Ch02/digits/trainingDigits/' + TrainFileList[i]
data,numbername = GetData(String)
DataSet.append(data)
NumberNameSet.append(numbername)
TestFileList = listdir('PythonTest/机器学习/machinelearninginaction-master/Ch02/digits/testDigits') #返回值是乱序的,不过无所谓拉
m = len(TestFileList)
right = 0
count = 0
for i in range(m):
String = 'PythonTest/机器学习/machinelearninginaction-master/Ch02/digits/testDigits/' + TestFileList[i]
testdata,testnumbername = GetData(String)
if KNN(DataSet, NumberNameSet, testdata, 3) == testnumbername:
right += 1
count += 1
print('预测准确率:'+ str(right/count))
这个地方与书上不同的是:
书上是将测试图片的特征值复制成很多行形成二维数组,二维数组的大小和训练图片的特征值集(N*1024)大小一样,然后直接对两个二维数组进行计算。我第一次做这个的时候,发现运行内存不够。所以将测试图片的特征值与特征值集的每行分别进行计算,这样就没之前那个问题了。