paddlepaddle实现resNet用于classification
- 简介
1)paddlepaddle是百度旗下深度学习开源平台框架,在日趋激烈的竞争环境下,paddlepaddle也占有一席之地,其必有自己的特长之处
2)resNet在2015、2016年学术界、竞赛中名声大噪,凭借着其出色的performance,摘得了一系列国际大赛的桂冠,令人望其项背
3)关于作者:当时就职于MSRA的凯明大神,我国T大的传奇人物(去年被Google挖走了) - resNet简介
1)resNet在2015年首次提出,凭借着resNet unit结构几乎包揽了所有国际大赛的桂冠,不得不说真的是一种很棒的网络结构,《Deep Residual Learning for Image Recognition》paper地址
2)resNet在2016年中进行了改进,主要论述Identity Mappings方式带来的卓越成效(相对constant scaling、exclusive gating、shortcut-only gating、conv shortcut、dropout shortcut等方式),《Identity Mappings in Deep Residual Networks》paper地址
3)上述两篇文章,很值得仔细阅读,毕竟经典 - paddlepaddle起源:现在深度学习框架市面上较多,Google的tensorflow,Facebook的caffe2和pytorch等等,但是这些都是国外的啊。。。于是我国百度一哥李厂长不甘示弱,开源了paddlepaddle深度学习开源框架,只是现在还不大流行,但谁知道10年之后具体是什么情况呢?
- 下面直接上代码:
注:此处我们使用cifar-10数据集,(50000[训练]+10000[测试]=60000张32*32*3的图像,共10个类别)
# 2.1)首先导入paddle和logging(用于保存日志信息)
from __future__ import print_function
import paddle.v2 as paddle
import sys
import logging # 用于保存日志文件
说明:
估计大家对此图已经审美疲劳了,但是这张图片展示了《Deep Residual Learning for Image Recognition》和《Identity Mappings in Deep Residual Networks》的主要区别以及两者之间微小的改动带来的train上的loss和test上的error之间performance之间的差别
下面我们来实现proposed(b)右侧的resNet unit:
# BN层+Activation function(ReLU)+Conv层 模块
def bn_conv_layer(input_x, ch_out, filter_size, stride, padding, ch_in=None):
tmp = paddle.layer.batch_norm(input=input_x, act=paddle.activation.Relu())
return paddle.layer.img_conv(input=tmp, filter_size=filter_size, num_channels=ch_in, num_filters=ch_out,
stride=stride, padding=padding, act=paddle.activation.Linear(), bias_attr=False)
说明:
论文中指出,当采用Identity Mapping时,网络可获得较好的performance,这时会出现当feature map个数在恒等映射前后个数不同时,应如何处理?此时我们不妨采用NIN中的思想,就是1*1的kernel进行扩展,也就是short-cut:
# Identity Mapping结构的实现,当feature map不匹配时,使用NIN中1*1的kernel进行feature map个数的扩展
def shortcut(input_x, ch_in, ch_out, stride=1):
if ch_in != ch_out:
return bn_conv_layer(input_x, ch_out, 1, stride, 0)
else:
return input_x
有了上面的resNet unit功能的实现和Identity Mapping的实现,于是我们将两部分进行组合:
# 一个resNet unit的基本结构,由2个(BN+ReLU+Conv)和1个(Identity Mapping)组成
def basicblock_changeC(ipt, ch_in, ch_out, stride):
tmp = bn_conv_layer(ipt, ch_out, 3, stride, 1)
tmp = bn_conv_layer(tmp, ch_out, 3, 1, 1)
short = shortcut(ipt, ch_in, ch_out, stride)
return paddle.layer.addto(input=[tmp, short], act=paddle.activation.Linear())
接下来我们对其进行堆叠
# 设置参数,获取不同的层数的网络
def layer_warp(block_func, ipt, ch_in, ch_out, count, stride):
tmp = block_func(ipt, ch_in, ch_out, stride)
for i in range(1, count):
tmp = block_func(tmp, ch_out, ch_out, 1)
return tmp
搭建resNet:
#
def resNet_(input_x, layer_num=[3, 4, 6, 3]):
conv_1 = bn_conv_layer(input_x, ch_in=3, ch_out=16, filter_size=3, stride=1, padding=1)
basic_1 = layer_warp(basicblock_changeC, conv_1, 16, 16, layer_num[0], 1)
basic_2 = layer_warp(basicblock_changeC, basic_1, 16, 32, layer_num[1], 2)
basic_3 = layer_warp(basicblock_changeC, basic_2, 32, 64, layer_num[2], 2)
basic_4 = layer_warp(basicblock_changeC, basic_3, 64, 128, layer_num[2], 2)
predict = paddle.layer.img_pool(input=basic_4, pool_size=4, stride=1, pool_type=paddle.pooling.Avg())
predict_ = paddle.layer.fc(input=predict, size=num_class, act=paddle.activation.Softmax())
return predict_
设置输入、输出、预测值和优化目标:
input_image = paddle.layer.data(name="image", type=paddle.data_type.dense_vector(data_dim))
images, label = input_image, paddle.layer.data(name="label", type=paddle.data_type.integer_value(num_class))
predict = resNet_(images)
cost = paddle.layer.classification_cost(input=predict, label=label)
parameters = paddle.parameters.create(cost)
优化方法和参数
# 使用SGD更新参数
optimizer = paddle.optimizer.Momentum(momentum=0.9, regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),
learning_rate=0.1 / 128.0, learning_rate_decay_a=0.1,
learning_rate_decay_b=50000 * 100, learning_rate_schedule='discexp')
trainer = paddle.trainer.SGD(cost=cost, parameters=parameters, update_equation=optimizer)
设置buffer size和batch size:
reader = paddle.batch(paddle.reader.shuffle(paddle.dataset.cifar.train10(), buf_size=100), batch_size=16)
feeding = {'image': 0, 'label': 1}
设置eventhander并进行训练
def event_handler(event):
if isinstance(event, paddle.event.EndIteration):
if event.batch_id % 10 == 0:
logger.info('pass_id:' + str(event.pass_id) + ',batch_id:' + str(event.batch_id) + ',train_cost:' + str(
event.cost) + ',s:' + str(event.metrics))
if isinstance(event, paddle.event.EndPass):
with open('params_pass_%d.tar' % event.pass_id, 'w') as f:
trainer.save_parameter_to_tar(f)
result = trainer.test(
reader=paddle.batch(
paddle.dataset.cifar.test10(), batch_size=64),
feeding=feeding)
logger.info('pass_id:' + str(event.pass_id) + ',s:' + str(result.metrics))
trainer.train(reader=reader, num_passes=20, event_handler=event_handler, feeding=feeding)
最后,logging的移交句柄
logger.removeHandler(file_handler)
logger.removeHandler(console_handler)
1万+





