欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

tensorflow2.0教程—快速入门

程序员文章站 2024-03-23 13:16:22
...


本文主要讲解tensorflow 2.0 搭建网络结构的技术细节。

在使用tensorflow 之前首先导入tensorflow

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
print(tf.__version__)
print(tf.keras.__version__)

tensorflow推荐使用keras构建网络,常见的方式有二种:序列化API、函数式API。

模型的序列化API

基本示例

序列化模型常用于:简单的神经网络层的堆叠。每一层都有一个输入tensor和一个输出tensor。

示例如下:

# Define Sequential model with 3 layers
model = keras.Sequential(
    [
        keras.Input(shape=(3,3)),
        layers.Dense(2, activation="relu", name="layer1"),
        layers.Dense(3, activation="relu", name="layer2"),
        layers.Dense(4, name="layer3"),
    ]
)
# Call model on a test input
x = tf.ones((3, 3))
y = model(x)

或者:

# Create 3 layers
layer1 = layers.Dense(2, activation="relu", name="layer1")
layer2 = layers.Dense(3, activation="relu", name="layer2")
layer3 = layers.Dense(4, name="layer3")

# Call layers on a test input
x = tf.ones((3, 3))
y = layer3(layer2(layer1(x)))

或者:

model = keras.Sequential()
model.add(layers.Dense(2, activation="relu"))
model.add(layers.Dense(3, activation="relu"))
model.add(layers.Dense(4))

推荐在模型一开始就定义模型的输入大小

model = keras.Sequential()
model.add(layers.Dense(2, activation="relu", input_shape=(4,)))

模型细节查看

通过以下代码查看模型细节:

model.summary()  # 在模型构建过程中随时查看output Shape

tensorflow2.0教程—快速入门

model.weights

tensorflow2.0教程—快速入门

查看序列化模型中间层的输出

initial_model = keras.Sequential(
    [
        keras.Input(shape=(250, 250, 3)),
        layers.Conv2D(32, 5, strides=2, activation="relu"),
        layers.Conv2D(32, 3, activation="relu",name="my_intermediate_layer"),
        layers.Conv2D(32, 3, activation="relu"),
    ]
)
# 方式一:查看最终结果
feature_extractor = keras.Model(
    inputs=initial_model.inputs,
    outputs=[layer.output for layer in initial_model.layers],
)
# 方式二:通过层名称查看输出结果
feature_extractor = keras.Model(
    inputs=initial_model.inputs,
    outputs=initial_model.get_layer(name="my_intermediate_layer").output,
)
# Call feature extractor on test input.
x = tf.ones((1, 250, 250, 3))
features = feature_extractor(x)

tensorflow2.0教程—快速入门

序列化API型缺陷

序列化模型不适用以下情况:

(1) 模型含有多个输入或多个输出

(2) 模型中的某一层含有多个输入或多个输出

(3) 模型中存在层共享的情况

(4) 模型中存在类似残差网络这样的非线性模型。

由于存在这些缺陷,我们引入函数式模型。

模型的函数式API

函数式API可以处理具有非线性拓扑的模型(残差神经网络),具有共享层的模型以及具有多个输入或输出的模型。

基本步骤

(1) 创建一个输入节点,常见的输入有以下两种:

# 输入是一个784维的向量,样本数不用指定,
inputs = keras.Input(shape=(784,))
# 输入是一个大小为32x32的3通道图片
img_inputs = keras.Input(shape=(32, 32, 3))

可以通过:inputs.shape,inputs.dtype来查看输入节点基本细节。

(2)定义其他网络层,以函数调用的形式同时传入inputs

x = layers.Dense(64, activation="relu")(inputs)
x = layers.Dense(64, activation="relu")(x)
outputs = layers.Dense(10)(x)

(3) 指定输入输出,创建模型

model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")

应用

1、 图片的编码解码器

先定义一个encoder:

encoder_input = keras.Input(shape=(28, 28, 1), name="original_img")
x = layers.Conv2D(16, 3, activation="relu")(encoder_input)
x = layers.Conv2D(32, 3, activation="relu")(x)
x = layers.MaxPooling2D(3)(x)
x = layers.Conv2D(32, 3, activation="relu")(x)
x = layers.Conv2D(16, 3, activation="relu")(x)
encoder_output = layers.GlobalMaxPooling2D()(x)

encoder = keras.Model(encoder_input, encoder_output, name="encoder")
encoder.summary()

