前言: 之前一直是做GAN对抗式生成网络的,最近参加了百度的一个关于图像检测的一个比赛,从代码的难度上来说,一直以来都认为图像检测比GAN要简单,毕竟最后图像检测只是把图像放到一个卷积神经网络之中,得到图像的隐层特征,然后使用优化器对图像进行分类即可。但是GAN的话不仅要把上面的操作完成,而且还要增加一个从噪音中生成图像。
okay 今天分享我自己写的第一个手写体图像程序,程序特别简单,将图像输入到卷积网络之中, 最后输出大小为[batch_size, 10]的隐层特征,然后使用softmax交叉熵计算损失值。这一章可以看成是一个baseline,下面一节我介绍一下使用 dropout 学习率递减 L1、L2正则 bacth normal正则化优化图像识别这个网络。
mnist图像识别代码:
# -*- coding: utf-8 -*-
# @Time : 2019/7/1 04:45
# @Author : YYLin
# @Email : 854280599@qq.com
# @File : Image_Classification_Mnist.py
# 第一版图像分类的目标 使用卷积神经网络处理图像 暂时不使用任何的优化技巧
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 定义网络中的一些通道数
batch_size = 128
img_high = 28
img_width = 28
Channel = 1
label = 10
dataset_name = 'mnist'
avg_of_test = []
# 首先是读取fashion-mnits数据集
mnist = input_data.read_data_sets("../Dataset/mnist_data", one_hot=True)
# 定义输入图像的占位符
inputs = tf.placeholder(tf.float32, [batch_size, img_high, img_width, Channel], name='inputs')
y = tf.placeholder(dtype=tf.float32, shape=[batch_size, label], name='label')
# 定义一个专门的卷积操作 默认的话卷积核大小是 5*5 步长是 2*2
def conv2d(input_, output_dim, k_h=5, k_w=5, d_h=2, d_w=2, stddev=0.02, name="conv2d"):
with tf.variable_scope(name):
w = tf.get_variable('w', [k_h, k_w, input_.get_shape()[-1], output_dim],
initializer=tf.truncated_normal_initializer(stddev=stddev))
conv = tf.nn.conv2d(input_, w, strides=[1, d_h, d_w, 1], padding='SAME')
biases = tf.get_variable('biases', [output_dim], initializer=tf.constant_initializer(0.0))
conv = tf.reshape(tf.nn.bias_add(conv, biases), conv.get_shape())
return conv
# 定义一个lrelu激活函数
def lrelu(x, leak=0.2, name="lrelu"):
return tf.maximum(x, leak*x)
# 定义一个MLP全连接操作
def linear(input_, output_size, scope=None, stddev=0.02, bias_start=0.0, with_w=False):
shape = input_.get_shape().as_list()
with tf.variable_scope(scope or "Linear"):
matrix = tf.get_variable("Matrix", [shape[1], output_size], tf.float32,
tf.random_normal_initializer(stddev=stddev))
bias = tf.get_variable("bias", [output_size], initializer=tf.constant_initializer(bias_start))
if with_w:
return tf.matmul(input_, matrix) + bias, matrix, bias
else:
return tf.matmul(input_, matrix) + bias
# 图像分类的模型经过两层卷积层 以及一个全连接层之后对图像类别的判断
def classifier(x):
net = lrelu(conv2d(x, 64, 4, 4, 2, 2, name='d_conv1' + '_' + dataset_name))
net = lrelu(conv2d(net, 128, 4, 4, 2, 2, name='d_conv2' + '_' + dataset_name))
net = tf.reshape(net, [batch_size, -1])
net = lrelu(linear(net, 1024, scope='d_fc1' + '_' + dataset_name))
h_flat = linear(net, 10, scope='d_fc2' + '_' + dataset_name)
return h_flat
# 开始调用分类器 输出判断结果
y_pred = classifier(inputs)
y_conv = tf.nn.softmax(y_pred)
cross_entropy = -tf.reduce_sum(y*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
# 开始训练数据
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(mnist.train.num_examples//batch_size):
img, img_label = mnist.train.next_batch(batch_size)
# print('使用 mnist.train.next_batch加载的数据集形状', img.shape, type(img))
img = img.reshape([batch_size, 28, 28, 1])
# print('经过 tf.reshape之后数据的形状以及类型是:', img.shape, type(img))
if i % 20 == 0:
train_accuracy = accuracy.eval(feed_dict={inputs: img, y: img_label})
print("step %d, training accuracy %g" % (i, train_accuracy))
train_step.run(feed_dict={inputs: img, y: img_label})
for test in range(mnist.test.num_examples//batch_size):
img_test, img_test_label = mnist.test.next_batch(batch_size)
img_test = img_test.reshape([batch_size, 28, 28, 1])
test_socre = accuracy.eval(feed_dict={inputs: img_test, y: img_test_label})
avg_of_test.append(test_socre)
all_score = 0
for i, socre in enumerate(avg_of_test):
all_score = all_score + socre
print("原始程序中测试集的平均分是:", (all_score/(len(avg_of_test))))
实验结果: mnist手写体程序比较简单, 我们可以看到仅仅是使用了两层卷积操作和一层全连接操作 最后的得分都可以达到0.92分左右