通过tensorflow.layers(tf.layers)的高级API进行神经网络训练,实现一个多层感知器来分辨MNIST数据集中的手写数字

import os
import sys
import struct
import numpy as np
import matplotlib.pyplot as plt
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

def load_mnist(path, kind='train'):
    """Load MNIST data from `path`"""
    # 图像以字节的格式存储
    labels_path = os.path.join(path,
                               '%s-labels-idx1-ubyte\\%s-labels.idx1-ubyte' % (kind, kind))
    images_path = os.path.join(path,
                               '%s-images-idx3-ubyte\\%s-images.idx3-ubyte' % (kind, kind))

    with open(labels_path, 'rb') as lbpath:
        # 返回一个由解包数据(string)得到的一个元组(tuple), 即使仅有一个数据也会被解包成元组
        # struct.pack()和struct.unpack()
        # >:这是大端字节序,它定义一串字节存储的顺序
        # 计算机的内部处理都是小端字节序。但是,人类还是习惯读写大端字节序
        # I:代表无符号整数
        magic, n = struct.unpack('>II',
                                 lbpath.read(8))
        # 存取数组内容的文件操作函数,fromfile()函数读回数据时需要用户指定元素类型,
        # 并对数组的形状进行适当的修改
        labels = np.fromfile(lbpath,
                             dtype=np.uint8)

    with open(images_path, 'rb') as imgpath:
        magic, num, rows, cols = struct.unpack(">IIII",
                                               imgpath.read(16))
        images = np.fromfile(imgpath,
                             dtype=np.uint8).reshape(len(labels), 784)
        # 逐个像素调整图像比例
        images = ((images / 255.) - .5) * 2

    return images, labels

X_train, y_train = load_mnist('xxx',
                              kind='train')
print('Rows: %d, columns: %d' % (X_train.shape[0], X_train.shape[1]))
X_test, y_test = load_mnist('xxx',
                            kind='t10k')
print('Rows: %d, columns: %d' % (X_test.shape[0], X_test.shape[1]))

## mean centering and normalization:
mean_vals = np.mean(X_train, axis=0)
std_val = np.std(X_train)
X_train_centered = (X_train - mean_vals)/std_val
X_test_centered = (X_test - mean_vals)/std_val
del X_train, X_test
print(X_train_centered.shape, y_train.shape)
print(X_test_centered.shape, y_test.shape)

n_features = X_train_centered.shape[1]
n_classes = 10
random_seed = 123
np.random.seed(random_seed)

# 全连接层:通常在CNN的尾部进行重新拟合,减少特征信息的损失
g = tf.Graph()
with g.as_default():
    tf.set_random_seed(random_seed)
    tf_x = tf.placeholder(dtype=tf.float32,
                       shape=(None, n_features),
                       name='tf_x')

    tf_y = tf.placeholder(dtype=tf.int32,
                        shape=None, name='tf_y')
    y_onehot = tf.one_hot(indices=tf_y, depth=n_classes)

    h1 = tf.layers.dense(inputs=tf_x, units=50,
                         activation=tf.tanh,  # 双曲正切曲线
                         name='layer1')

    h2 = tf.layers.dense(inputs=h1, units=50,
                         activation=tf.tanh,
                         name='layer2')

    logits = tf.layers.dense(inputs=h2,
                             units=10,
                             activation=None,
                             name='layer3')

    predictions = {
        'classes' : tf.argmax(logits, axis=1,
                              name='predicted_classes'),
        'probabilities' : tf.nn.softmax(logits,
                              name='softmax_tensor')
    }

# 定义成本函数
with g.as_default():
    # 计算 logits 和 labels 之间的 softmax 交叉熵
    cost = tf.losses.softmax_cross_entropy(
            onehot_labels=y_onehot, logits=logits)

    # 随机梯度下降作为优化的算法
    optimizer = tf.train.GradientDescentOptimizer(
            learning_rate=0.001)

    train_op = optimizer.minimize(loss=cost)

    init_op = tf.global_variables_initializer()

# 生成大量数据的一个生成器
def create_batch_generator(X, y, batch_size=128, shuffle=False):
    X_copy = np.array(X)
    y_copy = np.array(y)

    if shuffle:
        data = np.column_stack((X_copy, y_copy))
        np.random.shuffle(data)
        X_copy = data[:, :-1]
        y_copy = data[:, -1].astype(int)

    for i in range(0, X.shape[0], batch_size):
        yield (X_copy[i:i + batch_size, :], y_copy[i:i + batch_size])

