理解代碼
上文主要介紹了人工智能模型的集成過程。人工智能模型的正確集成,是我們案例中人工智能應(yīng)用開發(fā)的核心步驟。但要讓一個人工智能應(yīng)用順利地被使用,除了集成模型之外的一些工作也是必不可少的,比如處理輸入的數(shù)據(jù),進(jìn)行界面交互等。
應(yīng)用的主體邏輯都在 MNIST.App 項目的 文件中,該文件包括了界面聯(lián)動、數(shù)據(jù)預(yù)處理兩部分的代碼,以及一行推理預(yù)測的代碼。剩下的都是自動生成的代碼。界面聯(lián)動是為了實現(xiàn)手寫輸入時的良好體驗;而數(shù)據(jù)預(yù)處理部分是在推理前,將用戶輸入的筆跡變?yōu)槟P退枰斎氲母↑c數(shù)組。MainWindow.cs
小提示
代碼中包含了非常詳盡的注釋。建議在讀完本章節(jié)后,再通讀代碼中的注釋,以便更深入地理解整個代碼邏輯。
界面聯(lián)動
-
展開?MNIST.App?項目,找到 文件。所有的界面設(shè)計和代碼都在這里。先雙擊它,打開設(shè)計界面??梢钥吹?,設(shè)計界面和程序?qū)嶋H運行起來的效果非常像。窗體上包含了三個控件:,,以及 。稍后會介紹控件對應(yīng)的變量名稱,以及綁定的控件事件響應(yīng)函數(shù)、這些控件用途等。
MainWindow.cs
PictureBox
Label
Button
-
在窗體的設(shè)計界面上右擊,并選擇?查看代碼,可以看到核心的代碼。如圖所示。
- 打開代碼后,可以看到,幾乎每一行代碼都有對應(yīng)的注釋。除了類里的?等幾個變量外,剩下的邏輯幾乎都在事件響應(yīng)函數(shù)中。這些響應(yīng)函數(shù)是在控件屬性的事件面板中添加的。每個控件都在代碼中可以通過變量名稱來使用。界面邏輯的一些重要信息如下:
ImageSize
變量名稱 | 控件類型 | 綁定的事件響應(yīng)函數(shù) | 控件的用途 |
---|---|---|---|
Form1 |
Form |
Form1_Load |
主窗體。加載時會一次性初始化部分變量。 |
writeArea |
PictureBox |
writeArea_MouseDown 、writeArea_MouseMove writeArea_MouseUp
|
手寫區(qū)域。 在鼠標(biāo)操作時,響應(yīng)鼠標(biāo)的按下(MouseDown)、移動(MouseMove)、釋放(MouseUp)事件。 在觸摸屏操作時,與鼠標(biāo)操作類似,會響應(yīng)手指的接觸屏幕、在屏幕上移動、離開屏幕的事件。 |
outputText |
Label |
文本標(biāo)簽。顯示推理結(jié)果的數(shù)字。 | |
clean |
Button |
clean_Click |
清除按鈕。在每次推理前清除手寫區(qū)內(nèi)容,及文本標(biāo)簽顯示的數(shù)字。 |
數(shù)據(jù)預(yù)處理
數(shù)據(jù)預(yù)處理是 AI 應(yīng)用的重要一環(huán)。在大部分 AI 應(yīng)用中,特別是本文的圖片分類應(yīng)用中,通過監(jiān)督學(xué)習(xí)來訓(xùn)練模型。即先提供一些標(biāo)記過分類的圖片來訓(xùn)練出模型,然后輸入未知的圖片,推理預(yù)測出此圖片的類別。因此,在訓(xùn)練和推理過程中,每次輸入模型的數(shù)據(jù)格式必須完全一致,這樣才能保證預(yù)測推理的效果。
本示例已知了訓(xùn)練數(shù)據(jù)的輸入形式,所以按圖索驥就能寫出代碼。在 AI 的實際應(yīng)用中,一定要了解模型輸入數(shù)據(jù)的格式細(xì)節(jié),嚴(yán)格的實現(xiàn)它。如果數(shù)據(jù)格式細(xì)節(jié)不一致,通常會降低推理結(jié)果的正確率。而這類問題幾乎不會產(chǎn)生編譯或運行錯誤,而且數(shù)據(jù)是不易直觀理解的浮點數(shù)組,所以對此類問題的診斷和修正較困難。
下面會介紹一下本例中的數(shù)據(jù)預(yù)處理過程,從而體會一下數(shù)據(jù)預(yù)處理中的細(xì)節(jié)問題。
-
數(shù)據(jù)預(yù)處理的第一步,在窗體設(shè)計時,手寫區(qū)域調(diào)整為了正方形,和訓(xùn)練數(shù)據(jù)的形狀保持一致。
-
定義了類變量?常量等于?。這是訓(xùn)練數(shù)據(jù)的實際圖片尺寸。界面上的正方形最終會縮小為?。
ImageSize
28
28x28
private const int ImageSize = 28;
-
clear_Click
函數(shù)中設(shè)置了手寫區(qū)域的背景為白色。訓(xùn)練數(shù)據(jù)是黑白的,需要將前景、背景顏色同樣設(shè)置,而與訓(xùn)練數(shù)據(jù)一樣,達(dá)到最大的對比度。
graphics.Clear(Color.White);
-
writeArea_MouseMove
事件中設(shè)置了手寫筆風(fēng)格。手寫筆跡寬度是40,顏色為黑色,開始、結(jié)束位置設(shè)成圓頭。
筆跡寬度與圖片尺寸的比例基本匹配了訓(xùn)練數(shù)據(jù)的比例。但無法控制用戶輸入的文字大小,還會有一些誤差。好在深度學(xué)習(xí)的模型適應(yīng)性較強,對識別準(zhǔn)確率的影響不太大。
黑色筆跡配合了白色背景,形成最大的對比度。
筆跡的開始、結(jié)束位置為圓頭。在書寫過程中會多次調(diào)用到鼠標(biāo)移動事件中,每次根據(jù)上一次的結(jié)束位置到當(dāng)前位置畫了一條直線。如果不將筆頭設(shè)置為圓頭,就會像圖 13中一樣,這些直線會形成矩形拼接起來,形成很多不連續(xù)的位置。既影響識別,也不美觀。
Pen penStyle = new Pen(Color.Black, 40)
{
StartCap = LineCap.Round,
EndCap = LineCap.Round
};
-
writeArea_MouseUp
事件中包含了其它的數(shù)據(jù)處理邏輯。首先構(gòu)造了 28x28 的圖片,將手寫的圖片縮放到了新的圖片對象中。
Bitmap clonedBmp = new Bitmap(writeArea.Image, ImageSize, ImageSize);
- 按行、列遍歷了 28x28 位圖中的所有節(jié)點,并取出了每個像素,處理后存入數(shù)組中。
for (int y = 0; y < ImageSize; y++)
{
for (int x = 0; x < ImageSize; x++)
{
Color color = clonedBmp.GetPixel(x, y);
// 此處略過處理過程。包括reversed變量的定義,請參見下文。
image.Add((float)reversed);
}
}
- 將紅綠藍(lán)通道加和并平均,完成了像素灰度化。手寫識別模型的輸入數(shù)據(jù)是黑白圖。
手寫區(qū)是白底黑字,每個顏色通道的值其實是一樣的。為了邏輯上的嚴(yán)密和便于理解,所以對值取了均值,進(jìn)行灰度化。
double average = (color.R + color.G + color.B) / 3.0;
- 將取值范圍變換到了 0~1。機器學(xué)習(xí)中取值范圍變化很大,因此絕大部分機器學(xué)習(xí)模型都用浮點數(shù)進(jìn)行計算。
double oneValue = average / 255;
- 將數(shù)值翻轉(zhuǎn),并做+0.5 的位移。這一步可以減少輸入數(shù)據(jù)中零值的數(shù)量。
過多的零,會讓中間結(jié)果也出現(xiàn)更多的零,使得神經(jīng)網(wǎng)絡(luò)容易丟失信息。白色背景通過灰度化之后灰度值是 255,經(jīng)變換后為 -0.5;黑色筆跡灰度化之后灰度值是0,經(jīng)變換后為 0.5。這樣處理后,大部分值都成為了非零值。最重要的是我們所依賴的模型(衍生自腳本),對輸入數(shù)據(jù)的處理也是如此。mnist.py
對于數(shù)據(jù)的取反,是經(jīng)驗的做法。通過試驗,在很多情況下取反后的訓(xùn)練效果會更好。MNIST數(shù)據(jù)集的數(shù)據(jù)也是取反保存的。
double reversed = 0.5 - oneValue;
推理
推理即輸入數(shù)據(jù)并獲取模型的預(yù)測結(jié)果。這一步非常簡單,輸入變換后的一維數(shù)組,輸出預(yù)測結(jié)果即可。推理函數(shù)每次調(diào)用可以輸入多張圖片,進(jìn)行批量預(yù)測。
long inferResult = model.Infer(new List<IEnumerable<float>> { image }).First().First();
小提示
如果有興趣的話,可以看看Mnist 項目中生成的用于訪問模型代碼。該項目里還包含了優(yōu)化后的模型數(shù)據(jù)文件。
實際場景
本示例非常簡單,還不足以成為實際的手寫識別產(chǎn)品。但經(jīng)過這小小的一步,就邁入了開發(fā) AI 應(yīng)用的門檻。通過組合多個模型,混合傳統(tǒng)的編程方法,就能打造出強大的 AI 產(chǎn)品。
這里拋磚引玉,提出一些實際中會遇到的問題,并提出一些解決方案供參考。除此之外,在真正應(yīng)用時還會發(fā)現(xiàn)更多的問題,如連筆文字,歪斜矯正,梯形校正等等。所以,雖然有了 AI 模型,可以將更多的不可能變?yōu)榭赡埽枰能浖_發(fā)工程量還是很大。要做出一款產(chǎn)品,除了與 AI 相關(guān)的新問題外,傳統(tǒng)軟件開發(fā)中的問題一樣都不會少。
思考實際場景中問題的同時,也會培養(yǎng) AI 的應(yīng)用意識。做產(chǎn)品時,如果遇到了有很多數(shù)據(jù),但很難找到規(guī)律的情況。不妨思考一下,能否使用 AI 模型來解決這個問題?有了這樣的 AI 意識,就能更好的將 AI 和傳統(tǒng)軟件相結(jié)合,創(chuàng)造出讓人眼前一亮、用戶體驗自然的產(chǎn)品。
在大部分 AI 應(yīng)用中,數(shù)據(jù)非常重要。我們經(jīng)??梢钥吹揭恍?AI 討論中會說,數(shù)據(jù)是 AI 應(yīng)用的基礎(chǔ)。在下面的解決方案中也能看出,很多方案依賴于大量的、有代表性的數(shù)據(jù)才能實現(xiàn)。
另外,從下面的方案中也可以看到,傳統(tǒng)方案很易于理解和實現(xiàn),但處理噪音等數(shù)據(jù)卻比較棘手。AI 模型的質(zhì)量則取決于數(shù)據(jù)和算法。究竟哪個更好,要在實際應(yīng)用中進(jìn)行驗證,才能有結(jié)論。也可以同時使用多種方案,再通過一個 AI 模型來決定使用哪個方法的結(jié)果。
大小不一或沒有居中
在嘗試書寫的時候也會發(fā)現(xiàn),當(dāng)字寫得小一點,或者寫偏一點,錯誤識別的情況就會變多。這是因為訓(xùn)練數(shù)據(jù)為了提高識別率,對數(shù)據(jù)都進(jìn)行了居中、縮放的處理??赡艿慕鉀Q方案有兩種:
采用圖像處理算法,找到筆跡像素的分布中心,將其居中。并根據(jù)外圍的筆跡像素來進(jìn)行縮放,適配到識別區(qū)中。此方法邏輯清晰,不需要數(shù)據(jù)進(jìn)行訓(xùn)練。缺點是如果手寫數(shù)據(jù)來源于攝像頭,會有很多噪點,會造成誤判。
訓(xùn)練一個目標(biāo)檢測(Object Detect)的 AI 模型來自動框出合適的大小。這種方法會將需要的目標(biāo)(即字符)用矩形框出來、并基本保證其居中。將矩形做適當(dāng)?shù)目s放后,既可作為輸入。如果數(shù)據(jù)量足夠且有代表性,這種方法的效果會不錯。但目標(biāo)檢測需要的數(shù)據(jù)標(biāo)記工作卻很繁瑣,需要對每個訓(xùn)練數(shù)據(jù)中的字符畫框標(biāo)記,標(biāo)記的質(zhì)量也直接影響到了識別的質(zhì)量。
一次識別多個字符
在書寫時,實際情況通常是書寫一句話或者一個等式,很少只輸入一個字符。多字符識別時,需要將其分割為單字符進(jìn)行逐個識別。其中主要有兩個問題,一是將字符分割開,二是將字符進(jìn)行排序。
- 分割字符
傳統(tǒng)的解決方案較多,這里列舉兩種:
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#1f2328"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>a. 找到相鄰的點進(jìn)行擴展,找到每一筆,然后根據(jù)矩形是否重合來找到每個字。這種方法的缺點是如果在識別中文等情況下,遇到左右或者上下結(jié)構(gòu),可能會被識別成兩個字符。
b. 檢查每一列,如果沒有任何筆跡像素,則將左右兩方切割開來。但這樣在左右結(jié)構(gòu)時仍然會遇到問題,也不支持縱向書寫。
</code></span></span></span></span>
用 AI 模型,可以使用上文提到的目標(biāo)檢測(Object Detect)方法,框出每個字符。
- 字符排序
單個字符本身的意義還不夠,語言文字中需要將字符組成詞語和句子,才有更豐富的含義。在上一步中,雖然分割出了單個的字符,在完成識別后,還需要將它們組合成詞語和句子。除了常見的橫向書寫外,還有縱向書寫。如果紙上沒有畫線,還可能越寫越歪。這一步可以用傳統(tǒng)的方法根據(jù)各個方向的距離等因素判斷是否是連續(xù)的字符串。
個人風(fēng)格迥異
識別不同書寫風(fēng)格,是個數(shù)據(jù)問題。如果有了有代表性的數(shù)據(jù)集,這個問題就迎刃而解了。
識別字母、符號、中文
同上,數(shù)據(jù)是最重要的。另外,隨著問題規(guī)模的變大,使用的?模型有可能也需要做相應(yīng)的修改,需要有足夠的復(fù)雜度來容納新的信息。如,中文字符比較復(fù)雜,可能 28x28 的大小不夠表達(dá)足夠多的細(xì)節(jié),需要原始輸入的尺寸更大。AI
?
常見問題
克隆代碼出現(xiàn)錯誤
在教育網(wǎng)等網(wǎng)絡(luò)環(huán)境里,訪問 GitHub 較不穩(wěn)定。如果不能找到其它網(wǎng)絡(luò)環(huán)境的話,只能試著在網(wǎng)絡(luò)的非高峰使用期進(jìn)行克隆。
創(chuàng)建模型項目時出現(xiàn)錯誤
如果在添加模型項目完成后,沒有在目錄下看到?文件。通常是因為網(wǎng)絡(luò)不穩(wěn)定,下載超時造成的。請參考下面的過程手工下載依賴的庫。packages.config
右擊?Model?項目,選擇管理?NuGet 程序包...。
如下圖所示,在彈出的 NuGet 頁面里,點擊?瀏覽,然后輸入?ml.scoring,來手工搜索需要的 NuGet 包。
點選搜索出的?Microsoft.ML.Scoring,點擊右邊的?安裝,然后點擊?確定,如下圖所示。然后我們會在輸出界面看到開始添加?Microsoft.ML.Scoring?的信息。如果網(wǎng)速較慢,這一步會花費一些時間。完成后,即可根據(jù)本文內(nèi)容進(jìn)行下一步操作。
運行時提示"系統(tǒng)找不到指定的路徑"
一般是由于路徑中有中文字符造成的,需要將整個解決方案移動到不包含中文的路徑中。
???在線教程
- 麻省理工學(xué)院人工智能視頻教程?– 麻省理工人工智能課程
- 人工智能入門?– 人工智能基礎(chǔ)學(xué)習(xí)。Peter Norvig舉辦的課程
- EdX 人工智能?– 此課程講授人工智能計算機系統(tǒng)設(shè)計的基本概念和技術(shù)。
- 人工智能中的計劃?– 計劃是人工智能系統(tǒng)的基礎(chǔ)部分之一。在這個課程中,你將會學(xué)習(xí)到讓機器人執(zhí)行一系列動作所需要的基本算法。
- 機器人人工智能?– 這個課程將會教授你實現(xiàn)人工智能的基本方法,包括:概率推算,計劃和搜索,本地化,跟蹤和控制,全部都是圍繞有關(guān)機器人設(shè)計。
- 機器學(xué)習(xí)?– 有指導(dǎo)和無指導(dǎo)情況下的基本機器學(xué)習(xí)算法
- 機器學(xué)習(xí)中的神經(jīng)網(wǎng)絡(luò)?– 智能神經(jīng)網(wǎng)絡(luò)上的算法和實踐經(jīng)驗
- 斯坦福統(tǒng)計學(xué)習(xí)
有需要的小伙伴,可以點擊下方鏈接免費領(lǐng)取或者V掃描下方二維碼免費領(lǐng)取??
?
人工智能書籍
- OpenCV(中文版).(布拉德斯基等)
- OpenCV+3計算機視覺++Python語言實現(xiàn)+第二版
- OpenCV3編程入門 毛星云編著
- 數(shù)字圖像處理_第三版
- 人工智能:一種現(xiàn)代的方法
- 深度學(xué)習(xí)面試寶典
- 深度學(xué)習(xí)之PyTorch物體檢測實戰(zhàn)
- 吳恩達(dá)DeepLearning.ai中文版筆記
- 計算機視覺中的多視圖幾何
- PyTorch-官方推薦教程-英文版
- 《神經(jīng)網(wǎng)絡(luò)與深度學(xué)習(xí)》(邱錫鵬-20191121)
- …
第一階段:零基礎(chǔ)入門(3-6個月)
新手應(yīng)首先通過少而精的學(xué)習(xí),看到全景圖,建立大局觀。?通過完成小實驗,建立信心,才能避免“從入門到放棄”的尷尬。因此,第一階段只推薦4本最必要的書(而且這些書到了第二、三階段也能繼續(xù)用),入門以后,在后續(xù)學(xué)習(xí)中再“哪里不會補哪里”即可。
第二階段:基礎(chǔ)進(jìn)階(3-6個月)
熟讀《機器學(xué)習(xí)算法的數(shù)學(xué)解析與Python實現(xiàn)》并動手實踐后,你已經(jīng)對機器學(xué)習(xí)有了基本的了解,不再是小白了。這時可以開始觸類旁通,學(xué)習(xí)熱門技術(shù),加強實踐水平。在深入學(xué)習(xí)的同時,也可以探索自己感興趣的方向,為求職面試打好基礎(chǔ)。
第三階段:工作應(yīng)用
這一階段你已經(jīng)不再需要引導(dǎo),只需要一些推薦書目。如果你從入門時就確認(rèn)了未來的工作方向,可以在第二階段就提前閱讀相關(guān)入門書籍(對應(yīng)“商業(yè)落地五大方向”中的前兩本),然后再“哪里不會補哪里”。
?有需要的小伙伴,可以點擊下方鏈接免費領(lǐng)取或者V掃描下方二維碼免費領(lǐng)取??
?
文章來源:http://www.zghlxwxcb.cn/news/detail-820051.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-820051.html
到了這里,關(guān)于AI手寫數(shù)字識別(二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!