又是一個(gè)很有熱度的周末,除了炎熱的天氣,還有火熱的世界杯。今天人工智能頭條為大家準(zhǔn)備的技術(shù)干貨,讓大家可以在空調(diào)下,吃瓜看球兩不耽誤就可以輕松完成AI應(yīng)用實(shí)踐入門。多少次,在我們查找很多資源、技術(shù)指導(dǎo)后,實(shí)操時(shí)還是會(huì)被一個(gè)報(bào)錯(cuò)而終止了前進(jìn)的道路。小編也曾經(jīng)歷過這樣的心路歷程,所以一份好的指南對(duì)于剛開始實(shí)踐操作的同學(xué)來(lái)說(shuō)簡(jiǎn)直太有愛了,不僅節(jié)約了很多時(shí)間,操作和思路也都是清晰的。如果你是剛?cè)腴T的AI小白,想通過一些簡(jiǎn)單的應(yīng)用實(shí)踐對(duì)AI應(yīng)用有更深入的了解,現(xiàn)在就開始和我們一起開始吧!
作者簡(jiǎn)介:鄒欣,現(xiàn)任微軟亞洲研究院研發(fā)經(jīng)理,負(fù)責(zé)必應(yīng)搜索客戶端、必應(yīng)輸入法、必應(yīng)詞典、微軟小娜等產(chǎn)品。曾出版《移山之道》、《編輯之美》(合作)、《構(gòu)建之法》三部書籍。
下面為大家介紹鄒欣老師的AI應(yīng)用開發(fā)實(shí)踐系列教程之手寫識(shí)別應(yīng)用入門,本次教程學(xué)習(xí)主要分三步:
從零開始搭建你的開發(fā)環(huán)境,無(wú)論是Windows 還是 MAC OS 環(huán)境
簡(jiǎn)單的 MNIST 模型訓(xùn)練
入門手寫體識(shí)別應(yīng)用實(shí)踐
這波操作大家放心可以輕松完成,教程中不僅介紹了每步需要做什么,還為你準(zhǔn)備了有參考價(jià)值的命令行、代碼、各安裝軟件版本號(hào)的明確說(shuō)明、需要下載或者訪問的鏈接以及截圖和教程視頻,可以說(shuō)非常全面、到位了。
▌為你的 Windows 搭建開發(fā)環(huán)境并開始訓(xùn)練第一個(gè)模型
(1)準(zhǔn)備工作:一臺(tái)能聯(lián)網(wǎng)的電腦,使用 win10 64 位操作系統(tǒng),請(qǐng)確保鼠標(biāo)、鍵盤、顯示器都是好的
(2)安裝步驟:
安裝 Git
安裝 VS,等待時(shí)間看網(wǎng)絡(luò)狀況,沒準(zhǔn)可以看半場(chǎng)球反正不用擔(dān)心不用著急。
安裝 python
安裝 CUDA 和 cuDNN:這是教程中最繁瑣的一步,這一步直接拉高教程的平均難度。
配置機(jī)器學(xué)習(xí)環(huán)境:這是教程中最簡(jiǎn)單的一步,為了方便用戶配置環(huán)境,微軟提供了一鍵安裝工具!簡(jiǎn)直業(yè)界良心!
安裝 VS Tools For AI插件
(3)離線模型的訓(xùn)練:注意在此過程中使用最新的 mnist.py 文件
文章鏈接:
https://blog.csdn.net/softwareteacher/article/details/80770079
▌為你的 MAC OS 搭建開發(fā)環(huán)境并開始訓(xùn)練第一個(gè)模型
(1)準(zhǔn)備工作:一臺(tái)能聯(lián)網(wǎng)的電腦,使用 MAC OS 操作系統(tǒng),請(qǐng)確保鼠標(biāo)、鍵盤、顯示器都是好的
(2)安裝步驟:
安裝 VS,同樣時(shí)間長(zhǎng)的小伙伴們不妨考慮去看半場(chǎng)球啊!
安裝 python
安裝 Tools for AI 插件
安裝 Git
下載機(jī)器學(xué)習(xí)示例庫(kù)
(3)模型訓(xùn)練:也是小編的第一個(gè)模型!在教程中孩子特別補(bǔ)充講解了如何在遠(yuǎn)程 Linux 上進(jìn)行訓(xùn)練。
文章鏈接:
https://blog.csdn.net/softwareteacher/article/details/80770239
▌AI應(yīng)用開發(fā)實(shí)踐—手寫識(shí)別應(yīng)用入門
敲重點(diǎn)?。?!環(huán)境搭建和模型訓(xùn)練都搞定后,接下來(lái)終于可以上手應(yīng)用實(shí)踐了,以下為手寫識(shí)別應(yīng)用教程全文,enjoy!
手寫體識(shí)別的應(yīng)用已經(jīng)非常流行了,如輸入法,圖片中的文字識(shí)別等。但對(duì)于大多數(shù)開發(fā)人員來(lái)說(shuō),如何實(shí)現(xiàn)這樣的一個(gè)應(yīng)用,還是會(huì)感覺無(wú)從下手。本文從簡(jiǎn)單的 MNIST 訓(xùn)練出來(lái)的模型開始,和大家一起入門手寫體識(shí)別。
在本教程結(jié)束后,會(huì)得到一個(gè)能用的 AI應(yīng)用,也許是你的第一個(gè)AI應(yīng)用。雖然離實(shí)際使用還有較大的距離(具體差距在文章后面會(huì)分析),但會(huì)讓你對(duì)AI應(yīng)用有一個(gè)初步的認(rèn)識(shí),有能力逐步搭建出能夠?qū)嶋H應(yīng)用的模型。
原文鏈接:
https://blog.csdn.net/softwareteacher/article/details/80770347
▌準(zhǔn)備工作
使用 win10 64 位操作系統(tǒng)的計(jì)算機(jī)
參考上一篇博客 AI應(yīng)用開發(fā)實(shí)戰(zhàn) - 從零開始配置環(huán)境。在電腦上訓(xùn)練并導(dǎo)出 MNIST 模型。
▌一. 思路
通過上一篇文章搭建環(huán)境的介紹后,就能得到一個(gè)能識(shí)別單個(gè)手寫數(shù)字的模型了,并且識(shí)別的準(zhǔn)確度會(huì)在 98%,甚至 99% 以上了。那么我們要怎么使用這個(gè)模型來(lái)搭建應(yīng)用呢?
大致的步驟如下:
實(shí)現(xiàn)簡(jiǎn)單的界面,將用戶用鼠標(biāo)或者觸屏的輸入變成圖片。
將生成的模型包裝起來(lái),成為有公開數(shù)據(jù)接口的類。
將輸入的圖片進(jìn)行規(guī)范化,成為數(shù)據(jù)接口能夠使用的格式。
最后通過模型來(lái)推理 (inference) 出圖片應(yīng)該是哪個(gè)數(shù)字,并顯示出來(lái)。
是不是很簡(jiǎn)單?
▌二.動(dòng)手
步驟一:獲取手寫的數(shù)字
提問:那我們要怎么獲取手寫的數(shù)字呢?
回答:我們可以寫一個(gè)簡(jiǎn)單的 WinForm 畫圖程序,讓我們可以用鼠標(biāo)手寫數(shù)字,然后把圖片保存下來(lái)。
首先,我們打開 Visual Studio,選擇文件->新建->項(xiàng)目。

