caffe中googlenet caffemodel头文件里的具体函数实现在哪

这里使用的是一个Blob的容器是因为某些Layer包含多组学习参数,比如多个卷积核的卷积层。
以及Layer所传递的数据形式,后面还会涉及到这里:
vector&Blob&Dtype&*& &
vector&Blob&Dtype&*& *top
2.2. Layer:
2.2.1. 5大Layer派生类型
Caffe十分强调网络的层次性,也就是说卷积操作,非线性变换(ReLU等),Pooling,权值连接等全部都由某一种Layer来表示。具体来说分为5大类Layer
2.2.2. Layer的重要成员函数
在Layer内部,数据主要有两种传递方式,正向传导(Forward)和反向传导(Backward)。Forward和Backward有CPU和GPU(部分有)两种实现。Caffe中所有的Layer都要用这两种方法传递数据。
virtual void Forward(const vector&Blob&Dtype&*& &bottom,
vector&Blob&Dtype&*& *top) = 0;
virtual void Backward(const vector&Blob&Dtype&*& &top,
const vector&bool& &propagate_down,
vector&Blob&Dtype&*& *bottom) = 0;
Layer类派生出来的层类通过这实现这两个虚函数,产生了各式各样功能的层类。Forward是从根据bottom计算top的过程,Backward则相反(根据top计算bottom)。注意这里为什么用了一个包含Blob的容器(vector),对于大多数Layer来说输入和输出都各连接只有一个Layer,然而对于某些Layer存在一对多的情况,比如LossLayer和某些连接层。在网路结构定义文件(*.proto)中每一层的参数bottom和top数目就决定了vector中元素数目。
bottom: &decode1neuron&
// 该层底下连接的第一个Layer
bottom: &flatdata&
// 该层底下连接的第二个Layer
top: &l2_error&
// 该层顶上连接的一个Layer
name: &loss&
// 该层的名字
type: EUCLIDEAN_LOSS
// 该层的类型
loss_weight: 0
2.2.3. Layer的重要成员变量
vector&Dtype& loss_;
每一层又有一个loss_值,只不多大多数Layer都是0,只有LossLayer才可能产生非0的loss_。计算loss是会把所有层的loss_相加。
learnable parameters
vector&shared_ptr&Blob&Dtype& & & blobs_;
前面提到过的,Layer学习到的参数。
2.3. Net:
Net用容器的形式将多个Layer有序地放在一起,其自身实现的功能主要是对逐层Layer进行初始化,以及提供Update( )的接口(更新网络参数),本身不能对参数进行有效地学习过程。
vector&shared_ptr&Layer&Dtype& & & layers_;
同样Net也有它自己的
vector&Blob&Dtype&*&& Forward(const vector&Blob&Dtype&* & & bottom,
Dtype* loss = NULL);
void Net&Dtype&::Backward();
他们是对整个网络的前向和方向传导,各调用一次就可以计算出网络的loss了。
2.4. Solver
这个类中包含一个Net的指针,主要是实现了训练模型参数所采用的优化算法,它所派生的类就可以对整个网络进行训练了。
shared_ptr&Net&Dtype& & net_;
不同的模型训练方法通过重载函数ComputeUpdateValue( )实现计算update参数的核心功能
virtual void ComputeUpdateValue() = 0;
最后当进行整个网络训练过程(也就是你运行Caffe训练某个模型)的时候,实际上是在运行caffe.cpp中的train( )函数,而这个函数实际上是实例化一个Solver对象,初始化后调用了Solver中的Solve( )方法。而这个Solve( )函数主要就是在迭代运行下面这两个函数,就是刚才介绍的哪几个函数。
ComputeUpdateValue();
net_-&Update();
==============================================================
至此,从底层到顶层对Caffe的主要结构都应该有了大致的概念。为了集中重点介绍Caffe的代码结构,文中略去了大量Caffe相关的实现细节和技巧,比如Layer和Net的参数如何初始化,proto文件的定义,基于cblas的卷积等操作的实现(cblas实现卷积这一点我的个人主页中的《Caffe学习笔记5-BLAS与boost::thread加速》有介绍)等等就不一一列举了。
整体来看Layer部分代码最多,也反映出Caffe比较重视丰富网络单元的类型,然而由于Caffe的代码结构高度层次化,使得某些研究以及应用(比如研究类似非逐层连接的神经网络这种复杂的网络连接方式)难以在该平台实现。这也就是一开始说的一个不足。
另外,Caffe基本数据单元都用Blob,使得数据在内存中的存储变得十分高效,紧凑,从而提升了整体训练能力,而同时带来的问题是我们看见的一些可读性上的不便,比如forward的参数也是直接用Blob而不是设计一个新类以增强可读性。所以说性能的提升是以可读性为代价的。
最后一点也是最重要的一点,我从Caffe学到了很多。第一次看的C++项目就看到这么好的代码,实在是受益匪浅,在这里也感谢作者贾扬清等人的贡献。
甘宇飞更新于2/13/2015
&&&o&&o&&o&
楼上的大神回答的都很好了,非常感谢。这里我想说一下我自己学习caffe的方式,限于时间篇幅,并不想深入到具体的实现细节,只是从大的方向上谈谈,因为讲清楚一个细节都是一篇博客的篇幅了。
1.学习程序的第一步,先让程序跑起来,看看结果,这样就会有直观的感受。
Caffe的官网上&提供了很多的examples,你可以很容易地开始训练一些已有的经典模型,如LeNet。我建议先从&开始,因为数据集很小,网络也很小但很经典,用很少的时间就可以跑起来了。当你看到terminal刷拉拉的一行行输出,看到不断减少的loss和不断上升的accuracy,训练结束你得到了99+%的准确率,感觉好厉害的样子。你可以多跑跑几个例子,熟悉一下环境和接口。
2.单步调试,跟着Caffe在网络里流动
当玩了几天之后,你对Caffe的接口有点熟悉了,对已有的例子也玩腻了,你开始想看看具体是怎么实现的了。我觉得最好的方法是通过单步调试的方式跟着程序一步一步的在网络里前向传播,然后再被当成误差信息传回来。
Caffe就像一个你平常编程中Project,你可以使用IDE或者GDB去调试它,这里我们不细说调试的过程。你可以先跟踪前向传播的过程,无非就是从高层次到低层次的调用Forward函数, Solver-&Net-&Layer-&Specific Layer (Convolution等...).后向传播也类似,但因为你对Caffe里面的各种变量运算不熟悉,当你跟踪完前向传播时可能已经头晕眼花了,还是休息一下,消化一下整个前向传播的流程。
刚刚开始你没有必要对每个Layer的计算细节都那么较真,大概知道程序的运算流程就好,这样你才可以比较快的对Caffe有个大体的把握。
3.个性化定制Caffe
到这里,你已经可以说自己有用过Caffe了,但是还不能算入门,因为你还不知道怎么修改源码,满足自己特定的需求。我们很多时候都需要自己定义新的层来完成特定的运算,这时你需要在Caffe里添加新的层。
你一开肯定无从下手,脑子一片空白。幸运的是Caffe github上的Wiki&已经有了教程了,而且这是最接近latest Caffe的源码结构的教程,你在网上搜到的Blog很多是有点过时的,因为Caffe最近又重构了代码。你可以跟着它的指导去添加自己的层。
虽然你已经知道要在哪里添加自己的东西了,但你遇到最核心的问题是如何写下面这四个函数。
你可以先模仿已有的层去实现这四个函数,而且我相信forward函数很快就可以写出来了,但backward的还是一头雾水。这时我们就要补补神经网络里最核心的内容了——Backpropagation.
4.理解并实现Backpropagation
这个我觉得是与平台无关的,不管你是使用Caffe、Torch 7,还是Theano,你都需要深刻理解并掌握的。因为我比较笨,花了好长时间才能够适应推导中的各种符号。其实也不难,就是误差顺着Chain rule法则流回到前面的层。我不打算自己推导后向传播的过程,因为我知道我没有办法将它表达得很好,而且网上已经有很多非常好的教程了。下面是我觉得比较好的学习步骤吧。
第二个回答,讲得还是一样的乱,谢谢观看。
&&&o&&o&&o&&
反对,不会显示你的姓名
其实关于怎么用caffe,我一直想写篇文章,因为给太多人讲过怎么用了,也帮很多人基于caffe写过代码。14年初因为赶NIPS,开始用caffe,大概用了有一年半了。
先说个大概,知道了神经网络的结构,forward跟backward是怎样的一个过程,基本上就知道了caffe的结构了。按照神经网络的运行过程看Caffe就好了。
既然说神经网络,那么就得有一个网络出来,caffe里面就用Net这个类来记录这个网络。
那么网络是由很多个layer构成,自然而然就会有Layer这个类,为了统一管理这些类,自然而然就想要抽象,那么Layer这个抽象类作为一个最基本的单元出现了,接下来就会有实现各种功能的layer出现,如:Convolution/ReLU/Softmax等。
Layer间需要连接啊,Layer需要有输入输出啊,caffe里面用Bottom来表示输入,Top表示输出,前一层Layer的top是后一层layer的bottom,这样,连接搞掂了,输入输出也搞掂了。
网络搞掂了,layer搞掂了,那就要搞个求解算法啊,那么Solver这个类就出现了,这个就是用来求解网络的。
就酱紫,有时间再写得详细一点。反正就这么一句话:按照神经网络的运行过程看Caffe就好了。
from:&/question//answer/
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2878次
排名:千里之外
转载:16篇君,已阅读到文档的结尾了呢~~
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
caffe 网络结构几个部分简单介绍
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口caffe|LOFTER(乐乎) - 记录生活,发现同好
LOFTER for ipad —— 记录生活,发现同好
&nbsp&nbsp被喜欢
&nbsp&nbsp被喜欢
{list posts as post}
{if post.type==1 || post.type == 5}
{if !!post.title}${post.title|escape}{/if}
{if !!post.digest}${post.digest}{/if}
{if post.type==2}
{if post.type == 3}
{if !!post.image}
{if post.type == 4}
{if !!post.image}
{if !!photo.labels && photo.labels.length>0}
{var wrapwidth = photo.ow < 500?photo.ow:500}
{list photo.labels as labs}
{var lbtxtwidth = Math.floor(wrapwidth*(labs.ort==1?labs.x:(100-labs.x))/100)-62}
{if lbtxtwidth>12}
{if !!labs.icon}
{list photos as photo}
{if photo_index==0}{break}{/if}
品牌${make||'-'}
型号${model||'-'}
焦距${focalLength||'-'}
光圈${apertureValue||'-'}
快门速度${exposureTime||'-'}
ISO${isoSpeedRatings||'-'}
曝光补偿${exposureBiasValue||'-'}
镜头${lens||'-'}
{if data.msgRank == 1}{/if}
{if data.askSetting == 1}{/if}
{if defined('posts')&&posts.length>0}
{list posts as post}
{if post_index < 3}
{if post.type == 1 || post.type == 5}
{if !!post.title}${post.title|escape}{/if}
{if !!post.digest}${post.digest}{/if}
{if post.type == 2}
{if post.type == 3}
{if post.type == 4}
{if drlist.length>0}
更多相似达人:
{list drlist as dr}{if drlist.length === 3 && dr_index === 0}、{/if}{if drlist.length === 3 && dr_index === 1}、{/if}{if drlist.length === 2 && dr_index === 0}、{/if}{/list}
暂无相似达人,
{if defined('posts')&&posts.length>0}
{list posts as post}
{if post.type == 2}
{if post.type == 3}
{if post.type == 4}
this.p={ currentPage:1,pageNewMode:true,isgooglead3:false,ishotrecompost:false,visitorId:0, first:'',tag:'caffe',recommType:'new',recommenderRole:0,offset:20,type:0,isUserEditor:0,};新手使用caffe - 简书
<div class="fixed-btn note-fixed-download" data-toggle="popover" data-placement="left" data-html="true" data-trigger="hover" data-content=''>
写了48397字,被25人关注,获得了39个喜欢
新手使用caffe
1.首先,caffe的安装很麻烦,稍后有时间我在详细写一个教程。
先贴个官网的安装方法,
2.安装好之后,仔细阅读并照着流程跑一下官网给的例子,链接如下:
3.看完之后,可以仔细研究以下通过python来使用caffe的例子,了解使用caffe的方法。
4.以下以人脸识别问题使用以下库使用caffe进行训练和测试:
里面包括了40个人,每人10张人脸照片。如下图:
att_face数据库
由于官网上给出了Model_Zoo的链接,通过查询得知,已经有训练好的人脸识别模型,可以直接拿来使用,即:下载地址:
在网站中提供了模型和源码,具体使用参考相关说明即可,基本的流程应该比较简单:
在脚本源码中指定Caffe库的路径,指定.caffemodel模型,指定输入数据,通过函数调用网络的测试功能,获取网络输出结果。
执行脚本源码。
如果源码的使用说明不能够充分理解,可以参考的示例。基本流程与ImageNet的分类任务应该是相同的。另外,模型的数据集在相关论文的第三章有说明。
其次因为人脸图片是灰度图,需要首先用OpenCV将其转化成RGB的图片才能使用VGG。python代码如下:
import cv2
import sysdef
convert_gray_img_to_rgb(base_dir,dir_pre_str,dir_range_list,dir_post_str,file_format,partion_list):
for i in dir_range_list:
for index,partion_list_part in enumerate(partion_list):
for k in partion_list_part:
if base_dir=="":
base_dir_str=""
base_dir_str=base_dir+os.sep
if index==0:
type="train"
elif index==1:
type="tst"
file_input_path=base_dir_str+type+os.sep+dir_pre_str+str(i)+\
dir_post_str+os.sep+str(k)+file_format
img = cv2.imread( file_input_path,0 )
img = cv2.cvtColor( img, cv2.COLOR_GRAY2RGB )
out_file= base_dir_str+type+os.sep+dir_pre_str+\
str(i)+dir_post_str+os.sep+str(k)+".jpg"
cv2.imwrite(out_file, img)
if __name__=='__main__':
source_dir="/Users/Ren/Downloads/att_faces_back"
dir_pre_str="s"
dir_range_list=range(1,41)
test_partion_list=[7,8,9,10]
train_partion_list=[1,2,3,4,5,6]
dir_post_str=""
file_format=".pgm"
convert_gray_img_to_rgb(source_dir,dir_pre_str,dir_range_list\
,dir_post_str,file_format,[train_partion_list,test_partion_list])
对于此数据库,首先需要将人脸的数据进行划分:训练和测试集,并转换成lmdb模型。过程请参考:
#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs
EXAMPLE=examples/att_faces
DATA=data/att_faces
TOOLS=build/tools
DBTYPE=lmdb
TRAIN_DATA_ROOT=$DATA/train/
TEST_DATA_ROOT=$DATA/tst/
# 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=224
RESIZE_WIDTH=224
RESIZE_HEIGHT=0
RESIZE_WIDTH=0
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_att_faces.sh to the path" \
"where the ImageNet training data is stored."
if [ ! -d "$TEST_DATA_ROOT" ]; then
echo "Error: TEST_DATA_ROOT is not a path to a directory: $TEST_DATA_ROOT"
echo "Set the TEST_DATA_ROOT variable in create_att_faces.sh to the path" \
"where the ImageNet test data is stored."
echo "Creating train lmdb..."
rm -rf $EXAMPLE/att_faces_train_$DBTYPE $EXAMPLE/att_faces_tst_$DBTYPE
GLOG_logtostderr=1 $TOOLS/convert_imageset \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$DATA/train.txt \
$EXAMPLE/att_faces_train_$DBTYPE
echo "Creating tst lmdb..."
rm -f $EXAMPLE/mean.binaryproto
GLOG_logtostderr=1 $TOOLS/convert_imageset \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$DATA/tst.txt \
$EXAMPLE/att_faces_tst_$DBTYPE
echo "Computing image mean..."
./build/tools/compute_image_mean -backend=$DBTYPE \
$EXAMPLE/att_faces_train_$DBTYPE $EXAMPLE/mean.binaryproto
echo "Done."
之后可以使用该数据通过以models/finetune_flickr_style/train_val.prototxt 为模板,以vgg_face_caffe/VGG_FACE_deploy.prototxt 为内容将网络结构进行填充。即加入数据输入层与改变最后一层的全连接层输出数量,修正掉旧caffe的语法。修正后的内容如下:
name: "VGG_FACE_16_Net"
name: "data"
type: "ImageData"
top: "data"
top: "label"
phase: TRAIN
transform_param {
mirror: true
crop_size: 224
mean_file: "examples/att_faces/mean.binaryproto"
image_data_param {
source: "data/att_faces/train.txt"
batch_size: 1
new_height: 224
new_width: 224
name: "data"
type: "ImageData"
top: "data"
top: "label"
phase: TEST
transform_param {
mirror: false
crop_size: 224
mean_file: "examples/att_faces/mean.binaryproto"
image_data_param {
source: "data/att_faces/tst.txt"
batch_size: 1
new_height: 224
new_width: 224
name: "conv1_1"
type: "Convolution"
bottom: "data"
top: "conv1_1"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 64
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu1_1"
type: "ReLU"
bottom: "conv1_1"
top: "conv1_1"
name: "conv1_2"
type: "Convolution"
bottom: "conv1_1"
top: "conv1_2"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 64
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu1_2"
type: "ReLU"
bottom: "conv1_2"
top: "conv1_2"
name: "pool1"
type: "Pooling"
bottom: "conv1_2"
top: "pool1"
pooling_param {
kernel_size: 2
name: "conv2_1"
type: "Convolution"
bottom: "pool1"
top: "conv2_1"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 128
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu2_1"
type: "ReLU"
bottom: "conv2_1"
top: "conv2_1"
name: "conv2_2"
type: "Convolution"
bottom: "conv2_1"
top: "conv2_2"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 128
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu2_2"
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
name: "pool2"
type: "Pooling"
bottom: "conv2_2"
top: "pool2"
pooling_param {
kernel_size: 2
name: "conv3_1"
type: "Convolution"
bottom: "pool2"
top: "conv3_1"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 256
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu3_1"
type: "ReLU"
bottom: "conv3_1"
top: "conv3_1"
name: "conv3_2"
type: "Convolution"
bottom: "conv3_1"
top: "conv3_2"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 256
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu3_2"
type: "ReLU"
bottom: "conv3_2"
top: "conv3_2"
name: "conv3_3"
type: "Convolution"
bottom: "conv3_2"
top: "conv3_3"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 256
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu3_3"
type: "ReLU"
bottom: "conv3_3"
top: "conv3_3"
name: "pool3"
type: "Pooling"
bottom: "conv3_3"
top: "pool3"
pooling_param {
kernel_size: 2
name: "conv4_1"
type: "Convolution"
bottom: "pool3"
top: "conv4_1"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 512
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu4_1"
type: "ReLU"
bottom: "conv4_1"
top: "conv4_1"
name: "conv4_2"
type: "Convolution"
bottom: "conv4_1"
top: "conv4_2"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 512
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu4_2"
type: "ReLU"
bottom: "conv4_2"
top: "conv4_2"
name: "conv4_3"
type: "Convolution"
bottom: "conv4_2"
top: "conv4_3"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 512
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu4_3"
type: "ReLU"
bottom: "conv4_3"
top: "conv4_3"
name: "pool4"
type: "Pooling"
bottom: "conv4_3"
top: "pool4"
pooling_param {
kernel_size: 2
name: "conv5_1"
type: "Convolution"
bottom: "pool4"
top: "conv5_1"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 512
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu5_1"
type: "ReLU"
bottom: "conv5_1"
top: "conv5_1"
name: "conv5_2"
type: "Convolution"
bottom: "conv5_1"
top: "conv5_2"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 512
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu5_2"
type: "ReLU"
bottom: "conv5_2"
top: "conv5_2"
name: "conv5_3"
type: "Convolution"
bottom: "conv5_2"
top: "conv5_3"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 512
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu5_3"
type: "ReLU"
bottom: "conv5_3"
top: "conv5_3"
name: "pool5"
type: "Pooling"
bottom: "conv5_3"
top: "pool5"
pooling_param {
kernel_size: 2
name: "fc6"
type: "InnerProduct"
bottom: "pool5"
top: "fc6"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
inner_product_param {
num_output: 4096
weight_filler {
type: "gaussian"
std: 0.005
bias_filler {
type: "constant"
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
name: "drop6"
type: "Dropout"
bottom: "fc6"
top: "fc6"
dropout_param {
dropout_ratio: 0.5
name: "fc7"
type: "InnerProduct"
bottom: "fc6"
top: "fc7"
# Note that lr_mult can be set to 0 to disable any fine-tuning of this, and any other, layer
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
inner_product_param {
num_output: 4096
weight_filler {
type: "gaussian"
std: 0.005
bias_filler {
type: "constant"
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
name: "drop7"
type: "Dropout"
bottom: "fc7"
top: "fc7"
dropout_param {
dropout_ratio: 0.5
name: "fc8_flickr"
type: "InnerProduct"
bottom: "fc7"
top: "fc8_flickr"
# lr_mult is set to higher than for other layers, because this layer is starting from random while the others are already trained
propagate_down: false
inner_product_param {
num_output: 40
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "accuracy"
type: "Accuracy"
bottom: "fc8_flickr"
bottom: "label"
top: "accuracy"
phase: TEST
name: "loss"
type: "SoftmaxWithLoss"
bottom: "fc8_flickr"
bottom: "label"
top: "loss"
拷贝models/finetune_flickr_style/solver.prototxt,并将新的针对现问题进行修改,主要修改
net: "models/finetune/train_val.prototxt"
test_iter: 100
test_interval: 100
# lr for fine-tuning should be lower than when starting from scratch
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
# stepsize should also be lower, as we're closer to being done
stepsize: 2000
display: 20
max_iter: 10000
momentum: 0.9
weight_decay: 0.0005
snapshot: 1000
snapshot_prefix: "models/finetune/finetune"
# uncomment the following to default to CPU mode solving
#solver_mode: CPU
最后使用自己的数据对模型进行fine-tuning。代码如下:
./build/tools/caffe train -solver models/finetune/solver.prototxt -weights models/vgg_face_caffe/VGG_FACE.caffemodel -gpu 0
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:

我要回帖

更多关于 facenet caffe实现 的文章

 

随机推荐