tensorflow with求导_Tensorflow学习笔记(3):自动求导

1.根据导数定义

使用tensorflow近似求导:

# 求导数

def approximate_derivative(func, x, eps=1e-3):

return (func(x + eps) - func(x)) / eps

# 求偏导数

def approximate_gradient(g, x1, x2, eps=1e-3):

dg_x1 = approximate_derivative(lambda x: g(x, x2), x1, eps)

dg_x2 = approximate_derivative(lambda x: g(x1, x), x2, eps)

return dg_x1, dg_x2

2.使用tensorflow的自动求导功能官方API链接​www.tensorflow.org

x1 = tf.Variable(2.) # 网络里会发生变化的变量,一般是权重,需要定义在求导记录外

x2 = tf.Variable(3.)

with tf.GradientTape() as tape: # 使用with打开一个记录

z = g(x1, x2) # 具体操作

dz_x1 = tape.gradient(z, x1) # 求得z对x1的偏导

---------------------------------------------------------------

dz_x1

tape使用过一次后便会释放,若想多次使用,需要加入参数persistent=True(这样的话后面也需要手动释放tape,以免造成内存泄漏):

x1 = tf.Variable(2.) # 网络里会发生变化的变量,一般是权重,需要定义在求导记录外

x2 = tf.Variable(3.)

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

z = g(x1, x2)

dz_x1 = tape.gradient(z, x1)

dz_x2 = tape.gradient(z, x2)

# 也可使用list包裹要求偏导的变量

dz_x1x2 = tape.gradient(z, [x1, x2])

del tape # 记住释放tape

对于tf.constant类型的变量,也可以使用tape.watch加入自动求导记录里。API参考链接

x1 = tf.constant(2.)

x2 = tf.constant(3.)

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

tape.watch(x1)

tape.watch(x2)

z = g(x1, x2)

dz_x1x2 = tape.gradient(z, [x1, x2])

---------------------------------------------------

[tf.Tensor(9.0, shape=(), dtype=float32),

tf.Tensor(42.0, shape=(), dtype=float32)]

也可以同时对多个函数求导,输出的是对各个函数的倒数之和:

x = tf.Variable(5.)

with tf.GradientTape() as tape:

z1 = 3 * x

z2 = x ** 3

print(tape.gradient([z1, z2], x))

----------------------------------------------------

tf.Tensor(78.0, shape=(), dtype=float32)

最后,是求二阶倒数,嵌套两次tf.GradientTape。先求出inner_grads,即列表[

,

] 。再对列表中每个元素求偏倒,形成二维列表[[

],[

]]:

x1 = tf.Variable(2.)

x2 = tf.Variable(3.)

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]) # list

outer_grads = [outer_tape.gradient(inner_grad, [x1, x2]) for inner_grad in inner_grads] # list 列表生成

del outer_tape

del inner_tape

接下来,就可以通过tf.GranientTape自定义训练了,也就是自己实现model.compile 和model.fit()的功能。

首先,如之前的教程一样,自定义一个模型:

class MyModel(keras.models.Model):

def __init__(self):

super(MyModel, self).__init__()

self.d_1 = tf.keras.layers.Dense(30, activation='relu')

self.d_2 = tf.keras.layers.Dense(1)

def call(self, x, training=True, mask=None):

return self.d_2(self.d_1(x))

model = MyModel()

接着,定义一下总共的循环次数epochs,每一批的大小batch_size,以及一次循环多少批steps_per_epoch。

epochs = 100

batch_size = 32

steps_per_epoch = len(x_train_scaled) // batch_size

然后,是优化器与度量方式。优化器,也就是搜索策略,tf集成了很多常用的优化器,一般不需要自定义,不过在这还是自己实现了基本的数学运算,以便启发读者自定义未被集成的方法:

def train(model, input, true_output, learning_rate=0.01):

with tf.GradientTape() as tape:

pred_output = model(input)

current_loss = tf.reduce_mean(

keras.losses.mean_squared_error(true_output, pred_output))

grads = tape.gradient(current_loss, model.variables)

# 对模型中的每个变量进行计算

for idx in range(len(model.variables)):

model.variables[idx].assign_sub(learning_rate * grads[idx])

# 进行训练

for epoch in range(epochs):

for step in range(steps_per_epoch):

# random_batch起到随机遍历的作用,在此没有实现

x_batch, y_batch = random_batch(x_train_scaled, y_train, batch_size)

train(MyModel, x_batch, y_batch)

官方还是更推荐使用已有的优化器:

optimizer = keras.optimizers.SGD()

def train(model, input, true_output, learning_rate=0.01):

with tf.GradientTape() as tape:

pred_output = model(input)

current_loss = tf.reduce_mean(

keras.losses.mean_squared_error(true_output, pred_output))

grads = tape.gradient(current_loss, model.variables)

grads_and_variables = zip(grads, model.variables)

optimizer.apply_gradients(grads_and_variables)

# 进行训练

for epoch in range(epochs):

for step in range(steps_per_epoch):

# random_batch起到随机遍历的作用,在此没有实现

x_batch, y_batch = random_batch(x_train_scaled, y_train, batch_size)

train(MyModel, x_batch, y_batch)

附一个官网的自定义训练教程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值