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
'''
相关推荐
FreedomLeo16 天前
Python机器学习笔记(六、核支持向量机)
python·机器学习·scikit-learn·svm·svr 回归·svc 分类·axes3d
sinat_3842410910 天前
Python程序是一个基于Tkinter的GUI应用程序,用于录制和回放用户的鼠标和键盘操作
python·django·flask·beautifulsoup·numpy·scikit-learn
databook15 天前
scikit-learn中的Pipeline:构建高效、可维护的机器学习流程
python·机器学习·scikit-learn
985小水博一枚呀17 天前
【深度学习基础之Scikit-learn库3】Scikit-learn 库提供了丰富的功能,包括数据预处理、特征选择、模型训练与评估....
大数据·人工智能·python·深度学习·机器学习·scikit-learn
IT古董25 天前
【人工智能】Python常用库-Scikit-learn常用方法教程
人工智能·python·机器学习·scikit-learn
qq_1893704925 天前
鸢尾花植物的结构认识和Python中scikit-learn工具包的安装
python·机器学习·scikit-learn
deephub1 个月前
Scikit-learn Pipeline完全指南:高效构建机器学习工作流
人工智能·python·机器学习·scikit-learn
IT古董1 个月前
【机器学习】如何使用Python的Scikit-learn库实现机器学习模型,并对数据进行预处理和特征缩放以提高模型性能?
python·机器学习·scikit-learn
凤枭香1 个月前
Python Scikit-learn简介
开发语言·python·机器学习·scikit-learn