深度学习网络篇——AlexNet在MNIST的代码实现

AlexNet是深度学习网络篇学习的基础网络,这篇文章在MNIST上做一次实现。在MNIST上实现AlexNet的代码有很多大大们都写过,这篇文章分享一下我们自己写的时候有些小体会。

写代码之前的一点儿小准备

要搭建一个深度学习的网络,我们首先要了解数据集
整体来说,MNIST的AlexNet的实现(分类问题) MNIST的输入大小是28x28,手写数字0-9,共10类。如果有小伙伴想更深入的了解MNIST数据集,可以参考我的数据集的博客机器学习数据集篇——MNIST数据集
在我们了解了数据集后,我们再要思考的问题就是我们怎么搭建网络。我们可以把搭建网络可以比作盖房子,我们有了数据集,就相当于我们已经有了盖房子的水泥等原材料;我们现在要开始画图纸了,决定这个房子是盖一层还是摩天大厦,每一层房子里都放些什么东西,这也就说明我们要考虑网络建几层,每层都有些什么布置和考量。
对于MNIST上的AlexNet来说,网络就是5层卷积层,3层全连接层(含softmax层),输入是28x28的图像文件,输出是10个类;在卷积层中的操作是卷积—激活—池化(可选)—标准化(可选);在全连接层上我们考虑用多少个神经元来训练;还要定义损失函数和优化器等等。
综上所述,我们可以把构建网络模型分成四个步骤:
1.数据集的加载(了解数据集、获取数据集、明确输入等)
2.定义网络模型(明确要实现什么问题‘是分类or回归’、定义网络模型的结构、定义损失函数和优化器、定义评估函数等)
3.训练模型(初始化变量、在训练集上训练)
4.评估模型(在测试集上测试,输出损失)

AlexNet在MNIST的实现过程

首先我们要做一些导入的准备,比如说tensorflow,MNIST啥的。

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data",one_hot=True)

定义网络的超参数和基础参数

learning_rate = 0.001
training_iters = 20000
batch_size = 128    # 批处理大小128,每一次128张图片进行训练
display_step = 10    # 每10个记录打印一次
n_input = 784   #28x28
n_classes = 10
dropout = 0.75

构建网络模型(因为卷积函数、池化函数和标准化我们用的比较多,把它们封装起来,后续的可以直接调用)

def conv2d(name,x,W,b,strides=1):
    x = tf.nn.conv2d(x,W,strides=[1,strides,strides,1],padding='SAME')    # tf.nn.conv2d函数
    x = tf.nn.bias_add(x,b)                                              # 加一个bias
    return tf.nn.relu(x,name=name)   # 做激活

def maxpool2d(name,x,k=2):
    return tf.nn.max_pool(x,ksize=[1,k,k,1],strides=[1,k,k,1],padding='SAME',name=name)

def norm(name,l_input,lsize):
    return tf.nn.lrn(l_input,lsize,bias=1.0,alpha=0.001/9.0,beta=0.75,name=name)

之后需要定义网络参数W,b,这个可以自己设置,但是每次要经过推导,可以直接用AlexNet的网络参数。
再之后,我们就可以定义完整的AlexNet网络了,附上def代码:

