一.案例介绍
将42000个手写数字数据进行读取,进行数据格式转换、数据打印、模型选练、模型保存、模型评估,以达到KNN算法练习的目的
二.代码部分详解
1.导包
import matplotlib.pyplot as plt import pandas as pd import matplotlib matplotlib.use('TkAgg') # 解决后端错误 from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.neighbors import KNeighborsClassifier import joblib #保存模型 from collections import Counter #去重统计 from sklearn.metrics import accuracy_score2.数据读取
#1.接收用户传入的索引,展示该索引对应的图片 def show_digit(idx): #1.读取数据集,获取到原数据 df = pd.read_csv('./data/手写数字识别.csv') #print(df) #(42000行*785列) #2.判断传入的索引是否越界 if idx < 0 or idx > len(df) - 1: print('索引越界') return #3.走这里,说明没有越界,就正常获取数据 x = df.iloc[:, 1:] #第一个冒号代表所有数据,第二个代表从编号1开始拿数据 y = df.iloc[:,0] #4.查看用户传入的索引对应的图片是几 print(f'该图片对应的数字是:{y.iloc[idx]}') print(f'查看所有的标签的分布情况:{Counter(y)}') #5.查看下 用户传入的索引图片 的形状 print(x.iloc[idx].shape) #(784) 我们要想办法把(784)转换为(28,28) #print(x.iloc[idx].values) #具体的784个像素点数据 #6.把(748)转化为(28*28) x = x.iloc[idx].values.reshape(28, 28) #print(x) #已经转化为28 * 28像素点 #7.具体的绘制灰度图的动作 plt.imshow(x,cmap='gray') #灰度图 plt.axis('off') #不显示坐标 plt.show()运行效果展示
3.模型训练以及保存
#2.训练模型,并保存训练好的模型 def train_model(): #1.加载数据集 df = pd.read_csv('./data/手写数字识别.csv') #2.数据的预处理 #2.1拆分出特征列 x = df.iloc[:, 1:] #特征列 这里指的是行和列,如果是单:就是所有的意思 #2.2拆分出标签列 y = df.iloc[:,0] #标签列 #2.3打印特征和标签的形状 print(f'x的形状:{x.shape}') #42000 * 784 print(f'y的形状:{y.shape}') #42000 * 1 print(f'查看所有标签的分布情况:{Counter(y)}') #2.4对特征列(拆分前)进行归一化 x = x / 255 #2.5拆分训练集和测试集 #参1:特征列 参2:标签列 参3:测试集的比例 参4:随机种子 参5:参考y值进行抽取,保持标签的比例(数据均衡) x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=21, stratify=y) #3.模型训练 #3.1创建模型对象 estimator = KNeighborsClassifier(n_neighbors=3) #3.2 模型训练 estimator.fit(x_train,y_train) #4.模型评估 print(f'准确率:{estimator.score(x_test,y_test)}') print(f'准确率:{accuracy_score(y_test,estimator.predict(x_test))}') #5.保存模型 #参1:模型对象 参2:模型保存的路径 joblib.dump(estimator, './model/手写数字识别.pkl') #pickle文件:Python(pandas)独有的文件类型 print('模型保存成功')运行效果展示
4.模型测试
#3.测试模型 def test_model(): #1.加载图片 x = plt.imread('./data/demo.png') #28*28 注意imread函数在读数据时,自动进行归一化,数据为0-1之间 #2.绘制图片 plt.imshow(x, cmap='gray') plt.axis('off') plt.show() #3.加载模型 estimator = joblib.load('./model/手写数字识别.pkl') #4.模型预测 #4.1查看数据集转换 print(x.shape) #(28, 28) print(x.reshape(1, 784).shape) #(1, 784) print(x.reshape(1,-1).shape) #效果上等同于(1,784),语法糖 #4.2 具体的转换动作,记得归一化 #x = x.reshape(1,-1)/255 #可能会预测失败,应为读图的时候,像素点可能不是特别的精准 x = x.reshape(1, -1) #用原始的赌徒到的像素值,做预测 #4.3 模型预测 y_pre = estimator.predict(x) print(f'预测的结果为:{y_pre}')运行效果展示
5.完整代码
import matplotlib.pyplot as plt import pandas as pd import matplotlib matplotlib.use('TkAgg') # 解决后端错误 from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.neighbors import KNeighborsClassifier import joblib #保存模型 from collections import Counter #去重统计 from sklearn.metrics import accuracy_score #扩展:忽略警告 import warnings warnings.filterwarnings('ignore', module='sklearn') #参1表示忽略警报 参2表示忽略的模块 #1.接收用户传入的索引,展示该索引对应的图片 def show_digit(idx): #1.读取数据集,获取到原数据 df = pd.read_csv('./data/手写数字识别.csv') #print(df) #(42000行*785列) #2.判断传入的索引是否越界 if idx < 0 or idx > len(df) - 1: print('索引越界') return #3.走这里,说明没有越界,就正常获取数据 x = df.iloc[:, 1:] #第一个冒号代表所有数据,第二个代表从编号1开始拿数据 y = df.iloc[:,0] #4.查看用户传入的索引对应的图片是几 print(f'该图片对应的数字是:{y.iloc[idx]}') print(f'查看所有的标签的分布情况:{Counter(y)}') #5.查看下 用户传入的索引图片 的形状 print(x.iloc[idx].shape) #(784) 我们要想办法把(784)转换为(28,28) #print(x.iloc[idx].values) #具体的784个像素点数据 #6.把(748)转化为(28*28) x = x.iloc[idx].values.reshape(28, 28) #print(x) #已经转化为28 * 28像素点 #7.具体的绘制灰度图的动作 plt.imshow(x,cmap='gray') #灰度图 plt.axis('off') #不显示坐标 plt.show() #2.训练模型,并保存训练好的模型 def train_model(): #1.加载数据集 df = pd.read_csv('./data/手写数字识别.csv') #2.数据的预处理 #2.1拆分出特征列 x = df.iloc[:, 1:] #特征列 这里指的是行和列,如果是单:就是所有的意思 #2.2拆分出标签列 y = df.iloc[:,0] #标签列 #2.3打印特征和标签的形状 print(f'x的形状:{x.shape}') #42000 * 784 print(f'y的形状:{y.shape}') #42000 * 1 print(f'查看所有标签的分布情况:{Counter(y)}') #2.4对特征列(拆分前)进行归一化 x = x / 255 #2.5拆分训练集和测试集 #参1:特征列 参2:标签列 参3:测试集的比例 参4:随机种子 参5:参考y值进行抽取,保持标签的比例(数据均衡) x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=21, stratify=y) #3.模型训练 #3.1创建模型对象 estimator = KNeighborsClassifier(n_neighbors=3) #3.2 模型训练 estimator.fit(x_train,y_train) #4.模型评估 print(f'准确率:{estimator.score(x_test,y_test)}') print(f'准确率:{accuracy_score(y_test,estimator.predict(x_test))}') #5.保存模型 #参1:模型对象 参2:模型保存的路径 joblib.dump(estimator, './model/手写数字识别.pkl') #pickle文件:Python(pandas)独有的文件类型 print('模型保存成功') #3.测试模型 def test_model(): #1.加载图片 x = plt.imread('./data/demo.png') #28*28 注意imread函数在读数据时,自动进行归一化,数据为0-1之间 #2.绘制图片 plt.imshow(x, cmap='gray') plt.axis('off') plt.show() #3.加载模型 estimator = joblib.load('./model/手写数字识别.pkl') #4.模型预测 #4.1查看数据集转换 print(x.shape) #(28, 28) print(x.reshape(1, 784).shape) #(1, 784) print(x.reshape(1,-1).shape) #效果上等同于(1,784),语法糖 #4.2 具体的转换动作,记得归一化 #x = x.reshape(1,-1)/255 #可能会预测失败,应为读图的时候,像素点可能不是特别的精准 x = x.reshape(1, -1) #用原始的赌徒到的像素值,做预测 #4.3 模型预测 y_pre = estimator.predict(x) print(f'预测的结果为:{y_pre}') #4.测试 if __name__ =='__main__' : #绘制数字 #show_digit(9) #训练模型并保存模型 #train_model() #模型预测 test_model()三.总结
通过手写数字识别,训练了对于数据转换的注意事项,学习了相关API的调用,强化了对于KNN算法的认识