残差神经网络Resnet(MNIST数据集tensorflow实现)

简述:

残差神经网络(ResNet)主要是用于搭建深度的网络结构模型

(一)优势:

与传统的神经网络相比残差神经网络具有更好的深度网络构建能力,能避免因为网络层次过深而造成的梯度弥散和梯度爆炸。

(二)残差模块:

通过在一个浅层网络基础上叠加y=x的层,可以让网络随深度增加而不退化。

残差学习的函数是F(x) = H(x) - x,这里如果F(x) =0,那么就是恒等映射。

resnet"short connections” 的在connection是在恒等映射的情况。

输入和输出的差别H(x)-x就是残差。

这个是通过shortcut connection 实现,通过shortcut将这个block的输入和输出进行一个

element-wise的加叠,这个简单的加法并不会给网络带来多大额外计算量,同时可以大大

增加模型的训练速度,提高训练效果,并且当模型的层数加深时,这个简单的结构能很好的解决退化问题。

实现公式:

a[l+2] 加上了 a[l]的残差块,即:残差网络中,直接将a[l]向后拷贝到神经网络的更深层,在ReLU非线性激活前面

加上a[l],a[l]的信息直接达到网络深层。使用残差块能够训练更深层的网络,构建一个ResNet网络就是通过将很多

这样的残差块堆积在一起,形成一个深度神经网络。
对于大型的网络,无论把残差块添加到神经网络的中间还是末端,都不会影响网络的表现。

可以提升网络效率。

残差神经网络与传统神经网络的模型区别:

 

可以看到普通直连的卷积神经网络最大区别在于,ResNet有一个shortcut结构,而传统卷积或多或少存在信息丢失的问题

在实际中关于成本考虑,既将两个3*3的卷积替换成1*1+3*3+1*1,如下图,新结构

中的中间3*3的卷积层在一个1*1降维,另一个1*1做还原,既保持精度又减少计算量。

如图结构:

tensorflow代码实现

定义残差

class  ResNet:
    def __init__(self,X_input,kernel_size,in_filter,out_filters,stride):
        self.X=X_input
        self.X_sortcut=X_input
        self.stride=stride
        f1,f2,f3=out_filters
        self.conv_1=tf.Variable(tf.truncated_normal(shape=[1,1,in_filter,f1],stddev=0.1,mean=0,dtype=tf.float32))
        self.conv_b1=tf.Variable(tf.zeros([f1]))
        self.conv_2=tf.Variable(tf.truncated_normal(shape=[kernel_size,kernel_size,f1,f2],stddev=0.1,mean=0,dtype=tf.float32))
        self.conv_b2=tf.Variable(tf.zeros([f2]))
        self.conv_3=tf.Variable(tf.truncated_normal(shape=[1,1,f2,f3],stddev=0.1,mean=0,dtype=tf.float32))
        self.conv_b3=tf.Variable(tf.zeros([f3]))
        self.b_conv_fin = tf.Variable(tf.zeros([f3]))
    def ResNetChoice(self,choice):
        if(choice):
            # frist
            y = tf.nn.relu(tf.nn.conv2d(self.X,self.conv_1,strides=[1,1,1,1],padding="SAME")+self.conv_b1)
            #second
            y = tf.nn.relu(tf.nn.conv2d(y,self.conv_2,strides=[1,1,1,1],padding="SAME")+self.conv_b2)
            #third
            y = tf.nn.relu(tf.nn.conv2d(y,self.conv_3,strides=[1,1,1,1],padding="SAME")+self.conv_b3)
            #final steap
            add=tf.add(y,self.X_sortcut)
            add_result = tf.nn.relu(add + self.b_conv_fin)
            return add_result
        else:
            # frist
            y = tf.nn.relu(tf.nn.conv2d(self.X, self.conv_1, strides=[1, self.stride,self.stride, 1], padding="SAME") + self.conv_b1)
            # second
            y = tf.nn.relu(tf.nn.conv2d(y, self.conv_2, strides=[1, 1, 1, 1], padding="SAME") + self.conv_b2)
            # third
            y = tf.nn.relu(tf.nn.conv2d(y, self.conv_3, strides=[1, 1, 1, 1], padding="SAME") + self.conv_b3)
            # final steap
            add = tf.nn.conv2d(self.X_sortcut,self.conv_3,strides=[1,1,1,1],padding="SAME")
            add = tf.add(y,add)
            add_result = tf.nn.relu(add+self.b_conv_fin)
            return  add_result

网络结构

class Net:
    def __init__(self):
        # 输入x(数据输入为图片的格式)
        self.x=tf.placeholder(tf.float32,[None,28,28,1])
        # 输入y(标签)
        self.y=tf.placeholder(tf.float32,[None,10])
        # ----------------------------卷积初始化--------------------------------
        #卷积第一层
        self.conv1_w=tf.Variable(tf.random_normal([3,3,1,16],dtype=tf.float32,stddev=0.1))
        # 卷积第一层偏移
        self.convb1=tf.Variable(tf.zeros([16]))
    
        #--------------------------------全连接初始化---------------------------------------
        # 第一层全连接w
        self.W = tf.Variable(tf.random_normal([7*7*32,128],dtype=tf.float32,stddev=0.1))
        # 第一层全连接b
        self.B = tf.Variable(tf.zeros([128]))
        # 第二层全连接w
        self.W1 = tf.Variable(tf.random_normal([128,10],dtype=tf.float32,stddev=0.1))
        # 第二层全连接b
        self.B1 = tf.Variable(tf.zeros([10]))
    def forward(self):
        # ------------------------------卷积层-----------------------------------
        # 卷积第一层实现
        self.conv1=tf.nn.relu(tf.nn.conv2d(self.x,self.conv1_w,strides=[1,1,1,1],padding="SAME")+self.convb1)
        # 第一层池化
        self.pool1=tf.nn.max_pool(self.conv1,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
        # 残差部分
        Rt = ResNet(self.pool1, 3, 16, [8, 8, 16], 1)
        x = Rt.ResNetChoice(True)
        Rt1 = ResNet(x, 3, 16, [8, 8, 16], 1)
        x = Rt1.ResNetChoice(True)
        Rt2 = ResNet(x, 3, 16, [8, 8, 16], 1)
        x = Rt2.ResNetChoice(True)
        Rt3 = ResNet(x, 3, 16, [8, 8, 16], 1)
        x = Rt3.ResNetChoice(True)
        URt =ResNet(x,3,16,[16,16,32],1)
        x = URt.ResNetChoice(False)


        self.pool2=tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
        # 均值tf.nn.avg_pool
        # 归一化层tf.nn.batch_normalization
        # 形状处理
        self.flat = tf.reshape(self.pool2,[-1,7*7*32])
        # ---------------------------------全链接层-------------------------------------------
        self.y0 = tf.nn.relu(tf.matmul(self.flat,self.W)+self.B)
        self.yo = tf.nn.softmax(tf.matmul(self.y0,self.W1)+self.B1)

    def backword(self):
        self.cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.yo, labels=self.y))
        self.optimizer = tf.train.AdamOptimizer(0.003).minimize(self.cross_entropy)

训练:

if __name__ == '__main__':
    net = Net()
    net.forward()
    net.backword()
    init=tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for  i in range(100000):
        xs,ys = mnist.train.next_batch(128)
        cg=xs.reshape([128,28,28,1])
        rs,loss,_=sess.run([net.acc,net.cross_entropy,net.optimizer],feed_dict={net.x:cg,net.y:ys})

残差神经网络在图像识别领域很有优势

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值