python實現(xiàn)kNN算法識別手寫體數(shù)字的示例代碼
1??傮w概要
kNN算法已經(jīng)在上一篇博客中說明。對于要處理手寫體數(shù)字,需要處理的點主要包括:
(1)圖片的預處理:將png,jpg等格式的圖片轉(zhuǎn)換成文本數(shù)據(jù),本博客的思想是,利用圖片的rgb16進制編碼(255,255,255)為白色,(0,0,0)為黑色,獲取圖片大小后,逐個像素進行判斷分析,當此像素為空白時,在文本數(shù)據(jù)中使用0來替換,反之使用1來替換。
from PIL import Image
'''將圖片轉(zhuǎn)換成文檔,使用0,1分別替代空白和數(shù)字'''
pic = Image.open('/Users/wangxingfan/Desktop/1.png')
path = open('/Users/wangxingfan/Desktop/1.txt','a')
width = pic.size[0]
height = pic.size[1]
for i in range(0,width):
for j in range(0,height):
c_RGB = pic.getpixel((i,j))#獲取該像素所對應的RGB值
if c_RGB[0]+c_RGB[1]+c_RGB[2]>0:#白色
path.write('0')
elif c_RGB[0]+c_RGB[1]+c_RGB[2]==0:#黑色
path.write('1')
else:
pass
path.write('\n')
path.close()
(2)訓練集的構(gòu)建。首先想到的是將(1)中圖片處理后的文本數(shù)據(jù)構(gòu)建成list形式,所以訓練集將是二維數(shù)組,形如[[1,0,1,1,0,,,,,0,1],[0,1,1,1,10,,,,],[0,0,1,0,,,],,,,,]所以我們構(gòu)建函數(shù)處理訓練集數(shù)據(jù)。
2。代碼
簡單的總結(jié)這個算法,就是將測試數(shù)據(jù)向量化,逐個和同樣向量化的訓練數(shù)據(jù)進行kNN運算,求的最短距離出現(xiàn)最多的分類就是我們要的分類。建立訓練集的過程就是將文件數(shù)據(jù)向量化的過程。
#?。痷ser/bin/env python
#-*- coding:utf-8 -*-
from os import listdir#獲取文件目錄下所有文件
'''
from PIL import Image
#將圖片轉(zhuǎn)換成文檔,使用0,1分別替代空白和數(shù)字
pic = Image.open('/Users/wangxingfan/Desktop/1.png')
path = open('/Users/wangxingfan/Desktop/1.txt','a')
width = pic.size[0]
height = pic.size[1]
for i in range(0,width):
for j in range(0,height):
c_RGB = pic.getpixel((i,j))#獲取該像素所對應的RGB值
if c_RGB[0]+c_RGB[1]+c_RGB[2]>0:#白色
path.write('0')
elif c_RGB[0]+c_RGB[1]+c_RGB[2]==0:#黑色
path.write('1')
else:
pass
path.write('\n')
path.close()
'''
import numpy as np
import operator as opt
def kNN(dataSet, labels, testData, k):
'''首先明確列表不能想加減,dataSet是數(shù)組形式,而對于下面的test函數(shù),testData只是一列,相當于列表,所以在進行加減時,需要將其轉(zhuǎn)換為數(shù)組,我們使用np下的tile函數(shù)來實現(xiàn)'''
testDatasize = dataSet.shape[0]#獲取dataSet的總行數(shù)
dataSet = dataSet.astype('float64')#不進行轉(zhuǎn)換則報錯
testData1 = np.tile(testData,(testDatasize,1))#使用tile函數(shù)返回多個重復構(gòu)成的數(shù)組
testData1 = testData1.astype('float64')
distSquareMat = (dataSet - testData1) ** 2 # 計算差值的平方
distSquareSums = distSquareMat.sum(axis=1) # 求每一行的差值平方和,axis=0則按列計算
distances = distSquareSums ** 0.5 # 開根號,得出每個樣本到測試點的距離
sortedIndices = distances.argsort() # 排序,得到排序后的下標
indices = sortedIndices[:k] # 取最小的k個
labelCount = {} # 存儲每個label的出現(xiàn)次數(shù),出現(xiàn)次數(shù)最多的就是我們要選擇的類別
for i in indices:
label = labels[i]
labelCount[label] = labelCount.get(label, 0) + 1 # 次數(shù)加一,使用字典的get方法,第一次出現(xiàn)時默認值是0
sortedCount = sorted(labelCount.items(), key=opt.itemgetter(1), reverse=True) # 對label出現(xiàn)的次數(shù)從大到小進行排序
return sortedCount[0][0] # 返回出現(xiàn)次數(shù)最大的label
#定義函數(shù)讀取某個文件,返回該文件組成的數(shù)組
def file_data(fname):
arr = []
path = open(fname)
for i in range(0,32):
line = path.readline()
for j in range(0,32):
arr.append(line[j])
return arr
#建立訓練數(shù)據(jù)集
def train_data():
lables = []
file_list = listdir('/學習/視頻課程/源碼/第7周/testandtraindata/traindata/')
trainarr = np.zeros((len(file_list),1024))
for i in range(0,len(file_list)):
file = '/學習/視頻課程/源碼/第7周/testandtraindata/traindata/'+file_list[i]
lables.append(file_list[i].split('_')[0])#獲取對應的文件類別
trainarr[i,:] = file_data(file)#取所有列的第一個數(shù)據(jù)
return trainarr,lables
#測試函數(shù)
def test():
j = 0
k = 0
trainarr,lables = train_data()
testdata_list = listdir('/學習/視頻課程/源碼/第7周/testandtraindata/testdata/')
for i in range(0,len(testdata_list)):#逐個去測試
testfile = '/學習/視頻課程/源碼/第7周/testandtraindata/testdata/'+testdata_list[i]
testdata1 = file_data(testfile)
result = kNN(trainarr,lables,testdata1,k=3)
print(result+',real_number:'+testdata_list[i].split('_')[0])
if result == testdata_list[i].split('_')[0]:
j +=1
else:
k +=1
print('辨識成功率:'+j/(k+j))
test()
輸出結(jié)果為:

