NCNN使用總結

NCNN簡介

ncnn 是一個爲手機端極致優化的高性能神經網絡前向計算框架。ncnn 從設計之初深入考慮手機端的部署和使用。無第三方依賴,跨平臺,手機端 cpu 的速度快於目前全部已知的開源框架。基於 ncnn,開發者可以將深度學習算法輕鬆移植到手機端高效執行,開發出人工智能 APP,將 AI 帶到你的指尖。ncnn 目前已在騰訊多款應用中使用,如 QQ,Qzone,微信,每天P圖等。git

關於安裝、編譯、使用步驟等不在贅述,官網有很詳細文檔github

Windows Linux MacOS Android iOS
intel-cpu ✔️ ✔️ ✔️ /
intel-gpu ✔️ ✔️ /
amd-cpu ✔️ ✔️ ✔️ /
amd-gpu ✔️ ✔️ /
nvidia-gpu ✔️ ✔️ /
qcom-cpu ✔️ / /
qcom-gpu ✔️ / ✔️ /
arm-cpu / /
arm-gpu / ✔️ /
apple-cpu / / / /
apple-gpu / / / / ✔️

NCNN注意事項

其實ncnn已是一個完整的庫,不多有人去改源碼,固然若是你項目特別須要使能夠的。算法

使用出現問題主要是輸入輸出的地方不對應,如下是本人使用出現的問題。數組

  • 網絡問題一

使用caffe模型的時候,input部分必定要寫成規範格式:微信

input: "data"
layer {
  name: "data"
  type: "Input"
  top: "data"
  input_param { shape: { dim: 1 dim: 1 dim: 256 dim: 512 } }
}

千萬別圖省事寫成以下格式,caffe能夠運行沒問題,可是轉化沒法識別,這個ncnn數據結構致使!!!網絡

input: "data"
input_dim: 1
input_dim: 1
input_dim: 256
input_dim: 512
  • 網絡問題二

網絡定義的層千萬別出現重複狀況,必定要規範定義:數據結構

layer {
  name: "AAAA"
  type: "Concat"
  bottom: "box_softmax"
  bottom: "conv6_2"
  top: "concat_out1"
  concat_param {
    axis: 2
  }
}
layer {
  name: "BBBB"
  type: "Concat"
  bottom: "box_softmax"
  bottom: "concat_out1"
  top: "concat_out2"
  concat_param {
    axis: 2
  }
}

千萬別寫成以下網絡,在caffe能夠穩定運行,可是ncnn會讀取上第一次出現的top層!!!app

第一層輸出是concat_out1,第二層輸出也是concat_out1,當使用ncnn.extract會出現錯誤!!!框架

layer {
  name: "AAAA"
  type: "Concat"
  bottom: "box_softmax"
  bottom: "conv6_2"
  top: "concat_out1"
  concat_param {
    axis: 2
  }
}
layer {
  name: "BBBB"
  type: "Concat"
  bottom: "box_softmax"
  bottom: "concat_out1"
  top: "concat_out1"
  concat_param {
    axis: 2
  }
}
  • NCNN網絡問題三

這貌似是算做caffe的問題,在筆者使用的過程忽略了這一點,乾脆算NCNN操做裏面了。

Batch Normalization層有個use_global_stats參數,這個操做的做用是:是否使用caffe內部的均值和方差

換句話的意思就是:

---------true :使用caffe內部的均值和方差,其中方差和均值都是固定的,模型訓練好以後,這兩個值就固定了。
---------false :使用當前層計算的方差和均值,這個是不固定的,是在訓練過程一直改變,訓練好的時候達到最優。

其中NCNN默認使用true狀態,不論是false仍是true,最終都是算做true

caffe測試的時候得手動設置爲true

  • NCNN輸入數據一

正常來講ncnncaffe原版的偏差範圍在0.001左右,個人數據在0.000X範圍徘徊,若是你的數據精確不到第三個有效數字,那就得檢查網絡輸入精度了。

輸入的substract_mean_normalize得儘可能精確,尤爲是歸一化的值!!!

假設0-255的圖像須要歸一化到0-1

const float noml_vals[1] = { 0.0078431372549019607843137254902f };

千萬不要寫成下面這樣,讀者能夠本身測試,精度差異較大。

const float noml_vals[1] = { 0.0078 }
  • NCNN輸入數據二

這裏沒有錯誤點,只有心得點。

  1. 若是輸入的是opencv的Mat對象,那隻能是CV_8U類型,別想着去使用CV_32F等其餘類型,對結果沒有影響的。
  2. 關於使用opencv的處理圖像和ncnn的處理圖像效果同樣,好比opencv的resize、normalize、cvtcolor等函數,和ncnn的from_pixels_resize、substract_mean_normalize效果基本沒有區別,本人已經測試。

NCNN使用心得

小技巧

  • 輸出爲多層

看了NCNN的官網給的例子,它是將輸出轉化爲一行數據,而後一個一個的進行處理:

ncnn::Mat out_flatterned = out.reshape(out.w * out.h * out.c);
std::vector<float> scores;
scores.resize(out_flatterned.w);
for (int j=0; j<out_flatterned.w; j++)
{
    scores[j] = out_flatterned[j];
}

我的感受使用這種處理小數據仍是能夠的,本人使用網絡輸出100 × 100 × 10,這種狀況該如何處理?

  1. 你可使用那種方法去一個一個保存到數組,就是浪費點時間。
  2. 當你須要處理結果的時候呢?好比簡單說去找每一個channels的最大值,且主要知道座標?

本人使用處理以下:

for (size_t i = 0; i < out.c; i++)
    {
        cv::Mat cv_mat = cv::Mat::zeros(cv::Size(100, 100), CV_8UC1);
        ncnn::Mat ppp = out.channel(i);
         //轉化爲opencv的Mat進行操做,由於有不少矩陣運算就很方便
        ppp.to_pixels(cv_mat.data, ncnn::Mat::PIXEL_GRAY);
        double max_c = 0, min_c = 0;
        cv::Point min_loc, max_loc;
        cv::minMaxLoc(cv_mat, &min_c, &max_c, &min_loc, &max_loc);
        /*---------------後續操做-----------------*/
    }

小想法

NCNN官網有我的問能不能輸入和輸出多個通道數據,後者已經在上文實現,如下看前者。

  • NCNN的輸入爲Extractor.input(const char* blob_name, const Mat& in),其中inncnn::Mat類型數據,顯然是

    能夠多個channels輸入的。

  • 可使用ncnn建立100×100×10數據,而後對每一個channel經過from_pixel進行賦值操做便可。

沒有通過具體實現,官網也沒說明,不清楚能不能行,讀者能夠根據以上本身嘗試。

相關文章
相關標籤/搜索