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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

caffe之特征图可视化及特征提取

發布時間:2024/9/21 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 caffe之特征图可视化及特征提取 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上一篇博客,介紹了怎么對訓練好的model的各層權重可視化,這篇博客,我們介紹測試圖片輸入網絡后產生的特征圖的可視化

記得上篇中,我們是寫了一個新的文件test.cpp,然后編譯運行那個文件的,這是因為權重可視化,是不需要網絡的前向傳播,只要加載model就好了,而我們如果需要可視化特征圖,那就必須進行網絡的前向傳播了,所以,這次,我們對caffe根目錄下的examples/cpp_classification/classification.cpp文件基礎上,進行修改,添加我們自己需要的功能(可視化),同樣的,我們把這個文件拷貝過來,放在自己的某個文件夾下,假設取名依然為test.cpp,而我們要修改的,就是Predict函數,定位到Predict函數,在net_->Forward();后面加入以下代碼:

?

  • //打印出一張圖片經過網絡各層產出的各層輸出

  • cout<<"網絡中的Blobs名稱為:\n";

  • vector<shared_ptr<Blob<float> > > blobs=net_->blobs(); //得到各層的輸出特征向量

  • vector<string> blob_names=net_->blob_names(); //各層的輸出向量名字

  • cout<<blobs.size()<<" "<<blob_names.size()<<endl;

  • for(int i=0;i<blobs.size();i++){

  • cout<<blob_names[i]<<" "<<blobs[i]->shape_string()<<endl;

  • }

  • cout<<endl;

  • 編譯該文件,編譯命令參照上一篇博客,此時會打印出如下信息

  • 網絡中的Blobs名稱為:

  • 15 15

  • data 1 3 227 227 (154587)

  • conv1 1 96 55 55 (290400)

  • pool1 1 96 27 27 (69984)

  • norm1 1 96 27 27 (69984)

  • conv2 1 256 27 27 (186624)

  • pool2 1 256 13 13 (43264)

  • norm2 1 256 13 13 (43264)

  • conv3 1 384 13 13 (64896)

  • conv4 1 384 13 13 (64896)

  • conv5 1 256 13 13 (43264)

  • pool5 1 256 6 6 (9216)

  • fc6 1 4096 (4096)

  • fc7 1 4096 (4096)

  • fc8 1 1000 (1000)

  • prob 1 1000 (1000)

  • 可以看到,此時將每個層的輸出特征圖的維度信息都打印出來了,比如data層的輸出是1 3 227 277,因為網絡的輸入圖片是1個,3通道,尺寸是227*227;經過conv1層的輸出是1 96 55 55,因為conv1層有96個卷積核,卷積核大小為11*11,步長為4,所以其輸出的每個特征圖的尺寸為(227-11)/4+1=55,所以特征圖的尺寸也對應著1 96 55 55.

    ?

    好了,我們接下來再輸入一下代碼,進行對經過conv1的特征圖可視化,其尺寸是1 96 55 55,也就看出是96個55*55大小的灰度圖

    ?

  • //將測試圖片經過第一個卷積層的特征圖可視化

  • string blobName="conv1"; //我們取經過第一個卷積層的特征圖

  • assert(net_->has_blob(blobName)); //為免出錯,我們必須斷言,網絡中確實有名字為blobName的特征圖

  • shared_ptr<Blob<float> > conv1Blob=net_->blob_by_name(blobName); //1*96*55*55 斷言成功后,按名字返回該 特征向量

  • cout<<"測試圖片的特征響應圖的形狀信息為:"<<conv1Blob->shape_string()<<endl; //打印輸出的特征圖的形狀信息

  • //和前面的博客一樣,此時的特征向量是經過了ReLU激活函數的,范圍在0~無窮大,我們為了可視化,仍然需要歸一化到0~255

  • //下面的代碼,跟上一篇博客中是一樣的

  • float maxValue=-10000000,minValue=10000000;

  • const float* tmpValue=conv1Blob->cpu_data();

  • for(int i=0;i<conv1Blob->count();i++){

  • maxValue=std::max(maxValue,tmpValue[i]);

  • minValue=std::min(minValue,tmpValue[i]);

  • }

  • int width=conv1Blob->shape(2); //響應圖的寬度

  • int height=conv1Blob->shape(3); //響應圖的高度

  • int num=conv1Blob->shape(1); //個數

  • int imgHeight=(int)(1+sqrt(num))*height;

  • int imgWidth=(int)(1+sqrt(num))*width;

  • Mat img2(imgHeight,imgWidth,CV_8UC1,Scalar(0)); //此時,應該是灰度圖

  • ?
  • int kk=0;

  • for(int x=0;x<imgHeight;x+=height){

  • for(int y=0;y<imgWidth;y+=width){

  • if(kk>=num)

  • continue;

  • Mat roi=img2(Rect(y,x,width,height));

  • for(int i=0;i<height;i++){

  • for(int j=0;j<width;j++){

  • float value=conv1Blob->data_at(0,kk,i,j);

  • roi.at<uchar>(i,j)=(value-minValue)/(maxValue-minValue)*255;

  • }

  • }

  • kk++;

  • }

  • }

  • resize(img2,img2,Size(500,500));//進行顯示

  • imshow("2",img2);

  • waitKey(0);


  • ?

    ?

    輸入圖片

    特征圖

    ?

    會了這一點后,大家如果想將CNN單純的當做特征提取器,可以將第一個全連接層的前一層的輸出特征向量(比如這個網絡,是pool5層的輸出特征1*256*6*6=9216)提取出來,這是該圖片經過CNN后的最初步的特征,當然如果覺得維度高,也可以提取出第一個全連接層的特征向量,這里是4096維,然后再送進泛化性能更好的分類器(如SVM)去分類識別,我用提取第一個全連接層的4096維特征試驗了下SVM,在線性核下,分類效果大致相當。大家可以根據自己的需求去嘗試。

    總結

    以上是生活随笔為你收集整理的caffe之特征图可视化及特征提取的全部內容,希望文章能夠幫你解決所遇到的問題。

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