前几天去浙大蹭了一节蔡老师的课感觉收获挺大的。作业是两个,一个是用knn完成验证码识别。另一个是用python实现dnn的正反向传播,难度比较大。花了一个下午完成了knn,记录一下。实现效果如图:
knn的原理十分简单。假设空间中有一堆点,分为红,蓝两类。我们在这个空间中放入一个新点a,当我们想要知道a属于哪一类时,可以采取这种方法:1.计算a点和空间中所有点距离 2.找到与a最近的k个点 3.判断这k个点是红色类比较多还是蓝色类比较多,取多者作为a的类别。
第一个问题是手写一个knn实现的算法,从上面的流程我们可以看出需要4个参数:测试点,训练集(就是开始分布在空间中的点),训练集的标签(如红,蓝两类),还有k(取周围多少个点)。
我的代码基本准遵循这个过程,测试点是一个20002的点集,训练集是4002,标签是400的数组分为0和1两类,k为1,10,100。第一步是将测试点一个一个取出来,然后与400个点分别计算欧氏距离,然后选出最近的k个点。最后将k个点的标签取出来进行投票选出测试点的标签。
def knn(x, x_train, y_train, k):
'''
KNN k-Nearest Neighbors Algorithm.
INPUT: x: testing sample features, (N_test, P) matrix.
x_train: training sample features, (N, P) matrix.
y_train: training sample labels, (N, ) column vector.
k: the k in k-Nearest Neighbors
OUTPUT: y : predicted labels, (N_test, ) column vector.
'''
# Warning: uint8 matrix multiply uint8 matrix may cause overflow, take care
# Hint: You may find numpy.argsort & scipy.stats.mode helpful
# YOUR CODE HERE
XSetSize = x_train.shape[0]#首先计算训练集样本数量 400*2
xsize=x.shape[0]#计算输入样本的数量
y=[]
for t in x:
#然后扩展维度方便作差
from numpy import tile
diffMat = tile(t, (XSetSize, 1)) - x_train
#计算距离,取绝对值
sqDiffMat = diffMat ** 2
sqDistance = sqDiffMat.sum(axis=1)
distance = sqDistance ** 0.5
#排序
sortedDistIndicies = distance.argsort()
# 存放最终的分类结果及相应的结果投票数
classCount = {}
# 投票过程,就是统计前k个最近的样本所属类别包含的样本个数
for i in range(k):
voteIlabel = y_train[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
import operator
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
temp=sortedClassCount[0][0]
y.append(temp)
#print(y)
y=np.asarray(y)
return y
第二问是用前面写的knn完成二维码的识别。第一步是将二维码图片转化为1×140的灰度值数组,然后调用knn,相当于对140维的点作K近邻。当然,在此之前需要自己作一个数据集,这个很容易,我只做了一个20多张图片的数据集效果就很好了。
我把代码和题目都上传了,包含所有代码和数据集,这是我见过的最好的Knn习题。
https://download.youkuaiyun.com/download/liu506039293/10875793
环境是python3+jupyter notebook