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()))

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

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

相关文章推荐

caffe如何自定义网络以及自定义层(python)(四)

刚刚看了一下官方的demo还有两三个,一起学习一下python的使用吧。经过前面的学习,后面就比较简单了。 官网这个代码看似简单了点,但是里面其实已经将自己写好的东西采用python调用了。 进入到p...

[Caffe]:关于Check failed: registry.count(type) == 0 (1 vs. 0)错误

错误描述当我在终端下用caffe命令对带有PythonLayer的网络训练时,出现了如下错误。 该错误提示Layer的卷积类型已经注册过了。为什么会出现这个错误呢? 其实是,博主机子上有多个C...
  • cham3
  • cham3
  • 2017年05月22日 10:09
  • 434

Python2入门教程 超详细1小时学会Python

原文地址转:Python2入门教程 超详细1小时学会Python  本文适合有经验的程序员尽快进入Python世界.特别地,如果你掌握Java和Javascript,不用1小时你就可以用Python...

SAS入门教程2---建立SAS数据集

第二章 建立SAS数据集   前面我们介绍了关于SAS系统的一些基本概念以及基本的操作过程。我们知道SAS是以数据为中心的一个应用软件系统,一般来说,一个SAS的程序的运行,离不开SAS的数据集,...

JAVA爬虫WebCollector 2.x入门教程——基本概念

WebCollector是一个无须配置、便于二次开发的JAVA爬虫框架(内核),它提供精简的的API,只需少量代码即可实现一个功能强大的爬虫。WebCollector-Hadoop是WebCollec...
  • AJAXHu
  • AJAXHu
  • 2016年02月16日 12:58
  • 4046

Angular2 入门教程

一、 入门1、初识Angular2写一个Angular2的Hello World应用相当简单,分三步走: 引入Angular2预定义类型 import {Component,View,bootstra...

Weex入门教程之2,Android Studio安装Weex插件

配置:

剑网三插件入门教程(2):在游戏中调试Lua代码

本篇教程主要介绍了在游戏中运行和调试Lua代码的方法 先说一下关于Lua语法的学习 剑三的插件是用LUA脚本语言编写的,所以想要会写插件,必须要学会Lua。写插件并不需要用到Lua的高级技巧,...
  • wdykanq
  • wdykanq
  • 2013年09月23日 01:25
  • 3783

生产环境的开源容器管理平台--Rancher入门教程(2): Host

Rancher是一个用于部署和管理生产环境的容器的开源平台,它与Kubernetes/Mesos/Docker Swarm进行集成 使得在任何硬件环境上容器化应用变得触手可及.在这个系列的教程中...

OpenCV入门教程(2)-Mat类之像素的读写

主要借鉴书籍《OpenCV入门教程》一书,还有一些网上的博客等。
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Caffe2 入门教程
举报原因:
原因补充:

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