一个小目标:构建一个classfier超越 lenet5!(model_1)

闲来无事(好像也不闲啊)想从零开始构建一个model在mnist 上超过lenet5而且只训练1000steps,利用这两年看的论文,还是有信心的,毕竟lenet5 是20年前的模型啊!

 

首先看下baseline: 

 

emmmm,还是很高的。

 

先说说想法: 我想搞个 inception 那样的block 为啥呢因为我觉着 1.一个block里花样多一些有利于提取不同尺度下的特征,而且某种角度上看 inception就是resnet的跨层连接的变种。

首先构建block:

 

 

def block1(x,block_name):

    mw1=get_weight_variable([3,3,1,32],block_name+"_mW1weights")

    mw21=get_weight_variable([1,5,1,32],block_name+"_mW2weights1")
    mw22=get_weight_variable([5,1,32,32],block_name+"_mW2weights2")
    mb2=get_bias_variable([32],block_name+"_mb2")
    mwn=get_weight_variable([3,3,33,32],block_name+"_mWnweights")

    module1_out=conv2d(x,mw1)
    module2_out=conv2d(x,mw21)
    module2_out=conv2d(module2_out,mw22)
    module2_out+=mb2
    module3_out=pooling2d(x,[1,5,5,1],[1,1,1,1])
    module_out=module1_out+module2_out
    module_out=tf.concat([module_out,module3_out],3)
    return conv2d(module_out,mwn)

def block2(x,block_name):
    mw1=get_weight_variable([3,3,32,64],block_name+"_mW1weights")

    mw21=get_weight_variable([1,5,32,64],block_name+"_mW2weights1")
    mw22=get_weight_variable([5,1,64,64],block_name+"_mW2weights2")
    mb2=get_bias_variable([64],block_name+"_mb2")
    mwn=get_weight_variable([3,3,96,64],block_name+"_mWnweights")

    module1_out=conv2d(x,mw1,strides=[1,2,2,1])
    module2_out=conv2d(x,mw21)
    module2_out=conv2d(module2_out,mw22,strides=[1,2,2,1])
    module2_out+=mb2
    module3_out=pooling2d(x,[1,5,5,1],[1,2,2,1])
    module_out=module1_out+module2_out
    module_out=tf.concat([module_out,module3_out],3)
    return conv2d(module_out,mwn)

#这里所有的 conv 均 padding SAME

block 1 和block 2 区别在于 1:filter(卷积核)个数 一个32 一个64,block2 卷积和 pooling 均 用了stride 2来缩小 feature map(一下简称 fm)的 W 和H

block结构如下:

为什么 branch1 与branch2 用add? 为了减少参数量....

为什么,branch2 加了bias branch1 没有? 因为我branch1 忘加了...

有了block 就可以搭模型了!

模型结构如下:

x=tf.placeholder(shape=[None,784],dtype=tf.float32)
y=tf.placeholder(shape=[None,10],dtype=tf.float32)
x_image=tf.reshape(x,[-1,28,28,1])
keep=tf.placeholder(tf.float32)
block1_out=block1(x_image,"block1")
block1_out=tf.nn.swish(block1_out,name="block_1_act")
block1_out=tf.nn.dropout(block1_out,keep)

block2_out=block2(block1_out,"block2")
block2_out=pooling2d(block2_out,[1,3,3,1],[1,2,2,1])
block2_out=tf.nn.swish(block2_out,name="block_2_act")
block2_out=tf.nn.dropout(block2_out,keep)

gcw=get_weight_variable([7,7,64,1024],name="globalconv")
block_out=tf.nn.conv2d(block2_out,gcw,padding="VALID",strides=[1,1,1,1])
block_out=tf.reshape(block_out,[-1,1024])

#softmax
softmax_w=get_weight_variable([1024,10],"softmax_w")
softmax_b=get_bias_variable([10],"softmax_b")
y_out=tf.nn.softmax(tf.matmul(block_out,softmax_w)+softmax_b)

 使用交叉熵作为 loss

使用 adam lr=1e-4

模型结构大概长这样:

 

测试集上平均结果在98.5左右

 

改进1. 在输入时增加 规范化层即 (x-mean)/variance,同时再增加一个3*3的conv增大一些 chennels 再进block

在最后一个7*7的conv后增加activation function

规范化层:

#change 1:normalize input
mean,var=tf.nn.moments(x_image,[1,2],keep_dims=True)
x_image=tf.subtract(x_image,mean)
x_image=tf.divide(x_image,var)

最终 acc 98.91左右,已经非常接近了!

改进2:把最后的conv7*7 和FC用 global average pool +conv1*1 替换

#change3 add glob avg pool  -- bad
# block_out=tf.nn.avg_pool(block2_out,[1,7,7,1],[1,1,1,1],padding="VALID")
# gcw=get_weight_variable([1,1,64,10],name="globalconv")
# block_out=tf.nn.conv2d(block_out,gcw,padding="VALID",strides=[1,1,1,1])

很差,acc 只有0.8几,应该是fm chennel太少导致特征不够

所以我改成了:

gcw1=get_weight_variable([7,7,64,1024],name="globalconv1")
block_out=tf.nn.conv2d(block2_out,gcw1,padding="VALID",strides=[1,1,1,1])
#activate function nuibi
block_out=tf.nn.swish(block_out)
gcw2=get_weight_variable([1,1,1024,10],name="globalconv2")
block_out=tf.nn.conv2d(block_out,gcw2,padding="VALID",strides=[1,1,1,1])

conv7*7 加conv1*1 

用 conv 1*1 替换 之前的FC

感觉提升不明显(但是换种角度想,参数量比fc下降了呀)

最差结果在98.6 最好的结果99.2 已经超越kaggle了!

 

之后在训练策略上改变了下,前800 step batchsize=128 后 200 step batchsize 丧心病狂到512

前900 step 还用 adam 后100步用 sgd lr=1e-14 微调

最终结果....

训练了几次结果比较稳定在 99.05左右,emmmm 勉强算是超越了,之后准备在模型结构上改下试试。

代码在:

https://github.com/lordrebel/beatLenet5/tree/master model1.py

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章