天天看點

機器學習之KNN結合微信機器人實作手寫數字識别終極API手寫數字識别

機器學習之KNN結合微信機器人實作手寫數字識别終極API

  • 手寫數字識别
    • 功能概述
    • 實作步驟
    • 結果展示
    • 改進之處和TIPS

手寫數字識别

功能概述

微信機器人接收到的手寫數字圖檔,傳送給已經經過機器學習訓練過的knn分類器,進行預測,輸出數字結果。

實作步驟

  • 将手寫數字圖檔轉變為32*32的矩陣

    因為機器學習的訓練資料集是DBRHD資料集(訓練資料集已上傳到我的資料可以自行下載下傳),圖檔均歸一化為以數字為中心的32*32規格的矩陣:空白區域用0表示,字迹部分用1表示。是以首先就需要将手寫數字圖檔轉換成文本形式。

    ps:DBRHD資料集我已上傳到我的資源

from PIL import Image
import matplotlib.pylab as plt
import numpy as np


def picTo01(filename):
    """
    将圖檔轉化為32*32像素的檔案,用0 1表示
    :param filename:
    :return:
    """
    # 打開圖檔
    img = Image.open(filename).convert('RGBA')

    # 得到圖檔的像素值
    raw_data = img.load()

    # 将其降噪并轉化為黑白兩色
    for y in range(img.size[1]):
        for x in range(img.size[0]):
            if raw_data[x, y][0] < 90:
                raw_data[x, y] = (0, 0, 0, 255)

    for y in range(img.size[1]):
        for x in range(img.size[0]):
            if raw_data[x, y][1] < 136:
                raw_data[x, y] = (0, 0, 0, 255)

    for y in range(img.size[1]):
        for x in range(img.size[0]):
            if raw_data[x, y][2] > 0:
                raw_data[x, y] = (255, 255, 255, 255)

    # 設定為32*32的大小
    img = img.resize((32, 32), Image.LANCZOS)

    # 進行儲存,友善檢視
    img.save('test.png')

    # 得到像素數組,為(32,32,4)
    array = plt.array(img)

    # 按照公式将其轉為01, 公式: 0.299 * R + 0.587 * G + 0.114 * B

    gray_array = np.zeros((32, 32))

    # 行數
    for x in range(array.shape[0]):
        # 列數
        for y in range(array.shape[1]):
            # 計算灰階,若為255則白色,數值越小越接近黑色
            gary = 0.299 * array[x][y][0] + 0.587 * array[x][y][1] + 0.114 * array[x][y][2]

            # 設定一個阙值,記為0
            if gary == 255:
                gray_array[x][y] = 0
            else:
                # 否則認為是黑色,記為1
                gray_array[x][y] = 1

    # 得到對應名稱的txt檔案
    name01 = filename.split('.')[0]
    name01 = name01 + '.txt'

    # 儲存到檔案中
    np.savetxt(name01, gray_array, fmt='%d', delimiter='')


if __name__ == '__main__':
    picTo01('picture.jpg')
           
  • 手寫數字識别代碼編寫

    KNN的輸入是圖檔矩陣展開的1024維向量;輸出是一個數字。

    KNN手寫數字識别實體建構

    1.建立工程并導入sklearn包

    2.加載訓練資料

    3.建構knn分類器

    4.測試集評價

    5.進行預測

    6.将預測結果寫入txt檔案

# -*- coding: utf-8 -*-
"""
Created on Sat Aug  3 16:24:13 2019

@author: 53592
"""

import numpy as np
from os import listdir
from sklearn import neighbors

#将32*32的圖檔轉換為1*1024的向量
def img2vector(filename):
    retMat = np.zeros([1024],int)
    fr = open(filename)
    lines = fr.readlines()
    for i in range(32):
        for j in range(32):
            retMat[32*i+j] = lines[i][j]
    return retMat

#加載訓練資料
def readDataSet(path):
    fileList = listdir(path)
    numFiles = len(fileList)
    dataSet = np.zeros([numFiles,1024],int)
    hwLabels = np.zeros([numFiles])
    for i in range(numFiles):
        filePath = fileList[i]
        digit = int(filePath.split('_')[0])
        hwLabels[i] = digit
        dataSet[i] = img2vector(path+'/'+filePath)
    return dataSet,hwLabels

train_dataSet,train_hwLabels = readDataSet('trainingDigits')
test_dataSet,test_hwLabels = readDataSet('testDigits')

knn = neighbors.KNeighborsClassifier(algorithm='kd_tree',n_neighbors=3)
knn.fit(train_dataSet,train_hwLabels)
res = knn.predict(test_dataSet)
num = len(test_dataSet)
error_num = np.sum(res != test_hwLabels)
correct_num = np.sum(res == test_hwLabels)
print("Total num:",num,"Wrong num:",error_num,"WrongRate:",error_num/float(num),'correct_num:',correct_num,'CorrectRate:',correct_num/float(num))
           
  • 微信機器人的實作

    此處又用到了強大的wxpy

    官方說明書:點此進入

from wxpy import *

bot = Bot(cache_path=True)
client = bot.friends().search('friend')[0]
client.send("輸入‘功能’,檢視微信機器人功能")

@bot.register()
def response_function(msg):
#機器人的功能介紹(待完善。。。)
    if(msg.text=='功能'):
        client.send("手寫數字識别,請發送一張手寫數字圖檔")

@bot.register(client,msg_types=PICTURE)
def handdigit_recongnition(msg):
    client.send("手寫數字識别中。。。")
    msg.get_file(save_path='D:\Python\digit.jpg')
    '''
    此時執行圖檔轉換成矩陣的代碼
    還要進行knn.predict()将預測結果寫到檔案digit.txt中
    '''
    with open("D:\\Python\\digit.txt",'r') as f:
        f.seek(0)
        b=f.read()
        f.close()
        #機器人回複預測結果
        client.send(b)
        
embed()
           

結果展示

  • 與微信機器人的對話
    機器學習之KNN結合微信機器人實作手寫數字識别終極API手寫數字識别

改進之處和TIPS

  • 設定鄰居數量可以對比預測準确率
  • 設定交叉驗證可以檢測分類器的準确率
  • KNN算法隻是方法之一,還可以利用神經網絡進行識别,添加不同個數的神經元進行訓練,最後預測。
  • 由于神經網絡對于小資料容易過拟合沒是以準确率上面KNN大于MLP(多層感覺機),MLP對于參數調整比較敏感,若參數不合理容易得到較差的分類結果,是以參數設計對于MLP至關重要。
  • 微信機器人還可以進行其他有趣的功能,除了我之前寫的微信實作遠端控制,我後續還會發一些有趣的執行個體
  • 代碼分開了是以有的銜接我沒放,給大家想象的空間,自己繼續探索吧!