caffe安装,编译(包括CUDA和cuDNN的安装),并训练,测试自己的数据(caffe使用教程)

caffe是一个非常清晰且高效的深度学习框架,目前有着不少的用户,也渐渐的形成了自己的社区,社区上可以讨论相关的问题。

我从开始看深度学习的相关内容到能够用caffe训练测试自己的数据,看了不少网站,教程和博客,也走了不少弯路,在此把整个流程梳理和总结一遍,以期望可以可以仅仅通过这一篇文章就可以轻松的用caffe训练自己的数据,体验深度学习的乐趣。(本文中包含了很多的链接,链接中有我看过的详细的教程和讲解,以方便大家理解)



1.安装和配置caffe(包括安装CUDA) 

caffe的安装和编译,官网上已经写的非常的详细了。官网上的安装链接 : 链接        只要按照官网的说明一步步的进行,一般都是不会出什么问题的。并且,官网给出来ubuntu,Mac,和Windows环境下安装和配置的链接。条件允许的话,还是尽量在Ubuntu下安装和配置吧,对于不熟悉Ubuntu的人来说可能比较麻烦,但是我感觉,在linux下安装,编译,包括后面的使用都是比较方便的。

这里需要提前说明的一点是,在官方给的安装文档里,下面几个是可以选择安装的


  • OpenCV >= 2.4 including 3.0
  • IO libraries: lmdbleveldb (note: leveldb requires snappy)
  • cuDNN for GPU acceleration (v5)

其中,cuDnn是专门针对CUDA的加速套件,可以为在GPU上跑深度学习的程序进行加速,所以这个还是安装一下吧,为以后跑程序能省些时间。



2. cuDNN的安装

这里单独强调一下cuDNN的安装(网上给的很多教程有问题,会导致后面的编译失败),cuDNN的安装需要在CUDA安装完成后进行。

cuDnn需要从Nvidia的官网上下载,并且需要先注册才行,注册的时候会让你填写一些调查问卷,注册完成后,选择正确的版本进行下载。我这里下载的是:Download cuDNN v5 (May 27, 2016), for CUDA 8.0    cuDNN v5 Library for Linux版本,然后解压缩,并且放到相应的文件夹下,最后修改一下权限


<span style="background-color: rgb(240, 240, 240);">tar xvzf cudnn-8.0-linux-x64-v4.tgz #这里要注意你下载的版本,需要解压你下载的对应版本的文件</span>解压后的文件夹名字是cuda
sudo cp cuda/include/cudnn.h /usr/local/cuda/include
sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64
sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*
网上的不少教程一般给到上面这些就没有了,我安装的时候,仅仅进行上面的步骤,在make  test的时候会报错的。错误信息大致如下:

CXX/LD -o .build_release/tools/upgrade_net_proto_text.bin .build_release/lib/libcaffe.so: undefined reference to caffe::curandGetErrorString(curandStatus)
.build_release/lib/libcaffe.so: undefined reference to caffe::BaseConvolutionLayer::weight_gpu_gemm(double const*, double const*, double*)
.build_release/lib/libcaffe.so: undefined reference to caffe::BaseConvolutionLayer::forward_gpu_bias(double*, double const*)

找了好多资料,最后在stackoverflaw上找到了解决办法,我这里把链接贴出来:链接

其实方法就是,在/usr/local/cuda/lib64 目录下,执行如下操作(网上的大神说,复制过程破坏了软连接,所以要自己手动建立一下软连接)

sudo rm libcudnn.so.5 libcudnn.so
sudo ln -sf libcudnn.so.5 libcudnn.so
sudo ln -sf libcudnn.so.5.1.3 libcudnn.so.5
sudo ldconfig /usr/local/cuda/lib64

此时,再重新编译,运行 make all      然后,make test  ,在然后make runtest   就可以了。



3.在MNIST上用caffe训练LeNet网络

MNIST是一个手写数字的数据集,LeNet 是一个比较简单的深度学习网络模型。

这个过程,官方是给了教程的,附上链接:链接

但是当时我按着步骤一步步的执行,最后也能够完全运行成功,但是程序是怎么运行成功的,怎么跑通的,原理是什么,我还是搞不懂。

为了弄清楚程序具体的执行过程,我尝试利用自己找的一些数据进行训练和测试,以便加深对caffe和深度学习的理解。



4.训练和测试自己的数据

这里要感谢这篇博客的给我的巨大帮助:点击打开链接。虽然博客写的很好,但是还是有一些不详细的地方。我在这篇博客的基础上进行完成和补充,尽量把整个过程描述的更加详细。


1)准备数据

