使用AI算法进行手写数字识别
人工智能
??人工智能(Artificial Intelligence,簡稱AI)一詞最初是在1956年Dartmouth學(xué)會上提出的,從那以后,研究者們發(fā)展了眾多理論和原理,人工智能的概念也隨之?dāng)U展。由于人工智能的研究是高度技術(shù)性和專業(yè)的,各分支領(lǐng)域都是深入且各不相通的,因而涉及范圍極廣 。 人工智能的核心問題包括建構(gòu)能夠跟人類似甚至超越人類的推理、知識、學(xué)*、交流、感知、使用工具和操控機(jī)械的能力等,當(dāng)前人工智能已經(jīng)有了初步成果,甚至在一些影像識別、語言分析、棋類游戲等等單方面的能力達(dá)到了超越人類的水平 。
??人工智能的分支領(lǐng)域非常多,主要有演繹推理、知識表示、規(guī)劃、學(xué)*、自然語言處理……等十多個(gè)分支領(lǐng)域,而以機(jī)器學(xué)*為代表的“學(xué)*”領(lǐng)域,是目前研究最廣泛的分支之一。
機(jī)器學(xué)*
?? 機(jī)器學(xué)*(Machine Learning)是人工智能的一個(gè)分支,它是實(shí)現(xiàn)人工智能的一個(gè)途徑,即以機(jī)器學(xué)*為手段解決人工智能中的問題。機(jī)器學(xué)*在*30多年已發(fā)展為一門多領(lǐng)域交叉性的學(xué)科,涉及概率論、統(tǒng)計(jì)學(xué)、逼*論、凸分析、計(jì)算復(fù)雜性理論等多門學(xué)科。
?? 機(jī)器學(xué)*理論主要是設(shè)計(jì)和分析一些讓計(jì)算機(jī)可以自動“學(xué)*”的算法,該算法是一類從數(shù)據(jù)中自動分析獲得規(guī)律,并利用規(guī)律對未知數(shù)據(jù)進(jìn)行預(yù)測的算法。
深度學(xué)*
??深度學(xué)*(Deep Learning)是機(jī)器學(xué)*的分支,是一種以人工神經(jīng)網(wǎng)絡(luò)為架構(gòu),對數(shù)據(jù)進(jìn)行表征學(xué)*的算法。表征學(xué)*的目標(biāo)是尋求更好的表示方法并創(chuàng)建更好的模型來從大規(guī)模未標(biāo)記數(shù)據(jù)中學(xué)*這些表示方法。表示方法來自神經(jīng)科學(xué),并松散地創(chuàng)建在類似神經(jīng)系統(tǒng)中的信息處理和對通信模式的理解上,如神經(jīng)編碼,試圖定義拉動神經(jīng)元的反應(yīng)之間的關(guān)系以及大腦中的神經(jīng)元的電活動之間的關(guān)系。
??因此,人工智能、機(jī)器學(xué)*、深度學(xué)*的關(guān)系如下圖所示。
??至今已有數(shù)種深度學(xué)*模型,如深度神經(jīng)網(wǎng)絡(luò)、卷積神經(jīng)網(wǎng)絡(luò)和深度置信網(wǎng)絡(luò)和遞歸神經(jīng)網(wǎng)絡(luò)已被應(yīng)用在計(jì)算機(jī)視覺、語音識別、自然語言處理、音頻識別與生物信息學(xué)等領(lǐng)域并獲取了極好的效果。
??目前,業(yè)內(nèi)也已經(jīng)產(chǎn)生了多種優(yōu)秀的深度學(xué)*框架,例如TensorFlow、PyTorch、Caffe、Mxnet等等。但這些都不是本文討論的重點(diǎn),本文主要以機(jī)器學(xué)*初學(xué)者的身份,使用最基本的機(jī)器學(xué)*算法,加以微積分、線性代數(shù)、概率統(tǒng)計(jì)等基礎(chǔ)數(shù)學(xué)知識,來解決手寫數(shù)字的識別的問題。
問題背景
??為什么要去研究數(shù)字的識別問題呢?因?yàn)樽?剛過雙11,又看了到許多曝光快遞行業(yè)野蠻分揀的新聞。據(jù)某快遞公司負(fù)責(zé)人回應(yīng)稱,之所以會出現(xiàn)野蠻分揀的問題,主要是雙11期間快遞數(shù)量巨增,為了盡快派發(fā)收到的快遞,他們不得不請了許多“臨時(shí)工”,而這些“臨時(shí)工”缺乏培訓(xùn),缺乏規(guī)范操作,所以出現(xiàn)了暴力分揀快遞的問題。
問題分析
??針對分揀快遞這種簡單、重復(fù)的工作,可以交給機(jī)器去做嗎?我們來分析一下“臨時(shí)工”所做的工作。“臨時(shí)工”拿到一個(gè)快遞,找到快遞上的快遞單,然后再找到目的省(城市),如果是華北城市,則將快遞扔進(jìn)“北京”的筐里;如果是華東城市,則扔進(jìn)“上海”的筐里;如果是西南城市,則扔進(jìn)“成都”的筐里。那么機(jī)器可以完成嗎?
??如上圖所示,快遞通過傳送帶進(jìn)入“目的地識別系統(tǒng)”,識別后將該快遞分配到對應(yīng)地點(diǎn)的傳送帶即可。那么,該問題的關(guān)鍵就是“目的地識別系統(tǒng)”如何將快遞單上的目的地識別出來,并作出正確的判斷。
??以順豐速運(yùn)的快遞單為例,快遞單上已將目的地翻譯為了城市代碼,通過識別該代碼即可讓機(jī)器“知道”快遞的目的地,然后配置對應(yīng)傳送帶接收的具體城市代碼即可。
??識別數(shù)字技術(shù)在深度學(xué)*領(lǐng)域已經(jīng)非常成熟,常見的解決方案是OpenCV+Keras+TensorFlow,例如Github上有比較完善的車牌識別項(xiàng)目,但本文并不打算使用這些庫,而是采用最底層、最基礎(chǔ)的機(jī)器學(xué)*方法來實(shí)現(xiàn)。
數(shù)學(xué)建模
??數(shù)字照片通過掃描后,以像素點(diǎn)的方式進(jìn)行存儲,因此輸入數(shù)據(jù)即是像素點(diǎn),通過機(jī)器學(xué)*算法后,結(jié)果則是識別出來的0-9的數(shù)字。根據(jù)機(jī)器學(xué)*理論,每個(gè)樣本都有對應(yīng)的標(biāo)簽,因此屬于“監(jiān)督式學(xué)*”的范疇。而樣本的輸出值為0-9固定的10種情況,因此可以采用邏輯回歸的機(jī)器學(xué)*模型來解決,分別計(jì)算結(jié)果為0-9的概率,建模就是找到一個(gè)假設(shè)函數(shù)(Hypothesis Function),函數(shù)值是數(shù)據(jù)通過假設(shè)函數(shù)后獲得對應(yīng)的輸出結(jié)果,即概率。
??邏輯回歸的假設(shè)函數(shù)是由S型函數(shù)(Sigmoid Function)演變而來,S型函數(shù)的表達(dá)式及曲線如下圖所示:
??從曲線中可以看到,當(dāng)變量z趨*于正無窮時(shí),函數(shù)值趨*于1,當(dāng)變量z趨*于負(fù)無窮時(shí),函數(shù)值趨*于0。這樣就能夠很好的匹配邏輯回歸,因?yàn)檫壿嫽貧w的輸出為0或1,當(dāng)輸出值為0.7時(shí),則表示結(jié)果為1的概率是70%,為0的概率是30%,正好可以進(jìn)行概率的預(yù)測。
??受線性回歸所啟發(fā),邏輯回歸的假設(shè)函數(shù)公式為(其中θ為模型的參數(shù)矩陣,x為輸入變量矩陣,變量z變成了θ的轉(zhuǎn)置乘以x):
??如果要讓機(jī)器來識別數(shù)字,那么首先就要先用樣本去教會機(jī)器,即用樣本“訓(xùn)練”模型。為了獲得“最好”的模型,我們需要計(jì)算樣本在模型下的代價(jià)函數(shù)(Cost Function,也有資料稱為“損失函數(shù)”)。所謂代價(jià)函數(shù),就是在該模型下產(chǎn)生的輸出與實(shí)際結(jié)果間產(chǎn)生的偏差,偏差越小,則可以在一定程度上表明模型越好(也不是絕對的,可能會出現(xiàn)模型過度擬合(Overfit)的情況,需要一些手段來避免)。
??通過概率統(tǒng)計(jì)理論中的“最大似然估計(jì)”,可以得到如下的邏輯回歸的代價(jià)函數(shù):
??該函數(shù)看起來很復(fù)雜,可以將其拆開來看,log(h(x))是y=1時(shí)的代價(jià)函數(shù),log(1-h(x))是y=0時(shí)的代價(jià)函數(shù),最右邊的一項(xiàng)為正則化參數(shù),可以減小出現(xiàn)過度擬合的幾率。為了找到最好的模型(假設(shè)函數(shù)),我們需要找到該代價(jià)函數(shù)的最小值。找到最小值后,自變量θ即為我們要找的邏輯回歸的模型參數(shù)。
??根據(jù)高等數(shù)學(xué)中的“拉格朗日中值定理”,可以得知該函數(shù)為凹函數(shù),存在最小值。證明過程比較復(fù)雜,不在此闡述。
模型訓(xùn)練
??為了得到代價(jià)函數(shù)J(θ)的最小值,我們可以采用機(jī)器學(xué)*中最常用的“梯度下降”算法(Gradient Decent)來求得函數(shù)在區(qū)間內(nèi)的極小值。所謂梯度下降算法,就是對于任一函數(shù),首先取任一點(diǎn)(x1或者x2均可),在這一點(diǎn)減去這一點(diǎn)對應(yīng)的梯度(即該點(diǎn)的導(dǎo)數(shù)),那么這一點(diǎn)就會向該函數(shù)的某一極小值運(yùn)動,反復(fù)進(jìn)行梯度下降,則可以得到區(qū)間內(nèi)的極小值x0。如果函數(shù)為凹函數(shù),那么該極小值就是函數(shù)的最小值。
??因此,執(zhí)行梯度下降的公式為:
??這里需要對J(θ)求“偏導(dǎo)數(shù)”,求得后的結(jié)果為:
??至此,理論工作準(zhǔn)備完畢,可以進(jìn)行編碼實(shí)戰(zhàn)。
在Matlab/Octave中訓(xùn)練
??輸入樣本為手寫數(shù)字,以20 * 20像素點(diǎn)的形式存儲,將像素點(diǎn)數(shù)據(jù)攤開作為一行,每行就有400個(gè)像素點(diǎn)信息。訓(xùn)練樣本中搜集了5000個(gè)手寫數(shù)字的照片,因此樣本X為5000 * 400的矩陣,樣本結(jié)果y為5000 * 1的列向量。
% 計(jì)算代價(jià)函數(shù)
J = 1 / m * (-y' * log(sigmoid(X * theta)) - (1 - y)' * log(1 - sigmoid(X * theta)));
% 計(jì)算梯度
grad = 1 / m * X' * (sigmoid(X * theta) - y);
% 代價(jià)函數(shù)正則化
J = J + lambda / (2 * m) * (sum(theta(2:end) .^ 2));
% 梯度正則化
theta_temp = theta;
theta_temp(1) = 0;
grad = grad + lambda / m * theta_temp;
??通過以上代碼,就可以實(shí)現(xiàn)一次代價(jià)函數(shù)的計(jì)算,并返回當(dāng)前點(diǎn)的梯度。根據(jù)之前的分析,只要重復(fù)進(jìn)行梯度下降即可。而Matlab提供了一種更加簡便的方式“fmincg”函數(shù),它能采用類似梯度下降的方式,來自動優(yōu)化參數(shù)θ。
% 初始化theta
initial_theta = zeros(n + 1, 1);
% 參數(shù)
options = optimset('GradObj', 'on', 'MaxIter', 50);
% 循環(huán)所有數(shù)字
for c = 1:num_labels
% 訓(xùn)練出最優(yōu)theta
theta = fmincg(@(t)(lrCostFunction(t, X, (y == c), lambda)), initial_theta, options);
all_theta(c, :) = theta;
endfor
??可以看到,上述代碼進(jìn)行了1-10總共10個(gè)模型的訓(xùn)練,每個(gè)模型就是識別0-9這10個(gè)數(shù)字的概率。通過以上訓(xùn)練后,就可以得到最后的theta,將其帶入假設(shè)函數(shù)hθ(x),于是就得到了我們訓(xùn)練后的10個(gè)模型,可以用該模型來進(jìn)行手寫數(shù)字的識別。
數(shù)字識別
??利用已經(jīng)訓(xùn)練好的10個(gè)模型,我們就可以將機(jī)器從未見過的手寫數(shù)字通過10個(gè)模型,讓每個(gè)模型計(jì)算出他是對應(yīng)數(shù)字的概率,然后我們?nèi)∽罡叩母怕剩涂梢缘玫綑C(jī)器識別出的數(shù)字。我們來舉個(gè)例子:
??如圖紅框中的數(shù)字,可能有的人會認(rèn)成“4”,而有的人卻會認(rèn)成“6”。到底是4還是6呢?可能眾說紛紜,因?yàn)橛械娜?慣這樣寫4,而有的人卻不*慣這樣寫。在機(jī)器學(xué)*中,機(jī)器會學(xué)*之前樣本中的數(shù)據(jù),學(xué)*到作者寫數(shù)字的*慣,將該測試樣本分別輸入到10個(gè)模型后,得到如下的概率輸出(均保留5位有效數(shù)字):
| 數(shù)字 | 概率 | 數(shù)字 | 概率 |
|---|---|---|---|
| 0 | 0.0000021328% | 5 | 0.0000015184% |
| 1 | 0.0000021719% | 6 | 99.987% |
| 2 | 2.3224% | 7 | 0.000033508% |
| 3 | 0.0000012768% | 8 | 0.0011023% |
| 4 | 0.013391% | 9 | 0.032251% |
??通過如上數(shù)據(jù)可以看到,數(shù)字6的匹配度高達(dá)99.987%占據(jù)了絕對領(lǐng)先,第二則是數(shù)字2的2.3224%。而數(shù)字4只有0.013391的概率,看來在機(jī)器學(xué)*看來,這個(gè)數(shù)字基本可以判定為“6”,只是稍微有一丁點(diǎn)像“2”,跟其他數(shù)字都特別不像。我們?nèi)「怕首畲笾担贸隽苏_的結(jié)果為數(shù)字“6”。
??我們用測試樣本的真實(shí)值對模型進(jìn)行校驗(yàn),最終獲得訓(xùn)練的正確率為94.9%。那么取100個(gè)測試樣本的識別結(jié)果如何呢?
??可以看到,100個(gè)測試樣本的識別結(jié)果有5個(gè)數(shù)字識別錯(cuò)誤,測試識別率為95%。那么有什么方法可以提高識別率呢?
提高梯度下降次數(shù)
??通過之前的理論分析我們知道,梯度下降次數(shù)越多,代價(jià)函數(shù)就越接*最小值,于是我把次數(shù)從50提高到100時(shí),測試樣本準(zhǔn)確率達(dá)到了95.98,提升了約1%。然后又提高到200時(shí),達(dá)到了96.4%,提升了約0.5%。最后提高到500時(shí),仍為96.4%,沒有提升。
??看來在邏輯回歸模型下,手寫數(shù)字的識別率最高僅可以提升到96.4%,已經(jīng)達(dá)到了最高。還有其他辦法可以提升識別率嗎?
神經(jīng)網(wǎng)絡(luò)
??人工神經(jīng)網(wǎng)絡(luò)(Artificial Neural Network),簡稱神經(jīng)網(wǎng)絡(luò)(Neural Network,NN),在機(jī)器學(xué)*和認(rèn)知科學(xué)領(lǐng)域,是一種模仿生物神經(jīng)網(wǎng)絡(luò)(動物的中樞神經(jīng)系統(tǒng),特別是大腦)的結(jié)構(gòu)和功能的數(shù)學(xué)模型或計(jì)算模型,用于對函數(shù)進(jìn)行估計(jì)或*似。
??神經(jīng)網(wǎng)絡(luò)由大量的人工神經(jīng)元聯(lián)結(jié)進(jìn)行計(jì)算,大多數(shù)情況下人工神經(jīng)網(wǎng)絡(luò)能在外界信息的基礎(chǔ)上改變內(nèi)部結(jié)構(gòu),是一種自適應(yīng)系統(tǒng),通俗的講就是具備學(xué)*功能,并且是一種非線性統(tǒng)計(jì)性數(shù)據(jù)建模工具。
??不得不說,人類是真的聰明,居然可以想到建立類似于生物大腦神經(jīng)的模型來模擬大腦,從而實(shí)現(xiàn)部分人類的能力。神經(jīng)網(wǎng)絡(luò)模型如下:
??可以看到,基本的神經(jīng)網(wǎng)絡(luò)模型有輸入層、隱藏層、輸出層。輸入層用于接受輸入信號,類似于人類感知視覺信號、聲音信號、觸覺信號等等。隱藏層可以是多層,可以讓數(shù)據(jù)在不同層之間傳遞與處理,類似于人類的神經(jīng)元,可以逐級傳遞。輸出層用于輸出處理后的數(shù)據(jù)。如果有非常多的隱藏層,又可以稱為深度神經(jīng)網(wǎng)絡(luò),在這種模型下的機(jī)器學(xué)*又稱作深度學(xué)*。
??由于神經(jīng)網(wǎng)絡(luò)是一種非線性模型,屬于邏輯結(jié)構(gòu),因此沒有簡單的“假設(shè)函數(shù)”。要計(jì)算數(shù)據(jù)通過輸入層、隱藏層后到輸出層的數(shù)據(jù),可以通過“正向傳播算法”(Forward Propagation)。
正向傳播
??神經(jīng)網(wǎng)絡(luò)模型看似復(fù)雜,如果只看一層的話,就可以用邏輯回歸的模型來推導(dǎo),因?yàn)槊恳粚佣际沁壿嫽貧w問題。若θ1與θ2已知(圖中標(biāo)識),那么就可以用邏輯回歸來計(jì)算每一層的輸出,然后逐漸從左到右,正向傳遞,所以稱為正向傳播,最終得出輸出值hθ(x)。
??正向傳播的步驟如下:
??假設(shè)函數(shù)有了,如果我們能找到模型的θ1與θ2,那么模型就有了,就可以用這個(gè)模型來進(jìn)行數(shù)字識別了。那么怎么才能找到合適的θ1與θ2呢?與之前講的邏輯回歸類似,我們也可以先找到該模型的代價(jià)函數(shù),然后通過梯度下降找到代價(jià)函數(shù)的最小值,就可以找到神經(jīng)網(wǎng)絡(luò)的參數(shù)了。
代價(jià)函數(shù)
??前面已經(jīng)提到,神經(jīng)網(wǎng)絡(luò)模型其實(shí)就是有很多層的邏輯回歸模型,那么代價(jià)函數(shù)也可以采用邏輯回歸的代價(jià)函數(shù),然后將每一層網(wǎng)絡(luò)疊加起來就可以了,所以神經(jīng)網(wǎng)絡(luò)的代價(jià)函數(shù)如下:
??公式看起來比較嚇人,實(shí)際上只是多了網(wǎng)絡(luò)層數(shù)K,并且參數(shù)θ從向量變成了矩陣而已。如果把這個(gè)公式轉(zhuǎn)化為矩陣形式,其實(shí)非常的簡單(不含最右邊的正則化):
% m為樣本數(shù),y為樣本結(jié)果矩陣,h為由正向傳播計(jì)算出的輸出矩陣。
J = - 1 / m * (sum(sum(y .* log(h))) + sum(sum((1 - y) .* log(1-h))));
??代價(jià)函數(shù)有了,梯度該怎么算呢?與邏輯回歸不同,因?yàn)樵黾恿藢訑?shù)的概念,所以梯度計(jì)算也會變得比較復(fù)雜,神經(jīng)網(wǎng)絡(luò)里稱為“反向傳播算法”(Backward Propagation)。
反向傳播
??求解梯度,最終還是對代價(jià)函數(shù)進(jìn)行求偏導(dǎo)數(shù),但由于模型是非線性的,無法直接求偏導(dǎo)數(shù)。所以,反向傳播的基本思路就是將最終的計(jì)算偏差分?jǐn)偟矫恳粚樱饾u從右向左,反向傳遞,所以稱為反向傳播。
??反向傳播的步驟如下:
??通過第4步,我們就得到了J(θ)的偏導(dǎo)數(shù),即梯度。
隨機(jī)初始化
??在神經(jīng)網(wǎng)絡(luò)模型中,θ的初始化非常重要。我在訓(xùn)練神經(jīng)網(wǎng)絡(luò)的實(shí)踐中,就因?yàn)橥穗S機(jī)初始化θ,而導(dǎo)致模型非常糟糕,無論怎么訓(xùn)練,識別率都只有40%。吃一塹,長一智。神經(jīng)網(wǎng)絡(luò)不像邏輯回歸中的θ,邏輯回歸中的θ初始為0或者其他任何數(shù)都可以,神經(jīng)網(wǎng)絡(luò)中θ的初始化值直接影響了模型的好壞。
??θ的隨機(jī)初始化的要求如下:
在Matlab/Octave中訓(xùn)練
??正向傳播:
% 計(jì)算h(x)
a1 = [ones(m, 1) X]';
z2 = Theta1 * a1;
a2 = [ones(1, m); sigmoid(z2)];
z3 = Theta2 * a2;
a3 = sigmoid(z3);
h = a3';
??計(jì)算代價(jià)函數(shù):
J = - 1 / m * (sum(sum(y2 .* log(h))) + sum(sum((1 - y2) .* log(1-h))));
% 計(jì)算正則化后的J
% 去掉theta的第一列,即去掉theta0
Theta1_new = Theta1(:, 2:end);
Theta2_new = Theta2(:, 2:end);
J = J + (sum(sum(Theta1_new .^ 2)) + sum(sum(Theta2_new .^ 2))) * lambda / (2 * m);
??反向傳播:
% 將y2轉(zhuǎn)化為每一列為一個(gè)樣本
delta3 = a3 - y2';
Theta2_grad = delta3 * a2' / m;
% Theta2需要使用去掉了第一列針對偏置的權(quán)重
delta2 = Theta2_new' * delta3 .* sigmoidGradient(z2);
Theta1_grad = delta2 * a1' / m;
% 正則化,需要將theta的第一列設(shè)置為0
Theta1(:, 1) = 0;
Theta2(:, 1) = 0;
Theta2_grad = Theta2_grad + lambda / m * Theta2;
Theta1_grad = Theta1_grad + lambda / m * Theta1;
??梯度下降:
options = optimset('MaxIter', 50);
lambda = 1;
costFunction = @(p) nnCostFunction(p, ...
input_layer_size, ...
hidden_layer_size, ...
num_labels, X, y, lambda);
[nn_params, cost] = fmincg(costFunction, initial_nn_params, options);
??然后用同樣的訓(xùn)練樣本對神經(jīng)網(wǎng)絡(luò)模型訓(xùn)練后,循環(huán)50次,測試樣本識別率達(dá)到了95.82%。提高到100次,達(dá)到98.14%。提高到200次,達(dá)到了98.94%。最后提高到500次,最終達(dá)到了99.36%。可以看到,神經(jīng)網(wǎng)絡(luò)模型對于手寫數(shù)字識別率高于邏輯回歸模型。
總結(jié)
對于手寫數(shù)字,神經(jīng)網(wǎng)絡(luò)模型一般比邏輯回歸模型的準(zhǔn)確率更高。
邏輯回歸模型只能處理二維的輸出,如果是高維的輸出,需要用多個(gè)模型來降維,而神經(jīng)網(wǎng)絡(luò)可以直接處理多維輸出。
使用簡單的(非深度)神經(jīng)網(wǎng)絡(luò),就可以實(shí)現(xiàn)較高的手寫數(shù)字識別率。
神經(jīng)網(wǎng)絡(luò)模型的初始化參數(shù)非常重要。
在Maltab/Octave中,矩陣的運(yùn)算效率要遠(yuǎn)遠(yuǎn)高于循環(huán)的運(yùn)算效率,因此數(shù)據(jù)處理盡量采用矩陣形式。
??(由于水平有限,本文如有分析得不對之處,還請指正。)
總結(jié)
以上是生活随笔為你收集整理的使用AI算法进行手写数字识别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中年网名大全男78个
- 下一篇: 鱼泡网怎么收费标准(常见的鱼有哪些)