在彈出的窗口里選擇 Visual C#->Windows窗體應(yīng)用,項(xiàng)目名稱不妨叫做 DrawDigit,解決方案名稱不妨叫做 MnistForm,點(diǎn)擊確定。

此時(shí),Visual Studio 也自動(dòng)彈出了一個(gè)窗口的設(shè)計(jì)圖。

在 DrawDigit 項(xiàng)目上點(diǎn)擊右鍵,選擇屬性,在生成一欄將平臺(tái)目標(biāo)從 Any CPU 改為 x 64。

否則,DrawDigit(首選32位)與它引用的 MnistForm(64位)的編譯平臺(tái)不一致會(huì)引發(fā) System.BadImageFormatException 的異常。
然后我們對(duì)這個(gè)窗口做一些簡(jiǎn)單的修改:
首先我們打開 VS 窗口左側(cè)的工具箱,這個(gè)窗口程序需要以下三種組件:
1. PictureBox:用來(lái)手寫數(shù)字,并且把數(shù)字保存成圖片
2. Label:用來(lái)顯示模型的識(shí)別結(jié)果
3. Button:用來(lái)清理PictureBox的手寫結(jié)果
那經(jīng)過一些簡(jiǎn)單的選擇與拖動(dòng)還有調(diào)整大小,這個(gè)窗口現(xiàn)在是這樣的:

一些注意事項(xiàng)
這些組件都可以通過右鍵->查看屬性,在屬性里修改它們的設(shè)置
為了方便把 PictureBox 里的圖片轉(zhuǎn)化成 Mnist 能識(shí)別的格式,PictureBox 的需要是正方形
可以給這些控件起上有意義的名稱。
可以調(diào)整一下 label 控件大小、字體等,讓它更美觀。
經(jīng)過一些簡(jiǎn)單的調(diào)整,這個(gè)窗口現(xiàn)在是這樣的:

現(xiàn)在來(lái)讓我們愉快地給這些組件添加事件!
還是在屬性窗口,我們選擇某個(gè)組件,右鍵->查看屬性,點(diǎn)擊閃電符號(hào),給組件綁定對(duì)應(yīng)的事件。每次綁定后,會(huì)跳到代碼部分,生成一個(gè)空函數(shù)。點(diǎn)回設(shè)計(jì)視圖繼續(xù)操作即可。
| 組件類型 | 事件 |
| pictureBox1 | 在Mouse下雙擊MouseDown、MouseUp、MouseMove來(lái)生成對(duì)應(yīng)的響應(yīng)事件函數(shù)。 |
| button1 | 如上,在Action下雙擊Click。 |
| Form1 | 如上,在Behavior下雙擊Load。 |
然后我們開始補(bǔ)全對(duì)應(yīng)的函數(shù)體內(nèi)容。
注意,如果在上面改變了控件的名稱,下面的代碼需要做對(duì)應(yīng)的更改。
廢話少說(shuō)上代碼!
usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Drawing.Drawing2D;//用于優(yōu)化繪制的結(jié)果usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Windows.Forms;usingMnistModel;namespaceDrawDigit{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}privateBitmapdigitImage;//用來(lái)保存手寫數(shù)字privatePointstartPoint;//用于繪制線段,作為線段的初始端點(diǎn)坐標(biāo)privateMnistmodel;//用于識(shí)別手寫數(shù)字privateconstintMnistImageSize=28;//Mnist模型所需的輸入圖片大小privatevoidForm1_Load(objectsender,EventArgse){//當(dāng)窗口加載時(shí),繪制一個(gè)白色方框model=newMnist();digitImage=newBitmap(pictureBox1.Width,pictureBox1.Height);Graphicsg=Graphics.FromImage(digitImage);g.Clear(Color.White);pictureBox1.Image=digitImage;}privatevoidclean_click(objectsender,EventArgse){//當(dāng)點(diǎn)擊清除時(shí),重新繪制一個(gè)白色方框,同時(shí)清除label1顯示的文本digitImage=newBitmap(pictureBox1.Width,pictureBox1.Height);Graphicsg=Graphics.FromImage(digitImage);g.Clear(Color.White);pictureBox1.Image=digitImage;label1.Text="";}privatevoidpictureBox1_MouseDown(objectsender,MouseEventArgse){//當(dāng)鼠標(biāo)左鍵被按下時(shí),記錄下需要繪制的線段的起始坐標(biāo)startPoint=(e.Button==MouseButtons.Left)?e.Location:startPoint;}privatevoidpictureBox1_MouseMove(objectsender,MouseEventArgse){//當(dāng)鼠標(biāo)在移動(dòng),且當(dāng)前處于繪制狀態(tài)時(shí),根據(jù)鼠標(biāo)的實(shí)時(shí)位置與記錄的起始坐標(biāo)繪制線段,同時(shí)更新需要繪制的線段的起始坐標(biāo)if(e.Button==MouseButtons.Left){Graphicsg=Graphics.FromImage(digitImage);PenmyPen=newPen(Color.Black,40);myPen.StartCap=LineCap.Round;myPen.EndCap=LineCap.Round;g.DrawLine(myPen,startPoint,e.Location);pictureBox1.Image=digitImage;g.Dispose();startPoint=e.Location;}}privatevoidpictureBox1_MouseUp(objectsender,MouseEventArgse){//當(dāng)鼠標(biāo)左鍵釋放時(shí)//同時(shí)開始處理圖片進(jìn)行推理//暫時(shí)不處理這里的代碼}}}
步驟二:把模型包裝成一個(gè)類
將模型包裝成一個(gè) C# 是整個(gè)過程中比較麻煩的一步。所幸的是,Tools for AI 對(duì)此提供了很好的支持。進(jìn)一步了解,可以看這里(https://github.com/Microsoft/vs-tools-for-ai/blob/master/docs/zh-hans/docs/model-inference.md)。
首先,我們?cè)诮鉀Q方案 MnistForm 下點(diǎn)擊鼠標(biāo)右鍵,選擇添加->新建項(xiàng)目,在彈出的窗口里選擇 AI Tools->Inference->模型推理類庫(kù),名稱不妨叫做 MnistModel,點(diǎn)擊確定,于是我們又多了一個(gè)項(xiàng)目。

