Caffe各层参数详解

article/2025/10/3 19:35:16

在之前的文章中,整理了 ubuntu18安装和caffe-cpu安装问题汇总(含详细流程),这篇文章则对caffe的各个层进行一个剖析。文章篇幅较长,可根据目录按层选择阅读。

简述

Net是由Layer层层组成的

Net是由Solver文件支配的,Net的很多的hyper parameters都是由solver支配的。

如何学习caffe

  1. 第一步,用一个卷积网络,要有数据才行,首先要对数据进行一些预处理.比如你需要把数据做成(caffe支持的文件/夹格式)数据源的格式, 然后你再把数据集交给caffe, caffe再帮你做预测分类等

  2. 第二步, 需要定义一个网络,卷积神经网络是有各种各样的,如何定义各个层结构呢? 不需要!只需要去修改配置文件,按照一定流程去做。

    1. 所有的层都是按照流程图的格式,一层一层往下写的,每一层里都有很多可选项,参数项

  3. 第三步,由于net会受到一些hyper parameters的控制,所以我们需要定义一些solver控制hyper parameters

    1. solver就是专门配置你的caffe网络参数和超参数的文件,也是个prototxt文件

  4. 第四步,训练网络,只运行一个脚本文件,如果是linux系统,那一行命令就ok

看一下caffe的网络配置文件,我们该如何从头到尾去写这个东西呢??每一层的每个参数都表达什么意思呢?

下载好caffe后,可以去examples文件夹查看一些示例

数据层

关于LMDB相关内容,参考文章:数据集转换成LMDB格式

