日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Matlab实现CNN(二)

發布時間:2025/3/17 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Matlab实现CNN(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.前言

最近需要用到卷積神經網絡(CNN),在還沒完全掌握cuda+caffe+TensorFlow+python這一套傳統的深度學習的流程的時候,想到了matlab,自己查了一下documentation,還真的有深度學習的相關函數。所以給自己提個醒,在需要用到某個成熟的技術時先查一下matlab的幫助文檔,這樣會減少很多時間成本。記得機器學習的大牛Andrew NG.說過在硅谷好多人都是先用matlab/octava先實現自己的想法,再轉化成其他語言。

2.配置需求

要像用matlab實現deep learning,需要更新到2017a版本。GPU加速的話,需要安裝cuda8.0, 自己GPU 的compute capacity 要3.0 以上

3. 可以完成的任務

我們看一下matlab的新加的深度學習功能可以完成哪些任務

1. 獲取別人訓練好的CNN網絡 2. 遷移學習(transfer learning and fine-tune) 3. 解決分類問題(classifiy problem) 4. 解決回歸問題(regression problem) 5. 物體檢測(object detection) 6. 提取學習到的特征

3.1 獲取別人訓練好的網絡

matlab2017中,可以用別人訓練好的現成的網絡,也可以輸入caffe中的網絡。目前已知的可以用的網絡包括用于分類的:Alexnet, vgg16, vgg19。已經用于物體檢測的,RCNN, FastRCNN, Faster RCNN。由于最近一直研究的是分類和回歸問題,物體檢測的CNN在過后補全。這里只舉一個分類的例子。?
Alexnet作為2012年ImageNet的冠軍,它的提出確實影響到了CV的研究熱點,人們驚奇的發現深度網絡的描述能力居然這么強,雖然背后的數學原理一直沒能得到完美的解決,但不妨礙它強大的能力,我們看看她在matlab中是如何做分類的。首先貼出代碼:

clear;clc;close all; %獲取alexnet net = alexnet; %讀照片選物體 I= imread('peppers.png'); [cropedim, rect2]=imcrop(I); cropedim=imresize(cropedim,[227 227]); figure,imshow(cropedim); % 用AlexNet分類 label = classify(net, cropedim); % 顯示結果 figure; imshow(I); rectangle('position',rect2,'EdgeColor','r','LineWidth',2); text(10,20,char(label),'Color','white','FontSize',20);

用matlab自帶的照片測試一下分類的準確率,得到的結果如下?


bell pepper是甜椒的意思,我們發現效果還是不錯的,感興趣的同學可以多找幾張測試圖片試一下。用

net.Layers

命令可以看Alnexnet的網絡結構,得到以下?


這是一個25層的網絡,每一層都對應著詳細的說明。值得關注的是有5個卷積層(convolution layer)和三個全連接層(full connection layer)。其他的vgg16和vgg19是相同的道理,不過要看清楚網絡的輸入,使用vgg19時,需要改變上邊代碼中的兩行

net = vgg19; cropedim=imresize(cropedim,[224 224]);

剩下的部分是一樣的。當然也可以從caffe中導入自己訓練好的網絡,自己還沒有完全掌握caffe,熟悉這部分的同學可以自己實現一下。

3.2 遷移學習(transfer learning and fine-tune)

所謂遷移學習(transfer learning)就是微調(fine-tune)別人訓練好的網絡中的某些參數,使得它更適合自己的數據集。遷移學習使用的情況是:幾百到幾千個訓練樣本,想快速訓練網絡。網絡的訓練過程就是剛開始為各個參數賦予隨機的值,采用數值的方法(一般是梯度下降法)求讓cost function?達到最小值的各個參數的取值,這些參數主要產生于各個層之間連接時候的權值。Cost function是標定好的數據與通過網絡計算出的數據的差的累加。Cost function越小說明網絡的性能越好。我們看看matlab中是如何用現有的網絡做遷移學習的,我們舉一個手寫體識別的例子,其中matlab自己提供了訓練集和測試集。先貼出代碼:

%% transfer learning %讀取訓練集和測試集 digitDatasetPath = fullfile(matlabroot,'toolbox','nnet','nndemos', ...'nndatasets','DigitDataset'); digitData = imageDatastore(digitDatasetPath, ...'IncludeSubfolders',true,'LabelSource','foldernames'); [trainDigitData,testDigitData] = splitEachLabel(digitData,0.5,'randomize'); %顯示前20個訓練照片 numImages = numel(trainDigitData.Files); idx = randperm(numImages,20); for i = 1:20subplot(4,5,i)I = readimage(trainDigitData, idx(i));imshow(I) end % 獲取matlab自己訓練好的網絡 load(fullfile(matlabroot,'examples','nnet','LettersClassificationNet.mat')) % 改變輸出層的類別個數 layersTransfer = net.Layers(1:end-3); % 顯示新的類別個數 numClasses = numel(categories(trainDigitData.Labels)); % 把最后三層替換成新的類別 layers = [...layersTransferfullyConnectedLayer(numClasses,'WeightLearnRateFactor',20,'BiasLearnRateFactor',20)softmaxLayerclassificationLayer]; optionsTransfer = trainingOptions('sgdm',...'MaxEpochs',5,...'InitialLearnRate',0.0001,...'ExecutionEnvironment','cpu'); % 訓練網絡 netTransfer = trainNetwork(trainDigitData,layers,optionsTransfer); % 顯示測試準確率 YPred = classify(netTransfer,testDigitData); YTest = testDigitData.Labels; accuracy = sum(YPred==YTest)/numel(YTest); % 顯示測試結果 idx = 501:500:5000; figure for i = 1:numel(idx)subplot(3,3,i)I = readimage(testDigitData, idx(i));label = char(YTest(idx(i)));imshow(I)title(label) end

代碼的前邊的部分是讀取matlab中自帶的數據集和測試集,把它保存成imageDatastore格式,這種格式只需要提供圖片的路徑信息而不用把圖片全部讀入內存中,因此非常適合大規模的數據集。中間部分是修改訓練好的網絡中的最后三層,原網絡用來識別手寫的字母和數字有36類,而現在的任務只需要識別手寫體數字,所以把它們改成10類,在訓練時使用0.0001的學習率,共計算5輪,用cpu做訓練。代碼的最后部分是測試新訓練好的網絡,因為transfer learn是在現有的網絡基礎上做參數的微調,所以訓練速度很快,我們看一下訓練效果。?


由于是在cpu上做的訓練,而且是transfer learning 所以訓練的過程很快,我們發現重新訓練好的網絡能達到很高的準確率。我們再看gpu上的訓練?

由于參數的初始化是隨機的,因此得到的結果也是隨機的,不過可以看出gpu上做訓練明顯要快很多!GPU的第一輪計算慢是因為數據要重新初始化為gpu矩陣。最后放一張效果圖:?

我們發現識別的效果還是不錯的。

3.3 分類問題(classification problem)

CNN之所以能引起廣泛關注,就是在于它最初在圖像分類方面取得很大的成功,后來人們發現對于其他的分類問題,CNN也有很好的性能。上邊講的遷移學習解決的也是一種分類問題,接下來的敘述也就建立在上文的基礎上。?
我們這里要解決的分類問題,就是訓練自己的分類網絡。之前的遷移學習已經說明,所謂訓練就是為每層網絡之間尋找使得cost function最小的權值,這些權值剛開始是按照某種分布隨機初始化的,我們用數值的方法求cost function的最小值。一般來說,我們用神經網絡建立的是一個非常復雜的模型,我們往往能難找到這個模型的最小值,但可以找到它的極小值(局部最小值),這些極小值已經很接近我們要找到最小值。?
要訓練自己的網絡,我們要先建立自己的網絡,并設置一定的訓練參數。我們看一下matlabs是如何完成的。?
在matlab中用來建立網絡的語句如下:

layers = [ ...imageInputLayer([imsize imsize 1])convolution2dLayer(5,150)reluLayercrossChannelNormalizationLayer(5,'Alpha',0.00005,'Beta',0.75,'K',1) %Norm layer1 convolution2dLayer(3,300,'Stride',1,'BiasLearnRateFactor',2) %Cov2 layerreluLayerfullyConnectedLayer(1)softmaxLayerclassificationLayer];

直接用數組建立網絡,這個例子是建立一個9層的分類網絡,包括輸入層,卷積層1,激活函數層1,標準化層,卷積層2,激活函數層2,全連接層,去最大值層,分類層。至于如何選擇適合自己的網絡結構,我目前還沒有搞太清楚,不過,可以現在別人的網絡基礎上做修改。?
用來設定修改參數的語句如下:

options = trainingOptions('sgdm', ...'MaxEpochs',15, ...'InitialLearnRate',1e-4, ...'MiniBatchSize',256,...'ExecutionEnvironment','gpu');'OutputFcn',functions);

