1.mnist.py
import math
import tensorflow as tf
# MNIST 有10个类
NUM_CLASSES = 10
# MNIST 图像都是 28x28 展开成784维的特征向量
IMAGE_SIZE = 28
IMAGE_PIXELS = IMAGE_SIZE * IMAGE_SIZE
batch_size = 50 #
hidden1_units = 20 #第一隐藏层的大小
hidden2_units = 15 #第二隐藏层的大小
learning_rate = 0.1 #学习率
images_placeholder = tf.placeholder(tf.float32, shape=(batch_size, IMAGE_PIXELS))
labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))
#学习器模型的前向预测过程
def inference(images, hidden1_units, hidden2_units):
# Hidden 1:y1 = relu(x*W1 +b1)
with tf.name_scope('hidden1'):
weights = tf.Variable(
tf.truncated_normal([IMAGE_PIXELS, hidden1_units],
stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))),
name='weights')
biases = tf.Variable(tf.zeros([hidden1_units]), name='biases')
hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)
# Hidden 2: y2 = relu(y1*W2 + b2)
with tf.name_scope('hidden2'):
weights = tf.Variable(
tf.truncated_normal([hidden1_units, hidden2_units],
stddev=1.0 / math.sqrt(float(hidden1_units))),
name='weights')
biases = tf.Variable(tf.zeros([hidden2_units]), name='biases')
hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)
# Linear: logits = y2*W3 + b3
with tf.name_scope('softmax_linear'):
weights = tf.Variable(
tf.truncated_normal([hidden2_units, NUM_CLASSES],
stddev=1.0 / math.sqrt(float(hidden2_units))),
name='weights')
biases = tf.Variable(tf.zeros([NUM_CLASSES]), name='biases')
logits = tf.matmul(hidden2, weights) + biases
return logits
#logits和labels计算输出层损失函数
def loss(logits, labels):
labels = tf.to_int64(labels)
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=labels, logits=logits, name='xentropy')
return tf.reduce_mean(cross_entropy, name='xentropy_mean')
# 训练节点
def training(loss, learning_rate):
# 为保存loss的值添加一个标量汇总(scalar summary).
tf.summary.scalar('loss', loss)
# 创建梯度下降优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
# 创建一个变量来跟踪global step
global_step = tf.Variable(0, name='global_step', trainable=False)
# optimizer将梯度下降法应用到可调参数上来最小化损失函数
# (同时不断增加 global step 计数器)
train_op = optimizer.minimize(loss=loss, global_step=global_step)
return train_op
#评估模型
def evaluation(logits, labels):
correct = tf.nn.in_top_k(logits, labels, 1)
# 当前批次的样本中预测正确的样本数量
return tf.reduce_sum(tf.cast(correct, tf.int32))
logits = inference(images_placeholder,hidden1_units, hidden2_units)
batch_loss = loss(logits=logits, labels=labels_placeholder)
train_on_batch = training(loss=batch_loss, learning_rate=learning_rate)
correct_counts = evaluation(logits=logits, labels=labels_placeholder)
# 写入计算图
writer = tf.summary.FileWriter("logs/mnistboard", tf.get_default_graph())
writer.close()
2.训练模型
import argparse
import os.path
import sys
import time
import os
from six.moves import xrange
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
# 全局变量 存放模型(超)参数.
FLAGS = None
#产生 placeholder variables 来表达输入张量
def placeholder_inputs(batch_size):
# 注意:placeholders的shape与整体数据集中图像集和标签集的shape是相互匹配的
# 除了第一个维度现在是batch_size而不是训练集或测试集的全部大小
images_placeholder = tf.placeholder(tf.float32, shape=(batch_size,
mnist.IMAGE_PIXELS))
labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))
return images_placeholder, labels_placeholder
#填充 feed_dict 用于一个指定的训练阶段(given training step)
def fill_feed_dict(data_set, images_pl, labels_pl):
#为参数指定的占位符创建feed_dict,用下一个批次的`batch size`个样本填充.
images_feed, labels_feed = data_set.next_batch(FLAGS.batch_size, FLAGS.fake_data)
feed_dict = {images_pl: images_feed, labels_pl: labels_feed}
return feed_dict
#在给定的数据集上执行一次评估操作
def do_eval(sess, eval_correct,images_placeholder, labels_placeholder, data_set):
# 运行一个回合(one epoch)的评估过程
true_count = 0 # 对预测正确的样本计数.
steps_per_epoch = data_set.num_examples // FLAGS.batch_size #每个回合的执行步数
num_examples = steps_per_epoch * FLAGS.batch_size #样本总量
#累加每个批次样本中预测正确的样本数量
for step in xrange(steps_per_epoch):
feed_dict = fill_feed_dict(data_set, images_placeholder, labels_placeholder)
true_count += sess.run(eval_correct, feed_dict=feed_dict)
#所有批次上的样本的精确度
precision = float(true_count) / num_examples
print(' Num examples: %d Num correct: %d Precision @ 1: %0.04f' %
(num_examples, true_count, precision))
#对MNIST网络训练指定的次数(一次训练称为一个training step)
def run_training():
# 获取用于训练,验证和测试的图像数据以及类别标签集合
data_sets = input_data.read_data_sets(FLAGS.input_data_dir, FLAGS.fake_data)
# 告诉TensorFlow模型将会被构建在默认的Graph上.
with tf.Graph().as_default():
# 为图像特征向量数据和类标签数据创建输入占位符
images_placeholder, labels_placeholder = placeholder_inputs(FLAGS.batch_size)
# 从前向推断模型中构建用于预测的计算图
logits = mnist.inference(images_placeholder, FLAGS.hidden1, FLAGS.hidden2)
# 为计算图添加计算损失的节点.
loss = mnist.loss(logits, labels_placeholder)
# 为计算图添加计算和应用梯度的训练节点
train_op = mnist.training(loss, FLAGS.learning_rate)
# 添加节点用于在评估过程中比较 logits 和 ground-truth labels
eval_correct = mnist.evaluation(logits, labels_placeholder)
# 基于 TF collection of Summaries构建汇总张量.
merged_summaries = tf.summary.merge_all()
# 创建一个 saver 用于写入 训练过程中的模型的检查点文件(checkpoints).
saver = tf.train.Saver()
# 添加变量初始化节点(variable initializer Op).
init = tf.global_variables_initializer()
# 创建一个会话用来运行计算图中的节点
sess = tf.Session()
# 实例化一个 SummaryWriter 输出 summaries 和 Graph.
summary_writer = tf.summary.FileWriter(FLAGS.log_dir, sess.graph)
summary_writer.flush()
# 运行初始化节点来初始化所有变量(Variables).
sess.run(init)
# 开启训练循环.
for step in xrange(FLAGS.max_steps):
start_time = time.time()
# 在此特定的训练步,使用真实的图像和类标签数据集填充 feed dictionary
feed_dict = fill_feed_dict(data_sets.train,
images_placeholder,
labels_placeholder)
# 在当前批次样本上把模型运行一步(run one step).
# 返回值是从`train_op`和`loss`节点拿到的activations
_, loss_value = sess.run([train_op, loss], feed_dict=feed_dict)
# 计算当前批次的训练花费的时间
duration = time.time() - start_time
# 每隔100个批次就写入summaries并输出overview
if step % 100 == 0:
print('Step %d: loss = %.2f (%.3f sec)' % (step, loss_value, duration))
# 更新事件文件.还是调用sess.run()方法
summary_str = sess.run(merged_summaries, feed_dict=feed_dict)
summary_writer.add_summary(summary_str, step)
summary_writer.flush()
# 周期性的保存一个检查点文件并评估当前模型的性能
if (step + 1) % 1000 == 0 or (step + 1) == FLAGS.max_steps:
checkpoint_file = os.path.join(FLAGS.log_dir, 'model.ckpt')
saver.save(sess, checkpoint_file, global_step=step)
# 在所有训练集上评估模型.
print('Training Data Eval:')
do_eval(sess, eval_correct, images_placeholder, labels_placeholder, data_sets.train)
# 在验证集上评估模型.
print('Validation Data Eval:')
do_eval(sess, eval_correct, images_placeholder, labels_placeholder, data_sets.validation)
# 在测试集上评估模型.
print('Test Data Eval:')
do_eval(sess, eval_correct, images_placeholder, labels_placeholder, data_sets.test)
#创建日志文件夹 启动训练过程
def main(_):
if tf.gfile.Exists(FLAGS.log_dir):
tf.gfile.DeleteRecursively(FLAGS.log_dir)
tf.gfile.MakeDirs(FLAGS.log_dir)
#启动训练过程
run_training()
#用ArgumentParser类把模型的(超)参数全部解析到全局变量FLAGS里面
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'--learning_rate',
type=float,
default=0.1,
help='Initial learning rate.'
)
parser.add_argument(
'--max_steps',
type=int,
default=2000,
help='Number of steps to run trainer.'
)
parser.add_argument(
'--hidden1',
type=int,
default=128,
help='Number of units in hidden layer 1.'
)
parser.add_argument(
'--hidden2',
type=int,
default=32,
help='Number of units in hidden layer 2.'
)
parser.add_argument(
'--batch_size',
type=int,
default=100,
help='Batch size. Must divide evenly into the dataset sizes.'
)
parser.add_argument(
'--input_data_dir',
type=str,
default='MNIST_data/',
help='Directory to put the input data.'
)
parser.add_argument(
'--log_dir',
type=str,
default='logs/Fully_Connected_Feed',
help='Directory to put the log data.'
)
parser.add_argument(
'--fake_data',
default=False,
help='If true, uses fake data for unit testing.',
action='store_true'
)
#把模型的(超)参数全部解析到全局变量FLAGS里面
FLAGS, unparsed = parser.parse_known_args()
tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
3.运行结果:
/Users/dongyang/AI/anaconda3/python.app/Contents/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6
return f(*args, **kwds)
Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
Step 0: loss = 2.30 (0.134 sec)
Step 100: loss = 0.51 (0.004 sec)
Step 200: loss = 0.59 (0.002 sec)
Step 300: loss = 0.36 (0.005 sec)
Step 400: loss = 0.25 (0.002 sec)
Step 500: loss = 0.55 (0.002 sec)
Step 600: loss = 0.21 (0.002 sec)
Step 700: loss = 0.25 (0.003 sec)
Step 800: loss = 0.18 (0.002 sec)
Step 900: loss = 0.19 (0.002 sec)
Training Data Eval:
Num examples: 55000 Num correct: 51891 Precision @ 1: 0.9435
Validation Data Eval:
Num examples: 5000 Num correct: 4740 Precision @ 1: 0.9480
Test Data Eval:
Num examples: 10000 Num correct: 9428 Precision @ 1: 0.9428
Step 1000: loss = 0.28 (0.009 sec)
Step 1100: loss = 0.13 (0.109 sec)
Step 1200: loss = 0.13 (0.002 sec)
Step 1300: loss = 0.14 (0.002 sec)
Step 1400: loss = 0.18 (0.002 sec)
Step 1500: loss = 0.11 (0.002 sec)
Step 1600: loss = 0.07 (0.002 sec)
Step 1700: loss = 0.07 (0.002 sec)
Step 1800: loss = 0.05 (0.002 sec)
Step 1900: loss = 0.26 (0.002 sec)
Training Data Eval:
Num examples: 55000 Num correct: 53181 Precision @ 1: 0.9669
Validation Data Eval:
Num examples: 5000 Num correct: 4835 Precision @ 1: 0.9670
Test Data Eval:
Num examples: 10000 Num correct: 9643 Precision @ 1: 0.9643