net_->ForwardBackward()的大致梳理
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()的大致梳理的更多相关文章
- 带你梳理Jetty自定义ProxyServlet实现反向代理服务
摘要:最近要做一个将K8s中的某组件UI通过反向代理映射到自定义规则的链接地址上,提供给用户访问的需求.所以顺便研究了一下Jetty的ProxyServlet. 本文分享自华为云社区<Jetty ...
- Linux内核笔记--网络子系统初探
内核版本:linux-2.6.11 本文对Linux网络子系统的收发包的流程进行一个大致梳理,以流水账的形式记录从应用层write一个socket开始到这些数据被应用层read出来的这个过程中linu ...
- 【Bugly技术干货】那些年我们用过的显示性能指标
Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 前言: 注:Google 在自己文 ...
- Android消息机制:Looper,MessageQueue,Message与handler
Android消息机制好多人都讲过,但是自己去翻源码的时候才能明白. 今天试着讲一下,因为目标是讲清楚整体逻辑,所以不追究细节. Message是消息机制的核心,所以从Message讲起. 1.Mes ...
- tair源码分析——leveldb存储引擎使用
分析完leveldb以后,接下来的时间准备队tair的源码进行阅读和分析.我们刚刚分析完了leveldb而在tair中leveldb是其几大存储引擎之一,所以我们这里首先从tair对leveldb的使 ...
- 关闭对话框,OnClose和OnCancel
我们知道,在对话框中,屏蔽ESC键自己主动退出能够选择重载OnCancel为哑函数的方法: void CXXXXDlg::OnCancel() { // TODO: Add ...
- ssm+jsp+自定义标签实现分页,可以通用(前端实现)
近期做了一些分页方面的开发,大致梳理一下 1 jsp页面上关于分页的代码 <tr> <td colspan="9"> <ule1:pagination ...
- netty高级篇(3)-HTTP协议开发
一.HTTP协议简介 应用层协议http,发展至今已经是http2.0了,拥有以下特点: (1) CS模式的协议 (2) 简单 - 只需要服务URL,携带必要的请求参数或者消息体 (3) 灵活 - 任 ...
- 疑问:Spring中构造器、init-method、@PostConstruct、afterPropertiesSet孰先孰后,自动注入发生时间
问题:今天想写一个通用点的方法,根据传入的参数的类型(clazz对象),判断使用哪个mapper来插入mysql数据库. 下面是我的写法: public interface BizNeeqCommon ...
随机推荐
- Pie(二分)
http://poj.org/problem?id=3122 题意:将n个圆柱体的不同口味的pie分给m个人,要求每个人分得的pie必须体积相同,且来自于一块pie(即:只分得一种口味的pie),求最 ...
- Python 41 完整查询语句 和 一堆关键字
一:完整查询语句 1.拷贝表 *** create table copy_table select *from customer ; 拷贝结构 与数据 create table copy_table ...
- C指针基础知识
指针的声明 C语言声明格式:"类型 变量名;" 基本类型:int hoge; 指针类型:int *pointer; 区别在于: 声明 含义 int hoge; 声明整数类型的变量 ...
- 网易UI自动化测试工具Airtest中导入air文件中的方法
最近看了一下网易的Airtest ,UI测试工具,写了一些后在导入其他air文件中的.py文件,卡了一下,现在博客中纪录一下导入其他air文件的方式: 在Airtest 测试工具中,导入其他air文件 ...
- 一、SQL系列之~使用SQL语言导出数据及实现定时导出数据任务
一般情况下,SQL数据库中带有导入与导出数据的直接按键操作,点击数据表所在的数据库--任务--导出/导入数据,根据导入/导出向导直接将数据导出即可. 但导出的数据格式多为Excel格式,如果需要导出的 ...
- 机器学习——Day 1 数据预处理
写在开头 由于某些原因开始了机器学习,为了更好的理解和深入的思考(记录)所以开始写博客. 学习教程来源于github的Avik-Jain的100-Days-Of-MLCode 英文版:https:// ...
- cookie/session在nodes中的实战
cookie 和 session 众所周知,HTTP 是一个无状态协议,所以客户端每次发出请求时,下一次请求无法得知上一次请求所包含的状态数据,如何能把一个用户的状态数据关联起来呢? 比如在淘宝的某个 ...
- reduce多种方法计算数组中某个值的出现次数
先来了解下reduce用法 arr.reduce(callback[, initialValue]) callback执行数组中每个值的函数,包含四个参数: accumulator 累计器累计回调的返 ...
- .htaccess的基本用法与介绍
●自定义错误页 .htaccess的一个应用是自定义错误页面,这将使你可以拥有自己的.个性化的错误页面(例如找不到文件时),而不是你的服务商提供的错误页或没有任何页面.这会让你的网站在出错的时候看上去 ...
- Python之global
1 Global The global statement and its nonlocal cousin are the only things that are remotely like dec ...