tensorflow2.0教程—快速入门


本文主要讲解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

在这里插入图片描述

model.weights

在这里插入图片描述

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

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)

在这里插入图片描述

序列化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"],
)

常见的使用参数如下:

参数
OptimizersSGD(), RMSprop() ,Adam()
LossesMeanSquaredError(),KLDivergence(),CosineSimilarity()
MetricsAUC()、Precision()、Recall()
参数
OptimizersSGD(), RMSprop() ,Adam()
LossesMeanSquaredError(),KLDivergence(),CosineSimilarity()
Metricstf.keras.metrics.Accuracy(),tf.keras.metrics.AUC(),MAE()

更多Metrics 参考:Module: tf.keras.metrics

更多loss参考:Module: tf.keras.losses

更多Optimizers参考:Module: tf.keras.optimizers

也可自定义模型的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

在这里插入图片描述

当训练数据数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)

在这里插入图片描述

多输入多输出模型

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

在这里插入图片描述

模型代码如下:

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

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值