tensorflow基础之——自定义求导

目录

1. 导数/梯度的理论知识

2. 手撕求导函数

2.1 一元方程

2.2 二元方程

3. 用tensorflow中的库函数完成求导

3.1 一阶函数求导/梯度

3.2 二阶函数求导

4. 梯度下降算法的实现

4.1 手撕梯度下降算法

4.2  使用keras.optimizers.SGD() 中的 apply_gradient特性,完成梯度下降算法


1. 导数/梯度的理论知识

详见博客:梯度下降法(GD,SGD,Mini-Batch GD)在线性回归中的使用_zhao_crystal的博客-CSDN博客_sgd 线性回归本文代码见点击打开链接https://github.com/crystal30/SGDLinrearRegression一.梯度下降法(Batch Gradient Descent)1.梯度下降法的原理(1)梯度下降法是一种基于搜索的最优化方法,不是一个机器学习算法。(2)作用:最小化一个损失函数.扩展:梯度上升法与梯度下降法相反,是最大化一个效用函数。如下图eta太大,得不到最优...https://blog.csdn.net/zhao_crystal/article/details/80472720

相关代码详见:ML2/Gradient-Descent at main · crystal30/ML2 · GitHubhttps://github.com/crystal30/ML2/tree/main/Gradient-Descent

2. 手撕求导函数

2.1 一元方程

def f(x):
    return 3. * x ** 2 + 2. * x - 1

def approximae_derivative(f, x, eps=1e-3):
    return (f(x + eps) - f(x - eps)) / (2. * eps)

print(approximae_derivative(f, 1.))

2.2 二元方程

# 定义二元方程
def g(x1, x2):
    return (x1 + 5) * (x2 ** 2)


# 正确的对二元方程进行求导
def approximae_gradient(g, x1, x2, eps=1e-3):
    # 使用一元方程的求导函数approximae_derivative
    dg_x1 = approximae_derivative(lambda x: g(x, x2), x1, eps)
    dg_x2 = approximae_derivative(lambda x: g(x1, x), x2, eps)
    return dg_x1, dg_x2

print(approximae_gradient(g, 2., 3.))

3. 用tensorflow中的库函数完成求导

3.1 一阶函数求导/梯度

x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)

with tf.GradientTape() as tape:
    z = g(x1, x2) # g(x1, x2) 在前面定义过

dz_x1 = tape.gradient(z, x1)

# note:tape执行完一遍之后就会被释放,所以再调用tape就会报错
try:
    dz_x2 = tape.gradient(z, x2)
except RuntimeError as ex:
    print(ex)

tape执行完一遍之后就会被释放,遇到n元函数,难道要定义n次tape?

———— 设置tf.GradientTape中的参数 persistent=True

x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)

with tf.GradientTape(persistent=True) as tape:
    z = g(x1, x2) # g(x1, x2) 在前面定义过

dz_x1 = tape.gradient(z, x1)
dz_x2 = tape.gradient(z, x2)
print(dz_x1, dz_x2) # 输出结果和我们手动求导得到的结果一样哦

# 手动释放掉 tape
del tape

———— 在求梯度时,一次将所有的变量都传入

x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)

with tf.GradientTape() as tape: # 不设置 persistent=True
    z = g(x1, x2) # g(x1, x2) 在前面定义过

dz_x1_x2 = tape.gradient(z, [x1, x2]) # 求偏导时,将变量一次性传入
print(dz_x1_x2) # 输出结果和我们手动求导得到的结果一样哦

若函数的变量被赋予具体的数值,被定义为常量————需要使用watch,关注一下该常量

x1 = tf.constant(2.0)
x2 = tf.constant(3.0)

with tf.GradientTape() as tape: # 不设置 persistent=True
    # 和将变量定义为Variable不同的是,需要watch
    tape.watch(x1)
    tape.watch(x2)
    z = g(x1, x2) # g(x1, x2) 在前面定义过

dz_x1_x2 = tape.gradient(z, [x1, x2]) # 求偏导时,将变量一次性传入
print(dz_x1_x2) # 输出结果和我们手动求导得到的结果一样哦

对多个函数同时求导

x = tf.Variable(5.0)
with tf.GradientTape() as tape:
    z1 = 3 * x
    z2 = x ** 2

d_z1_z2 = tape.gradient([z1, z2], x) # 得到 dz1 + dz2
print(d_z1_z2)

3.2 二阶函数求导

x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)

with tf.GradientTape(persistent=True) as outer_tape:
    with tf.GradientTape(persistent=True) as inner_tape:
        z = g(x1, x2)
    inner_grads = inner_tape.gradient(z, [x1, x2])
