KNN_识别图片数字

1.实验过程省略灰度化处理过程,用已经处理好的txt数据进行训练

3.jpg

复制代码
from PIL import Image
def imgtotxt(imgfile,txtfile,size = (32,32)):
    image_file = Image.open(imgfile).resize(size,Image.LANCZOS).convert('L')
    width,height = image_file.size
    f = open(txtfile,'w')
    ascii_char = '10'
    for i in range(height):
        pix_char = ''
        for j in range(width):
            pixe1 = image_file.getpixel((j,i))
            pix_char += ascii_char[int(pixe1/128)]
        pix_char += '\n'
        f.write(pix_char)
    f.close()
imgtotxt('3.jpg','3_0.txt')
'''
3_0.txt
00000000000000000000000000000000
00000000000001111100000000000000
00000000111111111111111100000000
00000111111111111111111111000000
00011111111100000111111111100000
00011111000000000000111111110000
00011000000000000000001111111000
00000000000000000000000111111000
00000000000000000000000111111000
00000000000000000000000111111000
00000000000000000000000111111000
00000000000000000000001111110000
00000000000000000000011111110000
00000000000000000000111111100000
00000000000000000111111110000000
00000001111111111111100000000000
00000001111111111111110000000000
00000000111111111111111111000000
00000000000000000000111111110000
00000000000000000000000111111100
00000000000000000000000011111100
00000000000000000000000001111110
00000000000000000000000001111110
00000000000000000000000000111110
00000000000000000000000001111110
00000000000000000000000001111110
00000000000000000000000011111100
00111000000000000000000111111100
00111111100000000000111111111000
00111111111111111111111111100000
00001111111111111111111110000000
00000000011111111111100000000000
'''

2.数据预处理:txt2arry 函数将文本文件转换为 NumPy 数组,每个文件代表一个手写数字的图像,图像大小为 32x32 像素。

3.数据集构建:convert2dataset 函数从指定文件夹中读取所有文件,转换为数据集和标签。数据集中的每个样本都是一个 1x1024 的数组,标签是从文件名中提取的第一个字符。

4.模型训练:使用 KNeighborsClassifier 类训练 KNN 模型。模型参数 n_neighbors=43 表示考虑 43 个最近邻,weights='distance' 表示在投票时考虑距离的权重,p=2 表示使用欧氏距离。

5.模型评估:计算训练集上的准确率,并使用 classification_report 打印测试集的分类报告。

6.错误分析:找到第一个标签为 8 的样本,检查其预测结果,并打印出预测错误的样本。

7.混淆矩阵:使用 confusion_matrix 和 pd.crosstab 打印混淆矩阵,以评估模型的性能。

8.参数调优:测试不同的 k 值(奇数)对模型性能的影响,并绘制训练集和测试集准确率随 k 值变化的图表。

复制代码
import os
import numpy as np
#将文本文件转换为 NumPy 数组。
def txt2arry(filename):
    #创建了一个形状为 (1, 1024) 的全零数组,用于存储转换后的数据
    x = np.zeros((1,1024))
    f = open(filename)
    for i in range(32):
        lineStr = f.readline()
        for j in range(32):
            #将每个字符转换为整数,并存储在数组 x 的相应位置
            x[0,32*i+j] = int(lineStr[j])
    return x
#从指定文件夹中读取所有文件,转换为数据集和标签。
def convert2dataset(file_path):
    #获取指定文件夹中的所有文件名
    list_file = os.listdir(file_path)
    '''
    m 是文件的数量。
    datas 是一个形状为 (m, 1024) 
    的全零数组,用于存储转换后的数据。
    labels 是一个空列表,用于存储标签
    '''
    m = len(list_file)
    datas = np.zeros((m,1024))
    labels = []
    for i in range(m):
        #num = int(list_file[i][0]) 从文件名
        #中提取第一个字符并转换为整数,作为标签
        num = int(list_file[i][0])
        labels.append(num)
        #调用 txt2arry 函数将文件内容转换为数组,
        #并存储在 datas 的相应行中
        datas[i,:] = txt2arry(file_path+'\\'+list_file[i])
    return datas,labels

x_train,y_train = convert2dataset('trainingDigits')
x_test,y_test = convert2dataset('testDigits')
from sklearn.neighbors import KNeighborsClassifier

#使用 KNeighborsClassifier 训练模型。

knn = KNeighborsClassifier(n_neighbors=43,weights='distance',p=2)
knn.fit(x_train,y_train)

#计算训练集上的准确率。

score = (knn.score(x_train,y_train))
print('pricise = ',score)

#使用 classification_report 打印测试集的分类报告

from sklearn.metrics import classification_report
y_pred = knn.predict(x_test)
print(classification_report(y_test,y_pred))

#找到第一个标签为 8 的样本,检查其预测结果

i = y_test.index(8)
for j in range(91):
    if(y_test[i+j] != y_pred[i+j]):
        #打印出预测错误的样本
        print('{}[{}]->{}'.format(y_test[i+j],j,y_pred[i+j]))

#使用 confusion_matrix 和 pd.crosstab 打印混淆矩阵