3。幾個知識點代碼說明
(1)numpy.tile
p = np.array([0,0,0]) np.tile(p,(3,1))#表示columns方向重復三次,index方向不變 Out[12]: array([[0, 0, 0], [0, 0, 0], [0, 0, 0]]) np.tile(p,(1,3))#表示index方向重復三次,行還是一行 Out[13]: array([[0, 0, 0, 0, 0, 0, 0, 0, 0]])
(2)array[1,:]表示取所有列的第【索引1】個數(shù)據(jù)(也就是第二行數(shù)據(jù))
a = np.array([[1,1,1],[2,2,2],[3,3,3],[4,4,4]]) a[1,:] Out[21]: array([2, 2, 2]) a[:,1]#所有行的第二列數(shù)據(jù) Out[22]: array([1, 2, 3, 4])
(3)list并不能進行加減計算,需要使用numpy將數(shù)據(jù)轉(zhuǎn)換為數(shù)組形式,且在使用例如:arr1+arr2時,需要兩個數(shù)組的維度相同,在某個緯度上的數(shù)據(jù)長度也相同。
(4)使用os模塊下的listdir,可以顯示所有該文件夾下的文件,以列表的形式返回。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python實現(xiàn)生成隨機數(shù)據(jù)插入mysql數(shù)據(jù)庫的方法
這篇文章主要介紹了Python實現(xiàn)生成隨機數(shù)據(jù)插入mysql數(shù)據(jù)庫的方法,涉及Python隨機字符串生成及數(shù)據(jù)庫連接、插入等相關(guān)操作技巧,需要的朋友可以參考下2017-12-12
PySide2出現(xiàn)“ImportError: DLL load failed: 找不到指定的模塊”的問題及解決方法
這篇文章主要介紹了PySide2出現(xiàn)“ImportError: DLL load failed: 找不到指定的模塊”的問題及解決方法,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2020-06-06
Python PyQt5干貨滿滿小項目輕松實現(xiàn)高效摳圖去背景
PyQt5以一套Python模塊的形式來實現(xiàn)功能。它包含了超過620個類,600個方法和函數(shù)。本篇文章手把手帶你用PyQt5輕松實現(xiàn)圖片扣除背景,大家可以在過程中查缺補漏,提升水平2021-11-11

