net_->ForwardBackward()方法在net.hpp文件中

Dtype ForwardBackward() {
Dtype loss;
Forward(&loss);
Backward();
return loss;
}

首先进入Forward(&loss)

net.cpp

template <typename Dtype>
const vector<Blob<Dtype>*>& Net<Dtype>::Forward(Dtype* loss) {
if (loss != NULL) {
*loss = ForwardFromTo(, layers_.size() - );
} else {
ForwardFromTo(, layers_.size() - );
}
return net_output_blobs_;
}

接着进入*loss = ForwardFromTo(0, layers_.size() - 1)这句话

net.cpp

template <typename Dtype>
Dtype Net<Dtype>::ForwardFromTo(int start, int end) {
CHECK_GE(start, );
CHECK_LT(end, layers_.size());
Dtype loss = ;
for (int i = start; i <= end; ++i) {
for (int c = ; c < before_forward_.size(); ++c) {
before_forward_[c]->run(i);
}
// 一层一层地前向传播,bottom_vecs_[i]是各层的输入输入数据指针,top_vecs_[i]是各层的输出数据指针
Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], top_vecs_[i]);
loss += layer_loss;
if (debug_info_) { ForwardDebugInfo(i); }
for (int c = ; c < after_forward_.size(); ++c) {
after_forward_[c]->run(i);
}
}
return loss;
}

再进入Dtype layer_loss = layers_[i]->Forward(bottom_vecs_[i], top_vecs_[i])。首先会进入Layer类的Forward函数

layer.hpp

// Forward and backward wrappers. You should implement the cpu and
// gpu specific implementations instead, and should not change these
// functions.
template <typename Dtype>
inline Dtype Layer<Dtype>::Forward(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
Dtype loss = ;
Reshape(bottom, top);
switch (Caffe::mode()) {
case Caffe::CPU:
// Layer类的虚函数,具体由其不同的派生类作不同的实现,也就是此句将会调用不同网络层的Forward_cpu函数,下面的Forward_gpu同理。
Forward_cpu(bottom, top);
for (int top_id = ; top_id < top.size(); ++top_id) {
if (!this->loss(top_id)) { continue; }
const int count = top[top_id]->count();
const Dtype* data = top[top_id]->cpu_data();
const Dtype* loss_weights = top[top_id]->cpu_diff();
loss += caffe_cpu_dot(count, data, loss_weights);
}
break;
case Caffe::GPU:
Forward_gpu(bottom, top);
#ifndef CPU_ONLY
for (int top_id = ; top_id < top.size(); ++top_id) {
if (!this->loss(top_id)) { continue; }
const int count = top[top_id]->count();
const Dtype* data = top[top_id]->gpu_data();
const Dtype* loss_weights = top[top_id]->gpu_diff();
Dtype blob_loss = ;
caffe_gpu_dot(count, data, loss_weights, &blob_loss);
loss += blob_loss;
}
#endif
break;
default:
LOG(FATAL) << "Unknown caffe mode.";
}
return loss;
} template <typename Dtype>
inline void Layer<Dtype>::Backward(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) {
switch (Caffe::mode()) {
case Caffe::CPU:
Backward_cpu(top, propagate_down, bottom);
break;
case Caffe::GPU:
Backward_gpu(top, propagate_down, bottom);
break;
default:
LOG(FATAL) << "Unknown caffe mode.";
}
}

接下来再看ForwardBackward()中的Backward()

net.cpp

template <typename Dtype>
void Net<Dtype>::Backward() {
// 从最后一层开始反向传播
BackwardFromTo(layers_.size() - , );
if (debug_info_) {
Dtype asum_data = , asum_diff = , sumsq_data = , sumsq_diff = ;
for (int i = ; i < learnable_params_.size(); ++i) {
asum_data += learnable_params_[i]->asum_data();
asum_diff += learnable_params_[i]->asum_diff();
sumsq_data += learnable_params_[i]->sumsq_data();
sumsq_diff += learnable_params_[i]->sumsq_diff();
}
const Dtype l2norm_data = std::sqrt(sumsq_data);
const Dtype l2norm_diff = std::sqrt(sumsq_diff);
LOG(ERROR) << " [Backward] All net params (data, diff): "
<< "L1 norm = (" << asum_data << ", " << asum_diff << "); "
<< "L2 norm = (" << l2norm_data << ", " << l2norm_diff << ")";
}
}

进入BackwardFromTo(layers_.size() - 1, 0)

net.cpp

template <typename Dtype>
void Net<Dtype>::BackwardFromTo(int start, int end) {
CHECK_GE(end, );
CHECK_LT(start, layers_.size());
for (int i = start; i >= end; --i) {
for (int c = ; c < before_backward_.size(); ++c) {
before_backward_[c]->run(i);
}
if (layer_need_backward_[i]) {
// 反向传播过程中,top_vecs_[i]是各层的输入数据指针,bottom_vecs[i]是各层的输出数据指针,与前向传播正好相反
layers_[i]->Backward(
top_vecs_[i], bottom_need_backward_[i], bottom_vecs_[i]);
if (debug_info_) { BackwardDebugInfo(i); }
}
for (int c = ; c < after_backward_.size(); ++c) {
after_backward_[c]->run(i);
}
}
}

进入layers_[i]->Backward(top_vecs_[i], bottom_need_backward_[i], bottom_vecs_[i])

layer.hpp