outer_grads = [outer_tape.gradient(inner_gradient, [x1, x2]) \
               for inner_gradient in inner_grads]

print(outer_grads)

del inner_tape
del outer_tape

outer_grads 的输出为[[dz / d(x1)d(x1), dz / d(x1)d(x2)], [dz / d(x2)d(x1), dz / d(x2)d(x2)]]

4. 梯度下降算法的实现

4.1 手撕梯度下降算法

learning_rate = 0.1
x = tf.Variable(0.0)

for _ in range(100):
    with tf.GradientTape() as tape:
        z = f(x) # f(x) 前面有定义过,为:3. * x ** 2 + 2. * x - 1
    dz_x = tape.gradient(z, x)
    x.assign_sub(learning_rate * dz_x) # 梯度下降:x = x - learning_rate - dz_x

print(x)

4.2  使用keras.optimizers.SGD() 中的 apply_gradient特性,完成梯度下降算法

learning_rate = 0.1
x = tf.Variable(0.0)

optimizer = tf.optimizers.SGD(learning_rate = learning_rate)

for _ in range(100):
    with tf.GradientTape() as tape:
        z = f(x) # f(x) 前面有定义过,为:3. * x ** 2 + 2. * x - 1
    
    dz_x = tape.gradient(z, x)
    optimizer.apply_gradients([(dz_x, x)]) # 达到x = x - learning_rate - dz_x的效果

print(x)

相关代码详见:

5. 自定义求导在回归问题中的实践

(1)搭建好模型结构之后,batch遍历训练集metric

         自动求导,更新参数

(2)每个epoch结束,得到验证集metric

自定义获得批量数据的函数

# 定义自动得到批量数据的函数
def random_batch(x, y, batch_size=32):
    idx = np.random.randint(0, len(x), size = batch_size)
    return x[idx], y[idx]

训练模型

epochs = 100
batch_size = 32
steps_per_epoch = len(x_train_scaled) // batch_size
optimizer = keras.optimizers.SGD()
metric = keras.metrics.MeanSquaredError()

for epoch in range(epochs):
    metric.reset_states()
    # batch 遍历训练集,得到训练集的 metric
    for i in range(steps_per_epoch):
        x_batch, y_batch = random_batch(
            x_train_scaled, y_train, batch_size=batch_size)
        
        with tf.GradientTape() as tape:
            y_predict = model(x_batch)
            loss = tf.reduce_mean(
                keras.losses.mean_squared_error(y_batch, y_predict))
            metric(y_batch, y_predict)
        
        # 自定义求导
        grads = tape.gradient(loss, model.variables)
        grads_and_vars = zip(grads, model.variables)

        # 更新参数
        optimizer.apply_gradients(grads_and_vars)

        print("\rEpoch", epoch, " train mse:", metric.result().numpy(), end="")

    # 每个epoch结束,用验证集合进行验证
    y_valid_predict = model.predict(x_valid_scaled)
    valid_loss = tf.reduce_mean(
        keras.losses.mean_squared_error(y_valid, y_valid_predict))
    
    print("\t valid mse:", valid_loss.numpy())

代码详见:

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于关注和分享TensorFlow深度学习算法设计的人工智能学习者来说,《深入理解人工智能算法设计》这本书是一本非常宝贵的学习资源。TensorFlow是一个开源的机器学习框架,它提供了丰富的工具和库,可以帮助开发者设计和训练高效的深度学习模型。 这本书对于TensorFlow深度学习的算法设计提供了详细、系统的解读,对于想要深入学习和掌握TensorFlow的人来说非常有帮助。书中包含了各种不同的算法设计案例,从基础的神经网络模型到复杂的深度学习网络,涵盖了各个方面的知识。 通过关注和分享《深入理解人工智能算法设计》这本书,可以帮助更多的人了解和学习TensorFlow深度学习的算法设计。同时,分享这本书也可以推广和宣传TensorFlow这个强大的工具,让更多的人受益于人工智能算法设计的知识。 为了方便更多人获取这本书,《深入理解人工智能算法设计》的PDF版本可以通过下载来获得。PDF格式的书籍可以在各种电子设备上阅读,包括电脑、平板和手机。通过下载PDF版本,学习者可以随时随地地查阅这本书,提高学习效率。 因此,我鼓励大家关注和分享《深入理解人工智能算法设计》这本书,通过深入学习TensorFlow深度学习的算法设计,提升自己在人工智能领域的技能和能力。同时,也希望更多人可以通过下载PDF版本的方式获取这本书,便捷地进行学习。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值