簡(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è)喜歡或者贊或者收藏噢~