Caffe2 入门教程

原创 2017年09月11日 22:53:46

Caffe2 概念


Caffe2已经发布几个月了,但目前的使用率并不高,相关文档并不完善,与Caffe(1)相比入门较难。本文主要讲解Caffe2的一些概念,由于本人也是新手,仅做参考,欢迎交流。

Tutorials: Intro Tutorial

Blobs and Workspace, Tensors


和Caffe1一样,Caffe2也有Blobs,并也代表着内存中的数据块。大多数的blobs中都含有tensor,就像Tensorflow一样,可以简单视为一种多维数组,具体在python中被视为numpy arrays。

除了tensor还有workspace这一全新概念。下面举个例子,演示一下如何把blobs 添加到 workspace,并取出。Workspace会在你开始使用时初始化。

from caffe2.python import workspace, model_helper
import numpy as np
# 创建三维随机张量
x = np.random.rand(4, 3, 2)
print(x)
print(x.shape)

# 将创建的tensor输入到Workspace中,命名为"my_x"
workspace.FeedBlob("my_x", x)

# 从Workspace中取出数据
x2 = workspace.FetchBlob("my_x")
print(x2)

对比一下xx2,发现是一样的。

网络与操作符


Caffe2的基本对象是网络(net)。Net 是一种操作符(operators)的图,并每个操作符取输入blobs数据并输出一或多个blobs。
下面的程序块会创建一个简单的模型,包含这些组成:

  • 一个全连接层
    • Sigmoid activation with a Softmax
    • a CrossEntropy loss

直接组合网络是否乏味,因而最好使用一些有助于创建网络的模型助手。python中使用ModelHelper来帮助我们建立”my first net”网络。ModelHelper将创建两个相互关联的网络:

  1. 一个初始化参数 (ref. init_net)
  2. 一个运行实际的训练(ref. exec_net)
# 创建随机输入数据
data = np.random.rand(16, 100).astype(np.float32)

# 创建随机标签
label = (np.random.rand(16) * 10).astype(np.int32)

workspace.FeedBlob("data", data)
workspace.FeedBlob("label", label)

我们创建一些随机的输入和输出,并且添加到Workspace中。

# 使用模型助手建立模型
m = model_helper.ModelHelper(name="my first net")

现在使用model_helper创建了我们之前提到的两个网络(init_netexec_net)。 在下面的模型中使用FC操作符添加一个全连接层,但首先我们需要做一些准备工作:创建FC操作符所期望的一些随机数作为权重。 接下来,我们可以添加操作,并使用我们创建的权重和偏差blobs。

weight = m.param_init_net.XavierFill([], 'fc_w', shape=[10, 100])
bias = m.param_init_net.ConstantFill([], 'fc_b', shape=[10, ])

在Caffe2中,FC操作符的输入为:数据、权重、偏置。权重和偏置分别使用XavierFillConstantFill初始化,输入为空数组、名称、形状。

fc_1 = m.net.FC(["data", "fc_w", "fc_b"], "fc1")
pred = m.net.Sigmoid(fc_1, "pred")
[softmax, loss] = m.net.SoftmaxWithLoss([pred, "label"], ["softmax", "loss"])

首先创建了内存中的数据和标签的blob(但没有加载数据)。数据和标签第一个维度为16,是一个mini-batch。 许多Caffe2的操作符可以通过ModelHelper直接访问,并且可以处理一个mini-batch的输入。
其次,我们通过定义一组操作符来创建一个模型:FC,Sigmoid和SoftmaxWithLoss。 注意:在这一点上,运算符没有被执行,你只是创建模型的定义。
Model helper将创建两个网络:m.param_init_net只运行一次。它会初始化所有blob参数,如FC的权重。实际的训练是通过m.net的。 这对你来说是透明的,并且会自动运行。

网络定义储存在protobuf中,可以通过net.Proto()查看:

print(str(m.net.Proto()))

输出为:

name: "my first net"
op {
  input: "data"
  input: "fc_w"
  input: "fc_b"
  output: "fc1"
  name: ""
  type: "FC"
}
op {
  input: "fc1"
  output: "pred"
  name: ""
  type: "Sigmoid"
}
op {
  input: "pred"
  input: "label"
  output: "softmax"
  output: "loss"
  name: ""
  type: "SoftmaxWithLoss"
}
external_input: "data"
external_input: "fc_w"
external_input: "fc_b"
external_input: "label"

你也可以查看参数初始网络:

print(str(m.param_init_net.Proto()))

输出为:

name: "my first net_init"
op {
  output: "fc_w"
  name: ""
  type: "XavierFill"
  arg {
    name: "shape"
    ints: 10
    ints: 100
  }
}
op {
  output: "fc_b"
  name: ""
  type: "ConstantFill"
  arg {
    name: "shape"
    ints: 10
  }
}

可以看到有两个操作符可以为FC操作符的权重和偏置点创建随机初始化。
这是Caffe2 API的主要思想:使用Python方便地编写网络来训练模型,将网络传递给C ++代码作为序列化的原始缓冲区,然后让C ++代码运行网络,可以达到最好的性能。

