深度学习项目示例-采用caffe实现LENET网络实现铲齿识别-并可视化过程

跑出结果对应的记录

修改过程

  1. 起初我怀疑是由于图像生成错误导致的,但是那个实在找不出来错误了!标签也是从0开始了!图像存放位置肯定也没有问题!图像本身也就是灰色图像,感觉也翻不起大浪啊!
  2. 为何会出现连续多个Restarting data prefetching from start?大概连续8个,然后还会出现loss为87.33?
    • 将batch_size改为1就好了,原先为64等,我这个显卡的显存还是忒小,不能忒大!
    • batch_size减小后还不行咋办?图像还是大,那么就调一下crop_size,我将其改到180了!
  3. 修改成以上的结果后,发现:
    • Restarting data prefetching from start不会连续出现了
    • loss前两次迭代为8、7,然后又变成87.33了!
  4. 根据以上情况,我怀疑学习率太高了,所以降低学习率,从0.01改成0.0001,发现:
    • loss不会变成87.33了,但是最终会变成0,后面还带着(* 1 =0 loss)

最终修改

  1. 生成LMDB的时候并不resize到256x256,所以图像大小仍然是160x120。这样图像明显小了很多,batch_size可以稍微大一点!
  2. 用的是lenet网络、并不采用imagenet_mean.binaryproto的方式进行归一化!因为我们是用的是灰度图像,所以归一化的方式就是除以255,也就是:scale: 1/255 (0.0039625)
  3. 最终效果不错!准确率为100%,这个结果不难理解,图像忒简单、干扰很少、种类也很少。

reference

LMDB文件的生成,程序如下,这个文件可以在CAFFE_ROOT\examples\imagenet下面找到!

#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs
# reference: http://blog.csdn.net/u013534498/article/details/51387517
#    --resize_height=$RESIZE_HEIGHT \
#    --resize_width=$RESIZE_WIDTH \
set -e

EXAMPLE=examples/chanchi/data
DATA=examples/chanchi/data
TOOLS=build/tools

TRAIN_DATA_ROOT=examples/chanchi/data/train/
VAL_DATA_ROOT=examples/chanchi/data/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                        # if部分没有用,当前程序我没准备resize,放这儿无非就是无聊而已
  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 \
    --shuffle \
    $TRAIN_DATA_ROOT \
    $DATA/train.txt \
    $EXAMPLE/chanchi_train_lmdb
#    --backend=leveldb \                                                         # 如果需要将格式改为leveldb,则需要加上当前条件!
echo "Creating val lmdb..."

GLOG_logtostderr=1 $TOOLS/convert_imageset \
    --shuffle \                                                                            # 如果需要resize,需要加上--resize_height=... --resize_width=...
    $VAL_DATA_ROOT \                                                          # 测试图片存放地址!
    $DATA/val.txt \                                                                    # 定义标签文件在哪儿!
    $EXAMPLE/chanchi_val_lmdb                                           # LMDB文件存放地址!
echo "Done."

只要提示Processed就没有多大问题!
这里写图片描述

数据存放方式:

data目录下:存放训练样本、测试样本、训练标签、测试标签。

这里写图片描述

标签格式:


0normal/train_0normal_001.bmp 0
0normal/train_0normal_002.bmp 0
0normal/train_0normal_003.bmp 0
0normal/train_0normal_004.bmp 0
0normal/train_0normal_005.bmp 0
0normal/train_0normal_006.bmp 0
0normal/train_0normal_007.bmp 0
.
.
.

  • 标签需要从0开始,因为采用了sigmodloss!不然容易出现loss为87.3365!

  • 我这标签的生成采用的是matlab生成的,其实也是使用了批处理中的rename命令,(ps:如果出现名称中有空格,记着在文件名称两边加双引号,例如: rename "ni hao.txt" wozhenshuai.txt)以下为我的matlab程序:

