iOS 10 和macOS中的神經網路

周建丁發表於2016-07-04

原文:Neural Networks in iOS 10 and macOS
作者:Bolot Kerimbaev
編譯:劉崇鑫
責編:周建丁(zhoujd@csdn.net)

長期以來,蘋果公司一直在其產品中使用了機器學習:Siri回答我們的問題,並供我們娛樂;iPhoto能在我們的照片中進行人臉識別;Mail app能檢測垃圾郵件。作為應用開發者,我們已經利用了蘋果的API提供的一些功能,如人臉檢測,並且從iOS10開始,我們將獲得能用於語音識別和SiriKit的高階API。

有時候,我們可能想超越平臺內建API的限制,創造獨一無二的東西。但更多的時候,我們是使用了一些現成的庫或直接建於Accelerate或Metal的快速計算功能之上,推出自己的機器學習功能。

例如,我的同事專為辦公室建立了一個錄入系統,只使用一臺可檢測人臉的iPad,然後在Slack投遞一個gif,並允許使用者通過自定義命令開門。

圖片描述

但是現在,我們有了用於神經網路的第一方支援:在2016年的WWDC上,蘋果公司推出了兩個神經網路的API,分別稱為基礎神經網路子程式(BNNS)和卷積神經網路(CNN)。

機器學習和神經網路

AI先驅Arthur Samuel將機器學習定義為“沒有明確程式設計的情況下,給予計算機學習能力的研究領域”。人們用機器學習系統理解一些資料的意義,而這些資料不能很容易地使用傳統模型來描述。

例如,編寫一段計算房子建築面積的程式很容易,我們可以考慮到所有房間和其他空間的規模和形狀,但是卻不能在公式中計算房子的價值;而另一方面,機器學習系統卻非常適合解決這樣的問題。通過給系統提供已知的具體資料,如市場價值、房屋尺寸、臥室數量等,從而可以利用它預測價格。

神經網路是構建機器學習系統最常用的模型之一。早在半個多世紀前的1940年,已經發展了神經網路的數學基礎,而上世紀80年代,平行計算才使其更為可行;並且到了2000年,人們對於深度學習的興趣又引發了神經網路的回潮。

神經網路由多個層構造,其中每個層由一個或多個節點組成。最簡單的神經網路具有三層:輸入、隱藏和輸出。輸入層節點可以代表影像中的各個畫素或一些其他引數;如果我們試著自動檢測照片的內容,輸出層節點則經常作為分類的結果,例如“狗”或“貓”;隱藏層節點配置為對輸入執行操作,或配置為應用啟用函式。
圖片描述

層型別

三種常見的層的型別為:池化(pooling)層、卷積層和全連線層。

池化層通常通過使用輸入的最大值或平均值來彙集資料,降低其大小。一系列的卷積和池化層可以結合起來,用於將照片逐步提煉成越來越高層次的特徵集合。

卷積層將卷積矩陣用於影像的每個畫素,實現影像變換。如果你已經用過Pixelmator或Photoshop濾鏡,那你很可能也用過了卷積矩陣。卷積矩陣通常是一個3×3或5×5的矩陣,被施加到輸入影像的畫素中,以計算輸出影像中新的畫素值。為獲得輸出畫素值,我們就乘以原影像中的畫素值,並計算平均值。

例如,該卷積矩陣用於影像模糊:

1 1 1
1 1 1
1 1 1

而下面的矩陣能夠銳化影像:

 0 -1  0
-1  5 -1
 0 -1  0

神經網路的卷積層使用卷積矩陣處理輸入,併產生下一層的資料。例如,提取影像中的諸如邊緣特徵的新特性。

全連線層可以被認為是濾波器尺寸和原始影像相同的卷積層。換句話說,你可以這麼認為,全連線層是一個函式,能夠為每個畫素分配權重,平均其結果,然後給出單個的輸出值。

訓練和推理

每一層都需要配置適當的引數。例如,卷積層需要輸入和輸出影像的資訊(規模、通道數目等),也需要卷積層引數(核心大小、矩陣等)。全連線層通過輸入和輸出向量、啟用函式和權重來定義。

要獲得這些引數,必須訓練神經網路。需要以下幾步才能完成:通過神經網路傳遞輸入,確定輸出,測量誤差(即實際結果與預測結果相差多遠),並通過反向傳播調整權重。訓練神經網路可能需要數百、數千甚至成千上萬的樣本。

目前,蘋果公司新的機器學習API,可用於構建只做推理的神經網路,而不是訓練。這都是Big Nerd Ranch的功勞。

Accelerate: BNNS

第一個新的API是Accelerate框架的一部分,被稱為基礎神經網路子程式(BNNS,Basic Neural Network Subroutines)。BNNS補充了BLAS(基礎線性代數子程式),並用於一些第三方的機器學習應用。

