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