Eager模式及自定义训练

Eager模式及自定义训练

Tensorflow的eager模式是一个命令式编程环境,它可以使我们立即评估操作的结果,无需构建计算图
Tensorflow默认就是eager模式

import tensorflow as tf
tf.__version__

‘2.0.0’

# 判断是否处于eager模式
tf.executing_eagerly()

True

x = [[2]]
result = tf.matmul(x, x)
print(result)

tf.Tensor([[4]], shape=(1, 1), dtype=int32)

print(result.numpy())

[[4]]

变量操作

# 创建变量
var = tf.Variable(1)
var

<tf.Variable ‘Variable:0’ shape=() dtype=int32, numpy=1>

# 修改变量的值
var.assign(5)
var

<tf.Variable ‘Variable:0’ shape=() dtype=int32, numpy=5>

# 读取变量的值
var.read_value()

<tf.Tensor: id=14, shape=(), dtype=int32, numpy=5>

微分运算

# 变量求微分(必须是float类型)
w = tf.Variable([[1.0]])
# 记录运算过程
with tf.GradientTape() as t:
    loss = w * w
print(t.gradient(loss, w))

tf.Tensor([[2.]], shape=(1, 1), dtype=float32)

# 常量求微分
w = tf.constant([[2.0]])
with tf.GradientTape() as t:
    # 追踪w的变化
    t.watch(w)
    loss = w * w
print(t.gradient(loss, w))

tf.Tensor([[4.]], shape=(1, 1), dtype=float32)

# 以上操作只能计算一次微分,要计算多次微分,需要加上参数persistent=True
w = tf.Variable([[1.0]])
# 记录运算过程
with tf.GradientTape(persistent=True) as t:
    y = w * w
    z = y * y
print(t.gradient(y, w))
print(t.gradient(z, w))

tf.Tensor([[2.]], shape=(1, 1), dtype=float32)
tf.Tensor([[4.]], shape=(1, 1), dtype=float32)

tf.keras.metrics评估训练

# 初始化一个计算均值的对象,他会记录每次调用的值,求这些值的均值
m = tf.keras.metrics.Mean(name="mean")
m(1)

<tf.Tensor: id=88, shape=(), dtype=float32, numpy=1.0>

# 1和2的均值就是1.5
m(2)

<tf.Tensor: id=98, shape=(), dtype=float32, numpy=1.5>

# 获取数值
m.result()

<tf.Tensor: id=102, shape=(), dtype=float32, numpy=1.5>

# 重置
m.reset_states()
m(3)

<tf.Tensor: id=114, shape=(), dtype=float32, numpy=3.0>

自定义训练

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
image_num = x_train.shape[0]
print("x_train.shape:", x_train.shape)
print("x_test.shape", x_test.shape)

x_train.shape: (60000, 28, 28)
x_test.shape (10000, 28, 28)

# 维度扩增
x_train = tf.expand_dims(x_train, axis=-1)
x_test = tf.expand_dims(x_test, axis=-1)
print("x_train.shape:", x_train.shape)
print("x_test.shape", x_test.shape)

x_train.shape: (60000, 28, 28, 1)
x_test.shape (10000, 28, 28, 1)

# 数据类型转换
x_train = tf.cast(x_train / 255, tf.float32)
y_train = tf.cast(y_train, tf.int64)

x_test = tf.cast(x_test / 255, tf.float32)
y_test = tf.cast(y_test, tf.int64)
# 创建数据集
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
print("train_dataset:", train_dataset)
print("test_dataset:", test_dataset)

train_dataset: <TensorSliceDataset shapes: ((28, 28, 1), ()), types: (tf.float32, tf.int64)>
test_dataset: <TensorSliceDataset shapes: ((28, 28, 1), ()), types: (tf.float32, tf.int64)>

train_dataset = train_dataset.shuffle(image_num).batch(32)
test_dataset = test_dataset.batch(32)
print("train_dataset:", train_dataset)
print("test_dataset:", test_dataset)

