1.用到的部分函数
tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
input : 输入的要做卷积的图片,要求为一个张量,shape为 [ batch, in_height, in_weight, in_channel ],其中batch为图片的数量,in_height 为图片高度,in_weight 为图片宽度,in_channel 为图片的通道数,灰度图该值为1,彩色图为3。
filter: 卷积核,要求也是一个张量,shape为 [ filter_height, filter_weight, in_channel, out_channels ],其中 filter_height 为卷积核高度,filter_weight 为卷积核宽度,in_channel 是图像通道数 ,和 input 的 in_channel 要保持一致,out_channel 是卷积核数量。strides: 卷积时在图像每一维的步长,这是一个一维的向量,[ 1, strides, strides, 1],第一位和最后一位固定必须是1。
padding: string类型,值为“SAME” 和 “VALID”,表示的是卷积的形式,是否考虑边界。"SAME"是考虑边界,不足的时候用0去填充周围,"VALID"则不考虑。
use_cudnn_on_gpu: bool类型,是否使用cudnn加速,默认为true
tf.nn.relu(a)
a = tf.constant([-2,-1,0,2,3])
with tf.Session() as sess:
print(sess.run(tf.nn.relu(a)))
结果是
[0 0 0 2 3]
tf.nn.bias_add(value,bias,name=None)
一个叫bias的向量加到一个叫value的矩阵上,是向量与矩阵的每一行进行相加,得到的结果和value矩阵大小相同,类似于广播操作。
tf.nn.max_pool(value,ksize,strides,padding,data_format='NHWC',name)
Args:
- value: A 4 Dimensions Tensor with shape [batch, height, width, channels] and type tf.float32.
- ksize: A list of ints that has length >= 4. The size of the window foreach dimension of the input tensor.
- strides: A list of ints that has length >= 4. The stride of the slidingwindow for each dimension of the input tensor.
- padding: A string, either 'VALID' or 'SAME'. The padding algorithm.See the comment here
- data_format: A string. 'NHWC' and 'NCHW' are supported.
- name: Optional name for the operation.
Returns: A Tensor with type tf.float32. The max pooled output tensor.
2.代码
import tensorflow as tf
import numpy as np
import os
from tensorflow.examples.tutorials.mnist import input_data
batch_size = 100
learning_rate_base = 0.1
learning_rate_decay = 0.99
regularaztion_rate = 0.0001
training_steps = 30000
moving_average_decay = 0.99
model_save_path = "/path/to/model/"
model_name = "model.ckpt"
input_node = 784
output_node = 10
image_size = 28
num_channels = 1
num_labels = 10
conv1_deep = 32
conv1_size = 5
conv2_deep = 64
conv2_size = 5
# 全连接层的节点个数
fc_size = 512
def inference(input_tensor, train, regularizer) :
# 第一层卷积层
with tf.variable_scope('layer1-conv1', reuse=tf.AUTO_REUSE) :
conv1_weights = tf.get_variable(
"weight", [conv1_size, conv1_size, num_channels,conv1_deep],
initializer=tf.truncated_normal_initializer(stddev=0.1))
conv1_biases = tf.get_variable(
"bias", [conv1_deep],
initializer=tf.constant_initializer(0.0))
conv1 = tf.nn.conv2d(
input_tensor, conv1_weights, strides=[1,1,1,1], padding='SAME')
relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
# 第二层池化层
with tf.name_scope('layer2-pool1') :
pool1 = tf.nn.max_pool(
relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# 第三层卷积层
with tf.variable_scope('layer3-conv2', reuse=tf.AUTO_REUSE) :
conv2_weights = tf.get_variable(
"weight", [conv2_size, conv2_size, conv1_deep, conv2_deep],
initializer=tf.truncated_normal_initializer(stddev=0.1))
conv2_biases = tf.get_variable(
"bias", [conv2_deep],
initializer=tf.truncated_normal_initializer(stddev=0.0))
conv2 = tf.nn.conv2d(
pool1, conv2_weights, strides=[1, 1, 1, 1], padding='SAME')
relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))
# 第四层池化层
with tf.name_scope('layer4-pool2') :
pool2 = tf.nn.max_pool(
relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
pool_shape = pool2.get_shape().as_list()
nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]
reshaped = tf.reshape(pool2, [pool_shape[0], nodes])
# 第五层全连接层,dropout
with tf.variable_scope('layer5-fc1', reuse=tf.AUTO_REUSE) :
fc1_weights = tf.get_variable(
"weight", [nodes, fc_size],
initializer=tf.truncated_normal_initializer(stddev=0.1))
# 只有全连接层的权重需要加入正则化
if regularizer != None :
tf.add_to_collection('losses', regularizer(fc1_weights))
fc1_biases = tf.get_variable(
"bias", [fc_size],
initializer=tf.truncated_normal_initializer(stddev=0.1))
fc1 = tf.nn.relu(tf.matmul(reshaped, fc1_weights) + fc1_biases)
if train :
fc1 = tf.nn.dropout(fc1, 0.5)
# 第六层全连接层
with tf.variable_scope('layer6-fc2', reuse=tf.AUTO_REUSE) :
fc2_weights = tf.get_variable(
"weight", [fc_size, num_labels],
initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None :
tf.add_to_collection('losses', regularizer(fc2_weights))
fc2_biases = tf.get_variable(
"bias", [num_labels],
initializer=tf.truncated_normal_initializer(stddev=0.1))
logit = tf.matmul(fc1, fc2_weights) + fc2_biases
return logit
def train(mnist) :
tf.reset_default_graph()
x = tf.placeholder(tf.float32,
[batch_size, image_size, image_size, num_channels],
name='x-input')
y_= tf.placeholder(tf.float32, [None, output_node], name='y-input')
regularizer = tf.contrib.layers.l2_regularizer(regularaztion_rate)
y = inference(x, True, regularizer)
global_step = tf.Variable(0, trainable=False)
variable_averages = tf.train.ExponentialMovingAverage(
moving_average_decay, global_step)
variables_averages_op = variable_averages.apply(tf.trainable_variables())
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
logits=y, labels=tf.argmax(y_, 1))
cross_entropy_mean = tf.reduce_mean(cross_entropy)
loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))
learning_rate = tf.train.exponential_decay(
learning_rate_base, global_step,
mnist.train.num_examples/batch_size,
learning_rate_decay)
train_step = tf.train.GradientDescentOptimizer(learning_rate)\
.minimize(loss, global_step=global_step)
# 如果global_step非None,该操作还会为global_step做自增操作
with tf.control_dependencies([train_step, variables_averages_op]) :
train_op = tf.no_op(name='train')
with tf.Session() as sess :
tf.global_variables_initializer().run()
for i in range(training_steps) :
xs, ys = mnist.train.next_batch(batch_size)
reshaped_xs = np.reshape(xs,
(batch_size, image_size, image_size, num_channels))
_, loss_value, step = sess.run([train_op, loss, global_step],
feed_dict={x:reshaped_xs, y_:ys})
if i % 5 == 0 :
print("After %d training step(s), loss in training "
"batch is %f." % (step, loss_value))
def main(argv=None) :
mnist = input_data.read_data_sets("/path/to/MNIST_data", one_hot=True)
train(mnist)
if __name__ == '__main__' :
tf.app.run()