import pandas as pd
from sklearn.metrics import confusion_matrix
y_test = np.array(y_test)
cm = confusion_matrix(y_test,y_pred)
cm_df = pd.crosstab(y_test,y_pred,rownames=['真实值'],colnames=['预测值'],margins=True)
print(cm,cm_df,sep='\n')

#测试不同的 k 值(奇数)对模型性能的影响。
#绘制训练集和测试集准确率随 k 值变化的图表

neighbors = []
for i in range(13,45):
    if i%2 == 1:
        neighbors.append(i)
train_accuracy = np.empty(len(neighbors))
test_accuracy = np.empty(len(neighbors))
for i,k in enumerate(neighbors):
    knn = KNeighborsClassifier(n_neighbors=k,weights='distance',p=2)
    knn.fit(x_train,y_train)
    train_accuracy[i] = round(knn.score(x_train,y_train),2)
    test_accuracy[i] = round(knn.score(x_test,y_test),2)

from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.title('k值的变化对准确率的影响')
plt.plot(neighbors,train_accuracy,label='训练样本的准确率')
plt.plot(neighbors,test_accuracy,label='测试样本的准确率')
plt.legend()
plt.xlabel('最近邻k字值')
plt.ylabel('准确率值')
plt.show()
#后期可以遍历找出acc最值时k值
#k 代表的是在进行分类决策时考虑的最近邻的数量
'''
E:\平常学习代码包\mechine_learning\knn_num\.venv\Scripts\python.exe E:\平常学习代码包\mechine_learning\knn_num\knn_Num.py 
pricise =  1.0
              precision    recall  f1-score   support

           0       0.99      1.00      0.99        87
           1       0.88      0.97      0.92        97
           2       0.95      0.96      0.95        92
           3       0.95      0.94      0.95        85
           4       1.00      0.93      0.96       114
           5       1.00      0.94      0.97       108
           6       0.97      1.00      0.98        87
           7       0.92      1.00      0.96        96
           8       0.96      0.86      0.91        91
           9       0.91      0.93      0.92        89

    accuracy                           0.95       946
   macro avg       0.95      0.95      0.95       946
weighted avg       0.95      0.95      0.95       946

8[1]->3
8[3]->6
8[13]->2
8[28]->6
8[29]->1
8[30]->1
8[31]->1
8[33]->1
8[40]->1
8[47]->6
8[59]->1
8[62]->1
8[79]->1
[[ 87   0   0   0   0   0   0   0   0   0]
 [  0  94   2   0   0   0   0   1   0   0]
 [  0   1  88   0   0   0   0   2   0   1]
 [  0   0   2  80   0   0   0   0   2   1]
 [  1   2   0   0 106   0   0   3   1   1]
 [  0   0   0   1   0 102   0   0   0   5]
 [  0   0   0   0   0   0  87   0   0   0]
 [  0   0   0   0   0   0   0  96   0   0]
 [  0   8   1   1   0   0   3   0  78   0]
 [  0   2   0   2   0   0   0   2   0  83]]
预测值   0    1   2   3    4    5   6    7   8   9  All
真实值                                                 
0    87    0   0   0    0    0   0    0   0   0   87
1     0   94   2   0    0    0   0    1   0   0   97
2     0    1  88   0    0    0   0    2   0   1   92
3     0    0   2  80    0    0   0    0   2   1   85
4     1    2   0   0  106    0   0    3   1   1  114
5     0    0   0   1    0  102   0    0   0   5  108
6     0    0   0   0    0    0  87    0   0   0   87
7     0    0   0   0    0    0   0   96   0   0   96
8     0    8   1   1    0    0   3    0  78   0   91
9     0    2   0   2    0    0   0    2   0  83   89
All  88  107  93  84  106  102  90  104  81  91  946
'''
相关推荐
强化试剂瓶3 小时前
全面掌握Ergosterol-PEG-Biotin,麦角甾醇PEG生物素的使用与注意事项
python·scrapy·flask·scikit-learn·pyqt
郝学胜-神的一滴4 小时前
特征选择利器:深入理解SelectKBest与单变量特征选择
人工智能·python·程序人生·机器学习·数据分析·scikit-learn·sklearn
流㶡1 天前
scikit-learn之KNN算法实战鸢尾花分类
python·算法·scikit-learn·knn
李昊哲小课3 天前
机器学习核心概念与经典算法全解析
人工智能·算法·机器学习·scikit-learn
醉舞经阁半卷书14 天前
Python机器学习常用库快速精通
人工智能·python·深度学习·机器学习·数据挖掘·数据分析·scikit-learn
李昊哲小课4 天前
奶茶店销售额预测模型
python·机器学习·线性回归·scikit-learn
kuiini7 天前
scikit-learn 常用算法与评估方法【Plan 7】
python·算法·scikit-learn
小饼干超人9 天前
如何兼容不同版本的 scikit-learn(sklearn)库,统一获取“均方根误差(RMSE)”的计算函数
python·scikit-learn·sklearn
玖疯子10 天前
TCP/IP协议栈深度解析技术文章大纲
python·scikit-learn·pyqt·pygame
python机器学习ML10 天前
机器学习——16种模型(基础+集成学习)+多角度SHAP高级可视化+Streamlit交互式应用+RFE特征选择+Optuna+完整项目
人工智能·python·机器学习·分类·数据挖掘·scikit-learn·集成学习