刚才开会见了导师,老师的水平有点超出我的预期... 我得抓紧时间补了我靠。今天说老师的研究方向更偏向于网络一点,我这学机器学习是不是作用不大啊。不过没有说白学的知识,以后可能更多精力放在网页这一块儿。说现在主要在研究边缘算法,一会儿看看是什么东西,但是我还是想先把K最邻近算法这一块儿研究明白吧。开始。
接下来学的是《机器学习实战》这本书
从头开始创建模块,首先搞一些最基本的函数。
from numpy import *
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
导入了两个模块,科学计算包和运算符模块
自定义函数用来创建数据集和标签,改变当前路径到存储kNN.py的位置
跟舍友研究了一波终于弄好了,但是还是报错
TypeError: array() takes from 1 to 2 positional arguments but 4 were given
不知道这个有没有影响,先继续跑看一看
def classify0(inX,dataSet,labels,k):
dataSetSize = dataSet.shape[0]
difMat = tile(inx,(dataSetSize,1))-dataSet
sqDifMat = difMat**2
sqDistances = sqDifMat.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.iteritems(),
key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
classify0()有四个输入参数:用于分类的输入向量是inX,输入的训练样本集为dataSet,标签向量为labels,最后的参数k表示用于选择最近邻居的数目,其中标签向量的元素数目和矩阵dataSet的行数相同。
出现了以下报错
AttributeError: module 'kNN' has no attribute 'classify0'
查询后发现,在Python3中要把iteritems改为items
现在出现一个operands could not be broadcast together with shapes (4,2) (4,)
实在没辙了,卡住了。
上边还有一个报错大概意思就是
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
这个数组的维度不相同,但是我不知道为什么他不相同,应该就是这个不相同直接导致了钩编这个错误的产生,因为后边这个错误是因为**两边的维度不相同导致的,但是现在还不知道解决办法,先去上课,上完课回来研究。
上个问题跟舍友研究半天也没研究出来为甚么格式不对,从网上复制了代码也不对,最后是采用下面的方法解决的。
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = ['A','A','B','B']
将group 和labels直接定义在kNN中,放弃create函数,后边如果有影响的话再回来看,下继续往后走。
下面开始逐句研究。
.tile()函数是对张量(Tensor)进行扩展,作用是对当前张量内对数据进行一定规则的复制。
.argsort()将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y
先放个我查的资料的链接《机器学习实战》之k-近邻算法-基于Python3_华少的博客-CSDN博客,本来想看一下Python3和Python2有没有大佬重写,结果搜到了这个,看看我对每句话的理解,如果有不懂的我就去这里比对一下看是哪里出错了。
淘的这本书是基于Python2的,所以找了一个Python3的重写,下面对比着进行学习。
重写链接Python3代码实现《机器学习实战》k近邻算法改进约会网站配对效果中出现的问题_薰衣草PK向日葵的博客-CSDN博客
先去上课。
继续继续
重新写了一下kNN文件,终于解决了group创建不成功的问题,可以进行之后的学习了,还是先将classify0函数敲出来,然后进行逐句的学习。然后找到了之前为什么kNN一直加载不出来,其实还是放的路径位置不对,最后通过sys.path.append()找到了正确的路径并添加了进去。
在测试kNN.classify0([0,0],group,labels,3)时,出现了以下报错
NameError: name 'tile' is not defined
他显示的是我没有定义这个函数,但是我通过
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
定义了啊,不知道是哪里出现了问题。
解决了,原因是没有导入numpy整个包。
现在开始对约会网站的学习
首先还是先定义函数file2matrix(filename)
def file2matrix(filename):
fr = open(filename)
arrayOLines = fr.readlines()
numberOfLines = len(arrayOLines)
returnMat - zeros((numberOfLines,3))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip()
listFromLine = line.strip('\t')
returnMat[index,:] = listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1]))
index += 1
return returnMat,classLabelVector
在reload时在再次报错,原因是在Python2中,使用的是
import sys
sys.reload()
而在Python3中,应该使用的代码如下:
import importlib,sys
importlib.reload()就可以解决问题
之后继续进行测试
最后终于解决路径问题,将文件路径变成绝对路径就OK了
datingDataMat,datingLabels = kNN.file2matrix('F:\Pycharm\PyCharm Community Edition 2021.1.3\plugins\python-ce\helpers\pydev\datingTestSet2.txt')
顶不住了,明天继续,还剩最后的生成部分。
在舍友的指导下编写了测试文件,不用每次都导入包了,非常好用。
if __name__ == '__main__':
group,labels = createDataSet()
print(group)
print('\n')
print(labels)
print(classify0([0,0],group,labels,3))
datingDataMat,datingLabels = file2matrix('F:\Pycharm\PyCharm Community Edition 2021.1.3\plugins\python-ce\helpers\pydev\datingTestSet2.txt')
print(datingDataMat)
print('\n')
print(datingLabels[0:20])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
plt.show()
生成了点状图
其中y轴表示每周消费的冰淇淋公升数,x轴表示玩视频游戏所耗时间百分比
重新调用scatter函数
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
但是目前还是看不到有用信息。
上图是使用datingMat 的第一列和第二列数据来生成的图像
准备数据:归一化数值
因为有些特征值的取值范围较大,对结果会有较大的影响,但是从实际来看,各种特征值对计算结果的影响应该是等同的,因此使用一个公式
newValue = (oldValue-min)/(max-min)将任意范围的特征值转化为0到1区间内的值
下面准备归一特征值的代码
def autoNorm(dataSet):
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
将每列的最小值放在变量minVals中,将最大值放在maxVals中,其中dataSet.min(0)中 的参数0使得函数可以从列中选取最小值,而不是当前行 的最小值。
测试后得到
接下来是测试算法,可以使用错误率来检测分类器的正确率
def datingClassTest():
hoRatio = 0.10
datingDataMat,datingLabels = file2matrix('F:\Pycharm\PyCharm Community Edition 2021.1.3\plugins\python-ce\helpers\pydev\datingTestSet2.txt')
normMat,ranges,minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print("the classifierResult 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)))
首先还是对数据进行归一化处理,将m*hoRatio强制转换为int,shape[0]表示矩阵的行数。
找到发生频率最高的元素
测试结果如下:
接下来是预测函数
def classifyPerson():
resultList = ['not at all','in small doses','in large doses']
percentTats = float(input("percentage of time spent playing video games?"))
ffMiles = float(input("frequent flier miles earned per year?"))
iceCream = float(input("liters of ice cream consumed per year?"))
datingDatMat,datingLabels = file2matrix('F:\Pycharm\PyCharm Community Edition 2021.1.3\plugins\python-ce\helpers\pydev\datingTestSet2.txt')
normMat,ranges,minVals = autoNorm(datingDatMat)
inArr = array([ffMiles,percentTats,iceCream])
classifierResult = classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
print("You will probably like this person:",resultList[classifierResult-1])
加下来是测试(Python3中的输入函数是input())
测试成功
接下来是用k-近邻算法实现手写识别系统
首先我们肯定要将图像格式化处理为一个向量,通过函数来实现。
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)
return returnVect
接下来进行手写数字识别系统的测试代码
def handwritingClassTest():
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('tsetDigits')
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('testDigits/%s'%fileNameStr)
classifierResult = classify0(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("\nthe total number of error is :%d"% errorCount)
print("\nthe total error rate is : %f"%(errorCount/float(mTest)))