這些參數是CNN網絡的基本參數,MaxEpoch是計算的輪數,它的值越大越容易收斂,InitialLearRate是學習率,太大模型可能不會收斂,太小則收斂的太慢。MiniBatchSize是每次處理的數據的個數,ExcutionEnviroment是訓練網絡的環境,可以在CPU(‘cpu’)上做,也可在GPU(‘gpu’)上做,可以并行(‘paralle’),默認的情況是先測試gpu,如果不可用在測試gpu。在matlab上用gpu訓練網絡時需要cuda8.0, 顯卡計算能力為3.0。這些參數可以用指令gpuDevice來查看。OutputFcn是可以在訓練過程中調用的某些函數。比如:它可以用來畫cost function值的變化。如何像可視化訓練表格(上文輸出的那些)某些數據可以調用相應的函數,我在回歸問題時會再說明。?
設定好網絡結構和訓練參數后,可以用

net = trainNetwork(trainData,layers,options);

來訓練自己的網絡,訓練數據可以是ImageDatastore類型,可以是4-D數組,四個維度分別是長度,寬度,通道數,第幾個圖片。因為4-D數組是一次性裝入到內存中的,如果數據量太大時慎用,小心內存不足。同樣,我們舉一個完整的例子,也是利用matlab自帶的數據集去分類手寫體。代碼如下:

