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
'''
相关推荐
麦麦大数据4 天前
vue+flask+CNN电影推荐系统
pytorch·python·cnn·flask·scikit-learn·电影推荐
databook5 天前
软间隔:让支持向量机更“宽容”
python·机器学习·scikit-learn
databook6 天前
核函数:让支持向量机从“青铜”变“王者”
python·机器学习·scikit-learn
大雄野比6 天前
【scikit-learn基础】--『监督学习』之 逻辑回归分类
学习·逻辑回归·scikit-learn
大雄野比10 天前
【scikit-learn基础】--『监督学习』之 贝叶斯分类
学习·分类·scikit-learn
大雄野比10 天前
【scikit-learn基础】--『监督学习』之 K-近邻分类
学习·分类·scikit-learn
databook10 天前
多变量决策树:机器学习中的“多面手”
python·机器学习·scikit-learn
大雄野比10 天前
【scikit-learn基础】--『监督学习』之 支持向量机回归
学习·支持向量机·scikit-learn
大雄野比10 天前
【scikit-learn基础】--『监督学习』之 决策树回归
学习·决策树·scikit-learn
大雄野比12 天前
【scikit-learn基础】--『监督学习』之 岭回归
学习·回归·scikit-learn