再定义一个解码器decoder:

decoder_input = keras.Input(shape=(16,), name="encoded_img")
x = layers.Reshape((4, 4, 1))(decoder_input)
x = layers.Conv2DTranspose(16, 3, activation="relu")(x)
x = layers.Conv2DTranspose(32, 3, activation="relu")(x)
x = layers.UpSampling2D(3)(x)
x = layers.Conv2DTranspose(16, 3, activation="relu")(x)
decoder_output = layers.Conv2DTranspose(1, 3, activation="relu")(x)

decoder = keras.Model(decoder_input, decoder_output, name="decoder")
decoder.summary()

将图片先输入编码器,对输出结果进行解码,形成新的模型autoencoder

autoencoder_input = keras.Input(shape=(28, 28, 1), name="img")
encoded_img = encoder(autoencoder_input)
decoded_img = decoder(encoded_img)
autoencoder = keras.Model(autoencoder_input, decoded_img, name="autoencoder")
autoencoder.summary()

2、以下是将一组模型合并为一个平均其预测的模型的方法:

def get_model():
    inputs = keras.Input(shape=(128,))
    outputs = layers.Dense(1)(inputs)
    return keras.Model(inputs, outputs)


model1 = get_model()
model2 = get_model()
model3 = get_model()

inputs = keras.Input(shape=(128,))
y1 = model1(inputs)
y2 = model2(inputs)
y3 = model3(inputs)
outputs = layers.average([y1, y2, y3])
ensemble_model = keras.Model(inputs=inputs, outputs=outputs)

3、层共享

共享层通常用于编码来自相似空间的输入(例如,两个具有相似词汇的不同文本)。它们可以在这些不同的输入之间共享信息,并且可以在更少的数据上训练这种模型。下面是两个不同的文本输入共享的嵌入层:

# Embedding for 1000 unique words mapped to 128-dimensional vectors
shared_embedding = layers.Embedding(1000, 128)

# Variable-length sequence of integers
text_input_a = keras.Input(shape=(None,), dtype="int32")

# Variable-length sequence of integers
text_input_b = keras.Input(shape=(None,), dtype="int32")

# Reuse the same layer to encode both inputs
encoded_input_a = shared_embedding(text_input_a)
encoded_input_b = shared_embedding(text_input_b)

模型的训练和评估

(1)加载数据集

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# Preprocess the data (these are NumPy arrays)
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255

y_train = y_train.astype("float32")
y_test = y_test.astype("float32")

# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]

(2)模型的compile

在训练之前,通过compile( ) 指定模型的损失函数,优化器,评价指标:

model.compile(
    optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=[keras.metrics.SparseCategoricalAccuracy()],
)

或者:

model.compile(
    optimizer="rmsprop",
    loss="sparse_categorical_crossentropy",
    metrics=["sparse_categorical_accuracy"],
)

常见的使用参数如下:

参数
Optimizers SGD(), RMSprop() ,Adam()
Losses MeanSquaredError(),KLDivergence(),CosineSimilarity()
Metrics AUC()、Precision()、Recall()

也可自定义模型的Metrics,loss

def custom_mean_squared_error(y_true, y_pred):
    return tf.math.reduce_mean(tf.square(y_true - y_pred))


model.compile(optimizer=keras.optimizers.Adam(), loss=custom_mean_squared_error)

# We need to one-hot encode the labels to use MSE
y_train_one_hot = tf.one_hot(y_train, depth=10)
model.fit(x_train, y_train_one_hot, batch_size=64, epochs=1)

为了使用上的方便,可以通常将模型的定义与编译封装到一个函数中:

def get_uncompiled_model():
    inputs = keras.Input(shape=(784,), name="digits")
    x = layers.Dense(64, activation="relu", name="dense_1")(inputs)
    x = layers.Dense(64, activation="relu", name="dense_2")(x)
    outputs = layers.Dense(10, activation="softmax", name="predictions")(x)
    model = keras.Model(inputs=inputs, outputs=outputs)
    return model


def get_compiled_model():
    model = get_uncompiled_model()
    model.compile(
        optimizer="rmsprop",
        loss="sparse_categorical_crossentropy",
        metrics=["sparse_categorical_accuracy"],
    )
    return model

(3)模型的训练

