TensorFlow搭建神经网络

  • TensorFlow版本:2.13.0
  • TensorFlow官方文档
  • TensorFlow官方文档中文版

TensorFlow中搭建并训练一个神经网络分为以下几步:

  1. 定义神经网络
  2. 配置损失函数以及优化器
  3. 训练:反向传播、梯度下降

下面以LeNet-5为例,搭建一个卷积神经网络用于手写数字识别。(LeNet-5以及MNIST数据集介绍见PyTorch搭建神经网络)

1. 定义神经网络

TensorFlow提供了三种构建神经网络的方法,分别是继承Model类自定义模型、序列式以及函数式。

1.1 继承Model类自定义

  • 继承 keras.Model
  • 重写父类的 call 方法,该方法负责前向计算

例如:

from keras import layers
from tensorflow import keras


class MyModel(keras.Model):
    def __init__(self):
        super(MyModel, self).__init__()

        self.conv1 = layers.Conv2D(filters=6, kernel_size=(5, 5), strides=(1, 1), activation='relu')
        self.pool1 = layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2))
        self.conv2 = layers.Conv2D(filters=16, kernel_size=(5, 5), strides=(1, 1), activation='relu')
        self.pool2 = layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2))

        self.fc1 = layers.Dense(units=16 * 4 * 4, activation='relu')
        self.fc2 = layers.Dense(units=120, activation='relu')
        self.fc3 = layers.Dense(units=10, activation='softmax')

    def call(self, x):
        x = self.conv1(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = self.pool2(x)

        x = layers.Flatten()(x)  # 二维压缩成一维

        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        return x

1.2 序列式

  • 该方式适用于简单的层堆栈,其中每一层恰好有一个输入张量和一个输出张量
  • 在以下情况下不适合使用该方法:
    • 模型有多个输入或多个输出
    • 任何层都有多个输入或多个输出
    • 需要进行图层共享
    • 想要非线性拓扑(如残差连接、多分支模型)

例如:

from keras import layers
from tensorflow import keras


def my_model():
    model = keras.Sequential()

    model.add(layers.Conv2D(filters=6, kernel_size=(5, 5), strides=(1, 1), activation='relu'))
    model.add(layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2)))
    model.add(layers.Conv2D(filters=16, kernel_size=(5, 5), strides=(1, 1), activation='relu'))
    model.add(layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2)))

    model.add(layers.Flatten())

    model.add(layers.Dense(units=16 * 4 * 4, activation='relu'))
    model.add(layers.Dense(units=120, activation='relu'))
    model.add(layers.Dense(units=10, activation='softmax'))

    # 另一种堆叠神经网络的方式
    '''
    model = keras.Sequential(
        [
            layers.Conv2D(filters=6, kernel_size=(5, 5), strides=(1, 1), activation='relu'),
            layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2)),
            layers.Conv2D(filters=16, kernel_size=(5, 5), strides=(1, 1), activation='relu'),
            layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2)),

            layers.Flatten(),

            layers.Dense(units=16 * 4 * 4, activation='relu'),
            layers.Dense(units=120, activation='relu'),
            layers.Dense(units=10, activation='softmax'),
        ]
    )
    '''

    return model

1.3 函数式

  • 该方法允许多个输入、多个输出、分支和层共享,是构建Keras模型最流行的方法
  • 深度学习的模型通常是由层 (layers) 组成的有向无环图,而函数式就是构建这种图的一种有效方式
  • 该方法:
    • 需要单独定义输入
    • 然后,需要创建一个输出对象,同时创建所有层,这些层相互关联并与输出相关联
    • 最后,创建一个接受输入和输出作为参数的模型对象

例如:

from keras import layers
from tensorflow import keras


def my_model(input_shape):
    # 首先,创建一个输入节点
    inputs = keras.Input(input_shape)

    # 搭建神经网络
    x = layers.Conv2D(filters=6, kernel_size=(5, 5), strides=(1, 1), activation='relu')(inputs)
    x = layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2))(x)
    x = layers.Conv2D(filters=16, kernel_size=(5, 5), strides=(1, 1), activation='relu')(x)
    x = layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2))(x)

    x = layers.Flatten()(x)

    x = layers.Dense(units=16 * 4 * 4, activation='relu')(x)
    x = layers.Dense(units=120, activation='relu')(x)

    # 输出层
    outputs = layers.Dense(units=10, activation='softmax')(x)

    model = keras.Model(inputs=inputs, outputs=outputs)

    return model

