TF04-01: 使用Keras实现Le-Net5卷积神经网络

  本主题使用Tensorflow的高级API Keras实现Le-Net5卷积神经网络;
  备注:在Keras之前,Tensorflow提供layers包提供了层的封装,并提供对应的函数实现层的快捷创建方式。
  备注:训练结果是MNIST手写数字的部分样本进行训练与测试。


使用的包

%matplotlib inline
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
import math

一、输入层

#    1.1 训练集输入
input_layer_x = tf.keras.layers.Input(
    shape=(28, 28, 1),
    batch_size=None,
    dtype=tf.float32)

#    1.2 训练集标签
input_layer_y = tf.keras.layers.Input(
    shape=(10,),
    batch_size=None,
    dtype=tf.float32)

二、卷积层

# 2. 卷积层,池化层,dropout层
#    2.1 第一层 28*28*1->14*14*6
convolved_layer_28_28_6 = tf.keras.layers.Conv2D(
    filters=6,
    kernel_size=5,                        # 也可以元组,分别指定高宽(5, 5),
    strides=1,                            # 也可以元组,分别指定高宽(1, 1),
    padding='same',
    data_format='channels_last',          # 元组最后一个是通道数
    activation=tf.nn.relu                 # 激活函数
)(input_layer_x)
pooled_layer_14_14_6 = tf.keras.layers.MaxPool2D(
    pool_size=2,                          # 池化核大小,可以使用元组(2,2)
    strides=2,                            # 步长,可以使用元组(2,2)
    padding='valid',                      # 数据不足,是否补边
    data_format='channels_last'
)(convolved_layer_28_28_6)
#    2.2 第二层 14*14*6 -> 5*5*16
convolved_layer_10_10_16 = tf.keras.layers.Conv2D(
    filters=16,
    kernel_size=5,                        # 也可以元组,分别指定高宽(5, 5),
    strides=1,                            # 也可以元组,分别指定高宽(1, 1),
    padding='valid',
    data_format='channels_last',          # 元组最后一个是通道数
    activation=tf.nn.relu                 # 激活函数
)(pooled_layer_14_14_6)
pooled_layer_5_5_6 = tf.keras.layers.MaxPool2D(
    pool_size=2,                          # 池化核大小,可以使用元组(2,2)
    strides=2,                            # 步长,可以使用元组(2,2)
    padding='valid',                      # 数据不足,是否补边
    data_format='channels_last'
)(convolved_layer_10_10_16)
#    2.3 第三层 5*5*16 -> 1*1*120
convolved_layer_1_1_120 = tf.keras.layers.Conv2D(
    filters=120,
    kernel_size=5,                        # 也可以元组,分别指定高宽(5, 5),
    strides=1,                            # 也可以元组,分别指定高宽(1, 1),
    padding='valid',
    data_format='channels_last',          # 元组最后一个是通道数
    activation=tf.nn.relu                 # 激活函数
)(pooled_layer_5_5_6)

三、卷积层到全连接层格式转换

fc_120 = tf.keras.layers.Flatten(
    data_format='channels_last'
)(convolved_layer_1_1_120)

四、全连接层

# 3. 全连接层
#    3.2 第一层 120->84
fc_84 = tf.keras.layers.Dense(
    units=84,
    activation=tf.nn.relu
)(fc_120)
#    3.3 第二层 84->10
fc_10 = tf.keras.layers.Dense(
    units=10,
    activation=None,                # 最后不需要激活函数,使用的是f(x)=x恒等激活函数
)(fc_84)


五、损失函数与优化器

# 4. 损失函数与优化器
# 预测模型
o_predict = tf.nn.sigmoid(fc_10)
# 损失函数
loss = tf.losses.sigmoid_cross_entropy(input_layer_y, fc_10)
optimizer = tf.train.AdamOptimizer(0.0001)
opt_op = optimizer.minimize(loss)
print('Le-Net5神经网络模型定义完毕!')

六、模型训练

  • 这里训练采用了原始的方式(Tensorflow提供了更好的封装)
# 5. 数据加载-------------------------------------------------------
SAMPLE_PATH = 'samples/'
# 加载训练标签
result = np.loadtxt(SAMPLE_PATH + "train.txt", np.int)
NUM = 2000  # 训练集60000个,为了速度取一部分
result = result[0:NUM]
labels = np.zeros((len(result), 10), dtype=np.int)
for i in range(len(result)):
    lb = result[I]
    labels[i][lb] = 1

