zoukankan      html  css  js  c++  java
  • 【机器学习】knn——手写字识别案例

      1 import pandas as pd
      2 import numpy as np
      3 import matplotlib.pyplot as plt
      4 import os
      5 from sklearn.neighbors import KNeighborsClassifier  # knn分类
      6 
      7 
      8 def build_data(file_path):
      9     """
     10     加载并处理数据
     11     :param file_path:文件夹路径
     12     :return: 数据集
     13     """
     14     # 获取文件名称
     15     file_name_list = os.listdir(file_path)
     16     print("file_name_list:
    ", file_name_list)
     17 
     18     # 加载每一个文件中的内容
     19     # for循环加载
     20     # 大数组
     21     data_arr = np.zeros(shape=(len(file_name_list), 1025))
     22     for file_index, file_name in enumerate(file_name_list):
     23         # 获取文件序号 文件名称
     24         # print("file_index:", file_index)
     25         # print("file_name:", file_name)
     26         # 获取每一个文件的文件内容
     27         file_content = np.loadtxt(file_path + "/" + file_name, dtype=np.str)
     28         # print("file_content:
    ", file_content)
     29         # 单个样本
     30         single_sample_feture = np.zeros(shape=(len(file_content), 32))
     31         for file_content_num, file_content_data in enumerate(file_content):
     32             # print("file_content_num:", file_content_num)
     33             # print("file_content_data:", file_content_data)
     34             # 将每一个元素转化 数值类型 0 1 0 1
     35             # 法1
     36             # li = [int(i) for i in file_content_data]
     37             # print(li)
     38             # map函数
     39             li = list(map(int, file_content_data))
     40             # print(li)
     41             single_sample_feture[file_content_num, :] = li
     42         # print(single_sample_feture)
     43         # 将样本的二维数组展开成一维 作为样本的特征值
     44         single_data_arr_feature = single_sample_feture.ravel()
     45         # 将单个样本的特征值加到data_arr
     46         data_arr[file_index, :1024] = single_data_arr_feature
     47 
     48         # 获取目标值
     49         target = file_name.split("_")[0]
     50 
     51         # 将目标值添加到数组中
     52         data_arr[file_index, 1024] = target
     53 
     54     # print("data_arr:
    ",data_arr)
     55     # print("data_arr 的形状:
    ",data_arr.shape)
     56 
     57     return data_arr
     58 
     59 
     60 def save_data(file_data, file_name):
     61     """
     62     保存数据
     63     :param file_data: 数据
     64     :param file_name: 文件名称
     65     :return: None
     66     """
     67     # 如果data 文件不存在,就创建,如果存在,则不执行
     68     if not os.path.exists("./data"):
     69         os.makedirs("./data")
     70     # 保存文件
     71     np.save("./data/" + file_name, file_data)
     72 
     73 
     74 def load_data():
     75     """
     76     加载数据
     77     :return:train test
     78     """
     79     train = np.load("./data/train_data.npy")
     80     test = np.load("./data/test_data.npy")
     81 
     82     return train, test
     83 
     84 
     85 def distance(v1, v2):
     86     """
     87     计算距离
     88     :param v1:点1
     89     :param v2: 点2
     90     :return: 距离dist
     91     """
     92     # 法1
     93     # v1 是矩阵 将矩阵转化数组,再进行降为1维
     94     # v1 = v1.A[0]
     95     # print(v1)
     96     # sum_ = 0
     97     # for i in range(v1.shape[0]):
     98     #     sum_ += (v1[i] - v2[i]) ** 2
     99     # dist = np.sqrt(sum_)
    100     # print(dist)
    101     # 法2
    102     dist = np.sqrt(np.sum(np.power((v1 - v2), 2)))
    103     return dist
    104 
    105 
    106 def knn_owns(train, test, k):
    107     """
    108     knn识别手写字
    109     :param train: 训练集
    110     :param test: 测试集
    111     :param k: 邻居个数
    112     :return: 准确率
    113     """
    114     true_num = 0
    115     # 计算每一个测试样本与每一个训练样本的距离
    116     for i in range(test.shape[0]):
    117         # 构建数组 来保存 每一个测试样本与所有训练样本的距离
    118         arr_dist = np.zeros(shape=(train.shape[0], 1))
    119         for j in range(train.shape[0]):
    120             dist = distance(test[i, :1024], train[j, :1024])
    121             arr_dist[j, 0] = dist
    122         # print(arr_dist)
    123         # 将距离与训练集的目标值 组合起来
    124         mutile_arr = np.concatenate((arr_dist, train[:, 1024].reshape((-1, 1))), axis=1)
    125         # 因为数组排序不是整个样本一块动---排序---dataframe
    126         res_df = pd.DataFrame(data=mutile_arr, columns=["dist", "target"])
    127         # print(res_df)
    128         # 按照距离进行升序排序
    129         y_predict = res_df.sort_values(by="dist")["target"].head(k).mode()[0]
    130         # print("y_predict:", y_predict)
    131         if test[i, 1024] == y_predict:
    132             true_num += 1
    133     # 准确率
    134     score = true_num / test.shape[0]
    135 
    136     return score
    137 
    138 
    139 def show_res(score_list, k_list):
    140     """
    141     结果展示
    142     :param score_list: 准确率列表
    143     :param k_list: k列表
    144     :return: None
    145     """
    146     # 1、创建画布
    147     plt.figure()
    148     # 修改RC参数,来让其支持中文
    149     plt.rcParams['font.sans-serif'] = 'SimHei'
    150     plt.rcParams['axes.unicode_minus'] = False
    151     # 2、绘图
    152     plt.plot(k_list, score_list, color='r', linestyle=':', linewidth=1.2, marker="*", markersize=7, markerfacecolor='b',
    153              markeredgecolor='g')
    154     # 增加标题
    155     plt.title("随着k的不同,准确率的变化趋势")
    156     # 增加横轴、纵轴名称
    157     plt.xlabel("k值")
    158     plt.ylabel("准确率")
    159     # 增加横轴刻度
    160     plt.xticks(k_list)
    161     # 标注
    162     for i, j in zip(k_list, score_list):
    163         plt.text(i, j, "%.2f"%j,horizontalalignment='center')
    164     # 保存图片
    165     plt.savefig("./准确率变化走势图_sklearn.png")
    166     # 3、展示
    167     plt.show()
    168 
    169 
    170 def main():
    171     """
    172     主函数
    173     :return:
    174     """
    175     # # 1、加载并处理数据
    176     # train = build_data("./trainingDigits")
    177     # test = build_data("./testDigits")
    178     #
    179     # print("train:
    ",train)
    180     # print("train的形状:
    ",train.shape)
    181     #
    182     # print("test:
    ", test)
    183     # print("test的形状:
    ", test.shape)
    184     #
    185     # # 2、保存训练集与测试集数据
    186     # save_data(train,"train_data")
    187     # save_data(test,"test_data")
    188 
    189     # 1、加载数据
    190     train, test = load_data()
    191     print("train:
    ", train)
    192     print("test:
    ", test)
    193 
    194     # 2、自实现knn算法
    195     score_list = []
    196     k_list = [5, 6, 7, 8, 9, 10]
    197     # 自实现knn原理识别手写字
    198     # for k in k_list:
    199     #     score = knn_owns(train, test, k)
    200     #
    201     #     score_list.append(score)
    202     # print("score_list:
    ", score_list)
    203 
    204     # 使用sklearn 中的knn算法进行手写字识别
    205     for k in k_list:
    206         # (1)初始化算法实例
    207         knn = KNeighborsClassifier(n_neighbors=k)
    208         # (2) 训练数据
    209         knn.fit(train[:, :1024], train[:, 1024])
    210         # (3) 进行预测
    211         y_predict = knn.predict(test[:, :1024])
    212 
    213         # 获取准确率
    214         score = knn.score(test[:, :1024], test[:, 1024])
    215 
    216         print("预测值 y_predict:
    ", y_predict)
    217         score_list.append(score)
    218 
    219     # 3、结果展示
    220     show_res(score_list, k_list)
    221 
    222 
    223 if __name__ == '__main__':
    224     main()
  • 相关阅读:
    Echarts之美国新冠疫情地图制作
    前端三件套--CSS(pink老师课程笔记)
    数据预处理与转存(Hive--Mysql)
    HDFS的命令行使用
    hdfs的写入过程和读取过程
    树(一)树的基本知识
    指针中容易混淆的概念
    顺序查找、单链表查找、折半查找
    JAVA之I/O流
    SpringBoot-自定义spring-boot-starter
  • 原文地址:https://www.cnblogs.com/Tree0108/p/12116188.html
Copyright © 2011-2022 走看看