利用KNN算法实现手写数字识别
数据介绍
1.数据文件包含从0到9的手绘数字的灰度图像。
2.每个图像高28像素,宽28像素,共784个像素。
3 每个像素取值范围[0,255],取值越大意味着该像素颜色越深
4 训练数据集共785列。第一列为 “标签”,为该图片对应的手写数字。其余784列为该图像的像素值
5 训练集中的特征名称均有pixel前缀,后面的数字([0,783])代表了像素的序号。
# 导入numpy库和matplotlib库的pyplot模块,用于处理图像数据和绘图
import numpy as np
from matplotlib import pyplot as plt
# 读取图像文件,这里使用了绝对路径来指定图像文件的位置
# 我们真实拿到的数据应该是一组图片,我们需要将图片转换成矩阵形式,才能进行后续的运算。
img = plt.imread(r'D:\pythonProject2\data\0.png')
# 将二维图像数据转换为一维数组,方便后续处理
# print(f'读取的图片数据:{img.shape}')
img = img.reshape(1, -1)
# 在一维数组的开头插入一个值为2的元素,用于表示某种特征或标识
# print(f'转换后的图片数据:{img}')
# print(f'图片转换成矩阵:{img.shape}')
img = np.insert(img[0], 0, 2)
# 输出处理后的图像数据和其形状信息
print(img)
print(img.shape)
模型的训练
超参的选择方法
交叉验证
一种数据集的分割方法,将训练集划分为 n 份,拿一份做验证集(测试集)、其他n-1份做训练集
• 交叉验证法原理:将数据集划分为 cv=4 份
-
第一次:把第一份数据做验证集,其他数据做训练
-
第二次:把第二份数据做验证集,其他数据做训练
-
…以此类推,总共训练4次,评估4次。
-
使用训练集+验证集多次评估模型,取平均值做交叉验证为模型得分
-
若k=5模型得分最好,再使用全部训练集(训练集+验证集) 对k=5模型再训练一边,再使用测试集对k=5模型做评估
交叉验证法,是划分数据集的一种方法,目的就是为了得到更加准确可信的模型评分。
网格搜索
• 为什么需要网格搜索?
模型有很多超参数,其能力也存在很大的差异。需要手动产生很多超参数组合,来训练模型
每组超参数都采用交叉验证评估,最后选出最优参数组合建立模型。
• 网格搜索是模型调参的有力工具。寻找最优超参数的工具! 只需要将若干参数传递给网格搜索对象,它自动帮我们完成不同超参数的组合、模型训练、模型评估,
最终返回一组最优的超参数。
• 网格搜索 + 交叉验证的强力组合 (模型选择和调优)
交叉验证解决模型的数据输入问题(数据集划分)得到更可靠的模型
网格搜索解决超参数的组合
两个组合再一起形成一个模型参数调优的解决方案交叉验证网格搜索 – API和应用举例
• 交叉验证网格搜索API介绍
训练模型
# 加载手写数字识别数据集
data = pd.read_csv(r'D:\...\手写数字识别.csv')
# 对数据进行预处理,包括归一化
scaler = MinMaxScaler()
x = scaler.fit_transform(data.iloc[:,1:])
y = data.iloc[:,0]
# 将数据集划分为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=20)
# 实例化KNN分类器,并使用GridSearchCV进行超参数调优
estimator = KNeighborsClassifier(n_neighbors=5)
params = {'n_neighbors':range(3,10,2)}
estimator = GridSearchCV(estimator,params,cv=5)
estimator.fit(x_train,y_train)
# 选择最佳模型进行预测,并计算预测准确率
estimator = estimator.best_estimator_
score = estimator.score(x_test,y_test)
print(f'模型预测准确率:{score}')
# 保存训练好的模型
joblib.dump(estimator,'D:\...\model\knn_digit.pkl')
模型的预测
# 加载图片数据
img = plt.imread(r'D:\...\data\0.png')
# 将二维图片数据转换为一维数组
img = img.reshape(1,-1)
# 加载已训练好的KNN分类器模型
estimator = joblib.load(r'D:\...\model\knn_digit.pkl')
# 使用模型预测图片代表的数字
y_pred = estimator.predict(img)
# 输出预测结果
print(f'预测结果:{y_pred}')
完整代码
#-*- coding:utf-8 -*-
#Desc TODO 手写数字识别
#todo 0.导包
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import MinMaxScaler
import joblib
#todo 1.数据转换(图片转换)
def knn_train():
# 加载手写数字识别数据集
#todo 2.加载数据集并查看
data = pd.read_csv(r'D:\...\data\手写数字识别.csv')
# 对数据进行预处理,包括归一化
# todo 3.数据基本处理
# todo 3.1归一化
scaler = MinMaxScaler()
x = scaler.fit_transform(data.iloc[:,1:])
y = data.iloc[:,0]
# 将数据集划分为训练集和测试集
# todo 3.2 划分数据集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=20)
# 实例化KNN分类器,并使用GridSearchCV进行超参数调优
# todo 4.实例化模型
# todo 5.超参调优
estimator = KNeighborsClassifier(n_neighbors=5)
params = {'n_neighbors':range(3,10,2)}
estimator = GridSearchCV(estimator,params,cv=5)
estimator.fit(x_train,y_train)
# 选择最佳模型进行预测,并计算预测准确率
# todo 6.模型预测
estimator = estimator.best_estimator_
score = estimator.score(x_test,y_test)
print(f'模型预测准确率:{score}')
# 保存训练好的模型
# todo 7.模型保存
joblib.dump(estimator,'D:\...\model\knn_digit.pkl')
def knn_predict():
# 加载图片数据
# todo 1.加载图片
img = plt.imread(r'D:\...\data\0.png')
# 将二维图片数据转换为一维数组
# todo 2.图片转换成矩阵
img = img.reshape(1,-1)
# 加载已训练好的KNN分类器模型
# todo 3.加载模型
estimator = joblib.load(r'D:\...\model\knn_digit.pkl')
# 使用模型预测图片代表的数字
# todo 4.预测图片
y_pred = estimator.predict(img)
# 输出预测结果
print(f'预测结果:{y_pred}')
if __name__ == '__main__':
knn_predict()
knn_train()