print("Fit model on training data")
history = model.fit(
    x_train,
    y_train,
    batch_size=64,
    epochs=2,
    # We pass some validation for
    # monitoring validation loss and metrics
    # at the end of each epoch
    validation_data=(x_val, y_val),
)

可以通过history查看训练的损失值:

history.history

tensorflow2.0教程—快速入门

当训练数据数Numpy时,也可以事先不做验证集切分,直接通过validation_split设置验证集的大小:

model = get_compiled_model()
model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1)

在训练过程中可以指定类别权重和样本权重

指定类别权重:

import numpy as np

class_weight = {
    0: 1.0,
    1: 1.0,
    2: 1.0,
    3: 1.0,
    4: 1.0,
    # Set weight "2" for class "5",
    # making this class 2x more important
    5: 2.0,
    6: 1.0,
    7: 1.0,
    8: 1.0,
    9: 1.0,
}

print("Fit with class weight")
model = get_compiled_model()
model.fit(x_train, y_train, class_weight=class_weight, batch_size=64, epochs=1)

指定样本权重:

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.0

print("Fit with sample weight")
model = get_compiled_model()
model.fit(x_train, y_train, sample_weight=sample_weight, batch_size=64, epochs=1)

(4)模型的评估、预测

# Evaluate the model on the test data using `evaluate`
print("Evaluate on test data")
results = model.evaluate(x_test, y_test, batch_size=128)
print("test loss, test acc:", results)

# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print("Generate predictions for 3 samples")
predictions = model.predict(x_test[:3])
print("predictions shape:", predictions.shape)

tensorflow2.0教程—快速入门

多输入多输出模型

下图是一张典型的多输入多输出模型结构图:

tensorflow2.0教程—快速入门

模型代码如下:

image_input = keras.Input(shape=(32, 32, 3), name="img_input")
timeseries_input = keras.Input(shape=(None, 10), name="ts_input")

x1 = layers.Conv2D(3, 3)(image_input)
x1 = layers.GlobalMaxPooling2D()(x1)

x2 = layers.Conv1D(3, 3)(timeseries_input)
x2 = layers.GlobalMaxPooling1D()(x2)

x = layers.concatenate([x1, x2])  # 链接两个输出

score_output = layers.Dense(1, name="score_output")(x)
class_output = layers.Dense(5, activation="softmax", name="class_output")(x)

# 注意这里如何将数据输入模型已经如何接受模型的输出
model = keras.Model(
    inputs=[image_input, timeseries_input], outputs=[score_output, class_output]
)

在模型编译时可以传入多个loss和评估指标,并指定名称:

model.compile(
    optimizer=keras.optimizers.RMSprop(1e-3),
    loss={
        "score_output": keras.losses.MeanSquaredError(),  # 设置为None 时表示不指定
        "class_output": keras.losses.CategoricalCrossentropy(),
    },
    metrics={
        "score_output": [
            keras.metrics.MeanAbsolutePercentageError(),
            keras.metrics.MeanAbsoluteError(),
        ],
        "class_output": [keras.metrics.CategoricalAccuracy()],
    },
    #可以使用loss_weights参数为不同的特定于输出的损失赋予不同的权重
    #(例如,在我们的示例中,我们可能希望通过赋予类损失的重要性2倍来赋予“得分”损失以特权)
    loss_weights={"score_output": 2.0, "class_output": 1.0},
)

以合适的方式将数据传递给多输入或多输出模型

# Generate dummy NumPy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))

# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets], batch_size=32, epochs=1)

# Alternatively, fit on dicts
model.fit(
    {"img_input": img_data, "ts_input": ts_data},
    {"score_output": score_targets, "class_output": class_targets},
    batch_size=32,
    epochs=1,
)

模型的保存与读取

def get_model():
    # Create a simple model.
    inputs = keras.Input(shape=(32,))
    outputs = keras.layers.Dense(1)(inputs)
    model = keras.Model(inputs, outputs)
    model.compile(optimizer="adam", loss="mean_squared_error")
    return model


model = get_model()

# Train the model.
test_input = np.random.random((128, 32))
test_target = np.random.random((128, 1))
model.fit(test_input, test_target)

# Calling `save('my_model')` creates a SavedModel folder `my_model`.
model.save("my_model")

# It can be used to reconstruct the model identically.
reconstructed_model = keras.models.load_model("my_model")

# Let's check:下面的结果是一样的
model.predict(test_input), reconstructed_model.predict(test_input)

参考:
TensorFlow Core