KNN分类算法

算法步骤

  1. 先对一定对象分好类别(一个类别中可能有数量不同的对象)
  2. 对于待分类的对象,计算已知类别中的每个对象与当前对象的距离(不同任务距离算法不同)
  3. 按照距离递增将已知类别的对象排序
  4. 选取前k个对象
  5. 统计这些对象中所属类别频次最多的一类
  6. 将当前对象归为该类

手写数字识别

​ 首先输入已知结果的数字信息(32*32的0,1数组,保存在文本文件中),根据标签对这些对象先分好类。

读取文件方法,将32*32的数组转化为1*1024的数组
1
2
3
4
5
6
7
8
9
10
11
def img2vec(filename):
'''this is to...将32X32的图像转化为1X1024的行向量'''
returnvec = zeros((1,1024))

with open(filename) as fp:
for i in range(32):
line = fp.readline()
for j in range(32):
returnvec[0, 32*i + j] = int(line[j])
# returnVEC按32进位,j代表每位的32个元素
return returnvec
将文件中的所有已知结果的数字信息按照上述方法读入,并且打上标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
labels = []
File_list = listdir(train_dir)
# listdir函数作用是返回文件夹中所有文件或文件夹的列表
m = len(File_list) # 文件数量
train_mat = zeros((m,1024)) # 创建一个m*1024大小的二维数组,储存所有文件的信息
for i in range(m):
fname = File_list[i]
fstr = fname.split('.')[0] # 分裂'.'前后的内容,取第一个
fnumber = int(fstr.split('_')[0]) # 分裂'_'前后的内容,取第一个,然后将数字字符转化为int
# 比如'digits/testDigits/0_13.txt',被拆分为0,13,txt
# 此处0即为标签数字
labels.append(fnumber) # 储存标签,索引相对应
train_mat[i,:] = img2vec('%s/%s' % (train_dir,fname)) # 调用函数,储存信息

KNN算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def classify_KNN(test_X, train_set, labels, K):
# 参数:test_X为需要判断的对象,train_set 为已知对象集,lables为对象对应的标签,选取前k个结果。
rows = train_set.shape[0] # 已知对象的个数
diff = tile(test_X, (rows, 1)) - train_set
# tile函数作用:复制原矩阵,(rows, 1)第一个参数是纵向复制,第二个参数为横向复制,转换后得到的矩阵大小为rows*32,
#矩阵减法得到当前对象与已知对象集中各个分量的距离


sqDistance = (diff ** 2).sum(axis=1)
Distance = sqDistance ** 0.5
# 使用欧几里得距离公式将各个分量转化为一个标准值
sorted_Distance = Distance.argsort()
# 对距离进行排序,argsort函数的作用是返回 对象值 在排序前的索引,比如排序前列表中第三个是最小值,返回的列表第一个值是2(第三个索引是2)


classCount = {}
for i in range(K):
vote_label = labels[sorted_Distance[i]]
classCount[vote_label] = classCount.get(vote_label, 0) + 1
#记录距离最小的前K个类,并存放入列表。KEY对应标签,VALUE对应计数

sortedClassCount = sorted(classCount.items(),
key = operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
# 计算对用标签的频数,以最大值当做预测的结果
测试:使用测试集测试KNN分类算法的结果是否与标签相同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
test_File_list = listdir(test_dir)
error = 0.0 # 统计错误个数
test_m = len(test_File_list)
for i in range(test_m):
fname = test_File_list[i]
fstr = fname.split('.')[0]
fnumber = int(fstr.split('_')[0])
vec_test = img2vec('digits/testDigits/%s' % fname) # 调用函数
Result = classify_KNN(vec_test, train_mat, labels, 3) #KNN算法
print("the classifier came with: %d, the real answer is :%d " \
% (Result, fnumber)) # 打印预测值与真实值
if(Result != fnumber) : error += 1 #统计错误个数
# 这部分和Test模块相同,直接copy过来就好
print("the accuracy is %f | the error_rate is %f " % \
(1- (float(error) /float(test_m)),(float(error) /float(test_m))))
# 计算准确率

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!