1. 程式人生 > >caffe提取任意層深度特徵

caffe提取任意層深度特徵

一.資料模型與準備

(1) 進入caffe根目錄,建立臨時資料夾,用於存放所需要的臨時檔案

cd caffe
mkdir examples/_temp

我們首先生成temp.txt(帶標籤)檔案
接下來我們要建立一個sh指令碼檔案,手動建立並命名為create_temp.sh

# /usr/bin/env sh
DATA=/home/hca/caffe/examples/images  #DATA為訓練集的路徑
echo "Create train.txt..."
rm -rf $DATA/train.txt
find $DATA -name cat*.jpg | cut -d '/' -f | sed "s/$/ 1/"
>>$DATA/temp.txt find $DATA -name fish*.jpg | cut -d '/' -f | sed "s/$/ 2/">>$DATA/tmp.txt cat $DATA/tmp.txt>>$DATA/temp.txt rm -rf $DATA/tmp.txt echo "Done.."

接下來生成file_list.txt(不帶標籤)檔案
接下來我們要建立一個sh指令碼檔案,手動建立並命名為create_file_list.sh

# /usr/bin/env sh
DATA=/home/hca/caffe/examples/images  #DATA為訓練集的路徑
echo "Create train.txt..." rm -rf $DATA/train.txt find $DATA -name cat*.jpg | cut -d '/' -f | sed "s/$/ /">>$DATA/file_list.txt find $DATA -name fish*.jpg | cut -d '/' -f | sed "s/$/ /">>$DATA/tmp.txt cat $DATA/tmp.txt>>$DATA/file_list.txt rm -rf $DATA/tmp.txt echo "Done.."

然後執行剛剛建立好的兩個sh檔案,

cd caffe
sh /XXX/create_temp.sh
#/XXX/為存放create_temp.sh的路徑 sh /XXX/create_file_list.sh #/xxx/為存放create_file_list.sh的路徑

然後將生成的file_list.txt和temp.txt檔案存放到_temp資料夾中。

(3)我們需要準備好已經訓練好的網路模型和網路定義prototxt檔案,然後將訓練好的模型.caffemodel存放到/examples/imagenet資料夾下,將網路定義prototxt檔案存放到_temp
資料夾中。(本人會盡快上傳一個到百度雲,方便新手練習)

二.提取特徵並存儲
(1) 安裝CAFFE的python依賴庫,並使用以下兩個輔助檔案把lmdb轉換為mat。在caffe 根目錄下建立feat_helper_pb2.py 和lmdb2mat.py,直接copy 下面的python程式即可。

cd caffe
sudo gedit  feat_helper_pb2.py
sudo gedit lmdb2mat.py

需要新增的內容如下
feat_helper_pb2.py:

# Generated by the protocol buffer compiler.  DO NOT EDIT!

from google.protobuf import descriptor
from google.protobuf import message
from google.protobuf import reflection
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)


DESCRIPTOR = descriptor.FileDescriptor(
  name='datum.proto',
  package='feat_extract',
  serialized_pb='\n\x0b\x64\x61tum.proto\x12\x0c\x66\x65\x61t_extract\"i\n\x05\x44\x61tum\x12\x10\n\x08\x63hannels\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x05\x12\r\n\x05width\x18\x03 \x01(\x05\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\r\n\x05label\x18\x05 \x01(\x05\x12\x12\n\nfloat_data\x18\x06 \x03(\x02')


_DATUM = descriptor.Descriptor(
  name='Datum',
  full_name='feat_extract.Datum',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    descriptor.FieldDescriptor(
      name='channels', full_name='feat_extract.Datum.channels', index=0,
      number=1, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    descriptor.FieldDescriptor(
      name='height', full_name='feat_extract.Datum.height', index=1,
      number=2, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    descriptor.FieldDescriptor(
      name='width', full_name='feat_extract.Datum.width', index=2,
      number=3, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    descriptor.FieldDescriptor(
      name='data', full_name='feat_extract.Datum.data', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value="",
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    descriptor.FieldDescriptor(
      name='label', full_name='feat_extract.Datum.label', index=4,
      number=5, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    descriptor.FieldDescriptor(
      name='float_data', full_name='feat_extract.Datum.float_data', index=5,
      number=6, type=2, cpp_type=6, label=3,
      has_default_value=False, default_value=[],
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  serialized_start=29,
  serialized_end=134,
)

DESCRIPTOR.message_types_by_name['Datum'] = _DATUM

class Datum(message.Message):
  __metaclass__ = reflection.GeneratedProtocolMessageType
  DESCRIPTOR = _DATUM

  # @@protoc_insertion_point(class_scope:feat_extract.Datum)

# @@protoc_insertion_point(module_scope)

lmdb2mat.py:

import lmdb
import feat_helper_pb2
import numpy as np
import scipy.io as sio
import time

def main(argv):
    lmdb_name = sys.argv[1]
    print "%s" % sys.argv[1]
    batch_num = int(sys.argv[2]);
    batch_size = int(sys.argv[3]);
    window_num = batch_num*batch_size;

    start = time.time()
    if 'db' not in locals().keys():
        db = lmdb.open(lmdb_name)
        txn= db.begin()
        cursor = txn.cursor()
        cursor.iternext()
        datum = feat_helper_pb2.Datum()

        keys = []
        values = []
        for key, value in enumerate( cursor.iternext_nodup()):
            keys.append(key)
            values.append(cursor.value())

    ft = np.zeros((window_num, int(sys.argv[4])))
    for im_idx in range(window_num):
        datum.ParseFromString(values[im_idx])
        ft[im_idx, :] = datum.float_data

    print 'time 1: %f' %(time.time() - start)
    sio.savemat(sys.argv[5], {'feats':ft})
    print 'time 2: %f' %(time.time() - start)
    print 'done!'

if __name__ == '__main__':
    import sys
    main(sys.argv)

(2) 在caffe 根目錄下建立指令碼檔案extract_feature_example1.sh, 並執行,將在examples/_temp資料夾下得到lmdb檔案(features_conv1)和.mat檔案(features_conv1.mat)

cd caffe
sudo gedit extract_feature_example.sh

需要新增的內容如下:

#!/usr/bin/env sh
# args for EXTRACT_FEATURE
TOOL=./build/tools
MODEL=./examples/imagenet/caffe_reference_imagenet_model #下載得到的caffe model
PROTOTXT=./examples/_temp/imagenet_val.prototxt # 網路定義
LAYER=conv1 # 提取層的名字,如提取fc7等
LEVELDB=./examples/_temp/features_conv1 # 儲存的leveldb路徑
BATCHSIZE=10

# args for LEVELDB to MAT
DIM=290400 # 需要手工計算feature長度
OUT=./examples/_temp/features_conv1.mat #.mat檔案儲存路徑
BATCHNUM=1 # 有多少個batch, 本例只有兩張圖, 所以只有一個batch

$TOOL/extract_features.bin  $MODEL $PROTOTXT $LAYER $LEVELDB $BATCHSIZE lmdb
python lmdb2mat.py $LEVELDB $BATCHNUM  $BATCHSIZE $DIM $OUT

執行該檔案

cd caffe
sh extract_feature_example.sh

執行完之後,會在_temp資料夾下生成features_conv1資料夾和features_conv1.mat檔案