2. 配置损失函数以及优化器

  • 损失函数

    损失函数用于计算真实值和预测值之间的差异。在TensorFlow官方文档中,给出了可用的损失函数列表。

    这里,我们使用交叉熵损失函数keras.losses.SparseCategoricalCrossentropy。该损失函数有一个参数from_logits ,该参数决定是否对预测值进行Softmax,默认值为 false

  • 优化器

    优化器根据损失函数求出的损失,对神经网络的参数进行更新。在TensorFlow官方文档中,给出了可用的优化器。这里,我们使用keras.optimizers.SGD作为我们的优化器。

from tensorflow import keras


loss = keras.losses.SparseCategoricalCrossentropy()  # 预测值已Softmax,from_logits 取默认值
optimizer = keras.optimizers.SGD(0.0001)

3. 训练以及测试模型

3.1训练模型

模型训练只需在配置好训练参数后调用 fit 函数即可,该函数会自动进行前向计算、反向传播、梯度下降。

如:

# 加载数据集
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()

# 维度调整,增加一个维度代表通道数
# 卷积神经网络的输入数据是4维的,分别代表: batch size,图片高度、宽度、通道数
# 批量大小在训练时指定,因此输入的数据应该是3维的,分别代表:图片高度、宽度、通道数
train_images = tf.reshape(train_images, (train_images.shape[0], train_images.shape[1], train_images.shape[2], 1))
train_images = tf.cast(train_images, tf.float32)

test_images = tf.reshape(test_images, (test_images.shape[0], test_images.shape[1], test_images.shape[2], 1))
test_images = tf.cast(test_images, tf.float32)

model = my_model(train_images.shape[1:])

# 配置神经网络,设置损失函数、优化器
loss = keras.losses.SparseCategoricalCrossentropy()  # 预测值已Softmax,from_logits 取默认值
optimizer = keras.optimizers.SGD(0.0001)
model.compile(loss=loss, optimizer=keras.optimizers.SGD(0.00001))

# 训练神经网络,设置训练集与验证集的比例、迭代次数、batch size等
model.fit(train_images, train_labels, validation_split=0.3, epochs=1000, batch_size=20)

注:

TensorFlow会自动决定是使用GPU还是CPU,默认情况下优先使用GPU

3.2 测试模型

模型训练只需调用 predict 函数即可。

pre_labels = model.predict(test_images)

4. 整体代码

import tensorflow as tf
from keras import datasets
from keras import layers
from tensorflow import keras


def my_model(input_shape):
    # 首先,创建一个输入节点
    inputs = keras.Input(input_shape)

    # 搭建神经网络
    x = layers.Conv2D(filters=6, kernel_size=(5, 5), strides=(1, 1), activation='relu')(inputs)
    x = layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2))(x)
    x = layers.Conv2D(filters=16, kernel_size=(5, 5), strides=(1, 1), activation='relu')(x)
    x = layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2))(x)

    x = layers.Flatten()(x)

    x = layers.Dense(units=16 * 4 * 4, activation='relu')(x)
    x = layers.Dense(units=120, activation='relu')(x)

    # 输出层
    outputs = layers.Dense(units=10, activation='softmax')(x)

    model = keras.Model(inputs=inputs, outputs=outputs)

    return model


# 加载数据集
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()

# 维度调整,增加一个维度代表通道数
# 卷积神经网络的输入数据是4维的,分别代表: batch size,图片高度、宽度、通道数
# 批量大小在训练时指定,因此输入的数据应该是3维的,分别代表:图片高度、宽度、通道数
train_images = tf.reshape(train_images, (train_images.shape[0], train_images.shape[1], train_images.shape[2], 1))
train_images = tf.cast(train_images, tf.float32)

test_images = tf.reshape(test_images, (test_images.shape[0], test_images.shape[1], test_images.shape[2], 1))
test_images = tf.cast(test_images, tf.float32)

model = my_model(train_images.shape[1:])

# 配置神经网络,设置损失函数、优化器
loss = keras.losses.SparseCategoricalCrossentropy()  # 预测值已Softmax,from_logits 取默认值
optimizer = keras.optimizers.SGD(0.0001)
model.compile(loss=loss, optimizer=keras.optimizers.SGD(0.00001))

# 训练神经网络,设置训练集与验证集的比例、迭代次数、batch size等
model.fit(train_images, train_labels, validation_split=0.3, epochs=1000, batch_size=20)

pre_labels = model.predict(test_images)

你可能感兴趣的:(深度学习,tensorflow,神经网络)