Python徒手實(shí)現(xiàn)識(shí)別手寫數(shù)字—對(duì)圖片結(jié)果進(jìn)行加權(quán)處理

簡(jiǎn)單的加權(quán)算法

寫在前面

距離上一次更新已經(jīng)很久遠(yuǎn)了,所以這一次趁著放假就把全部補(bǔ)完,這一次主要寫的地方是針對(duì)上一章我們得出的排名來進(jìn)行一個(gè)加權(quán)處理,令最后的結(jié)果更可信一點(diǎn)。

因?yàn)榧訖?quán)的方法種類繁多,所以我這里只是簡(jiǎn)單的自己隨意“創(chuàng)造”了一種方法,主要目的還是訓(xùn)練編程能力,所以如果在邏輯方面上存在某些缺陷的話還望見諒。

方法概要

接著上一篇文章,我們得到了距離某一個(gè)待檢測(cè)圖片A1最近的十個(gè)訓(xùn)練用圖片B1, B2, ...,B10。如果通過直接觀察,我們通常情況下可以自己分析出這個(gè)圖片上的數(shù)字很有可能是幾。

比如說我舉個(gè)例子,這十個(gè)圖片上的數(shù)字分別為:3, 1, 1, 2, 1, 4, 1, 1, 2, 3.如果我們看第一名可以知道是3,但是在這十個(gè)數(shù)字中出現(xiàn)頻率最高的是1,并且還占據(jù)挺靠前的位置,另一個(gè)3是出現(xiàn)在最末尾。所以這時(shí)候我們可能會(huì)認(rèn)為這個(gè)數(shù)字是1的可能性更大一點(diǎn)。

也就是說,我們要設(shè)計(jì)一種加權(quán)算法,令最后的排名實(shí)現(xiàn)我們上述思考過程,得到一個(gè)處理后的真實(shí)結(jié)果。

加權(quán)

所以我的思路就是為每個(gè)排名分別加上權(quán)重。當(dāng)然,因?yàn)樯弦黄恼轮形覀兦蟮玫氖请x被識(shí)別數(shù)字的距離,通常我們認(rèn)為是距離越短就越相似,所以說我們最終的評(píng)判標(biāo)準(zhǔn)是越小越好的,那么我們這里的權(quán)重也設(shè)置為是越小越重要。比如說有三個(gè)權(quán)重1, 2, 3,那么1就要比2重要,2比3重要。

按照這樣的思路,我們?yōu)榱朔奖悖蝗【嚯x被識(shí)別數(shù)字最近的五個(gè)圖片B1-B5,權(quán)重分別為1, 2, 3, 4, 5。取成這樣的權(quán)重僅僅是為了方便,目前沒有其他意義。因?yàn)槭琼樖秩〉?,所以說在準(zhǔn)確度可能并沒有十分好。在以后的任務(wù)中我會(huì)想辦法找到一種能夠根據(jù)結(jié)果反饋權(quán)重的算法,從而來確定權(quán)重。

當(dāng)然,我們需要將上面五個(gè)權(quán)重進(jìn)行歸一化處理,也就是說權(quán)重之和為1.那么我們可以簡(jiǎn)單地列一個(gè)方程式,為

x + 2x + 3x + 4x + 5x = 1

其中的x就代表權(quán)重為1的歸一化后的權(quán)重,解出x就可以得到五個(gè)權(quán)重。因此我們可以通過編程很簡(jiǎn)單的得到歸一化后的權(quán)重列表

temp = np.array([1, 2, 3, 4, 5])
weight = list(temp/np.sum(temp))

可以得到五個(gè)權(quán)重分別為

B1 B2 B3 B4 B5
0.066 0.133 0.200 0.266 0.333

求相對(duì)距離

既然權(quán)重求出來了,那么某一個(gè)數(shù)字的總相對(duì)距離就很容易了。我們假設(shè)現(xiàn)在B1, B2屬于同一個(gè)數(shù)字2,B3,B5屬于同一個(gè)數(shù)字3,B4屬于數(shù)字4.所以數(shù)字2的總相對(duì)距離為

d2 = B1w1 + B2w2

數(shù)字3的總相對(duì)距離為

d3 = B3w3 + B5w5

數(shù)字4的總相對(duì)距離為

d4 = B4*w4

因此我們只需要比較d2, d3, d4就可以知道哪一個(gè)數(shù)字可能是這個(gè)待識(shí)別圖片上的數(shù)字。

放代碼

我們把以上內(nèi)容全部設(shè)定成一個(gè)函數(shù),為CalculateWeight函數(shù)。

def CalculateWeight(pictures, n, testFiles):
    '''計(jì)算加權(quán)距離'''
    #權(quán)重(前五名)
    temp = np.array([1, 2, 3, 4, 5])
    weight = list(temp/np.sum(temp))
    weightNum = len(weight)
    for j, pic in enumerate(pictures):
        print(testFiles[j])
        #存儲(chǔ)加權(quán)距離的字典
        weightDict = {}
        for i in range(weightNum):
            #判斷該數(shù)字之前是否出現(xiàn)過
            if str(pic[n+i]) in weightDict:
                weightDict[str(pic[n+i])] = weightDict[str(pic[n+i])] + weight[i]*pic[i]
            else:
                weightDict[str(pic[n+i])] = weight[i]*pic[i]
        ShowRank(weightDict)

