fcn 全卷积 caffee是否有官方的FCN的实现

【Caffe实践】基于Caffe的人脸识别实现 - 博客频道 - CSDN.NET
1983的专栏
拥抱变化,勇往直前!
分类:【Caffe实践】
深度学习深似海、尤其是在图像人脸识别领域,最近几年的顶会和顶刊常常会出现没有太多的理论创新的文章,但是效果摆在那边。
DeepID是深度学习方法进行人脸识别中的一个简单,却高效的一个网络模型,其结构的特点可以概括为两句话:1、训练一个多个人脸的分类器,当训练好之后,就可以把待测试图像放入网络中进行提取特征,2对于提取到的特征,然后就是利用其它的比较方法进行度量。具体的论文可以参照我的一篇论文笔记:
首先我们完全参考论文的方法用Caffe设计一个网络结构:
其拓扑图如图1所示:
图1:DeepID的网络结构,图像比较大,需要放大才能看的清楚
网络定义文件:
2. 数据选择
训练一个好的深度模型,一个好的训练数据是必不可少的。针对人脸识别的数据,目前公开的数据也有很多:比如最近的MegaFace、港大的Celbra A、中科研的WebFace 等等。在这里,我选择WebFace人脸数据库作为训练(人脸库不是很干净,噪声较多),图像公共50万张左右,共10575个人,但是数据不平衡。
要评测一个算法的性能,需要找一个公平的比对数据库来评测,在人脸验证中,LFW数据库无疑是最好的选择。在lfw评测中,给出6000千对人脸图像对进行人匹配。
3. 数据处理
训练数据和测试数据都选择好之后,就需要进行数据处理了,为了提供较好的识别准确度,我采用了训练数据和测试数据统一的预处理方法(虽然LFW上有提供已经预处理过的人脸图像,但是预处理的具体参数还是未知的),测试数据和训练数据都采样相同的人脸检测和对齐方法。
主要分为3个步骤:
1,人脸检测
2,人脸特征点检测
3、人脸的对齐
这三个步骤可以用我做的一个小工具: 来一键完成。
具体来说,需要选择一个标准的人脸图像作为对齐的基准,我挑选一位帅哥当标准图像:
训练数据通过对齐后是这样的:
LFW测试数据通过对齐后是这样的:
4.数据转换
图像处理好之后,需要将其转化为Caffe 可以接受的格式。虽然Caffe支持直接读图像文件的格式进行训练,但是这种方式磁盘IO会比较的大,所以我这里不采用图像列表的方式,而是将训练和验证图片都转化为LMDB的格式处理。
4.1 划分训练集验证集
划分训练集和验证集(我采样的是9:1的比例)
脚本如下:
4.2 数据转换
再调用Caffe 提供的转化函数:
脚本如下:
这样之后,训练的数据就准备好了。
上面的这些步骤之后,数据就已经处理好了,现在需要指定网络的超参数:
具体超参数设置如下:
训练的时候,可以查看学习曲线:
6.LFW上测试
LFW上,提供了6000对的人脸图像对来作为评测数据,由于我采用的是自己选的人脸检测和对齐方法,所以有些人脸在我的预处理里面丢失了(检测不到),为了简单的处理这种情况,在提特征的时候,没有检测到的图像就用原来的图像去替代。
然后进行人脸的比对
结果ROC曲线:
通过选择合适的脚本,得到的准确度为:0., 有点低。
7.结果分析
实验的结果没有理想中的那么好,主要的原因分为几个:
1、数据集不够好:有较多的噪声数据
2、数据集合不平衡:每个人的图片个数从几十张到几百张不等。
3,、网络结构没优化:原始的DeepID的大小为:48*48,而我选择的人脸图像大小为64*64,网络结构却没有相对应的调整。(主要影响在于全连接层的个数太多了)
chenriwei2
排名:第6412名
新浪微博:
(3)(9)(6)(9)(5)(5)(3)(5)(7)(3)(3)(0)(7)(5)(5)(3)(1)(1)基于Caffe的DeepID2实现(下) - 推酷
基于Caffe的DeepID2实现(下)
小喵的唠叨话:这次的博客,真心累伤了小喵的心。但考虑到知识需要巩固和分享,小喵决定这次把剩下的内容都写完。
四、数据的重整,简单的划分
前面的Data层用于生成成对的输入数据,Normalization层,用于将feature归一化,那么之后是不是就可以使用ContrastiveLoss层进行训练了呢?
且慢,还差一步。
ContrastiveLoss层要求有3个bottom:feature1、feature2以及表示对位的feature是否为同一个identity的label。
我们现在得到的feature却是所有的都在一起,data层直接得到的label也和这里要求的label不同。因此务必要对数据进行一次重整。
一个简单的规则就是按照奇偶,将feature划分成两部分。这样得到的两部分正好就是相同位置为一对。对于label的重整,也可以用类似的方法。小喵这里只对feature进行重整,而label的处理则是通过改ContrastiveLoss层来实现。
feature的重整本质上就是一个切片的操作,这里命名为id2_slice_layer,实现方法就是按照奇偶把bottom的数据复制到top。后馈的时候,也就是将两部分的feature的diff都直接复制到对应位置的bottom_diff中,具体实现如下:
// created by miao
#ifndef CAFFE_ID2_SLICE_LAYER_HPP_
#define CAFFE_ID2_SLICE_LAYER_HPP_
#include &vector&
#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"
namespace caffe {
* @brief Takes a Blob and slices it along either the num or channel dimension,
outputting multiple sliced Blob results.
* TODO(dox): thorough documentation for Forward, Backward, and proto params.
template &typename Dtype&
class Id2SliceLayer : public Layer&Dtype& {
explicit Id2SliceLayer(const LayerParameter& param)
: Layer&Dtype&(param) {}
virtual void LayerSetUp(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtual void Reshape(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtual inline const char* type() const { return "Id2Slice"; }
virtual inline int ExactNumBottomBlobs() const { return 1; }
virtual inline int MinTopBlobs() const { return 1; }
protected:
virtual void Forward_cpu(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtual void Forward_gpu(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtual void Backward_cpu(const vector&Blob&Dtype&*&& top,
const vector&bool&& propagate_down, const vector&Blob&Dtype&*&& bottom);
virtual void Backward_gpu(const vector&Blob&Dtype&*&& top,
const vector&bool&& propagate_down, const vector&Blob&Dtype&*&& bottom);
// namespace caffe
// CAFFE_ID2_SLICE_LAYER_HPP_
头文件,巨简单。。。
Cpp的代码,也非常简单,要注意id2_slice层的top有两个,每个的形状都是bottom的一半。
// created by miao
#include &algorithm&
#include &vector&
#include "caffe/layers/id2_slice_layer.hpp"
#include "caffe/util/math_functions.hpp"
namespace caffe {
template &typename Dtype&
void Id2SliceLayer&Dtype&::LayerSetUp(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top) {
template &typename Dtype&
void Id2SliceLayer&Dtype&::Reshape(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top) {
vector&int& top_shape = bottom[0]-&shape();
top_shape[0] /= 2;
top[0]-&Reshape(top_shape);
top[1]-&Reshape(top_shape);
template &typename Dtype&
void Id2SliceLayer&Dtype&::Forward_cpu(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top) {
const int feature_size = bottom[0]-&count(1);
for (int n = 0; n & bottom[0]-&num(); ++ n) {
caffe_copy(
feature_size,
bottom[0]-&cpu_data() + n * feature_size,
top[n & 1]-&mutable_cpu_data() + (n / 2) * feature_size
template &typename Dtype&
void Id2SliceLayer&Dtype&::Backward_cpu(const vector&Blob&Dtype&*&& top,
const vector&bool&& propagate_down, const vector&Blob&Dtype&*&& bottom) {
const int feature_size = bottom[0]-&count(1);
for (int n = 0; n & bottom[0]-&num(); ++ n) {
caffe_copy(
feature_size,
top[n & 1]-&cpu_diff() + (n / 2) * feature_size,
bottom[0]-&mutable_cpu_diff() + n * feature_size
#ifdef CPU_ONLY
STUB_GPU(Id2SliceLayer);
INSTANTIATE_CLASS(Id2SliceLayer);
REGISTER_LAYER_CLASS(Id2Slice);
// namespace caffe
GPU上的实现,为了简单起见,也是直接调用了CPU的前馈函数。
// created by miao
#include &vector&
#include "caffe/layers/id2_slice_layer.hpp"
#include "caffe/util/math_functions.hpp"
namespace caffe {
template &typename Dtype&
void Id2SliceLayer&Dtype&::Forward_gpu(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top) {
this-&Forward_cpu(bottom, top);
template &typename Dtype&
void Id2SliceLayer&Dtype&::Backward_gpu(const vector&Blob&Dtype&*&& top,
const vector&bool&& propagate_down, const vector&Blob&Dtype&*&& bottom) {
this-&Backward_cpu(top, propagate_down, bottom);
INSTANTIATE_LAYER_GPU_FUNCS(Id2SliceLayer);
// namespace caffe
这样就完成了feature的重整。由于没有用到新的参数,因此也不需要修改caffe.proto。
亲可以仿照这个方法对label来做类似的操作。鉴于小喵比较懒。。。这里就只是简单的改ContrastiveLoss层的代码了。
第一步,在ContrastiveLossLayer中新增一个用于记录feature pair是否是同一个identity的成员变量,取代原本的第三个bottom的功能。这样只需要在前馈的时候提前算好,就可以代替之前的第三个bottom来使用,而不需要再修改别的地方的代码。
为了大家使用的方便,小喵直接把修改之后的头文件粘贴出来(删掉注释)。新增的行,用“added by miao”这个注释标注出来。头文件只加了一行。
#ifndef CAFFE_CONTRASTIVE_LOSS_LAYER_HPP_
#define CAFFE_CONTRASTIVE_LOSS_LAYER_HPP_
#include &vector&
#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/layers/loss_layer.hpp"
namespace caffe {
template &typenameDtype&
class ContrastiveLossLayer : public LossLayer&Dtype& {
explicitContrastiveLossLayer(const LayerParameter& param)
: LossLayer&Dtype&(param), diff_() {}
virtualvoid LayerSetUp(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtualinlineint ExactNumBottomBlobs() const { return 3; }
virtualinlineconst char* type() const { return "ContrastiveLoss"; }
virtualinlinebool AllowForceBackward(const int bottom_index) const {
return bottom_index != 2;
protected:
/// @copydoc ContrastiveLossLayer
virtualvoid Forward_cpu(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtualvoid Forward_gpu(const vector&Blob&Dtype&*&& bottom,
const vector&Blob&Dtype&*&& top);
virtualvoid Backward_cpu(const vector&Blob&Dtype&*&& top,
const vector&bool&& propagate_down, const vector&Blob&Dtype&*&& bottom);
virtualvoid Backward_gpu(const vector&Blob&Dtype&*&& top,
const vector&bool&& propagate_down, const vector&Blob&Dtype&*&& bottom);
Blob&Dtype& diff_;
// cached for backward pass
Blob&Dtype& dist_sq_;
// cached for backward pass
Blob&Dtype& diff_sq_;
// tmp storage for gpu forward pass
Blob&Dtype& summer_vec_;
// tmp storage for gpu forward pass
Blob&Dtype& is_same_; // added by miao
// namespace caffe
// CAFFE_CONTRASTIVE_LOSS_LAYER_HPP_
源文件的修改也十分简单,这里只贴出来Cuda的部分。源文件,修改了与原来的bottom3相关的地方。
#include &algorithm&
#include &vector&
#include &iostream&
#include "caffe/layers/contrastive_loss_layer.hpp"
#include "caffe/util/math_functions.hpp"
namespace caffe {
template &typenameDtype&
void ContrastiveLossLayer&Dtype&::Forward_gpu(
const vector&Blob&Dtype&*&& bottom, const vector&Blob&Dtype&*&& top) {
const int count = bottom[0]-&count();
caffe_gpu_sub(
bottom[0]-&gpu_data(),
bottom[1]-&gpu_data(),
diff_.mutable_gpu_data());
// a_i-b_i
caffe_gpu_powx(
diff_.mutable_gpu_data(),
// a_i-b_i
diff_sq_.mutable_gpu_data());
// (a_i-b_i)^2
caffe_gpu_gemv(
CblasNoTrans,
bottom[0]-&num(),
bottom[0]-&channels(),
Dtype(1.0),
diff_sq_.gpu_data(),
// (a_i-b_i)^2
summer_vec_.gpu_data(),
Dtype(0.0),
dist_sq_.mutable_gpu_data());
// \Sum (a_i-b_i)^2
Dtypemargin = this-&layer_param_.contrastive_loss_param().margin();
bool legacy_version =
this-&layer_param_.contrastive_loss_param().legacy_version();
Dtypeloss(0.0);
for (int i = 0; i & bottom[0]-&num(); ++i) {
// added by miao
is_same_.mutable_cpu_data()[i] = (bottom[2]-&cpu_data()[2 * i] == bottom[2]-&cpu_data()[2 * i + 1])? 1:0;
if (is_same_.cpu_data()[i] == 1) {
// similar pairs
loss += dist_sq_.cpu_data()[i];
// dissimilar pairs
if (legacy_version) {
loss += std::max(margin - dist_sq_.cpu_data()[i], Dtype(0.0));
Dtypedist = std::max(margin - sqrt(dist_sq_.cpu_data()[i]),
Dtype(0.0));
loss += dist*
loss = loss / static_cast&Dtype&(bottom[0]-&num()) / Dtype(2);
top[0]-&mutable_cpu_data()[0] =
template &typenameDtype&
__global__void CLLBackward(const int count, const int channels,
const Dtypemargin, const bool legacy_version, const Dtypealpha,
const Dtype* y, const Dtype* diff, const Dtype* dist_sq,
Dtype *bottom_diff) {
CUDA_KERNEL_LOOP(i, count) {
int n = i /
// the num index, to access y and dist_sq
if (static_cast&int&(y[n])) {
// similar pairs
bottom_diff[i] = alpha * diff[i];
// dissimilar pairs
Dtypemdist(0.0);
Dtypebeta(0.0);
if (legacy_version) {
mdist = (margin - dist_sq[n]);
Dtypedist = sqrt(dist_sq[n]);
mdist = (margin - dist);
beta = -alpha * mdist / (dist + Dtype(1e-4)) * diff[i];
if (mdist & 0.0) {
bottom_diff[i] =
bottom_diff[i] = 0;
template &typenameDtype&
void ContrastiveLossLayer&Dtype&::Backward_gpu(const vector&Blob&Dtype&*&& top,
const vector&bool&& propagate_down, const vector&Blob&Dtype&*&& bottom) {
for (int i = 0; i & 2; ++i) {
if (propagate_down[i]) {
const int count = bottom[0]-&count();
const int channels = bottom[0]-&channels();
Dtypemargin = this-&layer_param_.contrastive_loss_param().margin();
const bool legacy_version =
this-&layer_param_.contrastive_loss_param().legacy_version();
const Dtypesign = (i == 0) ? 1 : -1;
const Dtypealpha = sign * top[0]-&cpu_diff()[0] /
static_cast&Dtype&(bottom[0]-&num());
// NOLINT_NEXT_LINE(whitespace/operators)
CLLBackward&Dtype&&&&CAFFE_GET_BLOCKS(count), CAFFE_CUDA_NUM_THREADS&&&(
count, channels, margin, legacy_version, alpha,
is_same_.gpu_data(),
// pair similarity 0 or 1
added by miao
diff_.gpu_data(),
// the cached eltwise difference between a and b
dist_sq_.gpu_data(),
// the cached square distance between a and b
bottom[i]-&mutable_gpu_diff());
CUDA_POST_KERNEL_CHECK;
INSTANTIATE_LAYER_GPU_FUNCS(ContrastiveLossLayer);
// namespace caffe
需要注意的时候,前馈和后馈都需要做一点代码上的修改,虽说十分的简单,但也要小心。
至此,基于Caffe的DeepID2的修改全部完成。
最后再给出一个基于AlexNet得到的一个train.prototxt。(具体能不能训练,小喵不能保证,这里只是示意一下各个层如何使用)其中fc7是特征层,fc8是分类的结果。这里一共使用了两个loss。
name: "AlexNet"
name: "data"
type: "Python"
top: "data"
top: "label"
phase: TRAIN
python_param {
module: "id2_data_layer"
layer: "ld2_data_layer"
param_str: "{'crop_size' : 128, 'batch_size' : 96, 'mean_file': '/path/to/mean_file', 'scale': 0.0078125, 'source': '/path/to/train_list', 'image_root_dir': '/path/to/image_root_dir'}"
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 96
kernel_size: 11
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu1"
type: "ReLU"
bottom: "conv1"
top: "conv1"
name: "norm1"
type: "LRN"
bottom: "conv1"
top: "norm1"
lrn_param {
local_size: 5
alpha: 0.0001
beta: 0.75
name: "pool1"
type: "Pooling"
bottom: "norm1"
top: "pool1"
pooling_param {
kernel_size: 3
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 256
kernel_size: 5
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
value: 0.1
name: "relu2"
type: "ReLU"
bottom: "conv2"
top: "conv2"
name: "norm2"
type: "LRN"
bottom: "conv2"
top: "norm2"
lrn_param {
local_size: 5
alpha: 0.0001
beta: 0.75
name: "pool2"
type: "Pooling"
bottom: "norm2"
top: "pool2"
pooling_param {
kernel_size: 3
name: "conv3"
type: "Convolution"
bottom: "pool2"
top: "conv3"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 384
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "relu3"
type: "ReLU"
bottom: "conv3"
top: "conv3"
name: "conv4"
type: "Convolution"
bottom: "conv3"
top: "conv4"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
convolution_param {
num_output: 384
kernel_size: 3
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
value: 0.1
name: "relu4"
type: "ReLU"
bottom: "conv4"
top: "conv4"
name: "conv5"
type: "Convolution"
bottom: "conv4"
top: "conv5"
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"
value: 0.1
name: "relu5"
type: "ReLU"
bottom: "conv5"
top: "conv5"
name: "pool5"
type: "Pooling"
bottom: "conv5"
top: "pool5"
pooling_param {
kernel_size: 3
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"
value: 0.1
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"
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"
value: 0.1
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
name: "drop7"
type: "Dropout"
bottom: "fc7"
top: "fc7"
dropout_param {
dropout_ratio: 0.5
name: "fc8"
type: "InnerProduct"
bottom: "fc7"
top: "fc8"
lr_mult: 1
decay_mult: 1
lr_mult: 2
decay_mult: 0
inner_product_param {
num_output: 10000
weight_filler {
type: "gaussian"
bias_filler {
type: "constant"
name: "loss"
type: "SoftmaxWithLoss"
bottom: "fc8"
bottom: "label"
top: "loss"
name: "norm_fea"
type: "Normalization"
bottom: "fc7"
top: "norm_fea"
name: "fea_slice"
type: "Id2Slice"
bottom: "norm_fea"
top: "feature1"
top: "feature2"
name: "id2_loss"
bottom: "feature1"
bottom: "feature2"
bottom: "label"
top: "id2_loss"
type: "ContrastiveLoss"
contrastive_loss_param {
margin: 1.0
最后,十分感谢小喵的师弟,胖喵的审查,每一篇博客都由胖喵第一手的阅读并提出意见。
转载请注明出处~
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
前言layer.hppcommon_layers.hpp
data_layers.hpp
loss_layers.hpp
neuron_layers.hpp
vision_layers.hpp
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/device_alternate.hpp"
#define STUB_GPU(classname)
#define STUB_GPU_FORWARD(classname, funcname)
#define STUB_GPU_BACKWARD(classname, funcname)
LayerParameter layer_param_;
// 这个是protobuf文件中存储的layer参数
vector&share_ptr&Blob&Dtype&&& blobs_;
// 这个存储的是layer的参数,在程序中用的
vector&bool& param_propagate_down_;
// 这个bool表示是否计算各个blob参数的diff,即传播误差
virtual void SetUp(const vector&Blob&Dtype&*&& bottom, vector&Blob&Dtype&*&* top)
inline Dtype Forward(const vector&Blob&Dtype&*&& bottom, vector&Blob&Dtype&*&* top);
inline void Backward(const vector&Blob&Dtype&*&& top, const vector&bool&& propagate_down, const &Blob&Dtype&*&* bottom);
data_layers.hpp#include "boost/scoped_ptr.hpp"
#include "hdf5.h"
#include "leveldb/db.h"
#include "lmdb.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/filler.hpp"
#include "caffe/internal_thread.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"
// A function to get a specific filler from the specification given in
// FillerParameter. Ideally this would be replaced by a factory pattern,
// but we will leave it this way for now.
template &typename Dtype&
Filler&Dtype&* GetFiller(const FillerParameter& param) {
const std::string& type = param.type();
if (type == "constant") {
return new ConstantFiller&Dtype&(param);
} else if (type == "gaussian") {
return new GaussianFiller&Dtype&(param);
} else if (type == "positive_unitball") {
return new PositiveUnitballFiller&Dtype&(param);
} else if (type == "uniform") {
return new UniformFiller&Dtype&(param);
} else if (type == "xavier") {
return new XavierFiller&Dtype&(param);
CHECK(false) && "Unknown filler name: " && param.type();
return (Filler&Dtype&*)(NULL);
neuron_layers.hppcommon_layers.hpploss_layers.hppvision_layers.hpp后语
阅读(11791)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'caffe源码简单解析——Layer层',
blogAbstract:'原文来自:/index.php/archives/68/ & Posted by 影风LEY on December 3, 2014ps.图总结的很好,i like~—————————————以下为原文———————————————前言
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}

我要回帖

更多关于 fcn caffe 的文章

 

随机推荐