%% 重命名文件
% for i=1:250
%     Image_source_name_normal0=['.\0normal\',num2str(i,'%03d'),'.bmp'];
%     Image_source_name_normal1=['.\1normal\',num2str(i,'%03d'),'.bmp'];
%     Image_source_name_normalh=['.\hnormal\',num2str(i,'%03d'),'.bmp'];
%     
%     Image_changed_name_normal0=['train_0normal_',num2str(i,'%03d'),'.bmp'];
%     Image_changed_name_normal1=['train_1normal_',num2str(i,'%03d'),'.bmp'];
%     Image_changed_name_normalh=['train_hnormal_',num2str(i,'%03d'),'.bmp'];
%     
%     eval(['!rename' , ',',Image_source_name_normal0 , ',',Image_changed_name_normal0]);
%     eval(['!rename' , ',',Image_source_name_normal1 , ',',Image_changed_name_normal1]);
%     eval(['!rename' , ',',Image_source_name_normalh , ',',Image_changed_name_normalh]);
% end
% 
% % for i=251:500
% %     Image_source_name_normal0=['.\0normal\',num2str(i,'%03d'),'.bmp'];
% %     Image_source_name_normal1=['.\1normal\',num2str(i,'%03d'),'.bmp'];
% %     Image_source_name_normalh=['.\hnormal\',num2str(i,'%03d'),'.bmp'];
% %     
% %     Image_changed_name_normal0=['0normal_',num2str(i,'%03d'),'.bmp'];
% %     Image_changed_name_normal1=['1normal_',num2str(i,'%03d'),'.bmp'];
% %     Image_changed_name_normalh=['hnormal_',num2str(i,'%03d'),'.bmp'];
% %     
% %     eval(['!rename' , ',',Image_source_name_normal0 , ',',Image_changed_name_normal0]);
% %     eval(['!rename' , ',',Image_source_name_normal1 , ',',Image_changed_name_normal1]);
% %     eval(['!rename' , ',',Image_source_name_normalh , ',',Image_changed_name_normalh]);
% % end

%% 训练标签生成
Fid_train_0normal_1normal_hNormal=fopen('.\train.txt','w+');
for i =1:250
    fprintf(Fid_train_0normal_1normal_hNormal,'%s %d\r\n',['0normal/','train_0normal_',num2str(i,'%03d'),'.bmp'],0);
end
for i =1:250
    fprintf(Fid_train_0normal_1normal_hNormal,'%s %d\r\n',['1normal/','train_1normal_',num2str(i,'%03d'),'.bmp'],1);
end
for i =1:250
    fprintf(Fid_train_0normal_1normal_hNormal,'%s %d\r\n',['hnormal/','train_hnormal_',num2str(i,'%03d'),'.bmp'],2);
end
fclose(Fid_train_0normal_1normal_hNormal);

%% 测试标签生成
Fid_test_0Normal_1Normal_hNormal=fopen('.\val.txt','w+');
for i=251:500
    fprintf(Fid_test_0Normal_1Normal_hNormal,'%s %d\r\n',['0normal/0normal_',num2str(i,'%03d'),'.bmp'],0); 
end
for i=251:500
    fprintf(Fid_test_0Normal_1Normal_hNormal,'%s %d\r\n',['1normal/1normal_',num2str(i,'%03d'),'.bmp'],1); 
end
for i=251:500
    fprintf(Fid_test_0Normal_1Normal_hNormal,'%s %d\r\n',['hnormal/hnormal_',num2str(i,'%03d'),'.bmp'],2); 
end
fclose(Fid_test_0Normal_1Normal_hNormal);
  • 当然也可以直接采用批处理来实现,命令行中:dir/s/on/b>d:/train.txt就可以在d盘下面生成train.txt,里面记录当前目录下面有什么东西!再根据替换啥的直接弄吧。也可以采用写bat文件或者sh文件来实现,并不难哈!

归一化方式:计算图像均值

彩色图像可以通过计算图像均值再除以的方式来归一化!至于为何归一化?防止梯度消失!
计算图像均值可以仿照以下程序来写:CAFFE_ROOT/examples/imagenet。
此处采用的是除以255的方式来归一化的,因为我们是被转化成灰度图像的!
以下为我的模型文件*prototxt中数据的定义:


layer {
name: "chanchi"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/chanchi/data/chanchi_train_lmdb"
batch_size: 8
backend: LMDB
}
}
layer {
name: "chanchi"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/chanchi/data/chanchi_val_lmdb"
batch_size: 8
backend: LMDB
}
}

读取每一层输出对应的记录

deploy如何写

  1. 首先,deploy是干什么的?

    • 就是部署下网络结构,输入是咋样的?输出是咋样的?每一层的网络结构是咋样的?
    • 只有确定了这些参数,才可以根据caffe_model往里面填参数啊!
  2. 其次,如何写

    • 其和train_test.prototxt文件很像,网络层数与参数都是一样的!主要区别就在于输入与输出!
    • 其主要就是告诉caffemodel,你那个里面的参数都是怎么放的,我只需要告诉你放哪儿就行了,怎么放、放什么都不归我管。本着这个宗旨,我这个delpoy压根不需要自己定weight与bias的初始值也不需要定学习率!
  3. 重点

    • 输入怎么定?这个要参考你的debug文件,里面有一层层的参数,看清楚了!!

    总得来说,deploy.prototxt就是在lenet_train_test.prototxt的基础上稍作改动,input_param { shape: { dim: 1 dim: 1 dim: 120 dim: 160 } } 这四个dim参数分别是
    第一个:对待识别样本图片进行数据增广的数量,一个图片会变成10个,之后输入到网络进行识别。如果不进行数据增广,可以设置成1。
    第二个:图片的通道数,一般灰度图片为单通道,则值为1,如果为非灰度图3通道图片则为3。这个要看你的LMDB文件是怎么生成的了,默认生成LMDB就是3通道的,如果你是灰度图像,并且不想生成3通道,那么需要在使用convert_imageset的时候加上--gray选项!!!!!!切记 我们默认图像是长x高哈~~~
    第三个:图片的高度,单位像素。
    第四个:图片的宽度,单位像素。

  4. 综上,我们的输入的定义应该是:input_param { shape: { dim: 1 dim: 1 dim: 120 dim: 160 } },我们matlab自己定义输入的时候应该是:160x120x1x1!!
  5. 我才开始错了那么长时间主要是忽略了,转换成LMDB时默认转换为3通道的,即使是灰度图像,且没有通过debug文件来及时发现错误!!(以上部分参考,不过别像他一样用py文件来弄,不麻烦吗??)
  6. 此外,当有crop的时候,输入的定义又不一样了。crop的定义是:当图像大于它时会自动剪裁(caffe默认是随机剪裁,我的笔记有介绍),是一种增加样本与减小图像的一种方式。比如当图像为256x256、crop为226x226时,会自动剪裁掉30x30。(测试的时候caffe默认是减掉中间部分!具体怎么减的看原始程序吧!!!!!)
  7. 所以这个时候该怎么办呢?需要自己进行crop抽样处理:参考,也就是deploy输入大小与crop大小保持一致,且自己进行抽样处理,抽样数的多少可以自己定义!我看他们都是定义10!
  8. 以下为我的deloy:(根据lenet改的!对比mnist的那个lenet例子看就可以! ps:我的图像是160x120,高是120,灰度图像,LMDB是1通道的)
name: "LeNet"
layer {
  name: "data"
  type: "Input"
  top: "data"
  input_param { shape: { dim: 8 dim: 1 dim: 120 dim: 160 } }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  convolution_param {
    num_output: 50
    kernel_size: 5
    stride: 1
  }
}
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"
  inner_product_param {
    num_output: 500
  }
}
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: 3
  }
}
layer {
  name: "prob"
  type: "Softmax"
  bottom: "ip2"
  top: "prob"
}

读取每一层的输出对应的matlab程序

  1. 主程序:
clear
i1= imread('.\chanchi\0.data\0normal\0normal_251.bmp');
i2= imread('.\chanchi\0.data\0normal\0normal_252.bmp');
i3= imread('.\chanchi\0.data\0normal\0normal_253.bmp');
i4= imread('.\chanchi\0.data\0normal\0normal_254.bmp');
i5= imread('.\chanchi\0.data\0normal\0normal_255.bmp');
i6= imread('.\chanchi\0.data\0normal\0normal_256.bmp');
i7= imread('.\chanchi\0.data\0normal\0normal_257.bmp');
i8= imread('.\chanchi\0.data\0normal\0normal_258.bmp');
%imshow(I);
crops_data = zeros(160,120,1,8, 'single');
for i=1:8
    eval(['crops_data(:,:,1,i)=single(i',num2str(i),')'';']); 
end
crops_data=crops_data./255;                              % 相当于归一化
feature_each_name=[2,3,4,5,6,7,8];
feature_chanchi=cell(1,7);
for feature_num=1:7
    mapnum=feature_each_name(feature_num);
    feature_chanchi{feature_num}=Extract_features_chanchi(crops_data,mapnum);
end
  1. 读取模型的数据
function [y] = Extract_features_chanchi(data,mapnum)
addpath('..') %加入+caffe路径
caffe.set_mode_cpu();%设置CPU模式

model_dir = './chanchi/1.lenet/';                     
model = [model_dir 'chanchi_deploy.prototxt'];                          %模型
weights = [model_dir 'lenet_chanchi_new_iter_1500.caffemodel'];         %参数

net=caffe.Net(model,'test');                                        %测试
net.copy_from(weights);                                             %得到训练好的权重参数

res=net.forward({data});

names=net.blob_names;
featuremap=net.blobs(names{mapnum}).get_data();                     %读取输出
y=featuremap;
end

尚存在的问题

  1. 为啥我输入到模型时,必须一次性输入8个图像呢?也就是上述deploy文件中input_param参数必须为8x1x160x120?
  2. 后来我把batchsize改成1了;又或者输入的时候仅输入1张图像,其余为0.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值