- 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: 数据
- """
- 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[:, :-1].values
- train_y = train.iloc[:, -1].values
- # 获取测试集的特征值 目标值
- test_x = test.iloc[:, :-1].values
- test_y = test.iloc[:, -1].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]
- if mode == test_y[i]:
- true_num += 1
- # print(test_y)
- score = true_num / test.shape[0]
- print(score)
- return score
- # train_data = build_data("./trainingDigits")
- # test_data = build_data("./testDigits")
- #
- # save_data("train_data",train_data)
- # save_data("test_data",test_data)
- # 加载数据
- 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,6,7,8,9,10]
- 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)
- # 进行结果可视化
- # 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()
来源: http://www.bubuko.com/infodetail-3204151.html