tensorflow学习019——Eager模式与自定义训练

变量与自动微分

点击查看代码
import tensorflow as tf

v = tf.Variable(1.0) #创建变量
v.assign(5) #改变变量的值为5
v.assign_add(2) #对变量进行+操作
v.read_value() #读取变量的值

w = tf.Variable([[1.0]])
with tf.GradientTape() as t: #可以跟踪变量的变化
    loss = w * w
grad = t.gradient(loss, w) #求解loss对w的微分
print(grad)
	
#对常量的微分
w = tf.constant(2.0)
with tf.GradientTape() as t:
    t.watch(w)
    loss = w * w
loss_dw = t.gradient(loss, w)
print(loss_dw)
需要注意的是计算的数据需要是float类型才可以

with tf.GradientTape(persistent=True) as t:

加上上面这行代码中的参数persistent,则后面可以多次调用t.gradient(),不加的话,则调用一次就释放了,后面不能再调用

自定义训练

点击查看代码
import tensorflow as tf

(train_image, train_labels), (test_image, test_labels)= tf.keras.datasets.mnist.load_data()
train_image = tf.expand_dims(train_image,-1)  # 原先形状为(60000,28,28),现在变为(60000,28,28,1) 扩展维度,也就是通道维度
# 如果使用参数1,那么形状就变为了(60000,1,28,28)
test_image = tf.expand_dims(test_image,-1)
test_image = test_image / 255
train_image = train_image / 255  # 进行归一化
train_image = tf.cast(train_image, tf.float32)  # 将数据类型转换为float,因为只有float才能进行自动微分
test_image = tf.cast(test_image, tf.float32)
train_labels = tf.cast(train_labels,tf.int64)
test_labels = tf.cast(test_labels, tf.int64)
dataset = tf.data.Dataset.from_tensor_slices((train_image,train_labels))  # 将图片和标签进行对应组合,这个函数是将第一维进行拆分
# 也就是可以拆分为60000个单独的数据
dataset = dataset.shuffle(1000).batch(32)  # 对数据进行混洗以及绑定32个为一组
test_dataset = tf.data.Dataset.from_tensor_slices((test_image,test_labels))
test_dataset = test_dataset.batch(32)

# 自定义训练,不需要编译模型,是自己写

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(16, [3,3], activation='relu', input_shape=(None,None,1)),  # None表示只要是灰度图都可以,没有规定大小
    tf.keras.layers.Conv2D(32, [3,3], activation='relu'),
    tf.keras.layers.GlobalMaxPool2D(),
    tf.keras.layers.Dense(10)  # 这里没有进行激活函数,那么就需要再后面的loss函数中进行一些操作
])
optimizer=tf.keras.optimizers.Adam()  # 优化器
loss_func = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)  # 前面没有加入激活函数,这里需要将该参数设为True

def loss(model, x, y):  # 计算损失的函数
    y_ = model(x)
    return loss_func(y,y_)


# 训练网络的一步  也就是单批次的训练过程
# def train_step(model, images, labels):  # 计算损失函数和model变量(可训练参数)之间的梯度
#     with tf.GradientTape() as t:  # 追踪了损失函数
#         loss_step = loss(model,images,labels)  # 每一步的损失值
#     grads = t.gradient(loss_step, model.trainable_variables)  # 获得交叉熵损失对网络可训练参数之间的梯度
#     optimizer.apply_gradients(zip(grads,model.trainable_variables))  # 优化器用获得梯度来改变可训练参数
#
# def train(epochs):
#     for epoch in range(epochs):
#         print('Epoch{} is starting'.format(epoch + 1))
#         for (batch, (images, labels)) in enumerate(dataset):
#             train_step(model,images,labels)
#             print(epoch," ",batch)


train_loss = tf.keras.metrics.Mean('train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy('train_accuracy')
test_loss = tf.keras.metrics.Mean('test_loss')
test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy('test_accuracy')


def train_step(model,images,labels):
    with tf.GradientTape() as t:
        pred = model(images)
        loss_step = loss_func(labels,pred)
    grads = t.gradient(loss_step,model.trainable_variables)
    optimizer.apply_gradients(zip(grads,model.trainable_variables))
    train_loss(loss_step)
    train_accuracy(labels,pred)

def test_step(model, images, labels):
    pred = model(images)
    loss_step = loss_func(labels,pred)
    test_loss(loss_step)
    test_accuracy(labels,pred)


def train(epoches):
    for epoch in range(epoches):
        for (batch,(images,labels)) in enumerate(dataset):
            train_step(model,images,labels)
        print('Epoch {}/{} loss is {},accuracy is {}'.format(epoch+1,epoches,train_loss.result(),train_accuracy.result()))

        for (batch,(images,labels)) in enumerate(test_dataset):
            test_step(model,images,labels)
        print('Epoch {}/{} test_loss is {},test_accuracy is {}'.format(epoch+1,epoches,test_loss.result(),test_accuracy.result()))

        train_loss.reset_states()
        train_accuracy.reset_states()
        test_loss.reset_states()
        test_accuracy.reset_states()

train(10)

tf.keras.metrics汇总计算模块

点击查看代码
# m = tf.keras.metrics.Mean('acc')  # 创建计算均值的对象  acc表示一个名称
# m(10)  # 也可以使用m([10,20,30,40])这样的形式
# m(20)
# print(m.result().numpy())  # 会返回15,是10和20的均值
# m.reset_states()  # 重置对象,也就是将里面的数值都重置,没有了10和20

# a = tf.keras.metrics.SparseCategoricalAccuracy('acc')  # 初始化一个计算正确率的对象
# print(a(labels,model(features)))  labels是正确的结果,model是一个模型,可以使用其对features进行预测,由于预测的结果是10个
# 概率值,而SparseCategoricalAccuracy会自动选出其中最大的进行计算
posted @ 2022-03-03 17:48  白菜茄子  阅读(132)  评论(0编辑  收藏  举报