train_dataset: <BatchDataset shapes: ((None, 28, 28, 1), (None,)), types: (tf.float32, tf.int64)>
test_dataset: <BatchDataset shapes: ((None, 28, 28, 1), (None,)), types: (tf.float32, tf.int64)>

# 构建模型
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(16, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
    tf.keras.layers.GlobalMaxPooling2D(),
    tf.keras.layers.Dense(10, activation='softmax')
])
model.summary()

Model: “sequential”
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 26, 26, 16) 160
_________________________________________________________________
conv2d_1 (Conv2D) (None, 24, 24, 32) 4640
_________________________________________________________________
global_max_pooling2d (Global (None, 32) 0
_________________________________________________________________
dense (Dense) (None, 10) 330
=================================================================
Total params: 5,130
Trainable params: 5,130
Non-trainable params: 0
_________________________________________________________________

# 创建一个优化器实例
optimizer = tf.keras.optimizers.Adam()
# 创建loss函数的计算方式
loss_func = tf.keras.losses.SparseCategoricalCrossentropy()
# 创建评估训练的指标
train_loss = tf.keras.metrics.Mean("train_loss")
train_acc = tf.keras.metrics.SparseCategoricalAccuracy("train_acc")
test_loss = tf.keras.metrics.Mean("test_loss")
test_acc = tf.keras.metrics.SparseCategoricalAccuracy("test_acc")
# 训练一步
def train_one_step(model, x, y_true):
    with tf.GradientTape() as t:
        # 计算损失
        y_pred = model(x)
        loss = loss_func(y_true, y_pred)
    # 计算梯度
    gradients = t.gradient(loss, model.trainable_variables)
    # 更新参数
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
    # 计算训练集的评估指标
    train_loss(loss)
    train_acc(y_true, y_pred)
# 测试一步
def test_one_step(model, x, y_true):
    # 计算loss
    y_pred = model(x)
    loss = loss_func(y_true, y_pred)
    # 计算测试集的评估指标
    test_loss(loss)
    test_acc(y_true, y_pred)
def train(model, train_dataset, test_dataset, epochs):
    for epoch in range(epochs):
        # 一次取出一个batch进行训练
        for (x, y_true) in train_dataset:
            train_one_step(model, x, y_true)
        for (x, y_true) in test_dataset:
            test_one_step(model, x, y_true)
        print("Epoch{} train_loss is {:.2f}, train_acc is {:.2f}, test_loss is {:.2f}, test_acc is {:.2f}".format(epoch+1, 
                                                                                                                  train_loss.result(),
                                                                                                                  train_acc.result(),
                                                                                                                  test_loss.result(),
                                                                                                                  test_acc.result()))
        train_loss.reset_states()
        train_acc.reset_states()
        test_loss.reset_states()
        test_acc.reset_states()
train(model, train_dataset, test_dataset, 10)

Epoch1 train_loss is 0.92, train_acc is 0.71, test_loss is 0.46, test_acc is 0.85
Epoch2 train_loss is 0.42, train_acc is 0.87, test_loss is 0.35, test_acc is 0.89
Epoch3 train_loss is 0.33, train_acc is 0.89, test_loss is 0.29, test_acc is 0.91
Epoch4 train_loss is 0.28, train_acc is 0.91, test_loss is 0.24, test_acc is 0.92
Epoch5 train_loss is 0.25, train_acc is 0.92, test_loss is 0.23, test_acc is 0.92
Epoch6 train_loss is 0.24, train_acc is 0.92, test_loss is 0.23, test_acc is 0.93
Epoch7 train_loss is 0.22, train_acc is 0.93, test_loss is 0.21, test_acc is 0.93
Epoch8 train_loss is 0.21, train_acc is 0.93, test_loss is 0.21, test_acc is 0.93
Epoch9 train_loss is 0.20, train_acc is 0.93, test_loss is 0.20, test_acc is 0.93
Epoch10 train_loss is 0.20, train_acc is 0.94, test_loss is 0.19, test_acc is 0.94

发布了14 篇原创文章 · 获赞 1 · 访问量 575

猜你喜欢

转载自blog.csdn.net/lan_faster/article/details/103531996
今日推荐