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


    目录

    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--问题补充

    未完待续!

  • 相关阅读:
    基础课8——知识图谱
    STC 51单片机47——外部中断控制流水灯
    进程概念[上]
    Android DEX 文件格式解析
    CSS-列表属性篇
    useEffect
    OpenvSwitch 子项目 OVN 功能介绍(一)
    11款新编程工具!
    Nginx+Tomcat
    java中的异常[35]
  • 原文地址:https://blog.csdn.net/weixin_43863869/article/details/127759715