1. 程式人生 > >iOS下執行CNN(深度學習)

iOS下執行CNN(深度學習)

1 引言

作為曾經的iOS開發者,在研究深度學習的時候,總有一個想法就是在iPhone上執行深度學習,不管是在手機上訓練還是利用訓練好的資料進行測試。 
因為iOS的開發環境支援C++,因此,只要你的程式碼是C/C++,本質上就可以在iOS上執行。 
怎麼才能更快更好地在iOS上執行CNN呢?

2 方法1:通過Matlab轉碼

Matlab自帶轉成c的工具,如果你研究過UFLDL的深度學習教程,就知道如何在Matlab上使用CNN,那麼,轉換成c後,放到iOS的開發環境中,然後將引數存成txt格式再讀取分割,也就是可以實現。 
如下圖就是已經將matlab程式碼轉換為c後匯入的結果: 
這裡寫圖片描述 
開啟predict.h檔案,可以看到可以呼叫的介面:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* Function Declarations */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extern</span> real_T predict(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> real_T Theta1[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10025</span>], <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> real_T Theta2[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">260</span>], <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> real_T X[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>]);
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

這是訓練MNIST的一個神經網路,我這邊用了測試手寫數字的識別。

因此,接下來需要對圖片進行處理,從而轉換為x[400]的向量格式。

這個只要能讀取圖片的畫素,進行轉換就可以。可以考慮用opencv來實現。

這裡寫圖片描述 
這裡我的方法是在用手畫出數字之後,將圖片轉換為20*20畫素的圖片,如右下角所示,再將右下角的圖片轉換為400的陣列,輸入predict得到的結果。

3 方法2:使用DeepBeliefSDK

4 方法3:使用tinyCNN

https://github.com/nyanp/tiny-cnn 
這個很不錯,它對比Caffe,Theano等框架最大的特點就是不需要安裝,只要能用C++ 11.然後裡面的例子使用了boost庫。因此,為了執行它,我們需要在xcode安裝ios的boost庫。

匯入boost庫的方法非常簡單:

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">In Xcode Build Settings <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> your project:

Add <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> Library Search Paths ( LIBRARY_SEARCH_PATHS ) $(SRCROOT)/../../../addons/ofxiOSBoost/libs/boost/lib/ios
Add <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> Header Search Paths ( HEADER_SEARCH_PATHS )
$(SRCROOT)/../../../addons/ofxiOSBoost/libs/boost/<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">include</span>
In <span class="hljs-operator" style="box-sizing: border-box;">the</span> Target under Build Phases

Add <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'Link Binary With Libraries'</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> boost.<span class="hljs-operator" style="box-sizing: border-box;">a</span> found <span class="hljs-operator" style="box-sizing: border-box;">in</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> ofxiOSBoost/libs/boost/lib/ios <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">directory</span>.
If <span class="hljs-operator" style="box-sizing: border-box;">not</span> openFrameworks just <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">add</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> libs/boost/<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">include</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> Header Search Paths <span class="hljs-operator" style="box-sizing: border-box;">and</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> libs/boost/ios <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> Library Search Paths</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

那麼具體在建立iOS應用的時候,這裡使用作者提供的訓練MNIST的例子,那麼要注意在使用資料時,要更改路徑:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *trainLabels = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSBundle</span> mainBundle] pathForResource:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"train-labels"</span> ofType:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"idx1-ubyte"</span>];
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *trainImages = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSBundle</span> mainBundle] pathForResource:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"train-images"</span> ofType:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"idx3-ubyte"</span>];
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *t10kLabels = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSBundle</span> mainBundle] pathForResource:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"t10k-labels"</span> ofType:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"idx1-ubyte"</span>];
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *t10kImages = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSBundle</span> mainBundle] pathForResource:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"t10k-images"</span> ofType:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"idx3-ubyte"</span>];


    parse_mnist_labels([trainLabels cStringUsingEncoding:NSUTF8StringEncoding], &train_labels);
    parse_mnist_images([trainImages cStringUsingEncoding:NSUTF8StringEncoding], &train_images);
    parse_mnist_labels([t10kLabels cStringUsingEncoding:NSUTF8StringEncoding], &test_labels);
    parse_mnist_images([t10kImages cStringUsingEncoding:NSUTF8StringEncoding], &test_images);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

基本上這樣就可以執行開始訓練了。

如果想在Mac上訓練,同樣需要安裝boost庫。這個只要在官網下載boost,我用的是1.58版本。然後在terminal中安裝,cd到路徑,然後./boostrap.sh 然後./b2 安裝就可以。然後在xcode引入路徑:

<code class="hljs r has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">The Boost C++ Libraries were successfully built!

The following directory should be added to compiler include paths:

    /Users/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>/boost

The following directory should be added to linker <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">library</span> paths:

    /Users/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>/<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>/boost/stage/lib</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

路徑初始為自己boost的資料夾地址。

4 小結

上面說了一些很方便的方法來實現在iOS下執行CNN。當然,我們更多需要就是進行影象的識別。相信大家自己測試會覺得很有趣。