layer {name: "cifar" # 就是你想给这个层叫什么名字你自己定type: "Data" # 写成data告诉caffe这个层是数据层top: "data"top: "label"# 每一层既有输入又有输出, 我们用bottom表示输入,top表述输出,多个top表示多个输出# 这是数据层,所以不存在输入的情况,只有输出# 数据层输出两个东西,一个是数据data, 一个是标签labelinclude {phase: TRAIN}}# 一般一边训练一边测试,训练几千次之后测试一下,这样可以提前终止, 
# 这个实现方法就在include里边phase(阶段):
# 写了个TRAIN 意思就是这层的数据,只有在我们训练层的时候才会用到,测试的时候不会用到TEST同理,测试层才用transform_param {mean_file: "examples/cifar10/mean.binaryproto"transform_param{scale:0.00390625mirror: 1crop_size: 227}}#   mean_file:这里求均值是为了对数据初始化操作, 这里可以思考正态分布转变成标准正态分布,当然是每个通道的像素减去这个通道的均值. 这里是一个配置文件, 通过这个配置文件来实现的,至于怎么做出来的,等会你就知道了
#   scale是用来归一化的, 就是0-255到0-1,为什么是0.00396625呢?是通过1/255=0.0039得到的
#   mirror镜像, 意思就是数据增强,把每个图片都镜面对称一下, 你不就有2倍的数据了吗, 1就是开启,0就是关闭
#   crop剪裁:如果你觉得数据比较少,那你可以通过随机剪裁,进行数据增强, 一个图给你剪成好多个图,你不多了好多倍 的数据了吗data_param {source: "examples/cifar10/cifar10_train_lmdb"batch_size: 111backend: LMDB}# data_param 数据参数
#    一般情况下caffe要求我们的数据集格式是lmdb, 我们要把数据搞成数据库的形式,然后把数据库的源交给caffe,就是根目录,做成数据库的话方便caffe读取,你想想用规则读取快还是不用规则读取快呢????另外,你读取数据是cpu来搞的, 你gpu是用来计算数据的, 所以你读取数据也得很快才行,
#    source:就是你创建好的LMDB格式数据集的根目录所在位置
#    batch_size是每次喂给net的样本个数,一般是2的n次幂,一般是越大越好,但是你要考虑你的硬件限制,一般GPU是8G的,1080是8G, TitanX12G, 显存决定了你的batch_size
#    backend:数据类型的名称 比如LMDB

LMDB格式数据层

layer {name: "cifar"type: "Data"top: "data"top: "label"include {phase: TEST}transform_param {mean_file: "examples/cifar10/mean.binaryproto"}data_param {source: "examples/cifar10/cifar10_test_lmdb"batch_size: 1000backend: LMDB}
}

HDF5格式数据层

layer {name: "data"type: "HDF5Data"top: "data"top: "label"include {phase: TRAIN}hdf5_data_param {source: "examples/hdf5_classification/data/train.txt" 
#这个txt文件里写了每个小数据库的具体路径,这里后续还会介绍batch_size: 10}
}

直接输入图片层

  1. 文件夹下有好多图片,同样的道理,我们把source的路径搞成.txt文件, 这个txt文件包括了所有图片的路径 但是要注意这里txt内容的格式, 是图片路径<空格>类别
  2. 看到new_height了吗? 你的图片可能是千奇百怪的大小,没有预处理过, 所以你需要先进行预处理resize, 这里是resize成了256*256的分辨率
layer {name: "data"type: "HDF5Data"top: "data"top: "label"include {phase: TRAIN}image_data_param {source: "examples/xjh_images/data/train.txt"batch_size: 10new_height: 256new_width:256}
}

LMDB文件常用来做分类,HDF5常用来做回归

卷积层

数据层介绍了三种数据层:HDF5、LMDB和直接输入图片。这里解释卷积层的相关信息。

layer {name: "conv1"         #该层的名字type: "Convolution"   #该层的类型,即卷积bottom: "data"        #输入层的名字top: "conv1"          #输出层的名字,注意这里就是本层param {lr_mult: 1}param {lr_mult: 2}
#param参数解释
#lr_mult    本层的学习率,并不是模型的学习率,模型的学习率是通过solver文件控制的
#           其实lr_mult表示的是模型学习率的系数
#如果该层有两个lr_mult参数,那么第一个表示模型学习率在本层的权值,第二个则表示对应偏置项,一般偏置=2*权值convolution_param {    #卷积参数num_output: 32       #输出的通道数channels,即卷积核的个数,如果有c个核,那么得到c个featuremaps一般来说channels=cpad: 2               #边缘处理方式,0表示不扩充kernel_size: 5       #卷积核大小stride: 1            #卷积核滑动步长weight_filter {      #卷积核的权值type:"xvaier"    #type表示卷积核的类型,即gauss核还是全0核等#全0核则默认type:"constant"#常用xvaier算法来初始化gaussian}bias_filter {        #偏置项初始化type:"constant"  #默认则偏置项=0}}}

输入如果是width=w, height=h

那么输出w' = [(w-k+2p)/s] +1

h'=[(h-k+2p)/s] +1

p就是padding边缘处理

stride就是步长

池化(合并)层

pool翻译成合并更能表示出pool层的作用:把kernel内覆盖的多个像素,合并成一个。

layer {name: "pool1"type: "Pooling"bottom: "conv1"top: "pool1"pooling_param {pool: MAX        #池化方法,有取最值max,也有取覆盖点均值等方法kernel_size: 3   #核大小stride: 2        #步长}
}

激活函数

上述设定了卷积层,但是卷积层需要输入给激活函数,将激活函数的结果作为输出。

激活函数的输入层一般是池化后的卷积层,即卷积层-池化层。

layer {name: "relu1"type: "ReLU"    #使用的函数是ReLU函数bottom: "pool1" #池化层top: "pool1"
}

相同名字的bottom和top这些blob就是同一个blob,占用的是同一个空间。
简单来解释就是:
int a;
a = 0;
a = 1;
你可以无数次对这个a进行改变。
对于blob来说也是一样。

至于谁先谁后,那就是看你的网络定义哪个layer在前,它就先计算。
如果有两个layer输出的blob名称是一样的,那么它们的输入blob也一定会有这个blob,也就是,如果layer不是对输入blob本身操作,就不允许输出blob同名。比如:
layer1和layer2的输入和输出blob都是blob1,它们都是对blob1进行操作,这是允许的,直接按顺序计算就可以了。
layer1的输入blob是blob1,输出blob是blob_out,layer2的输入blob是blob2,输出blob也是blob_out,那么这就是不允许的。因为它们不是对它们的输入blob本身进行操作,假设你允许这样的操作,那么后运算的layer会将blob_out覆盖成后运算的结果,前面运算的blob_out的结果就消失了。

当然,layer1和layer2的输入和输出blob都是blob1,它们都是对blob1进行操作,比如layer1先计算,然后layer2后计算,计算layer2的结果也是会把layer1的结果给覆盖,只不过是网络已经不需要这个layer1的结果而已,因为它已经前向传播过去了...

全链接FC层

FC层即全链接层,下文type:“InnerProduct”。

全链接层就是把之前提取到的特征,进行一个简单的组合,包装成一个向量的形式,根据这个向量就可以对其特征向量进行分析。

layer {name: "ip1"type: "InnerProduct"bottom: "pool3"top: "ip1"param {lr_mult: 1decay_mult: 250}param {lr_mult: 2decay_mult: 0}inner_product_param {num_output: 500weight_filter {type:"xavier"}bias_filter {type:"constant"}}
}layer {name:"accuracy"type:"Accuracy"bottom:"ip2"bottom:"label"top:"accuracy"include {phase:TEST}
}

LOSS层

layer {name: "loss"type: "SoftmaxWithLoss"bottom: "ip1"bottom: "label"top: "loss"
}

首先要把你预测的结果归一化,就是值域在0-1,相当于分类的概率值;

loss的计算方法你说了算,可以是softmax的loss数值也可以是softmax概率值;

loss层的输入是全连接层,和真实值层。

Reshape层

为什么存在reshape层,因为想要在不改变数据的情况下,改变维度

    比如[3, 15, 28, 28] 变成[3*15, 28*28]

layer {name:"reshape"type:"Reshape"bottom:"input"top:"output"reshape_param {shape {dim : 0dim : 2dim : 3dim : -1}}     
}

reshape_param参数:

    上述shape{}中的竖排:

        dim:a

        dim:b    

        dim:c        

        dim:d

是常见写法的:[a, b, c, d]

dim后的数字表示:示例dim:x

  • x=0时,就是保持abcd的值不变
  • x=-1时就是让caffe自己去推断数值

如果是具体的数值,比如把b换成23,就是你制定了b原来的数改成23

dropout层

还记得dropout吗?防止过拟合的,就是随机断开网络连接线,迭代一次

layer {name: "drop7"type: "Dropout"bottom: "fc7-conv"top: "fc7-conv"dropout_param {dropout_ratio: 0.5 #迭代一次断开的线数,0.5即50%}
}

完整的网络配置文件(mnist数据)

环境:ubuntu18.04,caffe-cpu

进入下载的caffe/examples/mnist/,选择lenet_train_test.prototxt,可以自行查看学习。

示例

在下面代码中标注了,Net中哪个部分设置了网络输出的纬度。(FC层)

name: "LeNet"
layer {name: "mnist"type: "Data"top: "data"top: "label"include {phase: TRAIN}transform_param {scale: 0.00390625}data_param {source: "examples/mnist/mnist_train_lmdb"batch_size: 64backend: 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: 100backend: LMDB}
}
layer {name: "conv1"type: "Convolution"bottom: "data"top: "conv1"param {lr_mult: 1}param {lr_mult: 2}convolution_param {num_output: 20kernel_size: 5stride: 1weight_filler {type: "xavier"}bias_filler {type: "constant"}}
}
layer {name: "pool1"type: "Pooling"bottom: "conv1"top: "pool1"pooling_param {pool: MAXkernel_size: 2stride: 2}
}
layer {name: "conv2"type: "Convolution"bottom: "pool1"top: "conv2"param {lr_mult: 1}param {lr_mult: 2}convolution_param {num_output: 50kernel_size: 5stride: 1weight_filler {type: "xavier"}bias_filler {type: "constant"}}
}
layer {name: "pool2"type: "Pooling"bottom: "conv2"top: "pool2"pooling_param {pool: MAXkernel_size: 2stride: 2}
}
layer {name: "ip1"type: "InnerProduct"bottom: "pool2"top: "ip1"param {lr_mult: 1}param {lr_mult: 2}inner_product_param {num_output: 500weight_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       #注意:这里就是输出结果的纬度,即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"
}

超参数solver配置文件

caffe提供了一个solver文件,根据这个solver进行修改,然后保存到项目根目录下即可。

solver是个.prototxt文件,通过mnist文件夹内的文件来看一下solver是如何控制haper parameters的。

# lenet_solver.prototxt文件一览
# The train/test net protocol buffer definition
net: "examples/mnist/lenet_train_test.prototxt"
# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_iter: 100
# Carry out testing every 500 training iterations.
test_interval: 500
# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005
# The learning rate policy
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# Display every 100 iterations
display: 100
# The maximum number of iterations
max_iter: 10000
# snapshot intermediate results
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
# solver mode: CPU or GPU
solver_mode: GPU

自定义的solver文件

loss fucntion的优化算法

往往loss function是非凸函数,没有解析解,需要通过优化方法来求解析解

caffe提供了六种常用的优化算法, 需要在solver文件中进行配置,即通过type关键字来选择

    Stochastic Gradient Descent (type:"SGD")

    AdaDelta (type:"AdaDelta")

    Adaptive Gradient (type:"AdaGrad")

    Adam(type:"Adam")

    Nesterov's Accelerated Gradient (type:"Nesterov")

    RMSprop(type:"RMSProp")

上述就是六种算法名字及在solver文件中type关键字对应的参数名

自定义solver

# 自己写一个solver.prototxt文件net: "examples/mnist/lenet_train_test.prototxt"
# net就是网络配置文件的路径test_iter: 100
# 一次迭代100个测试batch,
# 测试和训练时,都是一个batch一个batch喂给net的,test_iter表示了一次给net是100个batch
# test_iter的大小 = (样本个数)/(batch包含样本数)test_interval: 500
# 表示每训练500次,测试一次base_lr: 0.01
# 基础学习率,就是上文提到的网络模型的学习率
# 实习学习率 = 每个conv层设置的学习率权值数 * base_lr + 每个conv层设置的偏置项
# 若想修改学习率,最好只修改此处。momentum: 0.9
# 动量值,一般设置为0.9且常不修改weight_decay: 0.0005
# 不知道是什么lr_policy: "inv"
# 学习策略gamma: 0.0001
# 不知道是什么power: 0.75
# 不知道是什么display: 100
# 每训练100次打印一次结果,display:0时不显示max_iter: 10000
# 最大迭代次数,即迭代10000次时停止训练snapshot: 5000
# 快照保存模型,即当迭代5000次时保存一下模型snapshot_prefix: "examples/mnist/lenet"
# 快照存储位置solver_mode: GPU
# net的运行模,CPU/GPU

 

 

 

 

 

 

 


http://chatgpt.dhexx.cn/article/2PUcBgeM.shtml

相关文章

CoppeliaSim用户手册中文翻译版(二)

CoppeliaSim 用户手册 文章目录 5. 计算模块5.1 计算模块属性对话框5.2 碰撞检测5.3 距离计算5.4 逆运动学5.4.1 IK组和IK元素的基础知识5.4.2 解决IK和FK的任何类型的机制 5.5 逆运动对话框5.5.1 IK元素对话框 5.6 动力学5.6.1 设计动态仿真5.6.2 一般动力学特性5.6.2.1 动态引…

【记录】一个深度学习算法工程师的成长之路(思考和方法以及计划)

声明&#xff1a; 1&#xff09;该文章整理自网上的大牛和机器学习专家无私奉献的资料&#xff0c;具体引用的资料请看参考文献。 2&#xff09;本文仅供学术交流&#xff0c;非商用。所以每一部分具体的参考资料并没有详细对应。如果某部分不小心侵犯了大家的利益&#xff0c…

五年无人驾驶工作总结及展望

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达本文转自|计算机视觉工坊现在是晚上22点46分&#xff0c;大小美女都睡觉了&#xff0c;我突然想写一篇这五年无人驾驶工作的总结。没有打草稿&#xff0c;想到啥说啥。如…

CoppeliaSim用户手册中文翻译版(一)

CoppeliaSim 用户手册 文章目录 主要功能历史版本许可证致谢和鸣谢概述1. 用户界面1.1 页面和视图1.2 自定义用户界面1.3 位置/方向操作1.3.1 位置对话框1.3.2 方向对话框1.3.3 使用鼠标移动物体 1.4 欧拉角1.5 用户设置1.6 快捷键1.7 命令行 2. 场景和模型2.1 场景2.2 模型2.2…

深度学习一(PyTorch物体检测实战)

深度学习一(PyTorch物体检测实战) 文章目录 深度学习一(PyTorch物体检测实战)1、浅谈物体检测与PyTorch1.1、深度学习与计算机视觉1.1.1 发展历史1.2.2 计算机视觉 1.2、物体检测技术1.2.1、发展历程1.2.2、技术应用领域1.2.3、评价指标 3、PyTorch简介1.3.1、诞生于特点1.3.2、…

目前学什么专业的人在搞SLAM?各有什么优势?

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 原提问&#xff1a; 目前学什么专业的人在搞SLAM&#xff1f;如需要哪些专业知识&#xff0c;或者找什么专业的人合作&#xff1f; 李雅不诺夫 一些比较牛掰的论文后面都…

opencv-python学习笔记(十):实现人脸特征转换

引言 本次实验来自实验楼&#xff0c;而实验楼代码的出处为如下GitHub链接&#xff0c;加上一些自己的理解与说明&#xff0c;总结成本文笔记。 https://github.com/matthewearl/faceswap 所需环境 Dlib是一个高级的机器学习库&#xff0c;它是为解决复杂的现实世界问题而创…

ROS会议 ROSCon 2017

----ROSCon2012-2017----来源链接&#xff1a;https://roscon.ros.org 具体讲座的日程安排&#xff1a; 2017&#xff1a;https://roscon.ros.org/2017/ 2016&#xff1a;https://roscon.ros.org/2016/ 2015&#xff1a;https://roscon.ros.org/2015/ 2014&#xff1a;http…

Frenet坐标系下横纵向轨迹决策规划(SL投影及ST投影)及Apollo决策算法解析

参考&#xff1a; &#xff08;1&#xff09;《攻城狮说 | 应对复杂路况&#xff0c;自动驾驶如何规划它的下一步&#xff1f; “老司机”炼成记&#xff01;》微信公众号文章 Pony.ai小马智行 &#xff08;2&#xff09;《【Apollo】apollo3.5决策分享 --by 百度美研 Yifei J…

基于Ubuntu 18.04机器人操作系统环境和深度学习环境配置

基于Ubuntu 18.04机器人操作系统环境和深度学习环境配置详解 CUDACudnnROSanacondaubuntu装机必备 笔记本双系统安装U盘启动项安装ubuntu18.04.1关闭无线驱动冲突&#xff08;联想&#xff09;(option)更新软件源为国内软件源apt-get 锁问题rc.localaria2c BaiduExport ROS me…

几何向量:向量乘法(叉乘)

转载自: https://blog.csdn.net/yinhun2012/article/details/79444277 之前我们学习了物理意义上的做功&#xff0c;也就是数学中向量点积的实际意义&#xff0c;这一篇我们学习物理上另外一种力的作用&#xff0c;也就是力矩。 物理上定义力矩是力对物体产生转动作用的物理量…

向量和矩阵的点乘和叉乘

向量 定义&#xff1a;向量是由N个实数组成的一行N列或N行一列的的数组。 点乘&#xff1a;又叫做点积、内积、数量积、标量积&#xff0c;向量a[a1,a2,...,an]和向量b[b1,b2b...,bn]点乘的结果是一个标量&#xff0c;记作a.b&#xff1b; 几何解释&#xff1a;a.b |a| |b| &…

向量叉乘与叉乘矩阵

本文以三维向量来说明向量的叉乘计算原理以及叉乘矩阵如何求取 1、向量叉乘的计算原理 a、b分别为三维向量&#xff1a; a叉乘b一般定义为&#xff1a; 或 可是这只是一个符号的定义啊&#xff0c;具体怎么得到代数值呢 关键方法就是引入单位坐标向量&#xff0c; 这里用i j k…

3维向量的点乘叉乘运算

3维向量的点乘叉乘运算 文章目录 3维向量的点乘叉乘运算三维向量的点乘三维向量的叉乘点到直线的距离点到平面的距离 三维向量的点乘 点乘得到的是对应元素乘积的和&#xff0c;是一个标量&#xff0c;没有方向 V1( x1, y1, z1)V2(x2, y2, z2) x1x2 y1y2 z1*z2 点乘可以用…

通俗理解三维向量的点乘与叉乘

通俗理解三维向量的点乘和叉乘 一般接触得比较多的是二维向量的点乘和叉乘&#xff0c;但是做到与三维几何相关的工作的时候&#xff0c;三维向量的知识是必不可少的。 注意&#xff1a;三维向量和三维矢量是同一个东西&#xff0c;都是来自英文单词的Vector的中文翻译&#…

栅栏密码加密/解密【传统型】在线工具

栅栏密码(Rail-fence Cipher)就是把要加密的明文分成N个一组&#xff0c;然后把每组的第1个字符组合&#xff0c;每组第2个字符组合…每组的第N(最后一个分组可能不足N个)个字符组合&#xff0c;最后把他们全部连接起来就是密文。 遇到这种的栅栏加密的密文&#xff0c;解密的…

栅栏密码加密/解密【W型】在线工具

栅栏密码加密/解密【W型】在线工具 栅栏密码(Rail-fence Cipher)就是把要加密的明文分成N个一组&#xff0c;然后把每组的第1个字符组合&#xff0c;每组第2个字符组合…每组的第N(最后一个分组可能不足N个)个字符组合&#xff0c;最后把他们全部连接起来就是密文。 本工具所…

栅栏密码解密

题目&#xff1a; 一只小羊翻过了2个栅栏 KYsd3js2E{a2jda} 通过栅栏密码在线解密即可得出flag 解密结果&#xff1a; flagKEY{sad23jjdsa2}

猪圈密码 摩斯密码 QWE加密 栅栏加密 当铺密码

1.猪圈密码 猪圈密码&#xff1a;对应下图就是HORSE 2.摩斯密码 在线摩斯密码翻译器&#xff1a;http://www.mathsking.net/morse.htm 3.QWE加密 键盘按ABC的顺序排列得到对应的字母&#xff0c;QA,WB.... 4.栅栏加密 加密过程&#xff1a; 如果我们想要加密一句话&#xff0c;…