generateds.py用于将图片文件写为tfrecord数据格式文件,并提供了读取tfrecord文件,打乱以及获取一个批次tfrecord文件
# coding:utf-8
import tensorflow as tf
import numpy as np
from PIL import Image
import os
image_train_path = './mnist_data_jpg/mnist_train_jpg_60000/'
label_train_path = './mnist_data_jpg/mnist_train_jpg_60000.txt'
tfRecord_train = './data/mnist_train.tfrecords'
image_test_path = './mnist_data_jpg/mnist_test_jpg_10000/'
label_test_path = './mnist_data_jpg/mnist_test_jpg_10000.txt'
tfRecord_test = './data/mnist_test.tfrecords'
data_path = './data'
resize_height = 28
resize_width = 28
def write_tfRecord(tfRecordName, image_path, label_path):
writer = tf.python_io.TFRecordWriter(tfRecordName)
num_pic = 0
# 打开一个一个记录图片名称和标签的txt文件
f = open(label_path, 'r')
# 获取这个txt文件中的所以内容
contents = f.readlines() # contents为一个列表
f.close()
for content in contents:
# content为图片的路径以及标签
value = content.split()
img_path = image_path + value[0]
# 用PIL中image读取图片得到img对象
img = Image.open(img_path)
# 并用img自带函数转为二进制
img_raw = img.tobytes()
# 将标签转为列向量
labels = [0] * 10
labels[int(value[1])] = 1
# 写tfrecord文件的标准模式
example = tf.train.Example(features=tf.train.Features(feature={
'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])),
'label': tf.train.Feature(int64_list=tf.train.Int64List(value=labels))
}))
# 写tfrecord文件
writer.write(example.SerializeToString())
num_pic += 1
# 每隔1000张图输出一次
if num_pic % 1000 == 0:
print("the number of picture:", num_pic)
writer.close() # 写操作完成
print("write tfrecord successful")
def generate_tfRecord():
# 首先判断保存tfrecords文件目录
isExists = os.path.exists(data_path)
# 如果路径不存在,创建文件
if not isExists:
os.makedirs(data_path)
print('The directory was created successfully')
else:
print('directory already exists')
# 分别创建测试集和训练集的tfrecord文件
write_tfRecord(tfRecord_train, image_train_path, label_train_path)
write_tfRecord(tfRecord_test, image_test_path, label_test_path)
def read_tfRecord(tfRecord_path):
# 运用队列的方法读取tfrecord文件数据
filename_queue = tf.train.string_input_producer([tfRecord_path], shuffle=True)
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(serialized_example,
features={
'label': tf.FixedLenFeature([10], tf.int64),
'img_raw': tf.FixedLenFeature([], tf.string)
})
# 使用tensorflow自带方法读取图片
img = tf.decode_raw(features['img_raw'], tf.uint8)
# 将图片一维化排列
img.set_shape([784])
# 将像素点归一化
img = tf.cast(img, tf.float32) * (1. / 255)
# 读出标签
label = tf.cast(features['label'], tf.float32)
return img, label
def get_tfrecord(num, isTrain=True):
# 获取tfrecord数据
# 第二个输入参数代表训练集或测试集
if isTrain:
tfRecord_path = tfRecord_train
else:
tfRecord_path = tfRecord_test
# 读取图片
img, label = read_tfRecord(tfRecord_path)
# 取出批次并打乱顺序
img_batch, label_batch = tf.train.shuffle_batch([img, label],
batch_size=num,
num_threads=2,
capacity=1000,
min_after_dequeue=700)
return img_batch, label_batch
def main():
generate_tfRecord()
if __name__ == '__main__':
main()
forward.py 文件用于定义神经网络结构
import tensorflow as tf
INPUT_NODE = 28 * 28
OUTPUT_NODE = 10
LAYER1_NODE = 500
def get_weight(shape, regularizer):
# 定义全连接的权重,用正态分布随机数初始化
w = tf.Variable(tf.truncated_normal(shape, stddev=0.1))
# 添加正则化
if regularizer != None:
tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
return w
def get_bias(shape):
# 添加偏置层,使用0初始化
b = tf.Variable(tf.zeros(shape))
return b
def forward(x, regularizer):
# 全连接向前传播
# w1为 INPUT_NODE * LAYER1_NODE
# 第一层有500个神经元
w1 = get_weight([INPUT_NODE, LAYER1_NODE], regularizer)
b1 = get_bias([LAYER1_NODE])
# 计算经过第一层输出,激活函数relu
y1 = tf.nn.relu(tf.matmul(x, w1) + b1)
# 获取第二层的全连接权重,添加偏置层
w2 = get_weight([LAYER1_NODE, OUTPUT_NODE], regularizer)
b2 = get_bias([OUTPUT_NODE])
# 计算第二层输出
y = tf.matmul(y1, w2) + b2
return y
backward.py用来启动训练过程,训练模型
import tensorflow as tf
import mnist_forward
import os
import mnist_generateds
BATCH_SIZE = 200
LEARNING_RATE_BASE = 0.1
LEARNING_RATE_DECAY = 0.99
REGULARIZER = 0.0001
STEPS = 50000
MOVING_AVERAGE_DECAY = 0.99
MODEL_SAVE_PATH="./model/"
MODEL_NAME="mnist_model"
train_num_examples = 60000
def backward():
# 输入占位 28*28个输入
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
# 输出占位 10个输出
y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
# 给出三层图的结果
y = mnist_forward.forward(x, REGULARIZER)
# 定义步长计数器
global_step = tf.Variable(0, trainable=False)
# 交叉熵代价函数
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
# 求平均得到最终的代价函数
cem = tf.reduce_mean(ce)
# 将代价函数添加偏置层
loss = cem + tf.add_n(tf.get_collection('losses'))
# 指数衰减学习率
learning_rate = tf.train.exponential_decay(
LEARNING_RATE_BASE,
global_step,
train_num_examples / BATCH_SIZE,
LEARNING_RATE_DECAY,
staircase=True)
# 梯度下降优化器
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
# 下面为滑动平均变量
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
ema_op = ema.apply(tf.trainable_variables())
with tf.control_dependencies([train_step, ema_op]):
train_op = tf.no_op(name='train')
# 保存模型
saver = tf.train.Saver()
# 获取一个批次的训练数据
img_batch, label_batch = mnist_generateds.get_tfrecord(BATCH_SIZE, isTrain=True)#3
# 启动图,开始计算
with tf.Session() as sess:
# 定义初始化操作
init_op = tf.global_variables_initializer()
# 运行这个初始化操作
sess.run(init_op)
# 定义ckpt文件,用来保存计算进度
ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH)
# 如果定位到ckpt文件存在,加载ckpt文件,读取训练参数
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, ckpt.model_checkpoint_path)
# 这两行可能与加载训练集的批次有关
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
# 开始训练
for i in range(STEPS):
# 每次传入训练批次
xs, ys = sess.run([img_batch, label_batch])
# 运行图,计算每次的cost function
_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
if i % 1000 == 0:
# 每隔1000次输出训练结果
print("After %d training step(s), loss on training batch is %g." % (step, loss_value))
saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
# 关闭cord
coord.request_stop()
coord.join(threads)
def main():
backward()
if __name__ == '__main__':
main()
test.py 将训练集图片用来测试正确率
#coding:utf-8
import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import mnist_backward
import mnist_generateds
TEST_INTERVAL_SECS = 5
TEST_NUM = 10000
def test():
with tf.Graph().as_default() as g:
# 输入占位
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
# 输出占位
y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
# 定义向前传播计算输出的图 第二个参数None代表
y = mnist_forward.forward(x, None)
# 下面为滑动平均模型
ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
ema_restore = ema.variables_to_restore()
saver = tf.train.Saver(ema_restore)
# 将计算的输出与标记的输出做比较,计算正确率
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# 从测试集中读取一批次数据,进行计算
img_batch, label_batch = mnist_generateds.get_tfrecord(TEST_NUM, isTrain=False)
while True:
with tf.Session() as sess:
# 读取ckpt数据
ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, ckpt.model_checkpoint_path)
# 读取步长
global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
# 这里可能是声明批次的队列,加载训练数据
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
# 加载训练数据
xs, ys = sess.run([img_batch, label_batch])#5
# 喂入测试集,开始测试
accuracy_score = sess.run(accuracy, feed_dict={x: xs, y_: ys})
print("After %s training step(s), test accuracy = %g" % (global_step, accuracy_score))
coord.request_stop()#6
coord.join(threads)#7
else:
print('No checkpoint file found')
return
time.sleep(TEST_INTERVAL_SECS)
def main():
test()#8
if __name__ == '__main__':
main()
app.py 程序用PIL读取并预处理图片,最后一张图喂入神经网络,计算预测数据
# coding:utf-8
import tensorflow as tf
import numpy as np
from PIL import Image
import mnist_backward
import mnist_forward
def restore_model(testPicArr):
with tf.Graph().as_default() as tg:
# 输入占位
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
# 输出占位
y = mnist_forward.forward(x, None)
# 预测
preValue = tf.argmax(y, 1)
# 滑动模型
variable_averages = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
variables_to_restore = variable_averages.variables_to_restore()
saver = tf.train.Saver(variables_to_restore)
with tf.Session() as sess:
# 加载ckpt文件
ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, ckpt.model_checkpoint_path)
# 每一次喂入一张图
preValue = sess.run(preValue, feed_dict={x: testPicArr})
return preValue
else:
print("No checkpoint file found")
return -1
def pre_pic(picName):
# 使用PIL读取图片
img = Image.open(picName)
# 重新设置图片的尺寸
reIm = img.resize((28, 28), Image.ANTIALIAS)
im_arr = np.array(reIm.convert('L'))
threshold = 50
# 因为训练图片为黑底白字,需要转化为白底黑字
# 并二值化处理
for i in range(28):
for j in range(28):
im_arr[i][j] = 255 - im_arr[i][j]
if (im_arr[i][j] < threshold):
im_arr[i][j] = 0
else:
im_arr[i][j] = 255
# 将二维图片一维化
nm_arr = im_arr.reshape([1, 784])
nm_arr = nm_arr.astype(np.float32)
# 归一化
img = np.multiply(nm_arr, 1.0 / 255.0)
return nm_arr # img
def application():
print("start test")
testNum = input("input the number of test pictures:")
for i in range(int(testNum)):
# 输入图片地址
testPic = input("the path of test picture:")
# 图片预处理
testPicArr = pre_pic(testPic)
# 输出预测数字
preValue = restore_model(testPicArr)
print("The prediction number is:", preValue)
def main():
application()
if __name__ == '__main__':
main()