paddlepaddle实现resNet用于classification

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
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值