AI应用开发实战(转)
?
AI應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn) - 從零開(kāi)始配置環(huán)境
與本篇配套的視頻教程請(qǐng)?jiān)L問(wèn):https://www.bilibili.com/video/av24421492/
建議和反饋,請(qǐng)發(fā)送到
https://github.com/Microsoft/vs-tools-for-ai/issues
聯(lián)系我們
OpenmindChina@microsoft.com
零、前提條件
- 一臺(tái)能聯(lián)網(wǎng)的電腦,使用win10 64位操作系統(tǒng)
- 請(qǐng)確保鼠標(biāo)、鍵盤(pán)、顯示器都是好的
一、Windows下開(kāi)發(fā)環(huán)境搭建
本教材主要參考了如下資源:
官方github教程:https://github.com/microsoft/vs-tools-for-ai
斗魚(yú)tv教程:https://v.douyu.com/show/V6Aw87OBmXZvYGkg
本教程分為五步:
- 安裝VS:難度一星
- 安裝python:難度一星
- 安裝CUDA和cuDNN:這是本教程最繁瑣的一步,這一步直接拉高本教程的平均難度。
- 配置機(jī)器學(xué)習(xí)環(huán)境:這是本教程最簡(jiǎn)單的一步,為了方便用戶配置環(huán)境,微軟提供了一鍵安裝工具!沒(méi)錯(cuò),一鍵安裝工具!業(yè)界良心阿!
- 安裝VS Tools For AI插件:難度一星
note:本教程對(duì)各個(gè)軟件需要使用的版本都做出了明確說(shuō)明,請(qǐng)安裝指定的版本
請(qǐng)放輕松,接下來(lái)的傻瓜教程不需要?jiǎng)幽X子,你甚至可以打開(kāi)手機(jī)邊刷微博邊配置環(huán)境
0.安裝Git
訪問(wèn) https://git-scm.com/download/win
選擇64-bit Git for Windows Setup下載
雙擊.exe開(kāi)始安裝
選擇好自己的安裝路徑,一路next,直到Adjusting your PATH environment
請(qǐng)選擇Use Git from the Windows Command Prompt
這一步就已經(jīng)將Git添加到環(huán)境變量中了,然后就可以直接在命令行里使用Git啦。
然后繼續(xù)next,直到安裝結(jié)束
1.安裝VS
訪問(wèn) https://www.visualstudio.com/zh-hans/products/
在產(chǎn)品中點(diǎn)擊Visual Studio 2017
選擇Community版本下載
打開(kāi)Visual Studio Installer進(jìn)行如下的配置:
僅選擇.NET桌面開(kāi)發(fā)與Python開(kāi)發(fā)即可
僅選擇.NET桌面開(kāi)發(fā)與Python開(kāi)發(fā)即可
僅選擇.NET桌面開(kāi)發(fā)與Python開(kāi)發(fā)即可
note:請(qǐng)自行決定Visual Studio的安裝路徑
等待數(shù)分鐘,時(shí)長(zhǎng)視網(wǎng)絡(luò)狀況而定,這個(gè)時(shí)候你可以去泡一杯茶,或者聽(tīng)一首歌,如果你的網(wǎng)絡(luò)不是很好,那你可以去看集美劇或者別的什么,等待安裝結(jié)束。
note:坐 和 放寬
2.安裝python
注意!!!如果你已經(jīng)安裝了VS2017帶Python開(kāi)發(fā)的環(huán)境,就不需要再裝一遍python了。打開(kāi)vs2017, 點(diǎn)擊Tools->Python->Python Environments,應(yīng)該可以看到Python 3.6已經(jīng)安裝,在下面有個(gè)folder,大概是“c:\Program Files(x86)\Microsoft Visual Studio\Shared\Python36_64”,把這個(gè)字符串copy下來(lái)。然后打開(kāi)Settings->Home->About->System info,在彈出的窗口中選擇Advanced system settings->Advanced->Environment Variables->System variables->Path->Edit->New,把剛才的python環(huán)境變量字符串paste進(jìn)來(lái)。如果有多個(gè)python環(huán)境,建議把一些舊的版本卸載先,保證你的機(jī)器沒(méi)有那么多垃圾。
點(diǎn)擊OK后,再打開(kāi)一個(gè)command窗口,輸入Python,就可以正常使用了。
訪問(wèn) https://www.python.org/downloads/
選擇版本3.5.4或3.6.5?,Windows x86-64 executable installer下載。
打開(kāi)安裝包,在安裝前,請(qǐng)選擇Add Python 3.X to PATH,隨后按照默認(rèn)選項(xiàng)安裝即可。
點(diǎn)選后,程序?qū)⒆詣?dòng)將Python加入環(huán)境變量,這樣避免在安裝后手動(dòng)配置環(huán)境變量。
安裝結(jié)束后,請(qǐng)進(jìn)行如下操作驗(yàn)證python是否安裝成功
1.同時(shí)按下 win 與 R,在彈出的輸入框里輸入cmd 2.在彈出的窗口中輸入 python 3.輸入exit()退出 4.輸入python -m pip install -U pip以更新pip到最新版本note: pip是一個(gè)用來(lái)管理python包的工具
自此,你已經(jīng)完成了python的安裝,在朝著AI技術(shù)大牛的路上又前進(jìn)了一步!
note:請(qǐng)伸出大拇指給自己一個(gè)贊?
3.安裝CUDA與cuDNN
如果你的電腦裝有Nvidia的顯卡,請(qǐng)進(jìn)行這一步配置,否則請(qǐng)?zhí)^(guò)。
首先通過(guò)操作系統(tǒng)更新,升級(jí)顯卡驅(qū)動(dòng)到最新版。
3.1 安裝CUDA
打開(kāi) https://developer.nvidia.com/cuda-toolkit-archive
選擇CUDA 9.0 進(jìn)行安裝。
點(diǎn)擊后,選擇如下的配置:
note:請(qǐng)選擇local版本下載,一旦失敗還可以重新再來(lái);如果使用network版本,一旦失敗,需要重新下載1.4GB的安裝包
打開(kāi)安裝包,進(jìn)行安裝,請(qǐng)自行配置CUDA的安裝路徑,并手動(dòng)將CUDA庫(kù)添加至PATH環(huán)境變量中。
note:在Windows中,CUDA的默認(rèn)安裝路徑是:
"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin"
3.2 安裝cuDNN
note:打起精神!這是操作最復(fù)雜的一步!
訪問(wèn) https://developer.nvidia.com/rdp/cudnn-archive 找到我們需要的cuDNN版本:
cuDNN v7.0.5 (Dec 5, 2017), for CUDA 9.0
cuDNN v7.0.5 Library for Windows 10
點(diǎn)擊鏈接,等待著你的并不是文件下載,而是:
↑這就是本教程里最麻煩的一步:在下載cuDNN之前需要注冊(cè)Nvidia會(huì)員并驗(yàn)證郵箱。不過(guò)還好可以微信登錄,省掉一些步驟。
一番令人窒息的操作之后,我們終于得到了cuDNN,我們把文件解壓,取出這個(gè)路徑的cudnn64_7.dll,復(fù)制到CUDA的bin目錄下即可。默認(rèn)的地址是:
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin
note:到這里,我們已經(jīng)完成了本教程最復(fù)雜的一步了
4.安裝機(jī)器學(xué)習(xí)的軟件及依賴
這一步雖然是整個(gè)教程最簡(jiǎn)單的一步,甚至比把大象關(guān)進(jìn)冰箱更簡(jiǎn)單。
你只需要:
win + R ,打開(kāi)cmd,在命令行中輸入:cd c:\ //選擇一個(gè)你喜歡的路徑 md AI //在這里創(chuàng)建一個(gè)AI目錄 cd AI //打開(kāi)這個(gè)目錄 //克隆倉(cāng)庫(kù)到本地 git clone https://github.com/Microsoft/samples-for-ai.git cd samples-for-ai //打開(kāi)這個(gè)目錄 cd installer //還有這個(gè)目錄 python.exe install.py //開(kāi)始安裝然后刷會(huì)微博,等待安裝結(jié)束即可。
成功之后是這樣的:
或者你覺(jué)得自己不怕麻煩,那么請(qǐng)?jiān)L問(wèn):https://github.com/Microsoft/vs-tools-for-ai/blob/master/docs/zh-hans/docs/prepare-localmachine.md
根據(jù)教程按步安裝,相信我,你會(huì)回來(lái)選擇一鍵安裝的。
note:就差一步啦!成功就在眼前!
5.安裝tools for ai插件
打開(kāi)Visual Studio,選擇工具->擴(kuò)展和更新->選擇“聯(lián)機(jī)”->搜索“AI”
就像這樣:
等待下載完成之后,關(guān)閉Visual Studio,沒(méi)錯(cuò),關(guān)閉Visual Studio,系統(tǒng)將自動(dòng)安裝AI插件。
安裝完畢后再次打開(kāi)Visual Studio,你將在界面上看到這樣的內(nèi)容:
那么恭喜你!安裝成功!
note:千里之行始于足下,恭喜你成功地完成了環(huán)境的搭建,接下來(lái)就已經(jīng)可以使用Visual Studio Tools For AI進(jìn)行開(kāi)發(fā)了?
二、離線模型的訓(xùn)練
6.14日更新
GitHub上的samples-for-ai進(jìn)行了一定的更新,目前MNIST文件夾下只有一個(gè)mnist.py文件,
下述步驟中,請(qǐng)使用最新的mnist.py文件
在進(jìn)行完環(huán)境搭建后,我們馬上就可以開(kāi)始訓(xùn)練第一個(gè)模型了,我們選擇tensorflow下的MNIST作為第一個(gè)例子。
MNIST的介紹請(qǐng)參考這個(gè)鏈接 https://www.tensorflow.org/versions/r1.1/get_started/mnist/beginners
首先我們打開(kāi)這個(gè)路徑:C:\AI\samples-for-ai\examples\tensorflow,如果你在別的目錄下克隆了目錄,那么請(qǐng)打開(kāi)你對(duì)應(yīng)的目錄。然后雙擊TensorflowExamples.sln
就像這樣:
note:如果存在多個(gè)Python環(huán)境,你需要為Visual Studio的AI項(xiàng)目設(shè)置默認(rèn)的Python環(huán)境。
例如,手動(dòng)安裝的Python 3.5與Visual Studio 2017 Python開(kāi)發(fā)負(fù)載自動(dòng)安裝了64位的Python 3.6
如果要為Visual Studio設(shè)置全局的默認(rèn)Python環(huán)境,請(qǐng)打開(kāi)工具->Python?->?Python環(huán)境。然后,選擇自己需要的Python版本,點(diǎn)擊將此作為新項(xiàng)目的默認(rèn)環(huán)境。
然后在解決方案資源管理器中,選擇MNIST,單擊右鍵,選擇設(shè)為啟動(dòng)項(xiàng)目
然后選擇MNIST中的mnist.py,單擊右鍵,選擇在不調(diào)試的情況下啟動(dòng)
然后程序就開(kāi)始運(yùn)行了,就像這樣:
等待一段時(shí)間之后,模型就訓(xùn)練好了!這個(gè)時(shí)候打開(kāi)MNIST所在的文件夾,MNIST下是否多了三個(gè)文件夾?分別是input和output還有export,這三個(gè)文件夾分別存儲(chǔ)了訓(xùn)練模型的輸入文件、訓(xùn)練時(shí)的檢查點(diǎn)文件,還有最終導(dǎo)出的模型文件
檢查點(diǎn)文件:
模型文件:
可能存在的問(wèn)題
GPU ran out of memory
方法一:
修改convolutional.py第45行或第47行的BATCH_SIZE或EVAL_BATCH_SIZE為一個(gè)更小的數(shù)字。具體修改哪一個(gè),需要視你在程序運(yùn)行的哪個(gè)部分得到了ERROR決定。
方法二:
不使用GPU訓(xùn)練,在項(xiàng)目MNIST上單擊右鍵,選擇屬性(R)
修改環(huán)境變量為CUDA_VISIBLE_DEVICES=" "
?
AI應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn) - 手寫(xiě)識(shí)別應(yīng)用入門(mén)
手寫(xiě)體識(shí)別的應(yīng)用已經(jīng)非常流行了,如輸入法,圖片中的文字識(shí)別等。但對(duì)于大多數(shù)開(kāi)發(fā)人員來(lái)說(shuō),如何實(shí)現(xiàn)這樣的一個(gè)應(yīng)用,還是會(huì)感覺(jué)無(wú)從下手。本文從簡(jiǎn)單的MNIST訓(xùn)練出來(lái)的模型開(kāi)始,和大家一起入門(mén)手寫(xiě)體識(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)用的模型。
建議和反饋,請(qǐng)發(fā)送到
https://github.com/Microsoft/vs-tools-for-ai/issues
聯(lián)系我們
OpenmindChina@microsoft.com
準(zhǔn)備工作
- 使用win10 64位操作系統(tǒng)的計(jì)算機(jī)
- 參考上一篇博客AI應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn) - 從零開(kāi)始配置環(huán)境。在電腦上訓(xùn)練并導(dǎo)出MNIST模型。
一、 思路
通過(guò)上一篇文章搭建環(huán)境的介紹后,就能得到一個(gè)能識(shí)別單個(gè)手寫(xiě)數(shù)字的模型了,并且識(shí)別的準(zhǔn)確度會(huì)在98%,甚至99%以上了。那么我們要怎么使用這個(gè)模型來(lái)搭建應(yīng)用呢?
大致的步驟如下:
是不是很簡(jiǎn)單?
二、動(dòng)手
步驟一:獲取手寫(xiě)的數(shù)字
提問(wèn):那我們要怎么獲取手寫(xiě)的數(shù)字呢?
回答:我們可以寫(xiě)一個(gè)簡(jiǎn)單的WinForm畫(huà)圖程序,讓我們可以用鼠標(biāo)手寫(xiě)數(shù)字,然后把圖片保存下來(lái)。
首先,我們打開(kā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改為x64。
否則,DrawDigit(首選32位)與它引用的MnistForm(64位)的編譯平臺(tái)不一致會(huì)引發(fā)System.BadImageFormatException的異常。
然后我們對(duì)這個(gè)窗口做一些簡(jiǎn)單的修改:
首先我們打開(kāi)VS窗口左側(cè)的工具箱,這個(gè)窗口程序需要以下三種組件:
那經(jīng)過(guò)一些簡(jiǎn)單的選擇與拖動(dòng)還有調(diào)整大小,這個(gè)窗口現(xiàn)在是這樣的:
一些注意事項(xiàng)
經(jīng)過(guò)一些簡(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。 |
然后我們開(kāi)始補(bǔ)全對(duì)應(yīng)的函數(shù)體內(nèi)容。
注意,如果在上面改變了控件的名稱,下面的代碼需要做對(duì)應(yīng)的更改。
廢話少說(shuō)上代碼!
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D;//用于優(yōu)化繪制的結(jié)果 using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using MnistModel; namespace DrawDigit { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private Bitmap digitImage;//用來(lái)保存手寫(xiě)數(shù)字 private Point startPoint;//用于繪制線段,作為線段的初始端點(diǎn)坐標(biāo) private Mnist model;//用于識(shí)別手寫(xiě)數(shù)字 private const int MnistImageSize = 28;//Mnist模型所需的輸入圖片大小 private void Form1_Load(object sender, EventArgs e) { //當(dāng)窗口加載時(shí),繪制一個(gè)白色方框 model = new Mnist(); digitImage = new Bitmap(pictureBox1.Width, pictureBox1.Height); Graphics g = Graphics.FromImage(digitImage); g.Clear(Color.White); pictureBox1.Image = digitImage; } private void clean_click(object sender, EventArgs e) { //當(dāng)點(diǎn)擊清除時(shí),重新繪制一個(gè)白色方框,同時(shí)清除label1顯示的文本 digitImage = new Bitmap(pictureBox1.Width, pictureBox1.Height); Graphics g = Graphics.FromImage(digitImage); g.Clear(Color.White); pictureBox1.Image = digitImage; label1.Text = ""; } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { //當(dāng)鼠標(biāo)左鍵被按下時(shí),設(shè)置isPainting為true,并記錄下需要繪制的線段的起始坐標(biāo) startPoint = (e.Button == MouseButtons.Left) ? e.Location : startPoint; } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { //當(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) { Graphics g = Graphics.FromImage(digitImage); Pen myPen = new Pen(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; } } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { //當(dāng)鼠標(biāo)左鍵釋放時(shí) //同時(shí)開(kāi)始處理圖片進(jìn)行推理 //暫時(shí)不處理這里的代碼 } } }步驟二:把模型包裝成一個(gè)類
將模型包裝成一個(gè)C#是整個(gè)過(guò)程中比較麻煩的一步。所幸的是,Tools for AI對(duì)此提供了很好的支持。進(jìn)一步了解,可以看這里。
首先,我們?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ū)?#xff0c;這個(gè)時(shí)候就需要我們選擇自己之前訓(xùn)練好的模型了~
首先在模型路徑里選擇保存的模型文件的路徑。這里我們使用在AI應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn) - 從零開(kāi)始配置環(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)用開(kāi)發(fā)實(shí)戰(zhàn) - 從零開(kāi)始配置環(huán)境這篇博客最后生成的export目錄下的檢查點(diǎn)的SavedModel.pb文件,這時(shí)程序?qū)⒆詣?dòng)配置好配置推理接口,見(jiàn)下圖:
類名可以自己定義,因?yàn)槲覀冇玫氖荕NIST,那么類名就叫Mnist好了,然后點(diǎn)擊確定。
這樣,在解決方案資源管理器里,在解決方案MnistForm下,就多了一個(gè)MnistModel:
雙擊Mnist.cs,我們可以看到項(xiàng)目自動(dòng)把模型進(jìn)行了封裝,生成了一個(gè)公開(kāi)的infer函數(shù)。
然后我們?cè)贛nistModel上右擊,再選擇生成,等待一會(huì),這個(gè)項(xiàng)目就可以使用了~
步驟三:連接兩個(gè)部分
這一步差不多就是這么個(gè)感覺(jué):
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è)趐ictureBox1_MouseUp中添加上這些代碼,并且在文件最初添加上using MnistModel;:
最后讓我們嘗試一下運(yùn)行~
三、效果展示
現(xiàn)在我們就有了一個(gè)簡(jiǎn)單的小程序,可以識(shí)別手寫(xiě)的數(shù)字了。
趕緊試試效果怎么樣~
注意
擴(kuò)展
嘗試識(shí)別多個(gè)數(shù)字
我們已經(jīng)支持了單個(gè)手寫(xiě)數(shù)字的識(shí)別,那能不能支持多個(gè)手寫(xiě)數(shù)字的識(shí)別呢?同時(shí)寫(xiě)下多個(gè)數(shù)字,正是現(xiàn)實(shí)中更為常見(jiàn)的情形。相比之下,如果只能一次識(shí)別一個(gè)手寫(xiě)數(shù)字,應(yīng)用就會(huì)有比較大的局限性。
首先,我們可以嘗試在現(xiàn)有的應(yīng)用里一次寫(xiě)下兩個(gè)數(shù)字,看看識(shí)別效果(為了更好的展示效果,將筆畫(huà)的寬度由40調(diào)整為20。這一改動(dòng)對(duì)單個(gè)數(shù)字的識(shí)別并無(wú)大的影響):
識(shí)別效果不盡人意。
右上角展示的結(jié)果準(zhǔn)確地反應(yīng)了模型對(duì)我們手寫(xiě)輸入的推理結(jié)果(即result.First().First().ToString()),然而這一結(jié)果并不像我們期望的那樣是“42”。
了解MNIST數(shù)據(jù)集的讀者們可能已經(jīng)意識(shí)到了,這是“理所當(dāng)然”的。歸根結(jié)底,這一問(wèn)題的癥結(jié)在于:作為我們AI應(yīng)用核心的AI模型,本身并不具備識(shí)別多個(gè)數(shù)字的能力——當(dāng)前案例中我們使用的AI模型是基于MNIST數(shù)據(jù)集訓(xùn)練的(訓(xùn)練過(guò)程請(qǐng)回顧我們之前的博客AI應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn) - 從零開(kāi)始配置環(huán)境),而MNIST數(shù)據(jù)集只覆蓋了單個(gè)的手寫(xiě)數(shù)字;并且,我們并未對(duì)筆跡圖形作額外的處理。
結(jié)果是在寫(xiě)下多個(gè)數(shù)字的情況下,我們實(shí)際上在“強(qiáng)行”讓AI模型做超出其適應(yīng)性范圍的判斷。這屬于AI模型的誤用。其結(jié)果自然難以令人滿意。
那么,為了增強(qiáng)應(yīng)用的可用性,我們能不能改善它、讓它能識(shí)別多個(gè)數(shù)字呢?我們很自然地想到,既然MNIST模型已經(jīng)能很好地識(shí)別單個(gè)數(shù)字,那我們只需要把多個(gè)數(shù)字分開(kāi),一個(gè)一個(gè)地讓MNIST模型進(jìn)行識(shí)別就好了。這樣,我們就引入了一個(gè)新的子問(wèn)題,即是“多個(gè)手寫(xiě)數(shù)字的分割”。
子問(wèn)題:分割多個(gè)手寫(xiě)數(shù)字
我們注意到本文介紹的應(yīng)用有一個(gè)特點(diǎn),那就是最終用作輸入的圖形,是用戶當(dāng)場(chǎng)寫(xiě)下的,而非通過(guò)圖片文件導(dǎo)入的靜態(tài)圖片,即我們擁有筆畫(huà)產(chǎn)生過(guò)程中的全部動(dòng)態(tài)信息,比如筆畫(huà)的先后順序,筆畫(huà)的重疊關(guān)系等等??紤]到這些信息,我們可以設(shè)計(jì)一種基本的分割規(guī)則:在水平面上的投影相重疊的筆畫(huà),我們就認(rèn)為它們同屬于一個(gè)數(shù)字。
筆畫(huà)和水平方向上投影的關(guān)系示意如下圖:
因此書(shū)寫(xiě)時(shí),就要求不同的數(shù)字之間盡量隔開(kāi)。當(dāng)然為了盡可能處理不經(jīng)意的重疊,我們還可以為重疊部分相對(duì)每一筆畫(huà)的位置設(shè)定一個(gè)閾值,如至少進(jìn)入筆畫(huà)一端的10%以內(nèi)。
應(yīng)用這樣的規(guī)則后,我們就能比較好的把多個(gè)手寫(xiě)數(shù)字分割開(kāi),并能利用Visual Studio Tools for AI提供的批量推理功能,一次性對(duì)所有分割出的圖形做推理。
多個(gè)手寫(xiě)數(shù)字識(shí)別的最終效果如圖:
當(dāng)然,我們對(duì)問(wèn)題的定義還是非常理想化,分割算法也比較簡(jiǎn)單。在實(shí)際應(yīng)用中,我們還經(jīng)常要考慮非二值圖形、噪點(diǎn)、非數(shù)字的判別等等。并且對(duì)手寫(xiě)數(shù)字的分割可能比我們?cè)O(shè)定的規(guī)則要復(fù)雜,因?yàn)樵诂F(xiàn)實(shí)場(chǎng)景中,水平方向上的重疊可能會(huì)影響圖形的涵義。
將兩個(gè)手寫(xiě)數(shù)字分割開(kāi)這一問(wèn)題,實(shí)際上和經(jīng)典的圖像分割問(wèn)題非常類似。雖然本文示例中的圖像非常簡(jiǎn)單,但仍然可能具有相當(dāng)復(fù)雜的語(yǔ)義需要處理。為此,我們可能需要引入更多的模型,或者擴(kuò)展現(xiàn)有的模型來(lái)正確判斷多個(gè)圖形之間的關(guān)系。
進(jìn)階
那么,如果要識(shí)別多個(gè)連寫(xiě)的數(shù)字,或支持字母該怎么做呢?大家多用用也會(huì)發(fā)現(xiàn),如果數(shù)字寫(xiě)得很小,或者沒(méi)寫(xiě)到正中,識(shí)別起來(lái)正確率也會(huì)不高。要解決這些問(wèn)題,做成真正的產(chǎn)品,就不止這一個(gè)模型了。比如在多個(gè)數(shù)字識(shí)別中,可能要根據(jù)經(jīng)驗(yàn)來(lái)切分圖,或者訓(xùn)練另一個(gè)模型來(lái)檢測(cè)并分割數(shù)字。要支持字母,則需要重新訓(xùn)練一個(gè)包含手寫(xiě)字母的模型,并準(zhǔn)備更多的字母的數(shù)據(jù)。要解決字太小的問(wèn)題,還要檢測(cè)一下字的大小,做合適的放大等等。
我們可以看到,一個(gè)訓(xùn)練出來(lái)的模型本身到一個(gè)實(shí)際的應(yīng)用之間還有不少的功能要實(shí)現(xiàn)。希望我們這一系列的介紹,能夠幫助大家將機(jī)器學(xué)習(xí)的概念帶入到傳統(tǒng)的編程領(lǐng)域中,做出更聰明的產(chǎn)品。
?
?
| 此時(shí),界面會(huì)提示注冊(cè)Azure,因?yàn)槎ㄖ苹曈X(jué)服務(wù)實(shí)際上是Azure提供的一項(xiàng)云服務(wù),正式使用這項(xiàng)服務(wù)需要有Azure訂閱。 不過(guò)我們現(xiàn)在只是免費(fèi)試用,所以選擇Continue With trial,如果在根據(jù)這篇博客流程做完了一個(gè)小應(yīng)用之后,你覺(jué)得確實(shí)需要使用這項(xiàng)服務(wù),那么你可以去注冊(cè)Azure賬號(hào),獲取Azure訂閱。 |
三、創(chuàng)建定制化視覺(jué)服務(wù)項(xiàng)目
點(diǎn)擊New Project,填寫(xiě)項(xiàng)目信息。
這里不妨以一個(gè)熊的分類模型作為例子來(lái)實(shí)踐吧。
填寫(xiě)好Name和Description,這里Name不妨填寫(xiě)為BearClassification。
隨后選擇Classification和General(compact),點(diǎn)擊Create
| 在Project Type一欄,定制化視覺(jué)服務(wù)提供了識(shí)別和分類兩種服務(wù),另外提供了多種識(shí)別場(chǎng)景,其中末尾帶有(compact),也即壓縮字樣的三種。 壓縮模型,顧名思義,模型占用的空間更少,運(yùn)行更快,甚至可以放到手機(jī)這種移動(dòng)設(shè)備里。 當(dāng)然,會(huì)有一個(gè)小問(wèn)題就是精確度會(huì)受影響。導(dǎo)出模型后,模型文件的使用是沒(méi)有任何限制的,而其余的幾種場(chǎng)景只能通過(guò)調(diào)用API來(lái)進(jìn)行預(yù)測(cè),由于當(dāng)前屬于免費(fèi)試用,因此這種方式有10000次調(diào)用上限。 | |
| 由于分類服務(wù)需要準(zhǔn)備用來(lái)訓(xùn)練的數(shù)據(jù)集,請(qǐng)自行準(zhǔn)備幾種不同的熊的照片,將同種的熊放在以這種熊的名字命名的文件夾里,最后再將這些文件夾放在一個(gè)data文件夾中。然后點(diǎn)擊Add images | |
| 選擇一種熊的全部照片,然后創(chuàng)建對(duì)應(yīng)的標(biāo)簽,點(diǎn)擊Up load xxx files | |
| 在添加了所有的數(shù)據(jù)集和標(biāo)簽之后,點(diǎn)擊網(wǎng)頁(yè)上方的Train,開(kāi)始訓(xùn)練模型。 | |
| 一小會(huì)之后,點(diǎn)擊網(wǎng)頁(yè)上方的performance,就可以看到這次訓(xùn)練的結(jié)果了。 這里簡(jiǎn)單解釋一下Precision和Recall,這是兩個(gè)評(píng)估模型好壞的主要指標(biāo)。 簡(jiǎn)單來(lái)說(shuō),兩個(gè)數(shù)都是越大越好。在這個(gè)項(xiàng)目中,以Brown Bear為例: Precision就是識(shí)別出來(lái)的結(jié)果的準(zhǔn)確率,即在所有被識(shí)別為棕熊的圖片中真正有棕熊的圖片所占的比例;而Recall則是測(cè)試結(jié)果中正確識(shí)別為棕熊的圖片占測(cè)試集中所有棕熊圖片的比例。 | |
| 這時(shí)再點(diǎn)擊界面右上角的齒輪,可以看到免費(fèi)用戶每個(gè)項(xiàng)目能夠使用的服務(wù)額度: 一共可以上傳5000張圖片,創(chuàng)建50個(gè)不同標(biāo)簽,保存10次迭代的結(jié)果。 這十次迭代有什么用呢?當(dāng)需要增刪標(biāo)簽、給標(biāo)簽添加或刪除訓(xùn)練圖片時(shí),這次再訓(xùn)練,就會(huì)花費(fèi)掉一次迭代。 這些都是當(dāng)前項(xiàng)目的總數(shù)而不是累計(jì)值。對(duì)于一般的免費(fèi)用戶,這基本上就相當(dāng)于你可以隨意使用這項(xiàng)服務(wù)了,如果有大量的訓(xùn)練數(shù)據(jù),那么建議您還是訂閱Azure云服務(wù),Azure秉持著使用多少,收費(fèi)多少的原則,即使收費(fèi),也仍然良心。 | |
| 然后選擇剛剛訓(xùn)練好的這次迭代,點(diǎn)擊Export。 視覺(jué)認(rèn)知服務(wù)一共提供了適用于四種平臺(tái)的模型導(dǎo)出,對(duì)三大操作系統(tǒng)都能支持。 選擇ONNX,這個(gè)格式由微軟、臉書(shū)、亞馬遜等大廠鼎力支持,點(diǎn)擊Export,等待服務(wù)器把模型導(dǎo)出,然后點(diǎn)擊Download,即可下載模型。最后得到了一個(gè).onnx文件,然后就可以使用它來(lái)構(gòu)建應(yīng)用了。 |
如果需要上傳大量的圖片數(shù)據(jù),那么點(diǎn)擊鼠標(biāo)的方式肯定不夠方便,微軟同時(shí)提供了代碼的支持,詳見(jiàn)官方文檔:
https://docs.microsoft.com/en-us/azure/cognitive-services/custom-vision-service/home
四、使用Windows ML構(gòu)建應(yīng)用
這次不寫(xiě)Winform程序,而是搭建一個(gè)識(shí)別熊的UWP的AI應(yīng)用,通過(guò)這個(gè)應(yīng)用來(lái)教大家如何使用Windows ML導(dǎo)入模型。
這部分的代碼已經(jīng)完成了,請(qǐng)使用git克隆samples-for-ai到本地,UWP項(xiàng)目的代碼在/samples-for-ai/projects/BearClassificationUWPDemo中。
在運(yùn)行代碼之前,請(qǐng)先安裝開(kāi)發(fā)UWP所需的工作負(fù)載,流程如下:
另外,請(qǐng)將您的操作系統(tǒng)更新到1803版本,否則本程序?qū)⒉荒馨惭b。
如果您將進(jìn)行類似的開(kāi)發(fā),請(qǐng)將UWP項(xiàng)目設(shè)置成最低運(yùn)行目標(biāo)版本為17134,否則對(duì)于版本低于17134的用戶,在運(yùn)行時(shí)會(huì)出現(xiàn):
"Requested Windows Runtime type 'Windows.AI.MachineLearning.Preview.LearningModelPreview' is not registered."
詳見(jiàn):https://github.com/MicrosoftDocs/windows-uwp/issues/575
安裝需要的時(shí)間比較長(zhǎng),可以先看看UWP的視頻教程,做一做頭腦預(yù)熱: https://www.bilibili.com/video/av7997007
Visual Studio 和 Windows 更新完畢后,我們打開(kāi)CustomVisionApp.sln,運(yùn)行這個(gè)程序。
你可以從必應(yīng)上查找一些熊的圖片,復(fù)制圖片的URL,粘貼到輸入框內(nèi),然后點(diǎn)擊識(shí)別按鈕;或者,點(diǎn)擊瀏覽按鈕,選擇一張本地圖片,點(diǎn)擊確定,你就可以看到識(shí)別結(jié)果了:
現(xiàn)在來(lái)看看這個(gè)程序是怎么實(shí)現(xiàn)的。
我們來(lái)梳理一下這個(gè)應(yīng)用的邏輯,這個(gè)應(yīng)用的邏輯與上一篇博客中的手寫(xiě)數(shù)字識(shí)別大體上是一樣的:
1. 文件結(jié)構(gòu):
文件結(jié)構(gòu)見(jiàn)下圖:
- Assets文件夾存放了這個(gè)項(xiàng)目的資產(chǎn)文件,比如程序圖標(biāo)等等,在本示例程序中,.onnx文件也存放在其中。
- Strings文件夾存放了用于本地化與全球化資源文件,這樣可以支持不同的語(yǔ)言。
- ViewModel文件夾中則存放了本項(xiàng)目的關(guān)鍵代碼,整個(gè)程序運(yùn)行的邏輯都在ResultViewModel.cs中
- BearClassification.cs則是系統(tǒng)自動(dòng)生成的模型包裝文件
- MainPage.xaml是程序的UI布局文件
2. 核心代碼一:BearClassification.cs
這部分的代碼是自動(dòng)生成的,教程詳見(jiàn)鏈接:https://docs.microsoft.com/zh-cn/windows/uwp/machine-learning/
生成的文件共有三個(gè)類:
- BearClassificationModelInput:定義了該模型的輸入格式是VideoFrame
- BearClassificationModelOutput:定義了該模型的輸出為一個(gè)list和一個(gè)dict,list存儲(chǔ)了所有標(biāo)簽按照probability降序排列,dict則存儲(chǔ)了標(biāo)簽與概率的鍵值對(duì)
- BearClassificationModel:定義了該模型的初始化函數(shù)與推理函數(shù)
3. 核心代碼二:ResultViewModel.cs
通過(guò)之前的運(yùn)行可以發(fā)現(xiàn):每次識(shí)別圖片,UI中的內(nèi)容需要進(jìn)行頻繁地更新,為了簡(jiǎn)化更新控件內(nèi)容的代碼邏輯,這個(gè)程序使用UWP開(kāi)發(fā)中常用的MVVM(model-view-viewmodel)這一組合模式開(kāi)發(fā),使用“綁定”的方式,將UI控件與數(shù)據(jù)綁定起來(lái),讓數(shù)據(jù)與界面自動(dòng)地同步更新,簡(jiǎn)化了代碼邏輯,保證了ResultViewModel職責(zé)單一。
| string BearUrl | TextBox InputUriBox |
| ObservableCollection?Results | ListView ResultArea |
| BitmapImage BearImage | Image DisplayArea |
| string Description | TextBox DescribeArea |
| ICommand RecognizeCommand | Button RecognizeButton |
| ICommand BrowseCommand | Button BrowseButton |
綁定好之后,程序還需要一系列邏輯才能運(yùn)行,這里就包括:
導(dǎo)入與初始化模型:
在程序一開(kāi)始,需要調(diào)用LoadModel進(jìn)行模型初始化工作。
private async void LoadModel() { //導(dǎo)入模型文件,實(shí)例化模型對(duì)象 StorageFile modelFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/BearClassification.onnx")); model = await BearClassificationModel.CreateBearClassificationModel(modelFile); }圖片推理:
本程序提供了兩種方式訪問(wèn)圖片資源:
五、使用其他方法構(gòu)建應(yīng)用
同樣,用之前使用Visual Studio Tools for AI提供的推理類庫(kù)生成器也能夠構(gòu)建相似的應(yīng)用。想看視頻教程的請(qǐng)移步:
【教程】普通程序員一小時(shí)入門(mén)AI應(yīng)用——看圖識(shí)熊(不含公式,包會(huì))
該教程講解了如何使用模型瀏覽工具Netron
想看圖文教程請(qǐng)繼續(xù)往下看:
1. 界面設(shè)計(jì)
創(chuàng)建Windows窗體應(yīng)用(.NET Framework)項(xiàng)目,這里給項(xiàng)目起名ClassifyBear。
注意,項(xiàng)目路徑不要包含中文。
在解決方案資源管理器中找到Form1.cs,雙擊,打開(kāi)界面設(shè)計(jì)器。從工具箱中向Form中依次拖入控件并調(diào)整,最終效果如下圖所示:
左側(cè)從上下到依次是:
- Label控件,將內(nèi)容改為“輸入要識(shí)別的圖片地址:”
- TextBox控件,可以將控件拉長(zhǎng)一些,方便輸入U(xiǎn)RL
- Button控件,將內(nèi)容改為“識(shí)別”
- Lable控件,將label的內(nèi)容清空,用來(lái)顯示識(shí)別后的結(jié)果。因?yàn)閘abel也沒(méi)有邊框,所以在界面看不出來(lái)??梢詫⒋丝丶淖煮w調(diào)大一些,能更清楚的顯示推理結(jié)果。
右側(cè)的控件是一個(gè)PictureBox,用來(lái)預(yù)覽輸入的圖片,同時(shí),我們也從這個(gè)控件中取出對(duì)應(yīng)的圖片數(shù)據(jù),傳給我們的模型推理類庫(kù)去推理。建議將控件屬性的SizeMode更改為StretchImage,并將控件長(zhǎng)和寬設(shè)置為同樣的值,保持一個(gè)正方形的形狀,這樣可以方便我們直觀的了解模型的輸入,因?yàn)樵谇懊娌榭茨P托畔⒌臅r(shí)候也看到了,該模型的輸入圖片應(yīng)是正方形。
2. 查看模型信息
在將模型集成到應(yīng)用之前,我們先來(lái)看一看模型的基本信息,比如模型需要什么樣的輸入和輸出。打開(kāi)Visual Studio中的AI工具菜單,選擇模型工具下的查看模型,會(huì)啟動(dòng)Netron模型查看工具。該工具默認(rèn)不隨Tools for AI擴(kuò)展一起安裝,第一次使用時(shí)可以按照提示去下載并安裝。
Netron打開(kāi)后,點(diǎn)擊Open model選擇打開(kāi)之前下載的BearModel.onnx文件。然后點(diǎn)擊左上角的漢堡菜單顯示模型的輸入輸出。
上圖中可以看到該模型需要的輸入data是一個(gè)float數(shù)組,數(shù)組中要求依次放置227*227圖片的所有藍(lán)色分量、綠色分量和紅色分量,后面程序中調(diào)用時(shí)要對(duì)輸入圖片做相應(yīng)的處理。
上圖中還可以看到輸出有兩個(gè)值,第一個(gè)值loss包含所有分類的得分,第二個(gè)值classLabel是確定的分類的標(biāo)簽,這里只需用到第二個(gè)輸出即可。
3. 封裝模型推理類庫(kù)
由于目前模型推理用到的庫(kù)只支持x64,所以這里需要將解決方案平臺(tái)設(shè)置為x64。打開(kāi)解決方案資源管理器,在解決方案上點(diǎn)右鍵,選擇配置管理器。
在配置管理器對(duì)話框中,點(diǎn)開(kāi)活動(dòng)解決方案平臺(tái)下拉框,選擇新建
在新建解決方案平臺(tái)對(duì)話框中,輸入新平臺(tái)名x64,點(diǎn)擊確定即可
下面添加模型推理類庫(kù),再次打開(kāi)解決方案資源管理器,在解決方案上點(diǎn)右鍵,選擇添加,然后選擇新建項(xiàng)目。
添加新項(xiàng)目對(duì)話框中,將左側(cè)目錄樹(shù)切換到AI Tools下的Inference,右側(cè)選擇模型推理類庫(kù),下方填入項(xiàng)目名稱,這里用Model作為名稱。
確定以后會(huì)出現(xiàn)檢查環(huán)境的進(jìn)度條,耐心等待一會(huì)就可以出現(xiàn)模型推理類庫(kù)創(chuàng)建向?qū)?duì)話框。
點(diǎn)擊模型路徑后面的瀏覽按鈕,選擇前面下載的BearModel.onnx模型文件。
注意,這里會(huì)出現(xiàn)幾處錯(cuò)誤提示,我們需要手動(dòng)修復(fù)一下。首先會(huì)看到“發(fā)現(xiàn)不支持的張量的數(shù)據(jù)類型”提示,可以直接點(diǎn)確定。
確定后如果彈出“正在創(chuàng)建項(xiàng)目…”的進(jìn)度條,一直不消失,這里只需要在類名后面的輸入框內(nèi)點(diǎn)一下,切換下焦點(diǎn)即可。
然后,我們來(lái)手動(dòng)配置一下模型的相關(guān)信息。類名輸入框中填入模型推理類的名字,這里用Bear。然后點(diǎn)擊推理接口右側(cè)的添加按鈕,在彈出的編輯接口對(duì)話框中,隨便起個(gè)方法名,這里用Infer。輸入節(jié)點(diǎn)的變量名和張量名填入data,輸出節(jié)點(diǎn)的變量名和張量名填入classLabel,字母拼寫(xiě)要和之前查看模型時(shí)看到的拼寫(xiě)一模一樣。然后一路確定,再耐心等待一會(huì),就可以在解決方案資源管理器看到新建的模型推理類庫(kù)了。
還有一處錯(cuò)誤需要手動(dòng)修復(fù)一下,切換到解決方案資源管理器,在Model項(xiàng)目的Bear目錄下找到Bear.cs雙擊打開(kāi),將函數(shù)Infer的最后一行
return r0;替換為
List<List<string>> results = new List<List<string>>(); results.Add(r0); return results;至此,模型推理類庫(kù)封裝完成。相信Tools for AI將來(lái)的版本中會(huì)修復(fù)這些問(wèn)題,直接選擇模型文件創(chuàng)建模型推理類庫(kù)就可以了。
4. 使用模型推理類庫(kù)
首先添加對(duì)模型推理類庫(kù)的引用,切換到解決方案資源管理器,在ClassifyBear項(xiàng)目的引用上點(diǎn)右鍵,選擇添加引用。
在彈出的引用管理器對(duì)話框中,選擇項(xiàng)目、解決方案,右側(cè)可以看到剛剛創(chuàng)建的模型推理類庫(kù),勾選該項(xiàng)目,點(diǎn)擊確定即可。
在Form1.cs上點(diǎn)右鍵,選擇查看代碼,打開(kāi)Form1.cs的代碼編輯窗口。
添加兩個(gè)成員變量
// 使用Netron查看模型,得到模型的輸入應(yīng)為227*227大小的圖片 private const int imageSize = 227; // 模型推理類 private Model.Bear model;回到Form1的設(shè)計(jì)界面,雙擊Form的標(biāo)題欄,會(huì)自動(dòng)跳轉(zhuǎn)到代碼頁(yè)面并添加了Form1_Load方法,在其中初始化模型推理對(duì)象
private void Form1_Load(object sender, EventArgs e) { // 初始化模型推理對(duì)象 model = new Model.Bear(); }回到Form1的設(shè)計(jì)界面,雙擊識(shí)別按鈕,會(huì)自動(dòng)跳轉(zhuǎn)到代碼頁(yè)面并添加了button1_Click方法,在其中添加以下代碼:
首先,每次點(diǎn)擊識(shí)別按鈕時(shí)都先將界面上顯示的上一次的結(jié)果清除
// 識(shí)別之前先重置界面顯示的內(nèi)容 label1.Text = string.Empty; pictureBox1.Image = null; pictureBox1.Refresh();然后,讓圖片控件加載圖片
bool isSuccess = false; try {pictureBox1.Load(textBox1.Text);isSuccess = true; } catch (Exception ex) { MessageBox.Show($"讀取圖片時(shí)出現(xiàn)錯(cuò)誤:{ex.Message}"); throw; }如果加載成功,將圖片數(shù)據(jù)傳給模型推理類庫(kù)來(lái)推理。
if (isSuccess) {// 圖片加載成功后,從圖片控件中取出227*227的位圖對(duì)象Bitmap bitmap = new Bitmap(pictureBox1.Image, imageSize, imageSize);float[] imageArray = new float[imageSize * imageSize * 3]; // 按照先行后列的方式依次取出圖片的每個(gè)像素值 for (int y = 0; y < imageSize; y++) { for (int x = 0; x < imageSize; x++) { var color = bitmap.GetPixel(x, y); // 使用Netron查看模型的輸入發(fā)現(xiàn) // 需要依次放置227 *227的藍(lán)色分量、227*227的綠色分量、227*227的紅色分量 imageArray[y * imageSize + x] = color.B; imageArray[y * imageSize + x + 1* imageSize * imageSize] = color.G; imageArray[y * imageSize + x + 2* imageSize * imageSize] = color.R; } } // 模型推理類庫(kù)支持一次推理多張圖片,這里只使用一張圖片 var inputImages = new List<float[]>(); inputImages.Add(imageArray); // 推理結(jié)果的第一個(gè)First()是取第一張圖片的結(jié)果 // 之前定義的輸出只有classLabel,所以第二個(gè)First()就是分類的名字 label1.Text = model.Infer(inputImages).First().First(); }注意,這里的數(shù)據(jù)轉(zhuǎn)換一定要按照前面查看的模型的信息來(lái)轉(zhuǎn)換,圖片大小需要長(zhǎng)寬都是227像素,并且要依次放置所有的藍(lán)色分量、所有的綠色分量、所有的紅色分量,如果順序不正確,不能達(dá)到最佳的推理結(jié)果。
5. 測(cè)試
編譯運(yùn)行,然后在網(wǎng)上找一張熊的圖片,把地址填到輸入框內(nèi),然后點(diǎn)擊識(shí)別按鈕,就可以看到識(shí)別的結(jié)果了。注意,這個(gè)URL應(yīng)該是圖片的URL,而不是包含該圖片的網(wǎng)頁(yè)的URL。
六、下一步?
本篇博客我們學(xué)會(huì)了使用定制化視覺(jué)服務(wù)與在UWP應(yīng)用中集成定制化視覺(jué)服務(wù)模型。這里我提兩個(gè)課后習(xí)題:(想不到吧)
當(dāng)訓(xùn)練含有多個(gè)標(biāo)簽、大量圖片數(shù)據(jù)時(shí),如何做到一鍵上傳圖片并訓(xùn)練?
如何通過(guò)調(diào)用REST接口的方式完成對(duì)圖片的推理?
提示:請(qǐng)看看定制化視覺(jué)服務(wù)給我們提供的API,這一題肯定是要寫(xiě)代碼做的
https://docs.microsoft.com/en-us/azure/cognitive-services/custom-vision-service/home
加油!
七、內(nèi)容預(yù)告
接下來(lái)我們將會(huì)陸續(xù)推出:
請(qǐng)?jiān)谙路搅粞?#xff0c;告知我們您最想閱讀哪個(gè)教程,我們將優(yōu)先考慮。
如果您有別的想要了解的內(nèi)容,也可以在評(píng)論區(qū)留言。
?
AI應(yīng)用開(kāi)發(fā)基礎(chǔ)傻瓜書(shū)系列的目錄~
寫(xiě)在前面,為啥要出這個(gè)系列的教程呢?
總的說(shuō)來(lái),我們現(xiàn)在有了很多非常厲害的深度學(xué)習(xí)框架,比如tensorflow,pytorch,paddlepaddle,caffe2等等等等。然而,我們用這些框架在搭建我們自己的深度學(xué)習(xí)模型的時(shí)候,到底做了一些什么樣的操作呢?我們?cè)噲D去閱讀框架的源碼來(lái)理解框架到底幫助我們做了些什么,但是……很難!很難!很難!因?yàn)樯疃葘W(xué)習(xí)是需要加速啦,分布式計(jì)算啦,所以框架做了很多很多的優(yōu)化,也讓像我們這樣的小白難以理解這些框架的源碼。所以,為了幫助大家更進(jìn)一步的了解神經(jīng)網(wǎng)絡(luò)模型的具體內(nèi)容,我們整理了這樣一個(gè)系列的教程。
對(duì)于這份教程的內(nèi)容,如果沒(méi)有額外的說(shuō)明,我們通常使用如下表格的命名約定
| X | 輸入樣本 |
| Y | 輸入樣本的標(biāo)簽 |
| Z | 各層運(yùn)算的結(jié)果 |
| A | 激活函數(shù)結(jié)果 |
| 大寫(xiě)字母 | 矩陣或矢量,如A,W,B |
| 小寫(xiě)字母 | 變量,標(biāo)量,如a,w,b |
適用范圍
沒(méi)有各種基礎(chǔ)想學(xué)習(xí)卻無(wú)從下手哀聲嘆氣的玩家,請(qǐng)按時(shí)跟蹤最新博客,推導(dǎo)數(shù)學(xué)公式,跑通代碼,并及時(shí)提出問(wèn)題,以求最高療效;
深度學(xué)習(xí)小白,有直觀的人工智能的認(rèn)識(shí),強(qiáng)烈的學(xué)習(xí)欲望和需求,請(qǐng)?jiān)诓┛偷幕A(chǔ)上配合代碼食用,效果更佳;
調(diào)參師,訓(xùn)練過(guò)模型,調(diào)過(guò)參數(shù),想了解框架內(nèi)各層運(yùn)算過(guò)程,給玄學(xué)的調(diào)參之路添加一點(diǎn)心理保障;
超級(jí)高手,提出您寶貴的意見(jiàn),給廣大初學(xué)者指出一條明路!
前期準(zhǔn)備
環(huán)境:
windows(Linux也行),python(最好用3),anaconda(或者自己裝numpy之類的),tensorflow(嫌麻煩地請(qǐng)看這里《AI應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn) - 從零開(kāi)始配置環(huán)境》,tools for AI(按照鏈接教程走的就不用管這個(gè)了)。
自己:
清醒的頭腦(困了的同學(xué)請(qǐng)自覺(jué)泡茶),紙和筆(如果像跟著推公式的話),鬧鐘(防止久坐按時(shí)起來(lái)轉(zhuǎn)轉(zhuǎn)),厚厚的衣服(有暖氣的同學(xué)請(qǐng)忽略)
目錄
- 1-神經(jīng)網(wǎng)絡(luò)的基本工作原理
- 2-神經(jīng)網(wǎng)絡(luò)中反向傳播與梯度下降的基本概念
- 3-基本數(shù)學(xué)導(dǎo)數(shù)公式
- 4-激活函數(shù)
- 5-損失函數(shù)
- 6-單入單出的單層神經(jīng)網(wǎng)絡(luò)能做什么
- 7-單入單出的雙層神經(jīng)網(wǎng)絡(luò)能做什么
- 徒手搭建神經(jīng)網(wǎng)絡(luò)
- 徒手搭建CNN網(wǎng)絡(luò)
- 徒手搭建RNN網(wǎng)絡(luò)
- 模型內(nèi)部
?
?
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的AI应用开发实战(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: docker-compose 报错记录
- 下一篇: Flex Basis与Width的区别