执行


现在,当我们定义了模型训练运算符时,我们可以开始运行它来训练我们的模型。
首先,我们只运行一次param初始化:

workspace.RunNetOnce(m.param_init_net)

注意,像往常一样,这将实际上将param_init_net的protobuf下载到C ++运行。
然后我们创建实际的训练网络:

workspace.CreateNet(m.net)

我们创建一次,然后我们可以有效地运行它多次:

# 运行 100 x 10 次迭代
for j in range(0, 100):
    data = np.random.rand(16, 100).astype(np.float32)
    label = (np.random.rand(16) * 10).astype(np.int32)

    workspace.FeedBlob("data", data)
    workspace.FeedBlob("label", label)

    workspace.RunNet(m.name, 10)   # 运行10次

注意我们如何引用RunNet()中的网络名称。 由于网络是在workspace内创建的,所以我们不需要再次通过网络定义。
执行后,可以检查存储在输出blob中的结果(包含张量,即numpy数组):

反向传播


这个网只包含正向传播,所以没有学习任何东西。反向传播是通过在正向传播中为每个运算符创建梯度运算符而创建的。

在调用RunNetOnce()之前插入以下内容:

m.AddGradientOperators([loss])

检查protobuf的输出:

print(str(m.net.Proto()))

本文只是简单翻译一下官方教程,涉及内容不多,以后会尝试更多的功能。

版权声明:本文为博主原创文章,转载请标注出处。

贾扬清撰文详解Caffe2:从强大的新能力到入门上手教程

选自 Nvidia Blog 作者:Aaron Markham、贾扬清 机器之心编译 昨天,Facebook 推出了 Caffe2,一个兼具表现力、速度和模块性的开源...
  • chenhaifeng2016
  • chenhaifeng2016
  • 2017年04月20日 14:48
  • 2731

深度学习(六)caffe入门学习

本文主要讲解caffe的整个使用流程,适用于初级入门caffe,通过学习本篇博文,理清项目训练、测试流程。初级教程,高手请绕道。 我们知道,在caffe编译完后,在caffe目录下会生成一个build...
  • hjimce
  • hjimce
  • 2015年10月06日 19:48
  • 38496

caffe2 安装与介绍

一早发现caffe2的较成熟的release版发布了(the first production-ready release),那么深度学习平台在之后一段时间也是会出现其与tensorflow相互竞争的...
  • Yan_Joy
  • Yan_Joy
  • 2017年04月19日 15:31
  • 15245

Caffe 深度学习入门教程 运行caffe自带的两个简单例子

运行caffe自带的两个简单例子 为了程序的简洁,在caffe中是不带练习数据的,因此需要自己去下载。但在caffe根目录下的data文件夹里,作者已经为我们编写好了下载数据的脚本文件,...
  • Songyuan1993
  • Songyuan1993
  • 2017年04月06日 14:39
  • 392

Caffe 深度学习入门教程 运行caffe自带的两个简单例子

运行caffe自带的两个简单例子 为了程序的简洁,在caffe中是不带练习数据的,因此需要自己去下载。但在caffe根目录下的data文件夹里,作者已经为我们编写好了下载数据的脚本文件,我们...
  • cs24k1993
  • cs24k1993
  • 2017年04月10日 09:14
  • 97

Rxjava2入门教程五:Flowable背压支持——几乎可以说是对Flowable最全面而详细的讲解

为避免手机阅读时,代码格式错乱,本教程中大多数代码均以图片形式展示 如需下载源码,请访问 https://github.com/fengchuanfang/Rxjava2Tutorial 文章原创,转...
  • speverriver
  • speverriver
  • 2018年01月11日 17:16
  • 30

Rxjava2入门教程三:Operators操作符

为避免手机阅读时,代码格式错乱,本教程中大多数代码均以图片形式展示 如需下载源码,请访问 https://github.com/fengchuanfang/Rxjava2Tutorial 文章原创,转...
  • speverriver
  • speverriver
  • 2018年01月11日 17:13
  • 19

TensorFlow入门教程(2)占位符、变量、损失函数

TensorFlow入门教程
  • theeternal
  • theeternal
  • 2017年12月10日 12:10
  • 64

最简单的Dagger2入门教程

在上一篇博客中总结了依赖注入的原理与实现方式。 依赖注入的原理 依赖注入就是将调用者需要的另一个对象实例不在调用者内部实现,而是通过一定的方式从外部传入实例,解决了各个类之间的耦合。那么这个外部,到底...
  • lisdye2
  • lisdye2
  • 2016年07月18日 15:38
  • 17116

Android基础入门教程——5.2.2 Fragment实例精讲——底部导航栏的实现(方法2)

# Android基础入门教程——5.2.2 Fragment实例精讲——底部导航栏的实现(方法2) 标签(空格分隔): Android基础入门教程 ## 本节引言: 上一节中我们使用LinearLa...
  • zpj779878443
  • zpj779878443
  • 2015年08月29日 13:27
  • 4957
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Caffe2 入门教程
举报原因:
原因补充:

(最多只允许输入30个字)