# 加载图像数据
# 把图像数据转换成需要的格式
data = np.zeros((len(result), 28, 28, 1), np.float32)
for i in range(len(result)):
    # print('加载图像:%d' % I )
    img = np.array([plt.imread(SAMPLE_PATH + "train/TrainImage_%05d.bmp" % (i + 1))])
    data[i, :, :, 0] = img
print("加载完毕训练样本,个数:(%d)" % len(result))

# 加载测试集
# 加载测试标签
test_result = np.loadtxt(SAMPLE_PATH + "test.txt", np.int)
NUM = 200  # 测试集10000个,为了速度取一部分
test_result = test_result[0:NUM]

test_labels = np.zeros((len(test_result), 10), dtype=np.int)
for i in range(len(test_result)):
    lb = test_result[I]
    test_labels[i][lb] = 1

# 加载测试数据
test_data = np.zeros((len(test_result), 28, 28, 1), np.float32)
for i in range(len(test_result)):
    # print('加载图像:%d' % I )
    img = np.array([plt.imread(SAMPLE_PATH + "test/TestImage_%05d.bmp" % (i + 1))])
    test_data[i, :, :, 0] = img
print("加载完毕测试样本,个数:(%d)" % len(test_result))
# 6. 训练--------------------------------------------------------
# 定义准确率
correct = tf.equal(tf.argmax(o_predict, 1), tf.argmax(input_layer_y, 1))
accuracy = tf.reduce_mean(tf.cast(correct, 'float'))
# 执行训练
session = tf.Session()
session.run(tf.global_variables_initializer())

# 训练相关线束
TIMES = 1000
batch_size = 200
batch = int(math.ceil(len(data) / batch_size))
correct_rates = []  # 记录准确率,用于可视化。

is_over = False
for t in range(TIMES):
    loss_result = 0.0
    for idx in range(batch):
        _, loss_result = session.run([opt_op, loss],  # 边训练,边计算损失值。
                                     feed_dict={
                                         input_layer_x: data[idx * batch_size:(idx + 1) * batch_size],
                                         input_layer_y: labels[idx * batch_size:(idx + 1) * batch_size]})
        if loss_result < 0.000000001:
            is_over = True
            break

    # 没一轮训练就评估效果
    if t % 50 == 0:
        # 评估准确率
        correct_rate = session.run(accuracy, feed_dict={input_layer_x: test_data, input_layer_y: test_labels})
        # 输出
        print('测试集正确率: %5.2f%%,损失度:%f' % (correct_rate * 100.0, loss_result))
        correct_rates.append(correct_rate)
    if is_over:
        break
print('训练完毕')

七、训练结果可视化

# 7. 可视化训练过程中的准确率
# 可视化一下训练过程
figure = plt.figure(figsize=(8, 4))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8])
ax.plot(range(len(correct_rates)), correct_rates, color=(0, 0, 1, 1), marker='.', label='正确率曲线',
        markerfacecolor=(1, 0, 0, 1), markeredgecolor=(1, 0, 0, 1), markersize=3)
ax.set_xbound(lower=-1, upper=len(correct_rates))
ax.set_ybound(lower=0, upper=1)
plt.annotate(s='最高识别率:%5.2f%%' % (max(correct_rates) * 100.0), xy=(60, 0.5))
plt.legend()
# plt.grid(b=True)

plt.show()

输出结果

  • 运行输出
Le-Net5神经网络模型定义完毕!
加载完毕训练样本,个数:(2000)
加载完毕测试样本,个数:(200)
测试集正确率: 13.00%,损失度:0.702731
测试集正确率: 94.00%,损失度:0.017105
测试集正确率: 95.50%,损失度:0.002867
测试集正确率: 96.00%,损失度:0.000916
测试集正确率: 96.00%,损失度:0.000415
测试集正确率: 97.00%,损失度:0.000220
测试集正确率: 97.00%,损失度:0.000128
测试集正确率: 97.00%,损失度:0.000080
测试集正确率: 97.50%,损失度:0.000052
测试集正确率: 97.50%,损失度:0.000035
测试集正确率: 98.00%,损失度:0.000024
测试集正确率: 98.00%,损失度:0.000017
测试集正确率: 98.00%,损失度:0.000012
测试集正确率: 98.00%,损失度:0.000009
测试集正确率: 98.50%,损失度:0.000006
测试集正确率: 98.50%,损失度:0.000005
测试集正确率: 98.50%,损失度:0.000003
测试集正确率: 98.50%,损失度:0.000002
测试集正确率: 98.50%,损失度:0.000002
测试集正确率: 98.50%,损失度:0.000001
训练完毕
  • 可视化输出


    测试集识别正确率曲线

你可能感兴趣的:(TF04-01: 使用Keras实现Le-Net5卷积神经网络)