【北京大学】Tensorflow1笔记
一级目录
二级目录
三级目录
6.1 实现把任意图片放进训练好的网络进行测试
输入的图片是白底黑字的数字图片进行测试,测试前需要做两步
(1)转换图片矩阵大小为28*28符合网络的输入
(2)把图片的转换成白字黑底的黑白图片
√网络输入:一维数组(784 个像素点)
√像素点:0-1 之间的浮点数(接近 0 越黑,接近 1 越白) √网络输出:一维数组(十个可能性概率),数组中最大的那个元素所对应的索
引号就是预测的结果。 √关键处理:
def application():
testNum = input(“input the number of test pictures:”)
for i in range(testNum):
testPic = raw_input(“the path of test picture:”)
testPicArr = pre_pic(testPic)
preValue = restore_model(testPicArr)
print “The prediction number is:”, preValue
注解:
任务分成两个函数完成
1)testPicArr = pre_pic(testPic)对手写数字图片做预处理
2)preValue = restore_model(testPicArr) 将符合神经网络输入要求的图片喂
给复现的神经网络模型,输出预测值
√具体代码:fc3
与fc2前向后向传播测试一样
mnist_app.py 倒着看代码
import tensorflow as tf
import numpy as np
from PIL import Image
import mnist_backward
import mnist_forward
def restore_model(testPicArr):
# 利用tf.Graph()复现之前定义的计算图
with tf.Graph().as_default() as tg:
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
# 调用mnist_forward文件中的前向传播过程forword()函数
y = mnist_forward.forward(x, None)
# 得到概率最大的预测值
preValue = tf.argmax(y, 1)
# 实例化具有滑动平均的saver对象
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
# 预处理,包括resize,转变灰度图,二值化
def pre_pic(picName):
img = Image.open(picName)
reIm = img.resize((28, 28), Image.ANTIALIAS)
#把图片转换为灰度值图片
im_arr = np.array(reIm.convert('L'))
threshold = 50 %动态调整
# 模型的要求是黑底白字,但输入的图是白底黑字,所以需要对每个像素点的值改为255减去原值以得到互补的反色。
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
# 把图片形状拉成1行784列,并把值变为浮点型(因为要求像素点是0-1 之间的浮点数)
nm_arr = im_arr.reshape([1, 784])
nm_arr = nm_arr.astype(np.float32)
# 接着让现有的RGB图从0-255之间的数变为0-1之间的浮点数
img_ready = np.multiply(nm_arr, 1.0 / 255.0)
return img_ready #img_ready待识别图片
def application():
# 输入要识别的几张图片
testNum = int(input("input the number of test pictures:"))
for i in range(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()
报错from PIL import Image ImportError:
No module named PIL
pip install Pillow
运行后
输入 10(表示循环验证十张图片)
the path of test picture:pic/0.png
2021-07-29 20:58:47.023986: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
The prediction number is: [0]
6. 2 自定义制作数据集
关键代码解析
1)数据集生成读取文件(mnist_generateds.py)
tfrecords 文件
1)tfrecords:是一种二进制文件,可先将图片和标签制作成该格式的文件。
2)tf.train.Example: 用来存储训练数据。训练数据的特征用键值对的形式表示。
如:‘ img_raw ’ :值 ‘ label ’ :值 值是 Byteslist/FloatList/Int64List
#img_raw是原始图片,值可以是字符串 实数列表 正数列表
3)SerializeToString( ):把数据序列化成字符串存储。
√生成 tfrecords 文件
具体代码:
#生成 tfrecords 文件
解析生成 tfrecords 文件 的图片和标签
# 该函数会生成一个先入先出的队列,文件阅读器会使用它来读取数据
filename_queue = tf.train.string_input_producer([tfRecord_path], shuffle=True)
# 新建一个reader
reader = tf.TFRecordReader()
# 把读出的每个样本保存在serialized_example中进行解序列化,标签和图片的键名应该和制作tfrecords的键名相同,其中标签给出几分类。
_, serialized_example = reader.read(filename_queue)
# 将tf.train.Example协议内存块(protocol buffer)解析为张量
features = tf.parse_single_example(serialized_example,
features={
'label': tf.FixedLenFeature([10], tf.int64),
'img_raw': tf.FixedLenFeature([], tf.string)
})
# 将img_raw字符串转换为8位无符号整型
img = tf.decode_raw(features['img_raw'], tf.uint8)
# 将形状变为一行784列
img.set_shape([784])
img = tf.cast(img, tf.float32) * (1. / 255)
# 变成0到1之间的浮点数
label = tf.cast(features['label'], tf.float32)
注解:
1)==filename_queue = tf.train.string_input_producer([tfRecord_path]) ==
tf.train.string_input_producer( string_tensor,
num_epochs=None,
shuffle=True,
seed=None,
capacity=32,
shared_name=None,
name=None,
cancel_op=None)
该函数会生成一个先入先出的队列,文件阅读器会使用它来读取数据。
参数说明:string_tensor: 存储图像和标签信息的 TFRecord 文件名列表
num_epochs: 循环读取的轮数(可选)
shuffle:布尔值(可选),如果为 True,则在每轮随机打乱读取顺序
seed:随机读取时设置的种子(可选)
capacity:设置队列容量
shared_name:(可选) 如果设置,该队列将在多个会话中以给定名
称共享。所有具有此队列的设备都可以通过 shared_name 访问它。在分布式设置
中使用这种方法意味着每个名称只能被访问此操作的其中一个会话看到。
name:操作的名称(可选)
cancel_op:取消队列(None)
2)reader = tf.TFRecordReader() #新建一个 reader
3)_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(serialized_example,features={
‘img_raw’: tf.FixedLenFeature([ ], tf.string) ,
‘label’: tf.FixedLenFeature([10], tf.int64)}) #把读出的每个样本保存在 serialized_example 中进行解序列化,标签和图片的键名应该和制作 tfrecords 的键名相同,其中标签给出几分类。
tf.parse_single_example(serialized, features, name=None, example_names=None)
该函数可以将 tf.train.Example 协议内存块(protocol buffer)解析为张量。
参数说明:serialized: 一个标量字符串张量
features: 一个字典映射功能键 FixedLenFeature 或 VarLenFeature
值,也就是在协议内存块中储存的
name:操作的名称(可选)
example_names: 标量字符串联的名称(可选)
4)img = tf.decode_raw(features[‘img_raw’], tf.uint8)
#将 img_raw 字符串转换为 8 位无符号整型
5)img.set_shape([784]) #将形状变为一行 784 列
6)img = tf.cast(img, tf.float32) * (1. / 255) #变成 0 到 1 之间的浮点数
7)label = tf.cast(features[‘label’], tf.float32)#把标签列表变为浮点数
8)return image,label #返回图片和标签(跳回到 get_tfrecord)
生成自定义数据的完整代码 fc4
mnist_generateds.py文件
#mnist_generateds.py
# 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
# 3生成tfrecords文件
def write_tfRecord(tfRecordName, image_path, label_path): #接收图片路径和标签
# 新建一个writer
writer = tf.python_io.TFRecordWriter(tfRecordName)
num_pic = 0 #计数器
f = open(label_path, 'r') #打开标签文件 是txt文件 如mnist_train_jpg_60000.txt文件
#读取的txt文件格式是图片文件名+空格+标签 :28755_0.jpg 0
contents = f.readlines()#读取整个文件内容
f.close()
# 循环遍历每张图和标签
for content in contents:
value = content.split() #空格分行每行内容,组成列表value
img_path = image_path + value[0]
img = Image.open(img_path)
img_raw = img.tobytes()#图片转换为二进制数据
labels = [0] * 10 #把每个元素赋值为0
labels[int(value[1])] = 1 #标签位赋值为1
# 把每张图片和标签封装到example中
#tf.train.Example: 用来存储训练数据。训练数据的特征用键值对的形式表示。
#如:‘ img_raw ’ :值 ‘ label ’ :值 值是 Byteslist/FloatList/Int64List
#img_raw是原始图片,值可以是字符串 实数列表 正数列表
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))
}))
# 把example进行序列化
writer.write(example.SerializeToString())
num_pic += 1#每完成一张图片,计数器加1
print("the number of picture:", num_pic)
# 关闭writer
writer.close()
print("write tfrecord successful")
#2
def generate_tfRecord():
#判断保存路径是否存在
isExists = os.path.exists(data_path)
if not isExists:
os.makedirs(data_path)
print('The directory was created successfully')
else:
print('directory already exists')
#生成文件mnist_test.tfrecords mnist_train.tfrecords
write_tfRecord(tfRecord_train, image_train_path, label_train_path)
write_tfRecord(tfRecord_test, image_test_path, label_test_path)
# 5 解析tfrecords文件
def read_tfRecord(tfRecord_path):
# 该 tf.train.string_input_producer函数会生成一个先入先出的队列,文件阅读器会使用它来读取数据
filename_queue = tf.train.string_input_producer([tfRecord_path], shuffle=True)
# 新建一个reader
reader = tf.TFRecordReader()
# 把读出的每个样本保存在serialized_example中进行解序列化,标签和图片的键名应该和制作tfrecords的键名相同,其中标签给出几分类。
_, serialized_example = reader.read(filename_queue)
# 将tf.train.Example协议内存块(protocol buffer)解析为张量
features = tf.parse_single_example(serialized_example,
features={
'label': tf.FixedLenFeature([10], tf.int64),# 10表示标签的分类数量,手写数字是十分类
'img_raw': tf.FixedLenFeature([], tf.string)
})
# 将img_raw字符串转换为8位无符号整型
img = tf.decode_raw(features['img_raw'], tf.uint8)
# 将形状变为一行784列
img.set_shape([784])
img = tf.cast(img, tf.float32) * (1. / 255)
# 变成0到1之间的浮点数
label = tf.cast(features['label'], tf.float32)
# 返回图片和标签
return img, label
# 4 获取训练集或者测试集图像和标签
def get_tfrecord(num, isTrain=True): #true读取训练集
if isTrain:
tfRecord_path = tfRecord_train
else:
tfRecord_path = tfRecord_test
img, label = read_tfRecord(tfRecord_path) #调用自定义函数read_tfRecord
# 随机读取一个batch的数据,打乱数据
img_batch, label_batch = tf.train.shuffle_batch([img, label],
batch_size=num,
num_threads=2,# 线程为2
capacity=1000,
min_after_dequeue=700)
# 返回的图片和标签为随机抽取的batch_size组
return img_batch, label_batch
#步骤1
def main():
generate_tfRecord()
if __name__ == '__main__':
main()
其中解析tfrecords文件函数
tf.train.shuffle_batch( tensors,
batch_size,
capacity,
min_after_dequeue,
num_threads=1,
seed=None,
enqueue_many=False,
shapes=None,
allow_smaller_final_batch=False,
shared_name=None,
name=None)
这个函数随机读取一个 batch 的数据。
参数说明:tensors: 待乱序处理的列表中的样本(图像和标签)
batch_size: 从队列中提取的新批量大小
capacity:队列中元素的最大数量
min_after_dequeue: 出队后队列中的最小数量元素,用于确保元素
的混合级别
num_threads: 排列 tensors 的线程数
seed:用于队列内的随机洗牌
enqueue_many: tensor 中的每个张量是否是一个例子
shapes: 每个示例的形状
allow_smaller_final_batch: (可选)布尔值。 如果为 True,则在
队列中剩余数量不足时允许最终批次更小。
shared_name:(可选)如果设置,该队列将在多个会话中以给定名称
共享。
name:操作的名称(可选)
10)return img_batch,label_batch
#返回的图片和标签为随机抽取的 batch_size 组
mnist_backward.py(反向传播文件修改图片标签获取的接口)
关键操作:利用多线程 提高图片和标签的批获取效率
方法:将批获取的操作放到线程协调器开启和关闭之间
==开启线程协调器:
coord = tf.train.Coordinator( )
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
关闭线程协调器:
coord.request_stop( )
coord.join(threads) ==
注解:
tf.train.start_queue_runners( sess=None,
coord=None,
daemon=True,
start=True,
collection=tf.GraphKeys.QUEUE_RUNNERS)
这个函数将会启动输入队列的线程,填充训练样本到队列中,以便出队操作可以从队列中拿到样本。这种情况下最好配合使用一个 tf.train.Coordinator ,这样可以在发生错误的情况下正确地关闭这些线程。
参数说明:sess:用于运行队列操作的会话。 默认为默认会话。
coord:可选协调器,用于协调启动的线程。
daemon: 守护进程,线程是否应该标记为守护进程,这意味着它们不
会阻止程序退出。
start:设置为 False 只创建线程,不启动它们。
collection:指定图集合以获取启动队列的 GraphKey。默认为
GraphKeys.QUEUE_RUNNERS。
√具体对比反向传播中的 fc4 与 fc3 代码
线程协调器的代码是用################################################括起来的
#mnist_backward.py
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import os
import mnist_generateds # 1
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"
# 手动给出训练的总样本数6万
train_num_examples = 60000 # 给出数据集的数量,fc3
def backward():
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
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()
# 一次批获取 batch_size张图片和标签
################################################
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 = tf.train.get_checkpoint_state(MODEL_SAVE_PATH)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, ckpt.model_checkpoint_path)
#开启线程协调器
################################################
# 利用多线程提高图片和标签的批获取效率
coord = tf.train.Coordinator() # 4
# 启动输入队列的线程
threads = tf.train.start_queue_runners(sess=sess, coord=coord) # 5
################################################
for i in range(STEPS):
################################################
# 执行图片和标签的批获取
xs, ys = sess.run([img_batch, label_batch]) # 6
################################################
_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
if i % 1000 == 0:
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)
################################################
# 关闭线程协调器
coord.request_stop() # 7
coord.join(threads) # 8
################################################
def main():
backward() # 9
if __name__ == '__main__':
main()
mnist_test.py文件
线程协调器的代码是用################################################括起来的
手动给出样本量
################################################
# 用函数get_tfrecord替换读取所有测试集1万张图片
img_batch, label_batch = mnist_generateds.get_tfrecord(TEST_NUM, isTrain=False) # 2
################################################
pic文件是测试数据集
————————————————
原文链接:https://blog.youkuaiyun.com/weixin_43935696/article/details/111480327
7.1 CNN:有效提取图片特征
全连接神经网络是:每个神经元与前后相邻层的每一个神经元都有连接关系,输入是
特征,输出为预测的结果。
参数个数:∑ (前层 神经元个数× 后层神经元个数 + 后层)=Σ(w+b)
现实生活中高分辨率的彩色图像,像素点更多,且为红绿蓝三通道信息。
待优化的参数过多,容易导致模型过拟合。为避免这种现象,实际应用中一
般不会将原始图片直接喂入全连接网络。
√在实际应用中,会先对原始图像进行特征提取,把提取到的特征喂给全连接
网络,再让全连接网络计算出分类评估值。
5x5x1 的灰度图片,1 表示单通道,5x5 表示分辨率,共有 5 行 5列个灰度值。若用一个 3x3x1 的卷积核对此 5x5x1 的灰度图片进行卷积,偏置项b=1,则求卷积的计算是:(-1)x1+0x0+1x2+(-1)x5+0x4+1x2+(-1)x3+0x4+1x5+1=1(注
意不要忘记加偏置 1)。
输出图片边长=(输入图片边长–卷积核长+1)/步长,此图为:(5 – 3 + 1)/ 1 = 3,输出图片是 3x3 的分辨率,用了 1 个卷积核,输出深度是 1,最后输出的是3x3x1 的图片。
√全零填充 Padding 有时会在输入图片周围进行全零填充,这样可以保证输出图片的尺寸和输入图片一致
如果用全零填充,也就是 padding=SAME。如果不用全零填充,也就是 padding=VALID。
在TensorFlow框架中,用参数padding ='SAME’或padding = ‘VALID’ 表示
tf.nn.conv2d(输入描述,eg,[batch,5,5,1]
#5 5表示每张图片的分辨率大小5行5列,1表示通道数,如果是灰度图示1,如果是彩色图,有红绿蓝三种颜色,就是3通道
卷积核描述, eg.[3,3,1,16]
#3 3 行列分辨率 ,1,通道数,16核个数
核滑动步长,eg.[1,1,1,1]
#第一四个元素固定为1;中间表示行列步长
padding= 'VALID'
)
对多通道的图片求卷积
多数情况下,输入的图片是 RGB 三个颜色组成的彩色图,输入的图片包含了
红、绿、蓝三层数据,卷积核的深度应该等于输入图片的通道数,所以使用 3x3x3
的卷积核,最后一个 3 表示匹配输入图像的 3 个通道,这样这个卷积核有三层,
每层会随机生成 9 个待优化的参数,一共有 27 个待优化参数 w 和一个偏置 b。
池化 Pooling
池化用于减少特征数量;最大值池化可提取图片纹理,均值池化可保留背景特征
TensorFlow实现
pool =tf.nn.max_pool(输入描述,eg.[batch,28,28,6])
pool = tf.nn.avg_pool
舍弃Dropout
在神经网络训练的过程汇总,将一部分神经元按照一定概率从神经网络中暂时舍弃,使用时被舍弃的神经元恢复连接,减少过拟合,加快训练速度
TensorFlow实现
tf.nn.dropout(上层输出,暂时舍弃的概率)
if train: 输出 = tf.nn.dropout(上层输出,暂时舍弃的概率)
卷积神经网络可以认为由两部分组成,一部分是对输入图片进行特征提取,另一部分就是全连接网络,只不过喂入全连接网络的不再是原始图片,而是经过若干次卷积、激活和池化后的特征信息。
卷积神经网络从诞生到现在,已经出现了许多经典网络结构,比如 Lenet-5、 Alenet、VGGNet、GoogleNet 和 ResNet 等。每一种网络结构都是以卷积、激活、池化、全连接这四种操作为基础进行扩展。
Lenet5实现代码
Mnist 数据集中图片大小为 28281 的灰度图片,而 Lenet 神经网络的输入为 32321,故需要对 Lenet 神经网络进行微调。
Lenet 5神经网络
在 Mnist 数据集上的实现,主要分为三个部分:前向传播过程(mnist_lenet5_forward.py)、反向传播过程(mnist_lenet5_backword.py)、测试过程(mnist_lenet5_test.py)。
1)mnist_lenet5_forward.py
import tensorflow as tf
#每张图片分辨率为28*28
IMAGE_SIZE = 28
#Mnist数据集为灰度图,故输入图片通道数NUM_CHANNELS取值为1
NUM_CHANNELS = 1
#第一层卷积核大小为5
CONV1_SIZE = 5
#卷积核个数为32
CONV1_KERNEL_NUM = 32
#第二层卷积核大小为5
CONV2_SIZE = 5
#卷积核个数为64
CONV2_KERNEL_NUM = 64
#全连接层第一层为 512 个神经元
FC_SIZE = 512
#全连接层第二层为 10 个神经元
OUTPUT_NODE = 10
#权重w计算
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
#偏置b计算
def get_bias(shape):
b = tf.Variable(tf.zeros(shape))
return b
#卷积层计算
def conv2d(x, w):
return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding=‘SAME’) #w是卷积核描述,padding='SAME’使用零填充
#最大池化层计算
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding=‘SAME’) #池化核大小为 2*2,垂直方向步长为 1,水平方向步长为 1,填充方式为全零填充
#定义前向传播过程
def forward(x, train, regularizer):
# 1实现第一层卷积 核体积551 核个数32
#shape=[CONV1_SIZE, CONV1_SIZE, NUM_CHANNELS, CONV1_KERNEL_NUM]=[5,5,1,32]
conv1_w = get_weight([CONV1_SIZE, CONV1_SIZE, NUM_CHANNELS, CONV1_KERNEL_NUM], regularizer)
conv1_b = get_bias([CONV1_KERNEL_NUM])
conv1 = conv2d(x, conv1_w)
# 非线性激活
relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_b))
tf.nn.relu()用来实现非线性激活,相比 sigmoid 和 tanh 函数,relu 函数可以实现快速的收敛。
v # 最大池化
pool1 = max_pool_2x2(relu1)
#2 实现第二层卷积 5,5,32,64 第二层卷积核的个数=第一层卷积核的个数
conv2_w = get_weight([CONV2_SIZE, CONV2_SIZE, CONV1_KERNEL_NUM, CONV2_KERNEL_NUM], regularizer)
conv2_b = get_bias([CONV2_KERNEL_NUM])
conv2 = conv2d(pool1, conv2_w)
relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_b))
pool2 = max_pool_2x2(relu2)
#3 将第二层池化层的输出 pool2 矩阵转化为全连接层的输入格式即向量形式
#三维张量变为二维张量 7* 7* 64变为 二维[1,7* 7*64]
# 获取一个张量的维度
pool_shape = pool2.get_shape().as_list()
#根据.get_shape()函数得到 pool2 输出矩阵的维度
# pool_shape[1] 为长 pool_shape[2] 为宽 pool_shape[3]为高
nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]
#得到矩阵被拉长后的长度,pool_shape[0]为batch值
reshaped = tf.reshape(pool2, [pool_shape[0], nodes])
#4 实现第三层全连接层
#初始化全连接层的权重,并加入正则化。
fc1_w = get_weight([nodes, FC_SIZE], regularizer)
fc1_b = get_bias([FC_SIZE])
fc1 = tf.nn.relu(tf.matmul(reshaped, fc1_w) + fc1_b)
# 如果是训练阶段,则对该层输出使用50%dropout
#即随机的将该层输出中的一半神经元置为无效,是为了避免过拟合而设置的,一般只在全连接层中使用。
if train: fc1 = tf.nn.dropout(fc1, 0.5)
#5 实现第四层全连接层
fc2_w = get_weight([FC_SIZE, OUTPUT_NODE], regularizer)
fc2_b = get_bias([OUTPUT_NODE])
y = tf.matmul(fc1, fc2_w) + fc2_b
return y
get_shape 函数用于获取一个张量的维度,并且输出张量每个维度上面的值。
例如:
A = tf.random_normal(shape=[3,4])
print A.get_shape()
输出结果为:(3,4)
2)mnist_lenet5_backward.py文件
#卷积输入为四阶张量
#第一阶表示每轮喂入的图片数量,第二阶和第三阶分别表示图片的行分辨率和列分辨率,第四阶表示通道数
x = tf.placeholder(tf.float32, [
BATCH_SIZE,
mnist_lenet5_forward.IMAGE_SIZE,
mnist_lenet5_forward.IMAGE_SIZE,
mnist_lenet5_forward.NUM_CHANNELS])
y_ = tf.placeholder(tf.float32, [None, mnist_lenet5_forward.OUTPUT_NODE])
————————————————
# 读取一个batch数据,.reshape将输入数据xs转成与网络输入相同形状的矩阵
xs, ys = mnist.train.next_batch(BATCH_SIZE)
reshaped_xs = np.reshape(xs, (
BATCH_SIZE,
mnist_lenet5_forward.IMAGE_SIZE,
mnist_lenet5_forward.IMAGE_SIZE,
mnist_lenet5_forward.NUM_CHANNELS))
# 读取一个batch数据,将输入数据xs转成与网络输入相同形状的矩阵
, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: reshaped_xs, y: ys})
if i % 100 == 0:
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)
def main():
————————————————
3)mnist_lenet5_test.py文件,也对x形状进行改变,不使用dropout
#训练好的网络,故不使用 dropout
y = mnist_lenet5_forward.forward(x,False,None)