標籤:
翻譯水平有限,歡迎閱讀原文
一、深度學習當前,深度學習已經成為一個熱門話題。隨著深度學習演算法和GPU技術的發展,我們已經能夠解決許多領域(電腦視覺、自然語言處理和機器人學)曾經認為不可能的事情。深度學習是建立在傳統的深度神經網路之上的。最近幾年的熱點是大資料集和強大的GPUs的使用。神經網路本質上是一種並行演算法,因此多核GPUs的使用能夠明顯的減少用於訓練深度神經網路的時間。以下,我將會討論如何使用MATLAB以及深度卷積神經網路和GPUs開發一個對象識別系統
二、為什麼將深度學慣用於電腦視覺?機器學習技術是利用資料(映像,訊號,文本)來訓練機器(模型)進而用於映像分類、對象檢測以及語言翻譯等領域。傳統的機器學習技術依然可以用於解決具有挑戰性的映像分類問題。但是如果將傳統的機器學習技術直接用於處理映像,那麼得到的結果會比較差,因為傳統的方法忽略了映像的結構和屬性。目前,效能最好的機器學習技術是利用特徵提取演算法來提取一副映像的特徵部分(interesting parts),進而構成映像的特徵向量(feature vectors)。然後再將其與傳統的機器學習演算法結合起來作進一步處理。走進深度學習的世界!深度卷積神經網路(CNNs)屬於深度學習演算法中的一種特別類型。它彌補了傳統機器學習技術的不足之處,改變了我們解決問題的方法。CNNs不僅能夠用於分類,而且也能夠直接用於映像的提取特徵,因此避免了手動提取特徵的環節。在電腦視覺應用領域中,你遇到的問題不僅有映像分類,還需要用一種好的電腦視覺技術來進行對象檢測,同時也需要一些專業領域的知識並且還要瞭解如何有效使用GPUs.本文以下部分,我將用一個對象識別的例子來說明用MATLAB進行深度學習是一件非常容易的事情,即使你沒有電腦視覺領域的知識或者不會GPU編程也沒關係。
三、對象檢測與識別本部分的目標是從視頻中檢測一隻寵物,並且正確的分辨出其到底是一隻貓還是一隻狗。要完成這個例子,你需要有MATLAB的並行計算工具箱(Parallel Computing Toolbox),電腦視覺工具箱(Computer Vision System Toolbox)和統計與機器學習工具箱(Statistics and Machine Learning Toolbox).如果你沒有這些工具,可以到www.mathworks.com/trial去申請一個試用版。另外,我還用了NVIDIA Tesla K40 GPU,你可以在任何一個 MATLAB compatibleCUDA-enabled NVIDIA GPU運行本例子。我們的方法包括以下兩個步驟:
a、
對象檢測:“寵物在視頻中的什麼位置?”
b、
對象識別:“現在我知道了它在什麼位置,不過它到底是貓還是狗呢?”圖1顯示了最終結果。
圖1 映像檢測與識別系統
1、使用預先訓練過的CNN分類器第一步是訓練分類器,該分類器能夠區分貓與狗的映像。我可以通過:
a、收集一些映像,在合理的訓練時間範圍內進行裁剪、改變大小再標出映像中的貓和狗,或者
b、使用在大量常見映像中訓練過的模型來解決我的問題。對於本例,我將用第2種方法,因為第2種方法在實際中很常見。為此,我首先從一個在資料集ImageNet上訓練過的CNN分類器開始。然後,我會用到MatConvNet。MatConvNet是一個MATLAB CNN工具包,它使用NVIDIA cuDNN庫來加速訓練和預測時間(想要瞭解更多的cuDNN資訊,可以參考這裡 Parallel Forall post)。MatConvNet的下載和安裝指令可以在其首頁找到。以前,我已經在我的電腦上安裝過MatConvNet,因此現在我可以直接使用如下MATLAB代碼下載預訓練過的CNN分類器,然後進行預測。注意:我還使用了cnnPredict()協助函數,具體見我的Github。
%% Download and predict using a pretrained ImageNet model% Setup MatConvNetrun(fullfile(‘matconvnet-1.0-beta15‘,‘matlab‘,‘vl_setupnn.m‘));% Download ImageNet model from MatConvNet pretrained networks repositoryurlwrite(‘http://www.vlfeat.org/matconvnet/models/imagenet-vgg-f.mat‘, ‘imagenet-vgg-f.mat‘);cnnModel.net = load(‘imagenet-vgg-f.mat‘);% Load and display an example imageimshow(‘dog_example.png‘);img = imread(‘dog_example.png‘);% Predict label using ImageNet trained vgg-f CNN modellabel = cnnPredict(cnnModel,img);title(label,‘FontSize‘,20)
預訓練過的CNN分類器在對象分類中的效果超出想象。CNN模型能夠告訴我們在本例所用的映像中(映像2)有一個小獵犬。儘管這是一個好的開端,但是我們的問題與此有些不同。我想要:(1)在寵物周圍畫一個矩形(對象檢測),然後(2)準確的標出其到底是狗還是貓(分類)。接下來,讓我們利用預訓練過的CNN模型建立一個狗vs貓的分類器開始。
圖2 預訓練過的ImageNet模型將有一隻狗的映像認為是“小獵犬”
2、訓練狗vs貓分類器對象識別還是比較簡單的。首先要解決一個簡單的分類問題——給定一幅映像,訓練一個能夠準確識別該映像中是否有一隻狗或一隻貓的分類器。只要有足夠數量的貓和狗映像,然後再利用預訓練過的CNN分類器,這個問題還是很容易實現的。為了擷取本例中所需要的映像,我讓我的同事給我發了一些他們自己寵物的照片。然後我將其分成貓和狗兩類並放在檔案夾“pet_images”下的“cat”和“dog”檔案夾裡,這樣做的好處是方便imageSet函數自動處理這些映像。隨後,我用如下代碼將其加入到MATLAB裡。
%% Load images from folder% Use imageSet to load images stored in pet_images folderimset = imageSet(‘pet_images‘,‘recursive‘);% Preallocate arrays with fixed size for predictionimageSize = cnnModel.net.normalization.imageSize;trainingImages = zeros([imageSize sum([imset(:).Count])],‘single‘);% Load and resize images for predictionfor ii = 1:numel(imset) for jj = 1:imset(ii).Count trainingImages(:,:,:,jj) = imresize(single(read(imset(ii),jj)),imageSize(1:2)); endend% Get the image labelstrainingLabels = getImageLabels(imset);summary(trainingLabels) % Display class label distribution
3、利用CNN進行特徵提取下一步我要做到是利用上述資料和預訓練過的ImageNet來提取映像特徵。正如我之前提到的那樣,CNNs可以從映像中提取一般的特徵。然後,可以利用這些特徵來訓練新的分類器進而解決不同的問題,例如本例中的貓狗映像分類問題。CNN演算法是計算密集型的演算法,因此其計算過程可能比較長。而鑒於CNN本質上是並行演算法,因此我們可以利用GPUs來加速計算過程。下面是利用預訓練過的模型來進行特徵提取的代碼,同時也與利用多線程CPU和利用GPU實現進行了比較。
%% Extract features using pretrained CNN% Depending on how much memory you have on your GPU you may use a larger% batch size. I have 400 images, so I choose 200 as my batch sizecnnModel.info.opts.batchSize = 200;% Make prediction on a CPU[~, cnnFeatures, timeCPU] = cnnPredict(cnnModel,trainingImages,‘UseGPU‘,false);% Make prediction on a GPU[~, cnnFeatures, timeGPU] = cnnPredict(cnnModel,trainingImages,‘UseGPU‘,true);% Compare the performance increasebar([sum(timeCPU),sum(timeGPU)],0.5)title(sprintf(‘Approximate speedup: %2.00f x ‘,sum(timeCPU)/sum(timeGPU)))set(gca,‘XTickLabel‘,{‘CPU‘,‘GPU‘},‘FontSize‘,18)ylabel(‘Time(sec)‘), grid on, grid minor
圖3 利用CPU(左)和GPU(右)進行特徵提取的時間對比
圖4利用CPU和GPU從1128副映像中提取特徵的時間正4所示的那樣,在本例中利用GPUs帶來的效能提升是很明顯的——大約提高了15倍左右。函數cnnPredict已經在MatConvNet裡面的vl_simplenn預測函數裡封裝好了。如果你要用GPU來進行預測的話,只需改變圖5中紅色矩形部分的代碼即可。並行計算工具箱中的gpuArray函數使你非常方便的將在CPU上實現的代碼轉換到GPU上。
gpuArray和gather函數可以使你將MATLAB 工作空間中的資料轉換到GPU中" title="">
圖5
gpuArray和
gather函數可以使你將MATLAB 工作空間中的資料轉換到GPU中
4、利用CNN特徵訓練分類器有了C小節中提取到的CNN特徵,現在我們開始訓練一個簡單的分類器。為了訓練模型並將多個模型進行相互比較,我們需要用到統計與機器學習工具箱中的Classification Learner app。注意:想要瞭解MATLAB中的機器學習與分類問題可以到 Machine Learning Made Easy webinar。下一步,我首先用 fitcsvm函數提取特徵,之後用cnnFeature作為輸入或預測器,用trainingLabels作為輸出或預測值,然後在此基礎上來訓練SVM分類器。當然,為了驗證準確率我還會用交叉驗證來測試分類器。驗證得到的準確率是該分類器在實際資料上所得結果的無偏估計。
%% Train a classifier using extracted features% Here I train a linear support vector machine (SVM) classifier.svmmdl = fitcsvm(cnnFeatures,trainingLabels);% Perform crossvalidation and check accuracycvmdl = crossval(svmmdl,‘KFold‘,10);fprintf(‘kFold CV accuracy: %2.2f\n‘,1-cvmdl.kfoldLoss)
svmmdl是我的分類器,該分類器可以用於區分映像中的寵物是貓還是狗。
5、對象檢測除了寵物之外,大多數映像或視頻中還有許多其他的東西,有可能是樹或浣熊之類的。要是這樣的話,即使分類器很好(比如我上述用到的),其分類效果往往也不是很好。但是如果我們能夠定位到映像中的對象(狗或者貓),然後提取該對象所在地區並將其用到分類器中,那麼分類結果將明顯改善。而對象定位的過程就叫做對象檢測。為了檢測出所需對象,我要使用一種叫做 Optical Flow的技術。該技術的核心是對象像素在視頻的連續幀中具有不同的位置。圖6中顯示了視頻的一幀(帶有運動向量重疊)。
圖6 視頻中的一幀對象檢測的下一步是提取出運動的像素,然後使用 Image Region Analyzer app來分析二值映像中的連通部分以此來消除因相機運動而引起的雜訊像素。
四、對象檢測與識別步驟目前為止,我已經有了建立一個寵物檢測與識別系統所需的基本步驟,接下來我將把它們整理匯總。首先來快速回顧一下這些基本步驟:
A、 檢測寵物在映像中的位置;
B、 提取寵物所在地區並用訓練好的CNN來提取特徵;
C、 利用SVM分類器進行(特徵)分類。
寵物檢測與識別將上述基本步驟整理後,最終我可以得到如下MATLAB代碼所示的完整寵物檢測與識別系統。
%% Tying the workflow togethervr = VideoReader(fullfile(‘PetVideos‘,‘videoExample.mov‘));vw = VideoWriter(‘test.avi‘,‘Motion JPEG AVI‘);opticFlow = opticalFlowFarneback;open(vw);while hasFrame(vr)% Count framesframeNumber = frameNumber + 1;% Step 1. Read FramevideoFrame = readFrame(vr);% Step 2. Detect ROIvFrame = imresize(videoFrame,0.25); % Get video frameframeGray = rgb2gray(vFrame); % Convert to gray for detectionbboxes = findPet(frameGray,opticFlow); % Find bounding boxesif ~isempty(bboxes)img = zeros([imageSize size(bboxes,1)]);for ii = 1:size(bboxes,1)img(:,:,:,ii) = imresize(imcrop(videoFrame,bboxes(ii,:)),imageSize(1:2));end% Step 3. Recognize object% (a) Extract features using a CNN[~, scores] = cnnPredict(cnnModel,img,‘UseGPU‘,true,‘display‘,false);% (b) Predict using the trained SVM Classifierlabel = predict(svmmdl,scores);% Step 4. Annotate objectvideoFrame = insertObjectAnnotation(videoFrame,‘Rectangle‘,bboxes,cellstr(label),‘FontSize‘,40);end% Step 5. Write video to filewriteVideo(vw,videoFrame);fprintf(‘Frames processed: %d of %d\n‘,frameNumber,ceil(vr.FrameRate*vr.Duration));endclose(vw);
五、結論在解決現實世界的電腦視覺問題時,往往需要根據你的應用需求(效能、準確率和方案簡潔性)進行權衡。就視覺識別的準確度來說,深度學習這樣的進階技術相比傳統機器學習已經有了顯著提高。但是對於主流的應用來說,其效能代價往往也很顯著,不過GPU技術可以以數量級的加速倍數來彌補這些代價。MATLAB使得深度學習電腦視覺工作變得更加方便。一些便於使用的應用程式與其他編程環境,開源電腦視覺庫和機器學習演算法以及支援CUDA的顯卡等技術的結合使得MATLAB成為設計與快速實現電腦視覺問題的理想平台。如果你對這篇文章感興趣,可以註冊我們即將推出的網路研討會:Deep Learning for Computer Vision with MATLAB。研討會結束後,我們將進行現場問題解答。順便說一下,你可能也會對 previous MATLAB posts on Parallel Forall感興趣。
相關串連Deep Speech: Accurate Speech Recognition with GPU-Accelerated Deep LearningBIDMach: Machine Learning at the Limit with GPUsDeep Learning for Image Understanding in Planetary ScienceEasy Multi-GPU Deep Learning with DIGITS 2
Deep Learning for Computer Vision with MATLAB and cuDNN(譯文)