欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
【深度學(xué)習系列(二)】:基于c++實(shí)現一個(gè)簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò )(1)

      學(xué)習深度學(xué)習首先得知道反向傳播,這是神經(jīng)網(wǎng)絡(luò )能夠學(xué)習得重要原因,也是深度學(xué)習得基石。所以,本系列以此為開(kāi)篇,著(zhù)重介紹神經(jīng)網(wǎng)絡(luò )得正向/反向傳播得流程。哈哈,肯定有人會(huì )問(wèn)為什么用C++實(shí)現,python不是更好嗎?哈哈,本人嚴重C++控,好吧后續得一些文章大多是基于c++實(shí)現的,所以,最好有一定的c++基礎。本文代碼得配置要求:

  • C++

  • OpenCV3.4

完整的代碼工程可以訪(fǎng)問(wèn)我的github:https://github.com/kingqiuol/ann

一、網(wǎng)絡(luò )的框架結構

     本文代碼主要通過(guò)一個(gè)NN類(lèi)來(lái)實(shí)現,支持設定插入多個(gè)隱藏層及每個(gè)隱藏層的神經(jīng)元個(gè)數,當然這部分可以跳過(guò),主要讓大家有個(gè)整體的概念,我一般在實(shí)現某一個(gè)功能或框架時(shí)都會(huì )提前做好準備,需要那幾個(gè)功能/那些模塊,并一一列舉出來(lái),先寫(xiě)好,具體細節不用管。對于一個(gè)神經(jīng)網(wǎng)絡(luò )來(lái)說(shuō),這里包括大多數卷積神經(jīng)網(wǎng)絡(luò ),一般包括:模型的訓練模型的預測(使用),來(lái)說(shuō)一說(shuō)搭建該網(wǎng)絡(luò )具體的流程:

  • 模型訓練:加載數據  → 創(chuàng )建模型 → 參數設置/優(yōu)化器設置 → 模型訓練 →保存權重

  • 模型預測:創(chuàng )建模型 → 加載權重 → 傳入數據 → 預測結果

  1. #ifndef ANN_H_
  2. #define ANN_H_
  3. #include <iostream>
  4. #include <memory>
  5. #include <fstream>
  6. #include <sstream>
  7. #include <string>
  8. #include <time.h>
  9. #include <stdlib.h>
  10. #include <opencv2/opencv.hpp>
  11. using namespace std;
  12. using namespace cv;
  13. class NN{
  14. public:
  15. NN(size_t classes, size_t input = 0,
  16. float reg = 0.005, float learning_rate = 0.0001,
  17. size_t max_epochs = 5000,size_t batch_size = 500) :
  18. input_(input), classes_(classes),
  19. reg_(reg), learning_rate_(learning_rate),
  20. max_epochs_(max_epochs), batch_size_(batch_size),
  21. data_ptr(nullptr), label_ptr(nullptr){}
  22. ~NN(){}
  23. //加載數據
  24. void data_loader(const string &path);
  25. //添加隱藏層
  26. void add_hidden_layer(const vector<size_t> &num_hiddens = {});
  27. //初始化網(wǎng)絡(luò )
  28. void initial_networks();
  29. //前向傳播
  30. void forward(Mat &X);
  31. //反向傳播
  32. void backward();
  33. //計算損失函數
  34. float loss(Mat &y);
  35. //更新權重
  36. void update_weight();
  37. //訓練網(wǎng)絡(luò )
  38. void train(const string &file_path, const vector<size_t> &num_hiddens);
  39. //保存權重
  40. void save_weights(const string &save_path);
  41. //加載權重
  42. void load_weights(const string &load_path);
  43. //預測
  44. Mat predict(Mat &data);
  45. //其他方法
  46. inline float get_learning_rate()const{ return this->learning_rate_; }
  47. inline void set_learning_rate(float learning_rate){ this->learning_rate_ = learning_rate; }
  48. inline float get_reg() const{ return this->reg_; }
  49. inline void set_reg(float reg){ this->reg_ = reg; }
  50. inline size_t get_epoch()const{ return this->max_epochs_; }
  51. private:
  52. /***神經(jīng)網(wǎng)絡(luò )相關(guān)的函數***/
  53. void get_batch(Mat &batch_X,Mat &batch_y);
  54. void initial_layer(const size_t &input, const size_t &output);//單個(gè)層的初始化
  55. void relu(Mat &X);//激勵函數
  56. void softmax(Mat &out);//softmax分類(lèi)器
  57. float L2_regular();//L2正則化
  58. /***其他與矩陣操作相關(guān)的方法***/
  59. //計算矩陣行/列方向的和,并進(jìn)行矩陣增廣
  60. Mat mat_sum(const Mat &X, const int &axis, const int &dtype);
  61. //計算矩陣行/列方向的最大值,并進(jìn)行矩陣增廣
  62. Mat mat_max(const Mat &X, const int &axis, const int &dtype);
  63. //求矩陣行對對應的最大值的下標所在的列
  64. int argmax(Mat &row, float &max);//單行對應的下標
  65. Mat argmaxes(Mat &out);
  66. /***常見(jiàn)神經(jīng)網(wǎng)絡(luò )參數設置***/
  67. float reg_; //正則化系數
  68. float learning_rate_; //學(xué)習率
  69. size_t max_epochs_; //最大訓練次數
  70. size_t batch_size_; //批量處理大小
  71. private:
  72. //輸入數據、數據標簽
  73. shared_ptr<Mat> data_ptr, label_ptr;
  74. size_t input_; //輸入個(gè)數
  75. size_t classes_; //分類(lèi)個(gè)數
  76. vector<size_t> hiddens_; //各個(gè)隱藏層中神經(jīng)元個(gè)數
  77. vector<Mat> W_; //保存權重
  78. vector<Mat> b_; //保存偏置項
  79. vector<Mat> out_; //存儲各個(gè)層的輸出
  80. vector<Mat> dW_; //保存各個(gè)層的計算權重梯度
  81. vector<Mat> db_; //保存各個(gè)層的偏置項梯度
  82. };
  83. #endif // !ANN_H_

       正如頭文件所見(jiàn),對于整個(gè)網(wǎng)絡(luò )我們需要保存一些中間變量為后續反向傳播做準備。我們需要保存的節點(diǎn)有:每一層的輸入/輸出、當前層的權重、以及反向傳播時(shí)的梯度,然后還需要定義傳播過(guò)程中的操作,主要操作有:全連接、激活函數(relu)和分類(lèi)器(softmax)。對于當前大多數深度學(xué)習框架(tensorflow/pytorch/caffe)來(lái)說(shuō),基本都采用運算圖模型,說(shuō)白了就是一系列的節點(diǎn)+邊(操作),節點(diǎn)用于存儲中間結果,邊用于計算。這里的代碼不是很明顯,后續講到深度學(xué)習時(shí)你就會(huì )由此體會(huì )。接下來(lái)我將對這些流程進(jìn)行講解并一一細說(shuō)其中的一些基礎知識。