def alex_net(x,weights,biases,dropout):
    x = tf.reshape(x,shape=[-1,28,28,1])    # 定义输入
    
    conv1 = conv2d('conv1',x,weights['wc1'],biases['bc1'])   # 第一层卷积
    pool1 = maxpool2d('pool1',conv1,k=2)
    norm1 = norm('norm1',pool1,lsize=4)
    
    conv2 = conv2d('conv2',norm1,weights['wc2'],biases['bc2'])   # 第二层卷积
    pool2 = maxpool2d('pool2',conv2,k=2)
    norm2 = norm('norm2',pool2,lsize=4)
    
    conv3 = conv2d('conv3',norm2,weights['wc3'],biases['bc3'])   # 第三层卷积
    norm3 = norm('norm3',conv3,lsize=4)
    
    conv4 = conv2d('conv4',norm3,weights['wc4'],biases['bc4'])   # 第四层卷积
    norm4 = norm('norm4',conv4,lsize=4)
    
    conv5 = conv2d('conv5',norm4,weights['wc5'],biases['bc5'])   # 第五层卷积
    pool5 = maxpool2d('pool5',conv5,k=2)
    norm5 = norm('norm5',pool5,lsize=4)
    
    fc1 = tf.reshape(norm5,[-1,weights['wd1'].get_shape().as_list()[0]])   # 第一层全连接层
    fc1 = tf.nn.relu(tf.matmul(fc1,weights['wd1'])+biases['bd1'])
    fc1 = tf.nn.dropout(fc1,dropout)              # dropout

    fc2 = tf.reshape(fc1,[-1,weights['wd2'].get_shape().as_list()[0]])   # 第二层全连接层
    fc2 = tf.nn.relu(tf.matmul(fc2,weights['wd2'])+biases['bd2'])
    fc2 = tf.nn.dropout(fc2,dropout)
    
    out = tf.add(tf.matmul(fc2,weights['out']),biases['out'])   # softmax层
    return out

定义完了AlexNet后,我们要构建模型,包括输出、定义损失函数和优化器,还有评估函数。

# 构建模型
pred = alex_net(x,weights,biases,keep_prob)
# 定义损失函数和优化器
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits = pred, labels = y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

# 测试网络
correct_pred = tf.equal(tf.argmax(pred,1), tf.argmax(y,1))
#先将correct_pred中数据格式转换为float32类型
#求correct_pred中的平均值,因为correct_pred中除了0就是1,因此求平均值即为1的所占比例,即正确率
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

至此,我们所有构建网络的部分就都完成了,我们就开始要在训练集上训练啦~

# 初始化所有的共享变量
init = tf.global_variables_initializer()

# 在训练集上开始训练
with tf.Session() as sess:
    sess.run(init)
    step = 1
    while step * batch_size < training_iters:
        batch_xs, batch_ys = mnist.train.next_batch(batch_size)        # batch_xs为图片数据 ; batch_ys 为标签值
        sess.run(optimizer, feed_dict={x: batch_xs, y: batch_ys, keep_prob: dropout})
        if step % display_step == 0:
            # 计算精度
            acc = sess.run(accuracy, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 1.})
            # 计算损失值
            loss = sess.run(cost, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 1.})
            print ("Iter " + str(step*batch_size) + ", Minibatch Loss = " + "{:.6f}".format(loss) + ", Training Accuracy = " + "{:.5f}".format(acc))
        step += 1
    print ("Optimization Finished!")    

在测试集上评估模型,输出精度(和损失)。

 # 计算测试集上的精度
    print ("Testing Accuracy:", sess.run(accuracy, feed_dict={x: mnist.test.images[:256], y: mnist.test.labels[:256], keep_prob: 1.}))

在MNIST上的AlexNet就实现啦!

MNIST是个很好用的数据集,小伙伴们也可以用TensorFlow在MNIST上实现更多的网络(例如:VGGNet、GoogLeNet等等)。小伙伴们也可以尝试一下用tensorflow的slim来写一下AlexNet,这是tensorflow中用于图像分类的一个库,包含了用于定义、训练和评估复杂模型的轻量级高级API。

【参考的代码和博客】蟹蟹大大们的分享~
1.Tensorflow实战1:利用AlexNet训练MNIST(http://blog.csdn.net/felaim/article/details/65630312)
2.https://github.com/tensorflow/models/tree/master/slim/nets
3.https://blog.csdn.net/u013063099/article/details/74295796
4.《Tensorflow技术解析与实战》李佳璇著(121页——125页)

猜你喜欢

转载自blog.csdn.net/weixin_43624538/article/details/84325936