【ML&DL学习】10 tf diffs and keras regression manu diffs

自定义求导

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

def approximate_derivative(f, x, eps=1e-3):
	#向左移动eps的值 向右移动eps的值 得到两个点 这两个点的斜率就是在x点的导数近似
	#eps 越小 越逼近导数   纵坐标差值 / 横坐标差值
    return (f(x + eps) - f(x - eps)) / (2. * eps)

print(approximate_derivative(f, 1.))

在这里插入图片描述
两个变量求导数

def g(x1, x2):
    return (x1 + 5) * (x2 ** 2)

def approximate_gradient(g, x1, x2, eps=1e-3):
	# 固定x2 函数 对x1求导
    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

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

TensorFlow自动求导

x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)
# 导数求解
with tf.GradientTape() as tape:
    z = g(x1, x2)
#                  函数输出和变量
dz_x1 = tape.gradient(z, x1)
print(dz_x1)
# tape 只能调用一次 调用完会被消解释放
try:
    dz_x2 = tape.gradient(z, x2)
except RuntimeError as ex:
    print(ex)

在这里插入图片描述

x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)
# 声明可以保存
with tf.GradientTape(persistent = True) as tape:
    z = g(x1, x2)

dz_x1 = tape.gradient(z, x1)
dz_x2 = tape.gradient(z, x2)
print(dz_x1, dz_x2)
# 使用完删掉
del tape

在这里插入图片描述
同时求x1,x2偏导
在这里插入图片描述
在这里插入图片描述
可以通过一些变量来观测constant的导数
在这里插入图片描述
两个函数对同一个变量求导
在这里插入图片描述
计算出的是 两个函数在x点的导数和

求二阶导数

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_grad, [x1, x2])
               for inner_grad in inner_grads]
print(outer_grads)
del inner_tape
del outer_tape

在这里插入图片描述
得出的是一个2*2 的矩阵 左上角 是z对x1的二阶导,右上角是z先对x2求导在对x1求导,左下角是z先对x1求导再对x2求导,右下角是z对x2的二阶导。

learning_rate = 0.1
x = tf.Variable(0.0)
# 循环100步
for _ in range(100):
    with tf.GradientTape() as tape:
        z = f(x)
    # 进行求导
    dz_dx = tape.gradient(z, x)
    # 更新 x - lr * dz_dx
    x.assign_sub(learning_rate * dz_dx)
print(x)

在这里插入图片描述
结合optimizer 求导
在这里插入图片描述

使用自定义梯度求解问题

在这里插入图片描述
需要修改model.fit部分的代码

# metric使用
# 均方差
metric = keras.metrics.MeanSquaredError()
# 输入是两个列表
print(metric([5.], [2.]))
#metric 有累加功能 第一个9 第二个1 平均之后是5
print(metric([0.], [1.]))
print(metric.result())
# metric不累加数据
metric.reset_states()
metric([1.], [3.])
print(metric.result())

在这里插入图片描述

# fit函数做的事
# 1. batch 遍历训练集 metric
#    1.1 自动求导
# 2. epoch结束 验证集 metric
#定义变量 遍历多少次
epochs = 100
batch_size = 32
#每个epoch 需要训练多少次
steps_per_epoch = len(x_train_scaled) // batch_size
optimizer = keras.optimizers.SGD()
# 度量 评估方式
metric = keras.metrics.MeanSquaredError()
# 随机取32个样本
def random_batch(x, y, batch_size=32):
    idx = np.random.randint(0, len(x), size=batch_size)
    return x[idx], y[idx]

model = keras.models.Sequential([
    keras.layers.Dense(30, activation='relu',
                       input_shape=x_train.shape[1:]),
    keras.layers.Dense(1),
])

for epoch in range(epochs):
	# metric不累加数据
    metric.reset_states()
    # 循环遍历数据
    for step in range(steps_per_epoch):
    	# 取出数据
        x_batch, y_batch = random_batch(x_train_scaled, y_train,
                                        batch_size)
        # 手动计算求梯度
        with tf.GradientTape() as tape:
            y_pred = model(x_batch)
            y_pred = tf.squeeze(y_pred, 1)
            loss = keras.losses.mean_squared_error(y_batch, y_pred)
            metric(y_batch, y_pred)
        # 更新梯度
        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="")
    # 验证
    y_valid_pred = model(x_valid_scaled)
    y_valid_pred = tf.squeeze(y_valid_pred, 1)
    valid_loss = keras.losses.mean_squared_error(y_valid_pred, y_valid)
    print("\t", "valid mse: ", valid_loss.numpy())

训练
在这里插入图片描述

总结

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值