然后自己配置好這個(gè)項(xiàng)目的名稱、位置,點(diǎn)擊確定。
然后彈出一個(gè)模型推理類庫(kù)創(chuàng)建向?qū)?,這個(gè)時(shí)候就需要我們選擇自己之前訓(xùn)練好的模型了~

首先在模型路徑里選擇保存的模型文件的路徑。這里我們使用在AI應(yīng)用開發(fā)實(shí)戰(zhàn) - 從零開始配置環(huán)境博客中訓(xùn)練并導(dǎo)出的模型
note:模型可在 /samples-for-ai/examples/tensorflow/MNIST 目錄下找到,其中 output 文件夾保存了檢查點(diǎn)文件,export 文件夾保存了模型文件。
對(duì)于TensorFlow,我們可以選擇檢查點(diǎn)的 .meta 文件,或者是保存的模型的 .pb 文件
這里我們選擇在AI應(yīng)用開發(fā)實(shí)戰(zhàn) - 從零開始配置環(huán)境這篇博客最后生成的 export 目錄下的檢查點(diǎn)的 SavedModel.pb 文件,這時(shí)程序?qū)⒆詣?dòng)配置好配置推理接口,見下圖:

類名可以自己定義,因?yàn)槲覀冇玫氖?MNIST,那么類名就叫 Mnist 好了,然后點(diǎn)擊確定。
這樣,在解決方案資源管理器里,在解決方案 MnistForm 下,就多了一個(gè) MnistModel:

雙擊 Mnist.cs,我們可以看到項(xiàng)目自動(dòng)把模型進(jìn)行了封裝,生成了一個(gè)公開的 infer 函數(shù)。
然后我們?cè)?MnistModel 上右擊,再選擇生成,等待一會(huì),這個(gè)項(xiàng)目就可以使用了~
步驟三:連接兩個(gè)部分
這一步差不多就是這么個(gè)感覺:
I have an apple , I have a pen. AH~ , Applepen
首先,我們來(lái)給 DrawDigit 添加引用,讓它能使用 MnistModel。在 DrawDigit 項(xiàng)目的引用上點(diǎn)擊鼠標(biāo)右鍵,點(diǎn)擊添加引用,在彈出的窗口中選擇 MnistModel,點(diǎn)擊確定。