%讀取數據集并保存成imageDatastore形式 digitDatasetPath = fullfile(matlabroot,'toolbox','nnet','nndemos',...'nndatasets','DigitDataset'); digitData = imageDatastore(digitDatasetPath,...'IncludeSubfolders',true,'LabelSource','foldernames'); %隨機顯示二十個訓練集中的圖片 figure; perm = randperm(10000,20); for i = 1:20subplot(4,5,i);imshow(digitData.Files{perm(i)}); end %把數據集劃分成訓練集和測試集 trainingNumFiles = 750; rng(1) % For reproducibility [trainDigitData,testDigitData] = splitEachLabel(digitData,...trainingNumFiles,'randomize'); %建立自己的網絡 layers = [imageInputLayer([28 28 1]);convolution2dLayer(5,20);reluLayer();maxPooling2dLayer(2,'Stride',2);fullyConnectedLayer(10);softmaxLayer();classificationLayer()]; %設定訓練參數 options = trainingOptions('sgdm','MaxEpochs',20,...'InitialLearnRate',0.0001); %訓練網絡 convnet = trainNetwork(trainDigitData,layers,options); %測試網絡 YTest = classify(convnet,testDigitData); TTest = testDigitData.Labels; accuracy = sum(YTest == TTest)/numel(TTest); disp(accuracy);

我自己的訓練結果如下:?


自己是在gpu上做的,所以時間較短,最后得到分類準確率發現還不錯。

3.4 回歸問題(regression problem)

回歸問題與分類問題的處理方式相同,我們仍然需要訓練集和測試集。在網路結構上有些不同,最后一次必須是Regression layer, 而倒數第二次必須是卷積層。回歸問題的網絡中的參數與分類問題是一樣的,這里不再詳細說明,我們直接分析一個例子,看一下matlab是如何做分類的。這個問題同時看一下function參數的作用。這次要解決的問題是,圖片中的字母到底旋轉了多少度。數據集同樣來自matlab代碼如下:

