从零到LeNet实现(二)附代码详解

经过这两天的阅读,算是稍稍掌握了tensorflow的一些用法。

占位符

我们定义Lenet类,在类里构建网络。

构建类的实例需要初始化内部参数,内部参数通过self.***定义实现。

但是训练过程我们用的数据每一次是不同的,因此通过定义占位符实现,定义数据的格式和大小,在每一次训练时进行传递不同的数据。

占位符的使用在(一)里讲过了。


再说一下,tf.cast:用于改变某个张量的数据类型

tensorflow有一个命名域的问题:

https://blog.csdn.net/u012436149/article/details/53081454

本次代码中网络的构建是通过slim库实现的,这个库相当于对tf自带的conv又进行了一次封装。

https://blog.csdn.net/Cyiano/article/details/75006883

https://www.jianshu.com/p/4b608c2313e2

关于slim库的一些资料放在这里了。建议看到我这篇文章得大家看一下撒。

tip1:构建网络的过程中,我们往往需要随时查看现在网络的结果,但这些网络都是张量,所以通过get_shape()函数查看。

net = slim.max_pool2d(net, [2, 2], scope='pool4')
print(net.get_shape())

就像这样。

tip2:卷积过程中,我们总是会遇到一个padding的参数,它有两种选择,“SAME”"VALID"。

根据上述描述我们就可以知道;假设一个28*28的图像,经过5*5的卷积核,步长为1,那么卷积后的结果依旧是28*28.

其他的在代码里都有实现啦~~

不算上ui界面,这次代码就算是看完啦~理解了很多东西~嘎嘎嘎~

 

但是好像写的不够清晰。没事,以后有机会。

 

接下来,我要自己手撸一遍!

#!usr/bin/python
# -*- coding:<encoding name> -*-
import tensorflow as tf
import tensorflow.contrib.slim as slim
import config as cfg
import pdb
class Lenet:
    def __init__(self):
        # 占位符数据
        self.raw_input_image = tf.placeholder(tf.float32, [None, 784])
        self.input_images = tf.reshape(self.raw_input_image, [-1, 28, 28, 1])
        self.raw_input_label = tf.placeholder("float", [None, 10])
        # tf.cast() 改变数据类型
        self.input_labels = tf.cast(self.raw_input_label,tf.int32)
        self.dropout = cfg.KEEP_PROB

        with tf.variable_scope("Lenet") as scope:
            self.train_digits = self.construct_net(True)
            scope.reuse_variables()
            self.pred_digits = self.construct_net(False)
        #tf.argmax(vector, 1):返回的是vector中的最大值的索引号
        self.prediction = tf.argmax(self.pred_digits, 1)
        self.correct_prediction = tf.equal(tf.argmax(self.pred_digits, 1), tf.argmax(self.input_labels, 1))
        self.train_accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, "float"))
        # print('ddddd')


        #通过交叉熵函数求得loss值;
        self.loss = slim.losses.softmax_cross_entropy(self.train_digits, self.input_labels)
        #初始化学习率
        self.lr = cfg.LEARNING_RATE
        #根据学习率反向传播优化参数
        self.train_op = tf.train.AdamOptimizer(self.lr).minimize(self.loss)


    def construct_net(self,is_trained = True):
        with slim.arg_scope([slim.conv2d], padding='VALID',
                            weights_initializer=tf.truncated_normal_initializer(stddev=0.01),
                            weights_regularizer=slim.l2_regularizer(0.0005)):
            # 卷积默认经过relu;slim是对tf中卷积的简化;输入的图片大小为28*28;经过5*5的卷积核,因为是SAME,所以还是28*28;
            # print(self.input_images.get_shape())
            net = slim.conv2d(self.input_images, 6, [5, 5], 1, padding='SAME', scope='conv1')
            # print(net.get_shape())
            #max_pool的卷积核大小为2*2;步长为1;经过max 变成14*14
            net = slim.max_pool2d(net, [2, 2], scope='pool2')
            # print(net.get_shape())

            #14*14经过卷积变成10*10
            net = slim.conv2d(net, 16, [5, 5], 1, scope='conv3')
            # print(net.get_shape())
            #经过pool,变成5*5
            net = slim.max_pool2d(net, [2, 2], scope='pool4')
            # print(net.get_shape())
            # 经过卷积变成1*1
            net1 = slim.conv2d(net, 120, [5, 5], 1, scope='conv5')

            # n1 = net1.get_shape()
            # print(n1)
            # 将120个1*1的撕扯成一个120维的长向量
            net2 = slim.flatten(net1, scope='flat6')
            # print(net2.get_shape())
            #展开成84维
            net3 = slim.fully_connected(net2, 84, scope='fc7')
            # print(net3.get_shape())
            net4 = slim.dropout(net3, self.dropout, is_training=is_trained, scope='dropout8')
            # print(net4.get_shape())
            digits = slim.fully_connected(net4, 10, scope='fc9')
            # pdb.set_trace()
        return digits

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值