二、神經(jīng)網(wǎng)絡(luò )的訓練

1、數據加載

  1. void NN::data_loader(const string &path)
  2. {
  3. ifstream file(path);
  4. //將數據存儲到vector中
  5. vector<vector<float>> dataset;
  6. string ss;
  7. while (getline(file, ss)){
  8. vector<float> data;
  9. stringstream w(ss);
  10. float temp;
  11. while (w >> temp){
  12. data.push_back(temp);
  13. }
  14. if (data.size() == 0){
  15. continue;
  16. }
  17. dataset.push_back(data);
  18. }
  19. //隨機打亂數據
  20. srand(static_cast<unsigned int>(time(0)));
  21. random_shuffle(dataset.begin(), dataset.end());
  22. //將vector轉化為Mat并分別存儲到訓練集和label中
  23. int rows = static_cast<int>(dataset.size());
  24. int cols = static_cast<int>(dataset[0].size() - 1);
  25. //創(chuàng )建數據集和label矩陣
  26. Mat train_data(rows, cols, CV_32FC1);
  27. Mat labels(rows, 1, CV_32FC1);
  28. //加載數據
  29. auto it = dataset.begin();
  30. for (int i = 0; i < rows; ++i){
  31. float *data = train_data.ptr<float>(i);
  32. float *label = labels.ptr<float>(i);
  33. for (int j = 0; j < cols + 1; ++j){
  34. data[j] = (*it)[j];
  35. if (cols == j){
  36. label[0] = (*it)[j];
  37. }
  38. }
  39. ++it;
  40. }
  41. //將共享指針指向數據
  42. this->data_ptr = make_shared<Mat>(train_data);
  43. this->label_ptr = make_shared<Mat>(labels);
  44. }

      這一部分沒(méi)啥好說(shuō)的,每個(gè)人可以根據自己的數據形式進(jìn)行改變,最好在訓練前將數據打亂(shuffle)和進(jìn)行歸一化(normal)等預處理,這里我沒(méi)有進(jìn)行歸一化是因為我的數據在存儲時(shí)已經(jīng)進(jìn)行歸一化了。最主要的是最終訓練數據將轉化為矩陣形式,這也是為什么使用OenCV,有Mat的話(huà)更方便進(jìn)行相關(guān)矩陣操作,嘿嘿。注意,假設我們的數據的特征有F維,那么其矩陣形式維1XF,所以對于N個(gè)數據集,其矩陣形式如下:

  •  

