当前位置:   article > 正文

机器学习笔记--改进KNN算法实现人脸识别_python knn人脸识别orl

python knn人脸识别orl

目录

1--前言

2--路径总览

3--划分数据集

3.1--数据集介绍:

3.2--代码:

3.3--运行及结果:

4--主函数

4.1--原理分析:

4.2--源码:

4.3--运行及结果:

5--参考

6--问题补充


1--前言

①sysu模式识别作业

②数据集:ORL Database of Faces

③原理: wk_NNC算法

2--路径总览

3--划分数据集

3.1--数据集介绍:

①ORL数据集采用P5类型的PGM格式进行存储,下图以记事本打开一个样本为例进行说明:

分析:第一行说明图片为P5格式;第二行为图片的宽高数据;第三行为数据的最大值;第四行及之后存储了图片的像素值

注:需要说明的是,在划分数据集中用到了图片的宽高(H, W)数值,即(92,112),同时使用了min = 0max = 255进行归一化;

3.2--代码:

  1. import os
  2. from PIL import Image
  3. import numpy as np
  4. import random
  5. def split_dataset(data_path, proportion):
  6. # 初始化训练集、验证集及其标签
  7. train_dataset = []
  8. test_dataset = []
  9. train_labels = []
  10. test_labels = []
  11. for i in range(40): # 遍历40类
  12. sample_list = os.listdir(data_path + '/s' + str(i + 1)) # 10个样本名
  13. random.shuffle(sample_list) # 随机打乱10个样本
  14. for j in range(len(sample_list)): # 遍历打乱后的10个样本
  15. img = Image.open(data_path + '/s' + str(i + 1) + '/' + sample_list[j]) # 读取第j个样本
  16. if j < (proportion * len(sample_list)): # 前7个划分到训练集
  17. train_dataset.append(np.array(img, dtype=np.uint8)) # 存储训练数据
  18. train_labels.append(i) # 存储训练标签
  19. else:
  20. test_dataset.append(np.array(img, dtype=np.uint8)) # 存储验证数据
  21. test_labels.append(i) # 存储验证标签
  22. return train_dataset, train_labels, test_dataset, test_labels
  23. def process_data(train_dataset, train_labels, test_dataset, test_labels):
  24. # 计算训练集和验证集的数目
  25. train_sum = len(train_dataset) # 等于 40 * 10 * proportion
  26. test_sum = len(test_dataset) # 等于 40 * 10 * (1-proportion)
  27. # 初始化处理后的训练集和验证集
  28. train_data = np.zeros((train_sum, H * W))
  29. test_data = np.zeros((test_sum, H * W))
  30. train_label = np.array(train_labels)
  31. test_label = np.array(test_labels)
  32. for i in range(train_sum): # 遍历每一个样本
  33. temp = train_dataset[i].reshape(-1) # reshape成单维向量
  34. train_data[i] = (temp - 0) / (255 - 0) # 归一化
  35. for j in range(test_sum):
  36. temp = test_dataset[j].reshape(-1)
  37. test_data[j] = (temp - 0) / (255 - 0) # 归一化
  38. return train_data, train_label, test_data, test_label
  39. if __name__ == "__main__":
  40. # 参数
  41. data_path = './dataset/ORL/att_faces/orl_faces' # 数据集路径
  42. proportion = 0.7 # 划分比例 0.7训练 0.3验证
  43. H = 92
  44. W = 112
  45. # 划分数据集
  46. train_dataset, train_labels, test_dataset, test_labels = split_dataset(data_path = data_path, proportion = proportion)
  47. # 数据集预处理
  48. train_data, train_label, test_data, test_label = process_data(train_dataset, train_labels, test_dataset, test_labels)
  49. save_name = './dataset/dataset.npz'
  50. np.savez(save_name, x_train=train_data, y_train=train_label, x_test=test_data, y_test=test_label)

3.3--运行及结果:

python gen_dataset.py

4--主函数

4.1--原理分析:

(具体公式参考链接,这里只做原理简述)

①首先计算当前分类样本与训练样本的距离(常用欧式距离),让k个距离最小的训练样本拥有投票权;

②初始化所有类别的概率均为1,即初始化权重得分均为1;

③根据公式计算前k个训练样本的权重得分,并让投票样本的类别作为分类样本的预测类别;

④分类样本被预测为投票样本的概率由投票样本的权重得分决定

⑤最终权重得分和最高的类别为分类样本的预测类别。

4.2--源码:

  1. import numpy as np
  2. # KNN classifier
  3. def kNNClassify(test_x, train_x, train_y, k=4):
  4. # 计算与训练集样本的距离(280个),这里用欧几里得距离表示
  5. distance = np.sum(np.power((train_x - test_x), 2), axis=1) # 280
  6. sort_inx = np.argsort(distance, kind="quicksort")[:k] # 取前k个最小距离对应的索引,即训练集样本的索引
  7. w = [] # 初始化距离权重
  8. for i in range(k): # 利用 wk-NNC 算法公式计算k个近邻的权重
  9. w.append((distance[sort_inx[k - 1]] - distance[sort_inx[i]]) / (distance[sort_inx[k - 1]] - distance[sort_inx[0]]))
  10. score = np.ones(40) # 40个类别的得分
  11. for inx, data in enumerate(sort_inx):
  12. vote_label = train_y[data] # 投票类别,即当前邻居k对应的类别 (取值为0~39)
  13. score[vote_label] += w[inx] # 投票类别的得分 = 原始得分(初始化全为1) + 权重得分
  14. pre_label = np.argmax(score) # 取得分最高的类别作为预测类别
  15. return pre_label
  16. if __name__ == "__main__":
  17. # 读取数据集
  18. dataset_path = './dataset/dataset.npz'
  19. dataset = np.load(dataset_path)
  20. train_dataset = dataset['x_train']
  21. train_labels = dataset['y_train']
  22. test_dataset = dataset['x_test']
  23. test_labels = dataset['y_test']
  24. # 邻居数
  25. k = 4
  26. correct_sum = 0 # 预测正确的样本数
  27. test_sum = test_dataset.shape[0] # 验证集样本数
  28. string = "test_number: {0}, true_label: {1}, pre_label: {2}------>correct?: {3}" # 定义打印格式
  29. for i in np.arange(test_sum):
  30. # 利用KNN进行分类
  31. label = kNNClassify(test_x = test_dataset[i], train_x = train_dataset, train_y = train_labels, k=k)
  32. if label == test_labels[i]: # 分类正确
  33. correct_sum = correct_sum + 1
  34. print(string.format(i + 1, test_labels[i], label, label == test_labels[i])) # 打印当前样本分类结果
  35. print("Accuracy: {}%".format((correct_sum / test_sum) * 100)) # 打印最终准确率

4.3--运行及结果:

python knn.py

5--参考

参考1

参考2

6--问题补充

未完待续!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/373350
推荐阅读
相关标签
  

闽ICP备14008679号