編寫C語言版本的卷積神經網路CNN之一:前言與Minst資料集
前言
卷積神經網路是深度學習的基礎,但是學習CNN卻不是那麼簡單,雖然網路上關於CNN的相關程式碼很多,比較經典的是tiny_cnn(C++)、DeepLearnToolbox(Matlab)等等,但通過C語言來編寫CNN的卻比較少,本人因為想在多核DSP下執行CNN,所以便嘗試通過C語言來編寫,主要參考的程式碼是DeepLearnToolbox的內容,DeepLearnToolbox是用Matlab指令碼編寫,是我看過的最為簡單的CNN程式碼,程式碼清晰,閱讀方便,非常適合新手入門學習。
專案程式碼地址:https://github.com/tostq/DeepLearningC/tree/master/CNN
本文的CNN程式碼是一個最基本的卷積網路,主要用於手寫數字的識別,選擇的訓練測試是資料庫是Minst手寫數字庫,主要是包括了一個基本的多層卷積網路框架、卷積層、Pooling層、及全連線的單層神經網路輸出層,不過CNN其他重要的概念如Dropout、ReLu等暫時沒有涉及,但是個人對於新手,學習卷積網路的基本結構及其誤差反向傳播方法是完全足夠。
這裡要注意的是,本文的方法並不是深度學習之父Yann. LeCun在1998年就已經提出的成熟演算法LeNet-5卷積網路,而只是DeepLearnToolbox內的cnn程式碼的c語言實現,不過我們會比較二者之間的區別,因為二者的基本原理是相似的。另外,為了不使部落格篇幅過長,所以部落格中貼的程式碼並不完整,完整程式碼請見附件。
這篇部落格總共分為四節:
第一節:前言,介紹專案結構及Minst資料集測試訓練資料集
第二節:主要介紹CNN的網路結構、相關資料結構
第三節:重點介紹CNN學習訓練過程的誤差反向傳播方法,採用的是線上訓練方式
第四節:CNN的學習及測試結果的比較
論文參考文獻:
Y. LeCun, L. Bottou, Y. Bengio and P. Haffner: Gradient-Based Learning Applied to Document Recognition, Proceedings of the IEEE, 86(11):2278-2324,
November 1998
一、程式碼結構
本文的CNN程式碼是通過標準C編寫,也不需要呼叫任何三方庫檔案,附件共享的檔案是通過VS2010編譯的專案檔案(這裡雖然是.cpp檔案,但實際上完全是用C編寫的,直接改成.c檔案是完全可以使用的),當然也可以直接將相關的原始檔匯入到其他IDE上,也是能夠執行的。
檔案結構:
cnn.cpp cnn.h 存在關於CNN網路的函式、網路結構等
minst.cpp minst.h 處理Minst資料庫的函式、資料結構等
mat.cpp mat.h 一些關於矩陣的函式,如卷積操作、180度翻轉操作等
main.cpp 主函式和測試函式
二、MINST資料庫
MINST資料庫是由Yann提供的手寫數字資料庫檔案,其官方下載地址http://yann.lecun.com/exdb/mnist/
這個裡面還包含了對這個資料庫進行識別的各類演算法的結果比較及相關演算法的論文
資料庫的裡的影像都是28*28大小的灰度影像,每個畫素的是一個八位位元組(0~255)
這個資料庫主要包含了60000張的訓練影像和10000張的測試影像,主要是下面的四個檔案
上述四個檔案直接解壓就可以使用了,雖然資料未壓縮,但是我們還是需要將影像提取出來,方便我們進行操作
(1)儲存影像資料的相關資料結構:
單張影像結構及儲存影像的連結串列
影像實際數字標號(0~9),資料庫裡是用一個八位位元組來表示,不過為了方便學習,需要用10位來表示。
這裡的10位表示網路輸出層的10個神經元,某位為1表示數字標號即為該位。
(2)讀入影像資料的相關函式
ImgArr read_Img(const char* filename) // 讀入影像
{
FILE *fp=NULL;
fp=fopen(filename,"rb");
if(fp==NULL)
printf("open file failed\n");
assert(fp);
int magic_number = 0;
int number_of_images = 0;
int n_rows = 0;
int n_cols = 0;
//從檔案中讀取sizeof(magic_number) 個字元到 &magic_number
fread((char*)&magic_number,sizeof(magic_number),1,fp);
magic_number = ReverseInt(magic_number);
//獲取訓練或測試image的個數number_of_images
fread((char*)&number_of_images,sizeof(number_of_images),1,fp);
number_of_images = ReverseInt(number_of_images);
//獲取訓練或測試影像的高度Heigh
fread((char*)&n_rows,sizeof(n_rows),1,fp);
n_rows = ReverseInt(n_rows);
//獲取訓練或測試影像的寬度Width
fread((char*)&n_cols,sizeof(n_cols),1,fp);
n_cols = ReverseInt(n_cols);
//獲取第i幅影像,儲存到vec中
int i,r,c;
// 影像陣列的初始化
ImgArr imgarr=(ImgArr)malloc(sizeof(MinstImgArr));
imgarr->ImgNum=number_of_images;
imgarr->ImgPtr=(MinstImg*)malloc(number_of_images*sizeof(MinstImg));
for(i = 0; i < number_of_images; ++i)
{
imgarr->ImgPtr[i].r=n_rows;
imgarr->ImgPtr[i].c=n_cols;
imgarr->ImgPtr[i].ImgData=(float**)malloc(n_rows*sizeof(float*));
for(r = 0; r < n_rows; ++r)
{
imgarr->ImgPtr[i].ImgData[r]=(float*)malloc(n_cols*sizeof(float));
for(c = 0; c < n_cols; ++c)
{
// 因為神經網路用float型計算更為精確,這裡我們將影像畫素轉為浮點型
unsigned char temp = 0;
fread((char*) &temp, sizeof(temp),1,fp);
imgarr->ImgPtr[i].ImgData[r][c]=(float)temp/255.0;
}
}
}
fclose(fp);
return imgarr;
}
(3)讀入影像資料標號
LabelArr read_Lable(const char* filename)// 讀入影像
{
FILE *fp=NULL;
fp=fopen(filename,"rb");
if(fp==NULL)
printf("open file failed\n");
assert(fp);
int magic_number = 0;
int number_of_labels = 0;
int label_long = 10;
//從檔案中讀取sizeof(magic_number) 個字元到 &magic_number
fread((char*)&magic_number,sizeof(magic_number),1,fp);
magic_number = ReverseInt(magic_number);
//獲取訓練或測試image的個數number_of_images
fread((char*)&number_of_labels,sizeof(number_of_labels),1,fp);
number_of_labels = ReverseInt(number_of_labels);
int i,l;
// 影像標記陣列的初始化
LabelArr labarr=(LabelArr)malloc(sizeof(MinstLabelArr));
labarr->LabelNum=number_of_labels;
labarr->LabelPtr=(MinstLabel*)malloc(number_of_labels*sizeof(MinstLabel));
for(i = 0; i < number_of_labels; ++i)
{
// 資料庫內的影像標記是一位,這裡將影像標記變成10位,10位中只有唯一一位為1,為1位即是影像標記
labarr->LabelPtr[i].l=10;
labarr->LabelPtr[i].LabelData=(float*)calloc(label_long,sizeof(float));
unsigned char temp = 0;
fread((char*) &temp, sizeof(temp),1,fp);
labarr->LabelPtr[i].LabelData[(int)temp]=1.0;
}
fclose(fp);
return labarr;
}
專案程式碼地址:https://github.com/tostq/DeepLearningC/tree/master/CNN
相關文章
- 卷積神經網路CNN卷積神經網路CNN
- 卷積神經網路CNN實戰:MINST手寫數字識別——網路定義卷積神經網路CNN
- 看懂卷積神經網路(CNN)卷積神經網路CNN
- CNN神經網路之卷積操作CNN神經網路卷積
- 卷積神經網路(CNN)詳解卷積神經網路CNN
- 卷積神經網路(CNN)介紹與實踐卷積神經網路CNN
- Tensorflow-卷積神經網路CNN卷積神經網路CNN
- 卷積神經網路(CNN)模型結構卷積神經網路CNN模型
- 直白介紹卷積神經網路(CNN)卷積神經網路CNN
- Keras上實現卷積神經網路CNNKeras卷積神經網路CNN
- 卷積神經網路CNN-學習1卷積神經網路CNN
- CNN筆記:通俗理解卷積神經網路CNN筆記卷積神經網路
- TensorFlow上實現卷積神經網路CNN卷積神經網路CNN
- 【機器學習基礎】卷積神經網路(CNN)基礎機器學習卷積神經網路CNN
- 卷積神經網路學習資料卷積神經網路
- 卷積神經網路卷積神經網路
- CNN-卷積神經網路簡單入門(2)CNN卷積神經網路
- 卷積神經網路:Convolutional Neural Networks(CNN)卷積神經網路CNN
- 卷積神經網路(Convolutional Neural Network,CNN)卷積神經網路CNN
- 卷積神經網路(CNN)反向傳播演算法卷積神經網路CNN反向傳播演算法
- 詳解卷積神經網路(CNN)在語音識別中的應用卷積神經網路CNN
- 5.2.1 卷積神經網路卷積神經網路
- 卷積神經網路概述卷積神經網路
- 解密卷積神經網路!解密卷積神經網路
- 卷積神經網路初探卷積神經網路
- 卷積神經網路-1卷積神經網路
- 卷積神經網路-2卷積神經網路
- 卷積神經網路-3卷積神經網路
- 卷積神經網路(CNN)前向傳播演算法卷積神經網路CNN演算法
- 卷積神經網路十五問:CNN與生物視覺系統的研究探索卷積神經網路CNN視覺
- 9 大主題卷積神經網路(CNN)的 PyTorch 實現卷積神經網路CNNPyTorch
- “卷積神經網路(Convolutional Neural Network,CNN)”之問卷積神經網路CNN
- 機器學習從入門到放棄:卷積神經網路CNN(二)機器學習卷積神經網路CNN
- 卷積神經網路四種卷積型別卷積神經網路型別
- TensorFlow應用之進階版卷積神經網路CNN在CIFAR-10資料集上分類卷積神經網路CNN
- 卷積神經網路的缺點卷積神經網路
- 卷積神經網路CNN(2)—— BN(Batch Normalization) 原理與使用過程詳解卷積神經網路CNNBATORM
- 全卷積神經網路FCN卷積神經網路