接下來(lái),我將介紹在加載數據時(shí)進(jìn)行相關(guān)的預處理更多詳細的信息。對于常見(jiàn)的數據預處理有以下幾種情況:

(1)數據清洗

  • 去除缺失大量特征的數據

  • 去掉樣本數據的異常數據。(比如連續型數據中的離群點(diǎn))

  • 對于數據缺失的特征,可以使用該特征的均值來(lái)代替缺失的部分

  • 對于一些類(lèi)別類(lèi)型,如:L,R,可以one-hot形式進(jìn)行編碼

(2)數據采樣

       在我們采集數據時(shí)經(jīng)常會(huì )遇到樣本不均衡的問(wèn)題,我們可以采用上/下采樣的方法進(jìn)行樣本補充,其具體為假設正負樣本比例1:100,把正樣本的數量重復100次,這就叫上采樣,也就是把比例小的樣本放大。下采樣同理,把比例大的數據抽取一部分,從而使比例變得接近于1;1。通過(guò)這種方式可以避免樣本的不均衡問(wèn)題,同時(shí)我們也要注意在實(shí)際特征工程中,均衡問(wèn)題會(huì )極大影響訓練的結果。

(3)預處理

       數據歸一化,數據標準化的方法有很多,如對于所有的數值特征,我們都會(huì )減去均值,除以方差。博主主要工作方向是圖像處理領(lǐng)域,在圖像處理方面,主要的預處理方法為去均值,這里的均值為訓練集的均值,之后再驗證/測試集中都是減去這個(gè)均值。對于為什么要去均值,有很多的解釋?zhuān)缦拢?/p>

  1. 對于我們的自然圖像其實(shí)是一種平穩的數據分布【即圖像的每一維都服從相同的分布】。所以通過(guò)減去數據對應維度的統計平均值,來(lái)消除公共的部分,以凸顯個(gè)體之間的特征和差異。

  2. 根據求導的鏈式法則,w的局部梯度是X,當X全為正時(shí),由反向傳播傳下來(lái)的梯度乘以X后不會(huì )改變方向,要么為正數要么為負數,也就是說(shuō)w權重的更新在一次更新迭代計算中要么同時(shí)減小,要么同時(shí)增大。

      其中,w的更新方向向量只能在第一和第三象限。假設最佳的w向量如藍色線(xiàn)所示,由于輸入全為正,現在迭代更新只能沿著(zhù)紅色路徑做zig-zag運動(dòng),更新的效率很慢?;诖?,當輸入數據減去均值后,就會(huì )有負有正,會(huì )消除這種影響。

      當然,目前講的一些預處理方法只是我在機器學(xué)習方面的常用的方法,對于數據預處理還有很多方法還沒(méi)試過(guò),有興趣的小伙伴可以試試。常見(jiàn)的特征工程的處理方法如下圖:

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
學(xué)習OpenCV——關(guān)于三通道的CvMat的求和問(wèn)題
手撕ORB_SLAM2系列--跟蹤--單目初始化1
OpenCL快速入門(mén)教程 | Imagination中文技術(shù)社區
【Unity人工智能學(xué)習
OpenCV參考手冊之Mat類(lèi)詳解(三)
OpenCV學(xué)習筆記(2):Mat矩陣的初始化和元素訪(fǎng)問(wèn)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久