实验前准备如下
手写字分别存储在两个文件中,一个是训练集文件,一个是测试集文件。
两个文件夹下的txt文件命名格式是,下划线前面的数字代表文本内存储的文字内容,下划线后面的数字代表是第几个
如:1_12.txt代表文件内存储的内容为手写字1,这是存储手写字1的第12个文件。
本实验中K值与预测准确率的关系如下图
实现代码如下
import pandas as pd import numpy as np import matplotlib.pyplot as plt import os from sklearn.neighbors import KNeighborsClassifier def build_data(dir_name): """ 构建数据 :param dir_name: 指定传入文件夹名称 :return: 构建好的数据 """ # 获取文件名列表 file_name_list = os.listdir(dir_name + "/") print("获取到的文件名列表:\n", file_name_list) # 进行读取文件 data = np.zeros(shape=(len(file_name_list), 1025)) # 循环读取文件 for file_index, file_name in enumerate(file_name_list): # file_index 文本名称所对应的下标 # file_name 文本名称 # 加载数据 file_data = np.loadtxt(dir_name + "/" + file_name, dtype=np.str) # 构建一个列表 arr = [] for file_data_index, file_data_content in enumerate(file_data): # print(file_data_content) # print("*"*80) # 将 每一个元素转化为一个int 类型的列表 arr_sigle_list = [int(tmp) for tmp in file_data_content] # print(arr) # 把每个元素添加到列表中 arr.append(arr_sigle_list) # print(arr) # 将一个样本转化为数组 arr_single_sample = np.array(arr) # print(arr_single_sample) # np.savetxt("./hh.txt",arr_single_sample,fmt="%d") # 将二维数组展开为一维---特征值 arr_single_sample = arr_single_sample.ravel() # print(arr_single_sample) # 目标值 label = int(file_name[0]) # print(res) # print(arr_single_sample.shape) # 将一个 完整的样本拼接起来,组成完整的样本 arr_single_sample = np.concatenate((arr_single_sample, [label]), axis=0) # print(arr_single_sample) # print(arr_single_sample.shape) data[file_index, :] = arr_single_sample # print(data) return data def save_data(file_name, data): """ 保存文件 :param file_name: 保存的文件名称 :param data: 保存的数组 :return: None """ if not os.path.exists("./data/"): os.makedirs("./data/") np.save("./data/" + file_name, data) def load_data(file_name): """ 加载数据 :param file_name:文件路径+ 名称 :return: 数据 """ #是否允许读取pickled对象 data = np.load(file_name, allow_pickle=True) return data def show_res(k_list,score_list): #进行结果可视化 # 1、创建画布 plt.figure() # 默认不支持中文,需要配置RC 参数 plt.rcParams['font.sans-serif']='SimHei' # 设置字体之后不支持负号,需要去设置RC参数更改编码 plt.rcParams['axes.unicode_minus']=False # 2、绘图 x = np.array(k_list) y = np.array(score_list) plt.plot(x,y) plt.title("k与准确率的关系走势图") plt.xlabel("k值") plt.ylabel("准确率") # plt.savefig("./k值对准确率的影响.png") # 3、展示 plt.show() def main(): train = load_data("./data/train_data.npy") test = load_data("./data/test_data.npy") train = pd.DataFrame(train) test = pd.DataFrame(test) k_list = [5,6,7,8,9,10] score_list = [] for k in k_list: knn = KNeighborsClassifier(n_neighbors=k) #训练数据 knn.fit(train.iloc[:,:-1].values,train.iloc[:,-1].values) # 进行预测 y_predict = knn.predict(test.iloc[:,:-1].values) # 可以获取准确率 score = knn.score(test.iloc[:,:-1].values,test.iloc[:,-1].values) score_list.append(score) print(score_list) show_res(k_list,score_list) if __name__ == '__main__': main()
自实现的代码如下
import pandas as pd import numpy as np import matplotlib.pyplot as plt import os from sklearn.neighbors import KNeighborsClassifier def build_data(dir_name): """ 构建数据 :param dir_name: 指定传入文件夹名称 :return: 构建好的数据 """ # 获取文件名列表 file_name_list = os.listdir(dir_name + "/") print("获取到的文件名列表:\n", file_name_list) # 进行读取文件 data = np.zeros(shape=(len(file_name_list), 1025)) # 循环读取文件 for file_index, file_name in enumerate(file_name_list): # file_index 文本名称所对应的下标 # file_name 文本名称 # 加载数据 file_data = np.loadtxt(dir_name + "/" + file_name, dtype=np.str) # 构建一个列表 arr = [] for file_data_index, file_data_content in enumerate(file_data): # print(file_data_content) # print("*"*80) # 将 每一个元素转化为一个int 类型的列表 arr_sigle_list = [int(tmp) for tmp in file_data_content] # print(arr) # 把每个元素添加到列表中 arr.append(arr_sigle_list) # print(arr) # 将一个样本转化为数组 arr_single_sample = np.array(arr) # print(arr_single_sample) # np.savetxt("./hh.txt",arr_single_sample,fmt="%d") # 将二维数组展开为一维---特征值 arr_single_sample = arr_single_sample.ravel() # print(arr_single_sample) # 目标值 label = int(file_name[0]) # print(res) # print(arr_single_sample.shape) # 将一个 完整的样本拼接起来,组成完整的样本 arr_single_sample = np.concatenate((arr_single_sample, [label]), axis=0) # print(arr_single_sample) # print(arr_single_sample.shape) data[file_index, :] = arr_single_sample # print(data) return data def save_data(file_name, data): """ 保存文件 :param file_name: 保存的文件名称 :param data: 保存的数组 :return: None """ if not os.path.exists("./data/"): os.makedirs("./data/") np.save("./data/" + file_name, data) def load_data(file_name): """ 加载数据 :param file_name:文件路径+ 名称 :return: 数据 """ #是否允许读取pickled对象 data = np.load(file_name, allow_pickle=True) return data def distance(v1, v2): """ 计算距离 :param v1: 点1 :param v2: 点2 :return: 距离 """ dist = np.sqrt(np.sum(np.power((v1 - v2), 2))) return dist def knn_owns(train, test, k): """ 自定knn算法实现手写字识别 :param train: 训练集数据 :param test: 测试集数据 :param k: 邻居个数 :return: 准确率 """ # 设置计数器 true_num = 0 # 获取训练集的特征值 目标值 train_x = train.iloc[:, 0:1024].values # print("train_x的shape:\n",train_x.shape) train_y = train.iloc[:, 1024].values # 获取测试集的特征值 目标值 test_x = test.iloc[:, 0:1024].values # print("test_x的shape:\n",test_x.shape) test_y = test.iloc[:,1024].values # 计算每一个测试样本特征与每一个训练样本特征的距离 for i in range(test.shape[0]): # 循环每一个 测试样本 for j in range(train.shape[0]): # 计算距离 dist = distance(test_x[i,:],train_x[j,:]) train.loc[j,'dist'] = dist res = train.sort_values(by='dist') mode = res.iloc[:,-2][:k].mode()[0] print(mode) if mode == test_y[i]: true_num += 1 # print(test_y) score = true_num / test.shape[0] print(score) return score def show_res(k_list,score_list): #进行结果可视化 # 1、创建画布 plt.figure() # 默认不支持中文,需要配置RC 参数 plt.rcParams['font.sans-serif']='SimHei' # 设置字体之后不支持负号,需要去设置RC参数更改编码 plt.rcParams['axes.unicode_minus']=False # 2、绘图 x = np.array(k_list) y = np.array(score_list) plt.plot(x,y) plt.title("k与准确率的关系走势图") plt.xlabel("k值") plt.ylabel("准确率") # plt.savefig("./k值对准确率的影响.png") # 3、展示 plt.show() # train_data = build_data("./trainingDigits") # test_data = build_data("./testDigits") # # save_data("train_data",train_data) # save_data("test_data",test_data) def main(): """ 主函数 :return: None """ # 加载数据 train = load_data("./data/train_data.npy") test = load_data("./data/test_data.npy") train = pd.DataFrame(train) test = pd.DataFrame(test) # print(train) # print("*"*80) # print(test) k_list = [5] score_list = [] for k in k_list: score = knn_owns(train, test, k) score_list.append(score) # knn = KNeighborsClassifier(n_neighbors=k) # #训练数据 # knn.fit(train.iloc[:,:-1].values,train.iloc[:,-1].values) # # 进行预测 # y_predict = knn.predict(test.iloc[:,:-1].values) # # # 可以获取准确率 # score = knn.score(test.iloc[:,:-1].values,test.iloc[:,-1].values) score_list.append(score) print(score_list) if __name__ == '__main__': main()