BNNS在BNNSFilter類中定義層。Accelerate支援三種型別的層:

  • 卷積層(由BNNSFilterCreateConvolutionLayer函式建立)
  • 全連線層(BNNSFilterCreateFullyConnectedLayer)
  • 池化層(BNNSFilterCreatePoolingLayer)

MNIST 資料庫是一個眾所周知的資料集,包含數以萬計的手寫數字,用於掃描和調整,以適應20乘20畫素的影像。

一種處理影像資料的方法是將影像轉換成向量,並使之通過一個全連線層。對於MNIST資料,一個20×20的影像將成為400個值的向量。下面展示瞭如何將手寫的數字“1”轉換為向量:

圖片描述

下面是配置全連線層的例項程式碼,該層將大小為400的向量作為輸入,採用S形的啟用函式,輸出向量大小為25:

// input layer descriptor
    BNNSVectorDescriptor i_desc = {
        .size = 400,
        .data_type = BNNSDataTypeFloat32,
        .data_scale = 0,
        .data_bias = 0,
    };

    // hidden layer descriptor
    BNNSVectorDescriptor h_desc = {
        .size = 25,
        .data_type = BNNSDataTypeFloat32,
        .data_scale = 0,
        .data_bias = 0,
    };

    // activation function
    BNNSActivation activation = {
        .function = BNNSActivationFunctionSigmoid,
        .alpha = 0,
        .beta = 0,
    };

    BNNSFullyConnectedLayerParameters in_layer_params = {
        .in_size = i_desc.size,
        .out_size = h_desc.size,
        .activation = activation,
        .weights.data = theta1,
        .weights.data_type = BNNSDataTypeFloat32,
        .bias.data_type = BNNSDataTypeFloat32,
    };

    // Common filter parameters
    BNNSFilterParameters filter_params = {
        .version = BNNSAPIVersion_1_0;   // API version is mandatory
    };

    // Create a new fully connected layer filter (ih = input-to-hidden)
    BNNSFilter ih_filter = BNNSFilterCreateFullyConnectedLayer(&i_desc, &h_desc, &in_layer_params, &filter_params);

    float * i_stack = bir; // (float *)calloc(i_desc.size, sizeof(float));
    float * h_stack = (float *)calloc(h_desc.size, sizeof(float));
    float * o_stack = (float *)calloc(o_desc.size, sizeof(float));

int ih_status = BNNSFilterApply(ih_filter, i_stack, h_stack);

Metal!

該部分會得到更多的Metal嗎?確實是的,因為第二個神經網路API是Metal Performance Shaders(MPS)框架的一部分。Accelerate是在CPU上進行快速計算的框架,而Metal將GPU發揮了極致。Metal的特點是卷積神經網路(CNN,Convolution Neural Network)。

MPS自帶了一個類似的API集。

  • 建立卷積層需要使用MPSCNNConvolutionDescriptor和MPSCNNConvolution函式。
  • MPSCNNPoolingMax將為池化層提供引數。
  • 全連線層由MPSCNNFullyConnected函式建立。
  • 啟用函式由MPSCNNNeuron的子類定義:
    • MPSCNNNeuronLinear
    • MPSCNNNeuronReLU
    • MPSCNNNeuronSigmoid
    • MPSCNNNeuronTanH
    • MPSCNNNeuronAbsolute

BNNS和CNN的比較

下表為Accelerate和Metal啟用函式列表:

Accelerate/BNNS Metal Performance Shaders/CNN
BNNSActivationFunctionIdentity
BNNSActivationFunctionRectifiedLinear MPSCNNNeuronReLU
MPSCNNNeuronLinear
BNNSActivationFunctionLeakyRectifiedLinear
BNNSActivationFunctionSigmoid MPSCNNNeuronSigmoid
BNNSActivationFunctionTanh MPSCNNNeuronTanH
BNNSActivationFunctionScaledTanh
BNNSActivationFunctionAbs MPSCNNNeuronAbsolute

池化函式:

Accelerate/BNNS Metal Performance Shaders/CNN
BNNSPoolingFunctionMax MPSCNNPoolingMax
BNNSPoolingFunctionAverage MPSCNNPoolingAverage

Accelerate和Metal為神經網路提供的一組函式功能非常相似,所以二者選擇取決於每個應用程式。GPU通常首選各種機器學習所需的計算,而資料區域性性可能會導致Metal CNN的執行效能比Accelerate BNNS版本要差。如果神經網路對已存入GPU的影像進行操作,例如,使用MPSImage和新MPSTemporaryImage時,很明顯,這時更適合用Metal。


CCAI 2016中國人工智慧大會將於8月26-27日在京舉行,AAAI主席,多位院士,MIT、微軟、大疆、百度、滴滴專家領銜全球技術領袖和產業先鋒打造國內人工智慧前沿平臺,6大主題報告,人機互動、機器學習、模式識別、產業實戰相關4大專題論壇,1000+高質量參會嘉賓。門票限時六折優惠中

圖片描述

相關文章