%讀取數據集 [trainImages,~,trainAngles] = digitTrain4DArrayData; %顯示任意二十個結果 numTrainImages = size(trainImages,4);figure idx = randperm(numTrainImages,20); for i = 1:numel(idx)subplot(4,5,i)imshow(trainImages(:,:,:,idx(i)))drawnow end %建立回歸網絡 layers = [ ...imageInputLayer([28 28 1])convolution2dLayer(12,25)reluLayerfullyConnectedLayer(1)regressionLayer]; %設置訓練參數 functions={...@plotTrainingRMSE,...@(info)stopTrainingAtThreshold(info,0)}; options = trainingOptions('sgdm', ...'MaxEpochs',20, ...'InitialLearnRate',1e-3, ...'MiniBatchSize',128,...'ExecutionEnvironment','gpu',...'OutputFcn',functions); %訓練網絡 net = trainNetwork(trainImages,trainAngles,layers,options); %測試網絡 [testImages,~,testAngles] = digitTest4DArrayData; predictedTestAngles = predict(net,testImages); %查看擬合誤差 predictionError = testAngles - predictedTestAngles; thr = 10; numCorrect = sum(abs(predictionError) < thr); numTestImages = size(testImages,4); accuracy = numCorrect/numTestImages; disp('accuracy'); disp(accuracy); squares = predictionError.^2; rmse = sqrt(mean(squares)); disp('the rmse'); disp(rmse); %train function function plotTrainingRMSE(info)persistent plotObjif info.State == "start"figure;plotObj = animatedline;xlabel("Iteration")ylabel("Training RMSE") elseif info.State == "iteration"addpoints(plotObj,info.Iteration,double(info.TrainingRMSE))drawnow limitrate nocallbacks endendfunction stop = stopTrainingAtThreshold(info,thr)stop = false; if info.State ~= "iteration"return endpersistent TrainingRMSE% Append accuracy for this iteration T= info.TrainingRMSE;% Evaluate mean of iteration accuracy and remove oldest entrystop = T <thr;end

得到的回歸結果如下:?


我們在訓練過程中調用兩個函數,plotTrainingRMSE是用來畫cost function是如何變化的,(info)stopTrainingAtThreshold(info,0)是設置訓練提前結束的條件的,可以根據表中的某些參數讓訓練在一定條件下停下來。最后,我們看一下cost function 的變換規律,如下:?

目前為止,我們用cnn解決了最基本的分類問題和回歸問題,此外,還介紹了如何建立網絡和設定參數,后邊將補充檢測部分。

3.3 檢測問題(Detection problem)

同樣用matlab自帶數據集做車輛檢測,關于檢測的網絡有RCNN, Fast RCNN, Faster RCNN, 他們大同小異,差距在于速度的快慢,我們只測試Faster RCNN?
1) 讀取數據

data = load('fasterRCNNVehicleTrainingData.mat');

data是個結構體類型的數據,主要是用來四個屬性分別是detector, layers, result, vehicleTraining.?
其中,detector, layers, reault是提前訓練好的檢測子,網絡和測試結果,我們用vehicleTraining重新訓練CNN網絡,用layers來設計網絡結構?
2) 抽取用于訓練的圖像

trainingData = data.vehicleTrainingData; trainingData.imageFilename=fullfile(toolboxdir('vision'),'visiondata',... trainingData.imageFilename);

抽取出的trainingData是table格式的,matlab訓練網絡RCNN網絡只能用table格式。

3) 讀取網絡結構

layers=data.layers;

該網絡是個11層的網絡,訓練時我們可以設計自己的網絡結構,也可以在這個網絡的基礎上做訓練。

4) 設置訓練選項

options = trainingOptions('sgdm', ...'InitialLearnRate',1e-6,...'MaxEpochs',1,...'ExecutionEnvironment','gpu',...'CheckpointPath',tempdir);

這里設置的是初始學習率為 1e-6, 迭代1輪,用GPU做訓練,在訓練時會把checkpoint的結果存下來。

5) 訓練網絡

detector = trainFasterRCNNObjectDetector(trainingData,layers,options);

用trainingData做訓練數據,訓練layers網絡,在訓練過程中選擇option中的訓練參數,同樣用了GPU做訓練,其中的一步如下:?

6) 結果檢測

img=imread('highway.png'); [bbox,score,label]=detect(detector,img); detectedImg=insertShape(img,'Rectangle',bbox); figure,imshow(detectedImg);

從Matlab自身圖庫中選擇hightway這張照片,用剛才訓練出的網絡監測里邊的車輛,其中bbox是監測出的包圍盒的坐標,這個可以用來返回。?
這結果顯示如下:


總結

以上是生活随笔為你收集整理的Matlab实现CNN(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。