要想训练自己的网络,首先要有图片数据,前期在学习阶段,为了节省时间,先从小的数据集开始训练和学习比较合适,博客的博主给了一个小数据集的链接,共500张图片,分为大巴,恐龙,大象,鲜花和马 五个类别,每个类别100张,数据集的下载链接为:http://pan.baidu.com/s/1nuqlTnN

编号为3,4,5,6,7开头的,分别为一类,每一类的100张图片,用80个作为训练,20个作为测试,图片放在caffe目录下的data目录下,即训练图片的目录为data/re/train,测试图片的目录为data/re/test


2)图片转换为lmdb格式

caffe中,不能直接拿jpg,png之类的图片文件进行训练,需要将图片格式转换为lmdb格式才可以使用。而且caffe提供了转换格式所需要的工具,我们只需要写几行代码就能转换完成。

在examples文件夹下新建一个myffle文件夹,这个文件用来存放配置文件,脚本文件和lmdb文件,然后编写一个脚本文件,create_filelist.sh用来生成train.txt和test.txt两个文本文件,这连个文本文件包含图片的列表清单。然后编辑这个脚本文件如下:

#!/usr/bin/env sh
DATA=data/re/
MY=examples/myfile

echo "Create train.txt..."
rm -rf $MY/train.txt
for i in 3 4 5 6 7 
do
find $DATA/train -name $i*.jpg | cut -d '/' -f4-5 | sed "s/$/ $i/">>$MY/train.txt
done
echo "Create test.txt..."
rm -rf $MY/test.txt
for i in 3 4 5 6 7
do
find $DATA/test -name $i*.jpg | cut -d '/' -f4-5 | sed "s/$/ $i/">>$MY/test.txt
done
echo "All done"

然后运行这个脚本文件
sudo sh examples/myfile/create_filelist.sh
然后就可以得到train.txt和test.txt文件了,打开看看基本上就知道这个文件是干啥的了吧。(就是为每个图片做类别标记)

(其实,上述步骤的脚本文件如果看不懂或者觉得不方便,用c写个文件生成train.txt和test.txt也可以。我自己对脚本文件不太熟悉,所以这些操作我有时候会用c写。)

接着在编写一个脚本文件,调用convert_imageset命令来转换数据格式。(就是把图片格式的文件转换成了lmdb格式)

sudo vi examples/myfile/create_lmdb.sh

在其中插入

#!/usr/bin/env sh
MY=examples/myfile

echo "Create train lmdb.."
rm -rf $MY/img_train_lmdb
build/tools/convert_imageset \
--shuffle \
--resize_height=256 \
--resize_width=256 \
/home/xxx/caffe/data/re/ \
$MY/train.txt \
$MY/img_train_lmdb

echo "Create test lmdb.."
rm -rf $MY/img_test_lmdb
build/tools/convert_imageset \
--shuffle \
--resize_width=256 \
--resize_height=256 \
/home/xxx/caffe/data/re/ \
$MY/test.txt \
$MY/img_test_lmdb

echo "All Done.."

图片的大小不一致,所以统一转换成了256×256 的大小,运行成功后,会在examples/myfile下生成两个文件,img_train_lmdb和img_val_lmdb,这个两个文件就是图片数据集转换后的文件。


3)计算均值并保存

图片减去均值再训练,可以提高训练速度和精度。因此,一般都会有这个操作。(比如非常有名的描述AlexNet的论文中,也有这一步预操作)

同样的,减去均值的操作caffe也写好了,直接调用就行了,即compute_image_mean.cpp文件

sudo build/tools/compute_image_mean examples/myfile/img_train_lmdb examples/myfile/mean.binaryproto

compute_image_mean带两个参数,第一个参数是lmdb训练数据位置,第二个参数设定均值文件的名字及保存路径。
运行成功后,会在 examples/myfile/ 下面生成一个mean.binaryproto的均值文件。


4)创建神经网络模型并编写配置文件

这里,就使用caffe自带的caffenet模型进行训练,把该模型和相应的配置文件都拷贝过来,操作如下:

sudo cp models/bvlc_reference_caffenet/solver.prototxt examples/myfile/
sudo cp models/bvlc_reference_caffenet/train_val.prototxt examples/myfile/

solver.prototxt是整个网络的配置文件,将其修改如下:

net: "examples/myfile/train_val.prototxt"
test_iter: 2
test_interval: 50
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
stepsize: 100
display: 20
max_iter: 500
momentum: 0.9
weight_decay: 0.005
# snapshot intermediate results
snapshot: 500
snapshot_prefix: "examples/myfile/results/my"
solver_mode: GPU
关于配置文件参数不理解的地方,可以看链接:链接

然后,修改 train_val.protxt,修改成如下形式

