GradientTape求L2范数偏导

请高人指点江山,关于tensorflow使用GradientTape做L2范数求导的问题
模型使用余弦相似损失函数时偶然发现的问题,发现GradientTape算出的(Y/||Y||)的导数和手工算的不一致
GradientTape计算

```python
>>> y_pred=tf.convert_to_tensor([4.,3.])
>>> with tf.GradientTape() as g:
...     g.watch(y_pred)
...     with tf.GradientTape() as gg:
...         gg.watch(y_pred)
...         # 计算L2范数
...         mo_pred=tf.reduce_sum(y_pred**2)**0.5
...     # 计算L2范数一阶导数
...     dmo = gg.gradient(mo_pred, y_pred)
...
>>> # 计算L2范数二阶导数
>>> ddmo = g.gradient(dmo, y_pred)

```

#L2范数一阶导数=Y/||Y||,没问题
dmo

L2范数二阶导数=?,这里实际计算的就是(Y/||Y||)的导数,tape计算出的结果好像有点问题, 经手工算,这个导数应该是(||Y||^2-Y^2)/||Y||^3,其中^n表示n次幂运算, 后续贴出手算过程,而且这个Y/||Y||应该是单调增函数,怎么经过tape计算出的导数有负数呢?

ddmo

运行结果及详细报错内容
经手工算,这个导数应该是(||Y||^2-Y^2)/||Y||^3,其中^n表示n次幂运算,手算过程如下

img

还有Y/||Y||应该是单调增函数,举例假设Y是二维向量[y1,y2], 设y1固定为3的情况下,||Y||曲线应该是y2/((3^2+y^2)^0.5),这个函数在单个维度上明显是一个单调增函数呀,求偏导不应出现负数啊

img

我想要达到的结果,如果你需要快速回答,请尝试 “付费悬赏”
不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

这种情况可能是因为在计算梯度时,没有考虑到分母中的L2范数对分子的导数的影响。

在使用GradientTape计算(Y/||Y||)的导数时,需要考虑分母中的L2范数对分子的导数的影响,这可以通过链式法则来实现。具体来说,假设Y是一个向量,L2范数为norm(Y),则(Y/||Y||)的导数可以表示为:

d(Y/||Y||)/dY = (1/||Y|| - Y * (Y dot Y)^(-3/2)) * I

其中,* 表示点积,^ 表示幂运算,I 表示单位矩阵。

在使用GradientTape计算导数时,可以将上述公式直接应用于代码中,如下所示:


with tf.GradientTape() as tape:
    y_norm = tf.norm(y)
    y_normalized = y / y_norm
loss = tf.reduce_sum(tf.square(y_normalized))

# 计算梯度
grads = tape.gradient(loss, [y])
grad_normalized = (1 / y_norm - y * tf.pow(y_norm, -3)) * tf.eye(y.shape[0])
grads_normalized = tf.matmul(grad_normalized, grads[0])

这样计算出来的梯度应该就会和手工计算的结果一致了。