# 创建一个新的TensorFlow会话,初始化网络中的所有变量并对其进行训练。
# 同时也显示每次迭代后的平均训练损失
## create a session to launch the graph
sess =  tf.Session(graph=g)
## run the variable initialization operator
sess.run(init_op)
## 50 epochs of training:
training_costs = []
for epoch in range(50):
    training_loss = []
    batch_generator = create_batch_generator(
            X_train_centered, y_train,
            batch_size=64)
    for batch_X, batch_y in batch_generator:
        ## prepare a dict to feed data to our network:
        feed = {tf_x:batch_X, tf_y:batch_y}
        _, batch_cost = sess.run([train_op, cost],
                                 feed_dict=feed)
        training_costs.append(batch_cost)
    print(' -- Epoch %2d  '
          'Avg. Training Loss: %.4f' % (
              epoch+1, np.mean(training_costs)
    ))

# 预测:
feed = {tf_x: X_test_centered}
y_pred = sess.run(predictions['classes'],
                  feed_dict=feed)

print('Test Accuracy: %.2f%%' % (
        100 * np.sum(y_pred == y_test) / y_test.shape[0]))

运行结果:
Rows: 60000, columns: 784
Rows: 10000, columns: 784
(60000, 784) (60000,)
(10000, 784) (10000,)

– Epoch 1 Avg. Training Loss: 1.5841
– Epoch 2 Avg. Training Loss: 1.2739
– Epoch 3 Avg. Training Loss: 1.1002
– Epoch 4 Avg. Training Loss: 0.9846
– Epoch 5 Avg. Training Loss: 0.9005
– Epoch 6 Avg. Training Loss: 0.8360
– Epoch 7 Avg. Training Loss: 0.7845
– Epoch 8 Avg. Training Loss: 0.7422
– Epoch 9 Avg. Training Loss: 0.7067
– Epoch 10 Avg. Training Loss: 0.6764
– Epoch 11 Avg. Training Loss: 0.6501
– Epoch 12 Avg. Training Loss: 0.6271
– Epoch 13 Avg. Training Loss: 0.6066
– Epoch 14 Avg. Training Loss: 0.5884
– Epoch 15 Avg. Training Loss: 0.5719
– Epoch 16 Avg. Training Loss: 0.5569
– Epoch 17 Avg. Training Loss: 0.5433
– Epoch 18 Avg. Training Loss: 0.5308
– Epoch 19 Avg. Training Loss: 0.5192
– Epoch 20 Avg. Training Loss: 0.5085
– Epoch 21 Avg. Training Loss: 0.4985
– Epoch 22 Avg. Training Loss: 0.4892
– Epoch 23 Avg. Training Loss: 0.4805
– Epoch 24 Avg. Training Loss: 0.4724
– Epoch 25 Avg. Training Loss: 0.4647
– Epoch 26 Avg. Training Loss: 0.4574
– Epoch 27 Avg. Training Loss: 0.4505
– Epoch 28 Avg. Training Loss: 0.4440
– Epoch 29 Avg. Training Loss: 0.4378
– Epoch 30 Avg. Training Loss: 0.4319
– Epoch 31 Avg. Training Loss: 0.4262
– Epoch 32 Avg. Training Loss: 0.4209
– Epoch 33 Avg. Training Loss: 0.4157
– Epoch 34 Avg. Training Loss: 0.4108
– Epoch 35 Avg. Training Loss: 0.4060
– Epoch 36 Avg. Training Loss: 0.4015
– Epoch 37 Avg. Training Loss: 0.3971
– Epoch 38 Avg. Training Loss: 0.3929
– Epoch 39 Avg. Training Loss: 0.3888
– Epoch 40 Avg. Training Loss: 0.3849
– Epoch 41 Avg. Training Loss: 0.3811
– Epoch 42 Avg. Training Loss: 0.3775
– Epoch 43 Avg. Training Loss: 0.3739
– Epoch 44 Avg. Training Loss: 0.3705
– Epoch 45 Avg. Training Loss: 0.3672
– Epoch 46 Avg. Training Loss: 0.3639
– Epoch 47 Avg. Training Loss: 0.3608
– Epoch 48 Avg. Training Loss: 0.3578
– Epoch 49 Avg. Training Loss: 0.3548
– Epoch 50 Avg. Training Loss: 0.3519
Test Accuracy: 93.67%

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