name: "CaffeNet"
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
    crop_size: 227
    mean_file: "examples/myfile/mean.binaryproto"
  }
# mean pixel / channel-wise mean instead of mean image
#  transform_param {
#    crop_size: 227
#    mean_value: 104
#    mean_value: 117
#    mean_value: 123
#    mirror: true
#  }
  data_param {
    source: "examples/myfile/img_train_lmdb"
    batch_size: 50
    backend: LMDB
  }
}
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mirror: false
    crop_size: 227
    mean_file: "examples/myfile/mean.binaryproto"
  }
# mean pixel / channel-wise mean instead of mean image
#  transform_param {
#    crop_size: 227
#    mean_value: 104
#    mean_value: 117
#    mean_value: 123
#    mirror: false
#  }
  data_param {
    source: "examples/myfile/img_test_lmdb"
    batch_size: 50
    backend: LMDB
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 96
    kernel_size: 11
    stride: 4
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "conv1"
  top: "conv1"
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layer {
  name: "norm1"
  type: "LRN"
  bottom: "pool1"
  top: "norm1"
  lrn_param {
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "norm1"
  top: "conv2"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 256
    pad: 2
    kernel_size: 5
    group: 2
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 1
    }
  }
}
layer {
  name: "relu2"
  type: "ReLU"
  bottom: "conv2"
  top: "conv2"
}
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layer {
  name: "norm2"
  type: "LRN"
  bottom: "pool2"
  top: "norm2"
  lrn_param {
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
}
layer {
  name: "conv3"
  type: "Convolution"
  bottom: "norm2"
  top: "conv3"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 384
    pad: 1
    kernel_size: 3
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "relu3"
  type: "ReLU"
  bottom: "conv3"
  top: "conv3"
}
layer {
  name: "conv4"
  type: "Convolution"
  bottom: "conv3"
  top: "conv4"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 384
    pad: 1
    kernel_size: 3
    group: 2
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 1
    }
  }
}
layer {
  name: "relu4"
  type: "ReLU"
  bottom: "conv4"
  top: "conv4"
}
layer {
  name: "conv5"
  type: "Convolution"
  bottom: "conv4"
  top: "conv5"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
    group: 2
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 1
    }
  }
}
layer {
  name: "relu5"
  type: "ReLU"
  bottom: "conv5"
  top: "conv5"
}
layer {
  name: "pool5"
  type: "Pooling"
  bottom: "conv5"
  top: "pool5"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layer {
  name: "fc6"
  type: "InnerProduct"
  bottom: "pool5"
  top: "fc6"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 4096
    weight_filler {
      type: "gaussian"
      std: 0.005
    }
    bias_filler {
      type: "constant"
      value: 1
    }
  }
}
layer {
  name: "relu6"
  type: "ReLU"
  bottom: "fc6"
  top: "fc6"
}
layer {
  name: "drop6"
  type: "Dropout"
  bottom: "fc6"
  top: "fc6"
  dropout_param {
    dropout_ratio: 0.5
  }
}
layer {
  name: "fc7"
  type: "InnerProduct"
  bottom: "fc6"
  top: "fc7"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 4096
    weight_filler {
      type: "gaussian"
      std: 0.005
    }
    bias_filler {
      type: "constant"
      value: 1
    }
  }
}
layer {
  name: "relu7"
  type: "ReLU"
  bottom: "fc7"
  top: "fc7"
}
layer {
  name: "drop7"
  type: "Dropout"
  bottom: "fc7"
  top: "fc7"
  dropout_param {
    dropout_ratio: 0.5
  }
}
layer {
  name: "fc8"
  type: "InnerProduct"
  bottom: "fc7"
  top: "fc8"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 1000
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "fc8"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "fc8"
  bottom: "label"
  top: "loss"
}

这个文件其实就是定义了整个网络的模型,每一个layer就是一层,你在每一层中定义好这是卷积层还是池化层,神经元有多少等等,具体的参数的含义可以看链接:点击打开链接


5)训练和测试

只需要直接输入下面的命令就可以完成了。(这里需要注意的是,训练和测试整个的流程是一起执行的,因为上面的train_val.prototxt文件把train和test的参数都设定好了,所以程序训练完了以后就会直接进入测试数据的阶段,其实也可以写成两个文件分开执行。在solver.prototxt中,有一行为

snapshot_prefix: "examples/myfile/results/my"

这就表示,你训练好的权值都在results文件夹下面保存着,以后如果想要使用训练好的模型,直接调用rusult下的文件进行测试就可以。)

最后的输出结果中,

Test net output #0:accuracy:0.95

这一行,就表示在测试数据上,用自己训练的网络进行分类的正确率达到了95%。





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值