1. 程式人生 > >caffe入門學習

caffe入門學習

caffe入門學習

原文地址http://blog.csdn.net/hjimce/article/details/48933813

作者:hjimce

本文主要講解caffe的整個使用流程,適用於初級入門caffe,通過學習本篇博文,理清專案訓練、測試流程。初級教程,高手請繞道。

我們知道,在caffe編譯完後,在caffe目錄下會生成一個build目錄,在build目錄下有個tools,這個裡面有個可執行檔案caffe,如下圖所示:


有了這個可執行檔案我們就可以進行模型的訓練,只需要學會呼叫這個可執行檔案就可以了,這便是最簡單的caffe學習,不需要對caffe底層的東西懂太多,只需要會調引數,就可以構建自己的網路,然後呼叫這個可執行檔案就可以進行訓練,當然如果你不僅僅是調引數,而且想要更改相關的演算法,那就要深入學習caffe的底層函式呼叫了,這個以後再講。本篇博文僅適合於剛入門學習caffe,高手請繞道。廢話不多說,迴歸正題:

一、總流程

完成一個簡單的自己的網路模型訓練預測,主要包含幾個步驟:

1、資料格式處理,也就是把我們的圖片.jpg,.png等圖片以及標註標籤,打包在一起,搞成caffe可以直接方便呼叫的檔案。後面我將具體講解如何打包自己的資料,讓caffe進行呼叫。

2、編寫網路結構檔案,這個檔案的字尾格式是.prototxt。就是編寫你的網路有多少層,每一層有多少個特徵圖,輸入、輸出……。看個例子,看一下caffe-》example-》mnist-》lenet_train_test.prototxt。這個便是手寫字型網路結構檔案了,我們需要根據自己的需要學會修改這個檔案:

[cpp]
view plain copy print ?
  1. <span style="font-size:18px;">name: "LeNet"  
  2. layer {  
  3.   name: "mnist"  
  4.   type: "Data"  //data層  
  5.   top: "data"
      
  6.   top: "label"  
  7.   include {  
  8.     phase: TRAIN   //訓練階段  
  9.   }  
  10.   transform_param {  
  11.     scale: 0.00390625   //對所有的圖片歸一化到0~1之間,也就是對輸入資料全部乘以scale,0.0039= 1/255  
  12.   }  
  13.   data_param {  
  14.     source: "examples/mnist/mnist_train_lmdb"  //訓練資料圖片路徑  
  15.     batch_size: 64    //每次訓練採用的圖片64張,min-batch  
  16.     backend: LMDB  
  17.   }  
  18. }  
  19. layer {  
  20.   name: "mnist"  
  21.   type: "Data"  
  22.   top: "data"  
  23.   top: "label"  
  24.   include {  
  25.     phase: TEST   //測試  
  26.   }  
  27.   transform_param {  
  28.     scale: 0.00390625  
  29.   }  
  30.   data_param {  
  31.     source: "examples/mnist/mnist_test_lmdb" //測試資料圖片路徑  
  32.     batch_size: 100  
  33.     backend: LMDB  
  34.   }  
  35. }  
  36. layer {  
  37.   name: "conv1"   //卷積神經網路的第一層,卷積層  
  38.   type: "Convolution"  //這層操作為卷積  
  39.   bottom: "data"   //這一層的前一層是data層  
  40.   top: "conv1"   //  
  41.   param {  
  42.     lr_mult: 1     
  43.   }  
  44.   param {  
  45.     lr_mult: 2  
  46.   }  
  47.   convolution_param {  
  48.     num_output: 20    //定義輸出特徵圖個數  
  49.     kernel_size: 5    //定義卷積核大小  
  50.     stride: 1  
  51.     weight_filler {  
  52.       type: "xavier"  
  53.     }  
  54.     bias_filler {  
  55.       type: "constant"  
  56.     }  
  57.   }  
  58. }  
  59. layer {  
  60.   name: "pool1"  
  61.   type: "Pooling"      //池化層,這一層的操作為池化  
  62.   bottom: "conv1"   //這一層的前面一層名字為:conv1  
  63.   top: "pool1"  
  64.   pooling_param {  
  65.     pool: MAX   //最大池化  
  66.     kernel_size: 2  
  67.     stride: 2  
  68.   }  
  69. }  
  70. layer {  
  71.   name: "conv2"  
  72.   type: "Convolution"  
  73.   bottom: "pool1"  
  74.   top: "conv2"  
  75.   param {  
  76.     lr_mult: 1  
  77.   }  
  78.   param {  
  79.     lr_mult: 2  
  80.   }  
  81.   convolution_param {  
  82.     num_output: 50  
  83.     kernel_size: 5  
  84.     stride: 1  
  85.     weight_filler {  
  86.       type: "xavier"  
  87.     }  
  88.     bias_filler {  
  89.       type: "constant"  
  90.     }  
  91.   }  
  92. }  
  93. layer {  
  94.   name: "pool2"  
  95.   type: "Pooling"  
  96.   bottom: "conv2"  
  97.   top: "pool2"  
  98.   pooling_param {  
  99.     pool: MAX  
  100.     kernel_size: 2  
  101.     stride: 2  
  102.   }  
  103. }  
  104. layer {  
  105.   name: "ip1"  
  106.   type: "InnerProduct"  
  107.   bottom: "pool2"  
  108.   top: "ip1"  
  109.   param {  
  110.     lr_mult: 1  
  111.   }  
  112.   param {  
  113.     lr_mult: 2  
  114.   }  
  115.   inner_product_param {  
  116.     num_output: 500  
  117.     weight_filler {  
  118.       type: "xavier"  
  119.     }  
  120.     bias_filler {  
  121.       type: "constant"  
  122.     }  
  123.   }  
  124. }  
  125. layer {  
  126.   name: "relu1"  
  127.   type: "ReLU"  
  128.   bottom: "ip1"  
  129.   top: "ip1"  
  130. }  
  131. layer {  
  132.   name: "ip2"  
  133.   type: "InnerProduct"  
  134.   bottom: "ip1"  
  135.   top: "ip2"  
  136.   param {  
  137.     lr_mult: 1  
  138.   }  
  139.   param {  
  140.     lr_mult: 2  
  141.   }  
  142.   inner_product_param {  
  143.     num_output: 10  
  144.     weight_filler {  
  145.       type: "xavier"  
  146.     }  
  147.     bias_filler {  
  148.       type: "constant"  
  149.     }  
  150.   }  
  151. }  
  152. layer {  
  153.   name: "accuracy"  
  154.   type: "Accuracy"  
  155.   bottom: "ip2"  
  156.   bottom: "label"  
  157.   top: "accuracy"  
  158.   include {  
  159.     phase: TEST  
  160.   }  
  161. }  
  162. layer {  
  163.   name: "loss"  
  164.   type: "SoftmaxWithLoss"  
  165.   bottom: "ip2"  
  166.   bottom: "label"  
  167.   top: "loss"  
  168. }</span>  