template <typename Dtype>
inline void Layer<Dtype>::Backward(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,
const vector<Blob<Dtype>*>& bottom) {
switch (Caffe::mode()) {
case Caffe::CPU:
// 与前向传播类似,利用不同派生类的同名函数作出不同层的反向传播的具体实现
Backward_cpu(top, propagate_down, bottom);
break;
case Caffe::GPU:
Backward_gpu(top, propagate_down, bottom);
break;
default:
LOG(FATAL) << "Unknown caffe mode.";
}
}

不同层的前向、反向传播的具体实现见下一章节。

net_->ForwardBackward()的大致梳理的更多相关文章

  1. 带你梳理Jetty自定义ProxyServlet实现反向代理服务

    摘要:最近要做一个将K8s中的某组件UI通过反向代理映射到自定义规则的链接地址上,提供给用户访问的需求.所以顺便研究了一下Jetty的ProxyServlet. 本文分享自华为云社区<Jetty ...

  2. Linux内核笔记--网络子系统初探

    内核版本:linux-2.6.11 本文对Linux网络子系统的收发包的流程进行一个大致梳理,以流水账的形式记录从应用层write一个socket开始到这些数据被应用层read出来的这个过程中linu ...

  3. 【Bugly技术干货】那些年我们用过的显示性能指标

    Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 前言: 注:Google 在自己文 ...

  4. Android消息机制:Looper,MessageQueue,Message与handler

    Android消息机制好多人都讲过,但是自己去翻源码的时候才能明白. 今天试着讲一下,因为目标是讲清楚整体逻辑,所以不追究细节. Message是消息机制的核心,所以从Message讲起. 1.Mes ...

  5. tair源码分析——leveldb存储引擎使用

    分析完leveldb以后,接下来的时间准备队tair的源码进行阅读和分析.我们刚刚分析完了leveldb而在tair中leveldb是其几大存储引擎之一,所以我们这里首先从tair对leveldb的使 ...

  6. 关闭对话框,OnClose和OnCancel

    我们知道,在对话框中,屏蔽ESC键自己主动退出能够选择重载OnCancel为哑函数的方法: void CXXXXDlg::OnCancel()      {         // TODO: Add ...

  7. ssm+jsp+自定义标签实现分页,可以通用(前端实现)

    近期做了一些分页方面的开发,大致梳理一下 1 jsp页面上关于分页的代码 <tr> <td colspan="9"> <ule1:pagination ...

  8. netty高级篇(3)-HTTP协议开发

    一.HTTP协议简介 应用层协议http,发展至今已经是http2.0了,拥有以下特点: (1) CS模式的协议 (2) 简单 - 只需要服务URL,携带必要的请求参数或者消息体 (3) 灵活 - 任 ...

  9. 疑问:Spring中构造器、init-method、@PostConstruct、afterPropertiesSet孰先孰后,自动注入发生时间

    问题:今天想写一个通用点的方法,根据传入的参数的类型(clazz对象),判断使用哪个mapper来插入mysql数据库. 下面是我的写法: public interface BizNeeqCommon ...

随机推荐

  1. Django day05 虚拟环境 django 2.0和django 1.0 路由层区别

    一:虚拟环境 创建虚拟环境一般有三种方式: 1)   File--->New Project--> 出现如下图,点击Project Interpreter:New Virtualenv e ...

  2. git clone 出现错误

    看了好多资料终于搞定了git 中clone命令报错这个问题,废话不多说直接上步骤希望对大家有帮助. 1   删除.ssh文件夹(直接搜索该文件夹)下的known_hosts(手动删除即可,不需要git ...

  3. HDU3085 Nightmare Ⅱ

    题目: Last night, little erriyue had a horrible nightmare. He dreamed that he and his girl friend were ...

  4. 【Python小试牛刀】循环

    1.斐波那契数列 斐波那契数列,数列前两项为1,之后每一项都是前两项之和. #!/usr/bin/env python3 a, b = 0, 1 while b < 100: print(b) ...

  5. React新的安装less的方法

    yarn add less less-loader -D yarn eject 在webpack.config.js文件中 const sassRegex = /\.(scss|sass)$/; co ...

  6. ThinkPHP3.2.3扩展之自动分词获取关键字

    ThinkPHP自动获取关键词调用在线discuz词库 先按照下图路径放好插件 /** * 自动获取关键词(调用第三方插件) * @return [type] [description] * www. ...

  7. 3.朴素贝叶斯和KNN算法的推导和python实现

    前面一个博客我们用Scikit-Learn实现了中文文本分类的全过程,这篇博客,着重分析项目最核心的部分分类算法:朴素贝叶斯算法以及KNN算法的基本原理和简单python实现. 3.1 贝叶斯公式的推 ...

  8. Zeppelin0.6.2+sparkR2.0.2环境搭建

    0.序 先吐槽一下网上旧版本的Zeppelin和R的安装,让我折腾了几个小时. 不过最终还是调通了也不容易,其实我现在一点R都没有学呢,只是刚看了一节课,但是这个工具既然出现在了Spark中,我想它还 ...

  9. Codeforces 609D 被二分教做人

    传送门:http://codeforces.com/problemset/problem/609/D (如需转载,请注明出处,谢谢O(∩_∩)O) 题意: Nura想买k个小玩意,她手上有 s 个bu ...

  10. 时间框的属性编辑(WdatePicker日期插件)

    效果图如下:可以设置输入的时间不大于,或不小于某日. //引用js包 <script type="text/javascript" src="${basePath} ...