pictures是存儲(chǔ)目前所有待檢測(cè)圖片距離其最近的n個(gè)訓(xùn)練圖片的距離以及其對(duì)應(yīng)的數(shù)字,以array形式存在,每一行代表一個(gè)待檢測(cè)圖片,其中前n列寸的是距離,后n列存的是對(duì)應(yīng)的數(shù)字。

testFiles存儲(chǔ)的是每一個(gè)待檢測(cè)圖片的名稱。

利用for對(duì)每一個(gè)待檢測(cè)圖片進(jìn)行循環(huán),首先輸出當(dāng)前待檢測(cè)圖片的名稱,然后建立一個(gè)字典weightDict。這個(gè)字典用來存儲(chǔ)某一個(gè)數(shù)字的總相對(duì)距離,key為數(shù)字,value為總相對(duì)距離。

首先我們需要判斷當(dāng)前的數(shù)字是否已經(jīng)存在于這個(gè)字典中,如果存在,那么就將當(dāng)前算出來的相對(duì)距離加到這個(gè)key對(duì)應(yīng)的的value中;如果不存在,那么就直接將當(dāng)前的相對(duì)距離賦予key對(duì)應(yīng)的value。循環(huán)了weightNum次以后,我們就可以得到當(dāng)前圖片的所有數(shù)字的總相對(duì)距離。這里我們就需要一個(gè)ShowRank函數(shù)來講結(jié)果展示出來。

def ShowRank(weightDict):
    '''輸出單個(gè)圖片的排名順序'''
    maxRank = [0, 9999]
    for item in weightDict:
        #尋找最小距離的數(shù)字
        if weightDict[item] < maxRank[1]:
            maxRank = [item, weightDict[item]]
        print('數(shù)字'+item+'的相對(duì)距離為'+str(weightDict[item]))
    print('最有可能為數(shù)字'+maxRank[0]+',相對(duì)距離為'+str(weightDict[item]))

這個(gè)函數(shù)內(nèi)容就比較簡(jiǎn)單了,我就不再細(xì)說,主要是輸出每一個(gè)數(shù)字與其對(duì)應(yīng)的總相對(duì)距離,并找到最有可能(相對(duì)距離最小)的數(shù)字。

結(jié)果演示

我們可以拿五個(gè)測(cè)試,如下圖所示:

運(yùn)行程序以后我們直接得到了結(jié)果為

測(cè)試1.png
數(shù)字3.0的相對(duì)距離為14.5295906976
數(shù)字7.0的相對(duì)距離為21.6757647617
最有可能為數(shù)字3.0,相對(duì)距離為21.6757647617
測(cè)試2.png
數(shù)字4.0的相對(duì)距離為38.3158180871
最有可能為數(shù)字4.0,相對(duì)距離為38.3158180871
測(cè)試3.png
數(shù)字8.0的相對(duì)距離為2.51083001901
數(shù)字3.0的相對(duì)距離為29.8009289468
數(shù)字5.0的相對(duì)距離為8.16783067288
最有可能為數(shù)字8.0,相對(duì)距離為8.16783067288
測(cè)試4.png
數(shù)字1.0的相對(duì)距離為32.5987662245
數(shù)字3.0的相對(duì)距離為12.2730692216
最有可能為數(shù)字3.0,相對(duì)距離為12.2730692216
測(cè)試5.png
數(shù)字7.0的相對(duì)距離為18.5295580926
數(shù)字9.0的相對(duì)距離為7.94675193285
數(shù)字8.0的相對(duì)距離為14.284403787
最有可能為數(shù)字9.0,相對(duì)距離為14.284403787

可以看出除了測(cè)試4以外,其他全對(duì),測(cè)試4中可能的結(jié)果也有1,也說不上錯(cuò)得太離譜。當(dāng)然,之所以會(huì)出現(xiàn)這樣的結(jié)果,是因?yàn)樗械挠?xùn)練圖片都是我寫的,所以識(shí)別我寫的數(shù)字也就比較準(zhǔn),如果換一個(gè)人寫就不一定了。出現(xiàn)失誤的一切原因都是因?yàn)橛?xùn)練庫太少啊,所以做這種識(shí)別的算法,最主要的還是我們的訓(xùn)練的庫存。庫存越多,信心也就越大。

總結(jié)

這一次就相當(dāng)于告了一段落了,下一次就可能更加復(fù)雜,我想借用神經(jīng)網(wǎng)絡(luò)的那種負(fù)反饋機(jī)制來自動(dòng)修改權(quán)重,從而來達(dá)到更精確的效果。當(dāng)然,這就更加復(fù)雜了,也指不定什么時(shí)候能做出來。

目前來說下一篇應(yīng)該會(huì)是利用qqbot來做qq自動(dòng)回復(fù)機(jī)器人。其包括的功能大概有:指定短語回復(fù),天氣查詢,簽到與積分系統(tǒng)等。

如果喜歡的話,麻煩給一個(gè)喜歡或者贊或者收藏噢~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容