<span style="font-size:18px;">name: "LeNet"
layer {
  name: "mnist"
  type: "Data"  //data層
  top: "data"
  top: "label"
  include {
    phase: TRAIN   //訓練階段
  }
  transform_param {
    scale: 0.00390625   //對所有的圖片歸一化到0~1之間,也就是對輸入資料全部乘以scale,0.0039= 1/255
  }
  data_param {
    source: "examples/mnist/mnist_train_lmdb"  //訓練資料圖片路徑
    batch_size: 64    //每次訓練採用的圖片64張,min-batch
    backend: LMDB
  }
}
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST   //測試
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "examples/mnist/mnist_test_lmdb" //測試資料圖片路徑
    batch_size: 100
    backend: LMDB
  }
}
layer {
  name: "conv1"   //卷積神經網路的第一層,卷積層
  type: "Convolution"  //這層操作為卷積
  bottom: "data"   //這一層的前一層是data層
  top: "conv1"   //
  param {
    lr_mult: 1   
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 20    //定義輸出特徵圖個數
    kernel_size: 5    //定義卷積核大小
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"      //池化層,這一層的操作為池化
  bottom: "conv1"   //這一層的前面一層名字為:conv1
  top: "pool1"
  pooling_param {
    pool: MAX   //最大池化
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 50
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 10
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}</span>

上面的網路結構,定義的data層,就是定義我們輸入的訓練資料的路徑、圖片變換等。

3、網路求解檔案,這個檔案我們喜歡把它取名為:solver.prototxt,這個檔案的字尾格式也是.prototxt。這個檔案主要包含了一些求解網路,梯度下降引數、迭代次數等引數……,看下手寫字型的solver.prototxt檔案:

[cpp] view plain copy print ?
  1. <span style="font-size:18px;">net: "examples/mnist/lenet_train_test.prototxt"  //定義網路結構檔案,也就是我們上一步編寫的檔案  
  2.   
  3. test_iter: 100   
  4.   
  5. test_interval: 500 //每隔500次用測試資料,做一次驗證  
  6.   
  7. base_lr: 0.01     //學習率  
  8. momentum: 0.9   //動量引數  
  9. weight_decay: 0.0005   //權重衰減係數  
  10.   
  11. lr_policy: "inv"   //梯度下降的相關優化策略  
  12. gamma: 0.0001  
  13. power: 0.75  
  14.   
  15. display: 100  
  16.   
  17. max_iter: 10000   //最大迭代次數  
  18.   
  19. snapshot: 5000    //每迭代5000次,儲存一次結果  
  20. snapshot_prefix: "examples/mnist/lenet" //儲存結果路徑  
  21.   
  22. solver_mode: GPU   //訓練硬體裝置選擇GPU還是CPU</span>  
<span style="font-size:18px;">net: "examples/mnist/lenet_train_test.prototxt"  //定義網路結構檔案,也就是我們上一步編寫的檔案

test_iter: 100 

test_interval: 500 //每隔500次用測試資料,做一次驗證

base_lr: 0.01     //學習率
momentum: 0.9   //動量引數
weight_decay: 0.0005   //權重衰減係數

lr_policy: "inv"   //梯度下降的相關優化策略
gamma: 0.0001
power: 0.75

display: 100

max_iter: 10000   //最大迭代次數

snapshot: 5000    //每迭代5000次,儲存一次結果
snapshot_prefix: "examples/mnist/lenet" //儲存結果路徑

solver_mode: GPU   //訓練硬體裝置選擇GPU還是CPU</span>

這個檔案的輸入就是我們前面一步定義的網路結構。

4、編寫網路求解檔案後,我們可以說已經完成了CNN網路的編寫。接著我們需要把這個檔案,作為caffe的輸入引數,呼叫caffe可執行檔案,進行訓練就可以了。具體的命令如下:

[cpp] view plain copy print ?
  1. ./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt  
./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt

這樣就完事了,程式就開始訓練了。上面的第一個引數caffe,就是我們在編譯caffe,生成的可執行檔案:



然後solver就是我們在步驟3編寫的solver檔案了,只要在ubuntu終端輸入上面的命令,就可以開始訓練了。

回想一下檔案呼叫過程:首先caffe可執行檔案,呼叫了solver.prototxt檔案,而這個檔案又呼叫了網路結構檔案lenet_train_test.prototxt,然後lenet_train_test.prototxt檔案裡面又會呼叫輸入的訓練圖片資料等。因此我們如果要訓練自己的模型,需要備好3個檔案:資料檔案lmdb(該檔案包含尋資料)、網路結構lenet_train_test.prototxt、求解檔案solver.prototxt,這幾個檔名隨便,但是檔案字尾格式不要隨便亂改。把這三個檔案放在同一個目錄下,然後在終端輸入命令,呼叫caffe就可以開始訓練了。

二、相關細節

1、lmdb資料格式生成

caffe輸入訓練圖片資料我比較喜歡用lmdb格式,好像還有另外一種格式leveldb,這個具體沒用過,這裡主要講解lmdb格式資料的製作。其實在caffe-》example-》imagenet資料夾下面的一些指令碼檔案可以幫助我們快速生產相關的caffe所需的資料。


create_imagenet.sh這個檔案可以幫我們快速的生成lmdb的資料格式檔案,因此我們只需要把這個指令碼檔案複製出來,稍作修改,就可以對我們的訓練圖片、標註檔案進行打包為lmdb格式檔案了。製作圖片的指令碼檔案如下:

[python] view plain copy print ?
  1. <span style="font-size:18px;">#!/usr/bin/env sh  
  2. # Create the imagenet lmdb inputs  
  3. # N.B. set the path to the imagenet train + val data dirs  
  4.   
  5. EXAMPLE=.          # 生成模型訓練資料文化夾  
  6. TOOLS=../../build/tools                              # caffe的工具庫,不用變  
  7. DATA=.                  # python腳步處理後資料路徑  
  8.   
  9. TRAIN_DATA_ROOT=train/  #待處理的訓練資料圖片路徑  
  10. VAL_DATA_ROOT=val/      # 帶處理的驗證資料圖片路徑  
  11.   
  12.   
  13.   
  14. # Set RESIZE=true to resize the images to 256x256. Leave as false if images have  
  15. # already been resized using another tool.  
  16. RESIZE=true   #圖片縮放  
  17. if $RESIZE; then  
  18.   RESIZE_HEIGHT=256  
  19.   RESIZE_WIDTH=256  
  20. else  
  21.   RESIZE_HEIGHT=0  
  22.   RESIZE_WIDTH=0  
  23. fi  
  24.   
  25. if [ ! -d "$TRAIN_DATA_ROOT" ]; then  
  26.   echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"  
  27.   echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \  
  28.        "where the ImageNet training data is stored."  
  29.   exit 1  
  30. fi  
  31.   
  32. if [ ! -d "$VAL_DATA_ROOT" ]; then  
  33.   echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"  
  34.   echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \  
  35.        "where the ImageNet validation data is stored."  
  36.   exit 1  
  37. fi  
  38.   
  39. echo "Creating train lmdb..."  
  40.   
  41. GLOG_logtostderr=1 $TOOLS/convert_imageset \  
  42.     --resize_height=$RESIZE_HEIGHT \  
  43.     --resize_width=$RESIZE_WIDTH \  
  44.     --shuffle \  
  45.     $TRAIN_DATA_ROOT \  
  46.     $DATA/train.txt \     #標籤訓練資料檔案  
  47.     $EXAMPLE/train_lmdb  
  48.   
  49. echo "Creating val lmdb..."  
  50.   
  51. GLOG_logtostderr=1 $TOOLS/convert_imageset \  
  52.     --resize_height=$RESIZE_HEIGHT \  
  53.     --resize_width=$RESIZE_WIDTH \  
  54.     --shuffle \  
  55.     $VAL_DATA_ROOT \  
  56.     $DATA/val.txt \    #驗證集標籤資料  
  57.     $EXAMPLE/val_lmdb  
  58.   
  59. echo "Done."</span>  
<span style="font-size:18px;">#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs

EXAMPLE=.          # 生成模型訓練資料文化夾
TOOLS=../../build/tools                              # caffe的工具庫,不用變
DATA=.                  # python腳步處理後資料路徑

TRAIN_DATA_ROOT=train/  #待處理的訓練資料圖片路徑
VAL_DATA_ROOT=val/      # 帶處理的驗證資料圖片路徑



# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
RESIZE=true   #圖片縮放
if $RESIZE; then
  RESIZE_HEIGHT=256
  RESIZE_WIDTH=256
else
  RESIZE_HEIGHT=0
  RESIZE_WIDTH=0
fi

if [ ! -d "$TRAIN_DATA_ROOT" ]; then
  echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"
  echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \
       "where the ImageNet training data is stored."
  exit 1
fi

if [ ! -d "$VAL_DATA_ROOT" ]; then
  echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"
  echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \
       "where the ImageNet validation data is stored."
  exit 1
fi

echo "Creating train lmdb..."

GLOG_logtostderr=1 $TOOLS/convert_imageset \
    --resize_height=$RESIZE_HEIGHT \
    --resize_width=$RESIZE_WIDTH \
    --shuffle \
    $TRAIN_DATA_ROOT \
    $DATA/train.txt \     #標籤訓練資料檔案
    $EXAMPLE/train_lmdb

echo "Creating val lmdb..."

GLOG_logtostderr=1 $TOOLS/convert_imageset \
    --resize_height=$RESIZE_HEIGHT \
    --resize_width=$RESIZE_WIDTH \
    --shuffle \
    $VAL_DATA_ROOT \
    $DATA/val.txt \    #驗證集標籤資料
    $EXAMPLE/val_lmdb

echo "Done."</span>
同時我們需要製作如下四個檔案:

1、資料夾train,用於存放訓練圖片

2、資料夾val,用於存放驗證圖片

3、檔案train.txt,裡面包含這每張圖片的名稱,及其對應的標籤。

[python] view plain copy print ?
  1. <span style="font-size:18px;">first_batch/train_female/992.jpg    1  
  2. first_batch/train_female/993.jpg    1  
  3. first_batch/train_female/994.jpg    1  
  4. first_batch/train_female/995.jpg    1  
  5. first_batch/train_female/996.jpg    1  
  6. first_batch/train_female/997.jpg    1  
  7. first_batch/train_female/998.jpg    1  
  8. first_batch/train_female/999.jpg    1  
  9. first_batch/train_male/1000.jpg 0  
  10. first_batch/train_male/1001.jpg 0  
  11. first_batch/train_male/1002.jpg 0  
  12. first_batch/train_male/1003.jpg 0  
  13. first_batch/train_male/1004.jpg 0  
  14. first_batch/train_male/1005.jpg 0  
  15. first_batch/train_male/1006.jpg 0  
  16. first_batch/train_male/1007.jpg 0  
  17. first_batch/train_male/1008.jpg 0</span>  
<span style="font-size:18px;">first_batch/train_female/992.jpg	1
first_batch/train_female/993.jpg	1
first_batch/train_female/994.jpg	1
first_batch/train_female/995.jpg	1
first_batch/train_female/996.jpg	1
first_batch/train_female/997.jpg	1
first_batch/train_female/998.jpg	1
first_batch/train_female/999.jpg	1
first_batch/train_male/1000.jpg	0
first_batch/train_male/1001.jpg	0
first_batch/train_male/1002.jpg	0
first_batch/train_male/1003.jpg	0
first_batch/train_male/1004.jpg	0
first_batch/train_male/1005.jpg	0
first_batch/train_male/1006.jpg	0
first_batch/train_male/1007.jpg	0
first_batch/train_male/1008.jpg	0</span>

上面的標籤編號:1,表示女。標籤:0,表示男。

4、檔案val.txt,同樣這個檔案也是儲存圖片名稱及其對應的標籤。

這四個檔案在上面的指令碼檔案中,都需要呼叫到。製作玩後,跑一下上面的指令碼檔案,就ok了,跑完後,即將生成下面兩個資料夾:


資料夾下面有兩個對應的檔案:


製作完後,要看看檔案的大小,有沒有問題,如果就幾k,那麼正常是每做好訓練資料,除非你的訓練圖片就幾張。

二、訓練

1、直接訓練法

[python] view plain copy print ?
  1. #!/usr/bin/env sh  
  2. TOOLS=../cafferead/build/tools  
  3. $TOOLS/caffe train --solver=gender_solver.prorotxt  -gpu all  #加入 -gpu 選項  
#!/usr/bin/env sh
TOOLS=../cafferead/build/tools
$TOOLS/caffe train --solver=gender_solver.prorotxt  -gpu all  #加入 -gpu 選項

-gpu 可以選擇gpu的id號,如果是 -gpu all表示啟用所有的GPU進行訓練。

2、採用funing-tuning 訓練法

[python] view plain copy print ?
  1. $TOOLS/caffe train --solver=gender_solver.prorotxt -weights gender_net.caffemodel #加入-weights  
$TOOLS/caffe train --solver=gender_solver.prorotxt -weights gender_net.caffemodel #加入-weights

加入-weights,這個功能很好用,也經常會用到,因為現在的CNN相關的文獻,很多都是在已有的模型基礎上,進行fine-tuning,因為我們大部分人都缺少訓練資料,不像谷歌、百度這些土豪公司,有很多人專門做資料標註,對於小公司而言,往往缺少標註好的訓練資料。因此我們一般使用fine-tuning的方法,在少量資料的情況下,儘可能的提高精度。我們可以使用:-weights 選項,利用已有的模型訓練好的引數,作為初始值,進行繼續訓練。

三、呼叫python介面

訓練完畢後,我們就可以得到caffe的訓練模型了,接著我們的目標就預測,看看結果了。caffe為我們提供了方便呼叫的python介面函式,這些都在模組pycaffe裡面。因此我們還需要知道如何使用pycaffe,進行測試,檢視結果。下面是pycaffe的預測呼叫使用示例:

[python] view plain copy print ?
  1. # coding=utf-8  
  2. import os  
  3. import numpy as np  
  4. from matplotlib import pyplot as plt  
  5. import cv2  
  6. import shutil  
  7. import time  
  8.   
  9. #因為RGB和BGR需要調換一下才能顯示  
  10. def showimage(im):  
  11.     if im.ndim == 3:  
  12.         im = im[:, :, ::-1]  
  13.     plt.set_cmap('jet')  
  14.     plt.imshow(im)  
  15.     plt.show()  
  16.   
  17. #特徵視覺化顯示,padval用於調整亮度  
  18. def vis_square(data, padsize=1, padval=0):  
  19.     data -= data.min()  
  20.     data /= data.max()  
  21.   
  22.     #因為我們要把某一層的特徵圖都顯示到一個figure上,因此需要計算每個圖片佔用figure多少比例,以及繪製的位置  
  23.     n = int(np.ceil(np.sqrt(data.shape[0])))  
  24.     padding = ((0, n ** 2 - data.shape[0]), (0, padsize), (0, padsize)) + ((00),) * (data.ndim - 3)  
  25.     data = np.pad(data, padding, mode='constant', constant_values=(padval, padval))  
  26.   
  27.     # tile the filters into an image  
  28.     data = data.reshape((n, n) + data.shape[1:]).transpose((0213) + tuple(range(4, data.ndim + 1)))  
  29.     data = data.reshape((n * data.shape[1], n * data.shape[3]) + data.shape[4:])  
  30.   
  31.     showimage(data)  
  32.   
  33.   
  34. #設定caffe原始碼所在的路徑  
  35. caffe_root = '../../../caffe/'  
  36. import sys  
  37. sys.path.insert(0, caffe_root + 'python')  
  38. import caffe  
  39.   
  40.   
  41.   
  42.   
  43. #載入均值檔案  
  44. mean_filename='./imagenet_mean.binaryproto'  
  45. proto_data = open(mean_filename, "rb").read()  
  46. a = caffe.io.caffe_pb2.BlobProto.FromString(proto_data)  
  47. mean  = caffe.io.blobproto_to_array(a)[0]  
  48.   
  49. #建立網路,並載入已經訓練好的模型檔案  
  50. gender_net_pretrained='./caffenet_train_iter_1500.caffemodel'  
  51. gender_net_model_file='./deploy_gender.prototxt'  
  52. gender_net = caffe.Classifier(gender_net_model_file, gender_net_pretrained,mean=mean,  
  53.                        channel_swap=(2,1,0),#RGB通道與BGR  
  54.                        raw_scale=255,#把圖片歸一化到0~1之間  
  55.                        image_dims=(256256))#設定輸入圖片的大小  
  56.   
  57.   
  58. #預測分類及其可特徵視化  
  59. gender_list=['Male','Female']  
  60. input_image = caffe.io.load_image('1.jpg')#讀取圖片  
  61.   
  62. prediction_gender=gender_net.predict([input_image])#預測圖片性別  
  63. #列印我們訓練每一層的引數形狀  
  64. print 'params:'  
  65. for k, v in gender_net.params.items():  
  66.     print 'weight:'  
  67.     print (k, v[0].data.shape)#在每一層的引數blob中,caffe用vector儲存了兩個blob變數,用v[0]表示weight  
  68.     print 'b:'  
  69.     print (k, v[1].data.shape)#用v[1]表示偏置引數  
  70. #conv1濾波器視覺化  
  71. filters = gender_net.params['conv1'][0].data  
  72. vis_square(filters.transpose(0231))  
  73. #conv2濾波器視覺化  
  74. '''''filters = gender_net.params['conv2'][0].data 
  75. vis_square(filters[:48].reshape(48**2, 5, 5))'''  
  76. #特徵圖  
  77. print 'feature maps:'  
  78. for k, v in gender_net.blobs.items():  
  79.     print (k, v.data.shape);  
  80.     feat = gender_net.blobs[k].data[0,0:4]#顯示名字為k的網路層,第一張圖片所生成的4張feature maps  
  81.     vis_square(feat, padval=1)  
  82.   
  83.   
  84.   
  85.   
  86.   
  87. #顯示原圖片,以及分類預測結果  
  88. str_gender=gender_list[prediction_gender[0].argmax()]  
  89. print str_gender  
  90.   
  91. plt.imshow(input_image)  
  92. plt.title(str_gender)  
  93. plt.show()  
# coding=utf-8
import os
import numpy as np
from matplotlib import pyplot as plt
import cv2
import shutil
import time

#因為RGB