Caffe2 玩玩回归(Toy Regression)[5]

前言

这一节将讲述如何使用Caffe2的特征进行简单的线性回归学习。主要分为以下几步:
- 生成随机数据作为模型的输入
- 用这些数据创建网络
- 自动训练模型
- 查看梯度递减的结果和学习过程中网络参数的变化
ipython notebook教程请看这里
译者注:如果图片看不清,可以保存到本地查看。

这是一个快速的例子,展示如何使用前面的基础教程进行快速的尝试用CNN进行回归。我们要解决的问题非常简单,输入是二维的x,输出是一维的y,权重w=[2.0,1.5],偏置b=0.5。所以生成ground truth的等式是y=wx+b

在这个教程中,我们将会使用Caffe2的op生成训练数据。注意,这和你日常训练工作不同:在真实的训练中,训练数据一般从外部源载入,比如Caffe的DB数据库,或者Hive表。我们将会在MNIST的例程中讲到。

这个例程中,每一个Caffe2 的op将会写得非常详细,所以会显得太多繁杂。但是在MNIST例程中,我们将使用CNN模型助手来构建CNN模型。

from caffe2.python import core, cnn, net_drawer, workspace, visualize
import numpy as np
from IPython import display
from matplotlib import pyplot

声明计算图

这里,我们声明两个图:一个用于初始化计算中将会用到的变量参数和常量,另外一个作为主图将会用于跑起梯度下降,也就是训练。(译者注:不明白为啥叫做计算图(computation graphs),其实看代码和前一个教程的一样,就是创建两个net,一个用于初始化参数,一个用于训练。)

首先,初始化网络:网络的名字不重要。我们基本上把初始化代码放在一个net中,这样,我们就可以调用RunNetOnce()函数来执行。我们分离init_net的原因是,这些操作在整个训练的过程中只需要执行一次。

init_net = core.Net("init")
# ground truth 参数.
W_gt = init_net.GivenTensorFill( [], "W_gt", shape=[1, 2], values=[2.0, 1.5])
B_gt = init_net.GivenTensorFill([], "B_gt", shape=[1], values=[0.5])
# Constant value ONE is used in weighted sum when updating parameters.
ONE = init_net.ConstantFill([], "ONE", shape=[1], value=1.)
# ITER是迭代的次数.
ITER = init_net.ConstantFill([], "ITER", shape=[1], value=0, dtype=core.DataType.INT32)

# 随机初始化权重,范围在[-1,1],初始化偏置为0
W = init_net.UniformFill([], "W", shape=[1, 2], min=-1., max=1.)
B = init_net.ConstantFill([], "B", shape=[1], value=0.0)
print('Created init net.')

上面代码创建并初始化了init_net网络。主训练网络如下,我们展示了创建的的每一步。
- 前向传播产生loss
- 通过自动微分进行后向传播
- 使用标准的SGD进行参数更新

train_net = core.Net("train")
# First, 生成随机的样本X和创建ground truth.
X = train_net.GaussianFill([], "X", shape=[64, 2], mean=0.0, std=1.0, run_once=0)
Y_gt = X.FC([W_gt, B_gt], "Y_gt")
# 往ground truth添加高斯噪声
noise = train_net.GaussianFill([], "noise", shape=[64, 1], mean=0.0, std=1.0, run_once=0)
Y_noise = Y_gt.Add(noise, "Y_noise")
#注意到不需要讲梯度信息传播到 Y_noise层,
#所以使用StopGradient 函数告诉偏微分算法不需要做这一步
Y_noise = Y_noise.StopGradient([], "Y_noise")

# 线性回归预测
Y_pred = X.FC([W, B], "Y_pred")

# 使用欧拉损失并对batch进行平均
dist = train_net.SquaredL2Distance([Y_noise, Y_pred], "dist")
loss = dist.AveragedLoss([], ["loss"])