然后,由于 MNIST 的模型的輸入是一個(gè) 28×28 的白字黑底的灰度圖,因此我們首先要對(duì)圖片進(jìn)行一些處理。
首先將圖片轉(zhuǎn)為 28×28 的大小。
然后將 RGB 圖片轉(zhuǎn)化為灰階圖,將灰階標(biāo)準(zhǔn)化到 [-0.5,0.5] 區(qū)間內(nèi),轉(zhuǎn)換為黑底白字。
最后將圖片用 mnist 模型要求的格式包裝起來(lái),并傳送給它進(jìn)行推理。
于是,我們?cè)?pictureBox1_MouseUp 中添加上這些代碼,并且在文件最初添加上 using MnistModel;:
privatevoidpictureBox1_MouseUp(objectsender,MouseEventArgse){//當(dāng)鼠標(biāo)左鍵釋放時(shí)//開始處理圖片進(jìn)行推理if(e.Button==MouseButtons.Left){BitmapdigitTmp=(Bitmap)digitImage.Clone();//復(fù)制digitImage//調(diào)整圖片大小為Mnist模型可接收的大小:28×28using(Graphicsg=Graphics.FromImage(digitTmp)){g.InterpolationMode=InterpolationMode.HighQualityBicubic;g.DrawImage(digitTmp,0,0,MnistImageSize,MnistImageSize);}//將圖片轉(zhuǎn)為灰階圖,并將圖片的像素信息保存在list中varimage=newList
最后讓我們嘗試一下運(yùn)行~
▌三.效果展示
現(xiàn)在我們就有了一個(gè)簡(jiǎn)單的小程序,可以識(shí)別手寫的數(shù)字了。
趕緊試試效果怎么樣~
▌注意
1.路徑中不能有中文字符,否則可能找不到模型。
▌進(jìn)階
那么,如果要識(shí)別多個(gè)連寫的數(shù)字,或支持字母該怎么做呢?大家多用用也會(huì)發(fā)現(xiàn),如果數(shù)字寫得很小,或者沒寫到正中,識(shí)別起來(lái)正確率也會(huì)不高。要解決這些問題,做成真正的產(chǎn)品,就不止這一個(gè)模型了。比如在多個(gè)數(shù)字識(shí)別中,可能要根據(jù)經(jīng)驗(yàn)來(lái)切分圖,或者訓(xùn)練另一個(gè)模型來(lái)檢測(cè)并分割數(shù)字。要支持字母,則需要重新訓(xùn)練一個(gè)包含手寫字母的模型,并準(zhǔn)備更多的字母的數(shù)據(jù)。要解決字太小的問題,還要檢測(cè)一下字的大小,做合適的放大等等。
我們可以看到,一個(gè)訓(xùn)練出來(lái)的模型本身到一個(gè)實(shí)際的應(yīng)用之間還有不少的功能要實(shí)現(xiàn)。希望我們這一系列的介紹,能夠幫助大家將機(jī)器學(xué)習(xí)的概念帶入到傳統(tǒng)的編程領(lǐng)域中,做出更聰明的產(chǎn)品。
-
WINDOWS
+關(guān)注
關(guān)注
4文章
3702瀏覽量
94055 -
AI
+關(guān)注
關(guān)注
91文章
39793瀏覽量
301412 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8553瀏覽量
136953
原文標(biāo)題:一邊吃瓜看球,一邊完成AI應(yīng)用實(shí)踐——手寫體識(shí)別入門
文章出處:【微信號(hào):AI_Thinker,微信公眾號(hào):人工智能頭條】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
如何學(xué)習(xí)ARM?
【「大模型啟示錄」閱讀體驗(yàn)】對(duì)大模型更深入的認(rèn)知
嵌入式開發(fā)中的一些硬件相關(guān)的概念有哪些
了解MOSFET的一些原理
介紹PMIC硬件電路相關(guān)的一些知識(shí)
模擬電路的一些簡(jiǎn)單的特性
對(duì)3525A運(yùn)用的一些了解
SNMP協(xié)議的一些基本知識(shí)
歸納AI領(lǐng)域一些方向的重要技術(shù)進(jìn)展
如何生成簡(jiǎn)單脈寬調(diào)制所需的基本步驟帶你了解一些基本nhet模塊的操作
通過一些簡(jiǎn)單的應(yīng)用實(shí)踐對(duì)AI應(yīng)用有更深入的了解
評(píng)論