现在让我们看看网络是什么样子的。从下面的图可以看到,主要包含四部分。
- 随机生成X
- 使用W_gt,B_gtFC操作生成grond truth Y_gt
- 使用当前的参数W和B进行预测
- 比较输出和计算损失

graph = net_drawer.GetPydotGraph(train_net.Proto().op, "train", rankdir="LR")
display.Image(graph.create_png(), width=800)

现在,和其他框架相似,Caffe2允许我们自动地生成梯度操作,让我们试一下,并看看计算图有什么变化。

# Get gradients for all the computations above.
gradient_map = train_net.AddGradientOperators([loss])
graph = net_drawer.GetPydotGraph(train_net.Proto().op, "train", rankdir="LR")
display.Image(graph.create_png(), width=800)

一旦我们获得参数的梯度,我们就可以将进行SGD操作:获得当前step的学习率,更参数。在这个例子中,我们没有做任何复杂的操作,只是简单的SGD。

# 迭代数增加1.
train_net.Iter(ITER, ITER)
# 根据迭代数计算学习率.
LR = train_net.LearningRate(ITER, "LR", base_lr=-0.1, policy="step", stepsize=20, gamma=0.9)
# 权重求和
train_net.WeightedSum([W, ONE, gradient_map[W], LR], W)
train_net.WeightedSum([B, ONE, gradient_map[B], LR], B)

graph = net_drawer.GetPydotGraph(train_net.Proto().op, "train", rankdir="LR")
display.Image(graph.create_png(), width=800)

再次展示计算图



既然我们创建了网络,那么跑起来

workspace.RunNetOnce(init_net)
workspace.CreateNet(train_net)

在我们开始训练之前,先来看看参数:

print("Before training, W is: {}".format(workspace.FetchBlob("W")))
print("Before training, B is: {}".format(workspace.FetchBlob("B")))

参数初始化如下

Before training, W is: [[-0.77634162 -0.88467366]]
Before training, B is: [ 0.]

训练:

for i in range(100):
    workspace.RunNet(train_net.Proto().name)

迭代100次后,查看参数:

print("After training, W is: {}".format(workspace.FetchBlob("W")))
print("After training, B is: {}".format(workspace.FetchBlob("B")))

print("Ground truth W is: {}".format(workspace.FetchBlob("W_gt")))
print("Ground truth B is: {}".format(workspace.FetchBlob("B_gt")))

参数如下:

After training, W is: [[ 1.95769441  1.47348857]]
After training, B is: [ 0.45236012]
Ground truth W is: [[ 2.   1.5]]
Ground truth B is: [ 0.5]

看起来相当简单是不是?让我们再近距离看看训练过程中参数的更新过程。为此,我们重新初始化参数,看看每次迭代参数的变化。记住,我们可以在任何时候从workspace中取出我们的blobs。

workspace.RunNetOnce(init_net)
w_history = []
b_history = []
for i in range(50):
    workspace.RunNet(train_net.Proto().name)
    w_history.append(workspace.FetchBlob("W"))
    b_history.append(workspace.FetchBlob("B"))
w_history = np.vstack(w_history)
b_history = np.vstack(b_history)
pyplot.plot(w_history[:, 0], w_history[:, 1], 'r')
pyplot.axis('equal')
pyplot.xlabel('w_0')
pyplot.ylabel('w_1')
pyplot.grid(True)
pyplot.figure()
pyplot.plot(b_history)
pyplot.xlabel('iter')
pyplot.ylabel('b')
pyplot.grid(True)

你可以发现非常典型的批梯度下降表现:由于噪声的影响,训练过程中存在波动。在Ipython notebook中跑多几次这个案例,你将会看到不同的初始化和噪声的影响。
当然,这只是一个玩玩的例子,在MNIST例程中,我们将会看到一个更加真实的CNN训练的例子。

译者注: 转载请注明出处:http://www.jianshu.com/c/cf07b31bb5f2

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容