解密NumPy求解梯度的一个关键难点
关于numpy的gradient方法,在参数edge_order等于2时,如何得到左右两个边界值,是比较难理解的地方,而网上的博文几乎都千篇一律,都没有对此做出正确的解释。
而关注我的老粉「高新区运气王」经过深思熟虑,找出规律,总结出edge_order等于2时左右两个边界值的推导,难能可贵!在此以飨关注我的读者。
1 Numpy求梯度
import numpy as np
x = np.random.randint(10, size=(6, ))
f = x**2
print(f"f:{f}")
# >> 0, 1, 4, 9, 16
grad1 = np.gradient(f)
print(f"不设置edge_order时, f的默认梯度:{grad1}")
grad2 = np.gradient(f, edge_order=1)
print(f"edge_order=1时,f的梯度:{grad2}")
print(f"查看f的默认梯度是否和edge_order=1时的梯度值相等:{(grad1==grad2).all()}")
grad3 = np.gradient(f, edge_order=2)
print(f"edge_order=2时, f的梯度:{grad3}")
输出结果如下:
f:[49 36 36 9 4 49]
不设置edge_order时, f的默认梯度:[-13. -6.5 -13.5 -16. 20. 45. ]
edge_order=1时,f的梯度:[-13. -6.5 -13.5 -16. 20. 45.]
查看f的默认梯度是否和edge_order=1时的梯度值相等:True
edge_order=2时, f的梯度:[-19.5 -6.5 -13.5 -16. 20. 70. ]
2 一阶中心差分
这里我对整个过程进行解析:
f的计算这里应该不用说,就是对生成的一维随机矩阵x
求平方得到的。
根据打印结果我们会发现,默认情况下和edge_order=1时,f的梯度是一样的。
具体怎么算的呢?
先说下边界
,整体来讲就是,左边界:f[1]
– f[0]
,右边界:f[-1]
– f[-2]
比如本例中,左边界 = 36 – 49 = -13,右边界 = 49 - 4 = 45
再说下中间梯度:就是用的一阶中心差分
,简而言之就是:
比如本例中,f的第二个梯度值 = (f的第三个数 – f的第一个数) / 2 = (36 - 49) / 2 = -6.5, 其他中间梯度值的计算也是同理。
3 理解难点(edge_order=2)
关键地方来了, edge_order=2
时我们会发现,所得到的梯度值中间部分跟edge_order=1(也就是默认值)是一样的,区别就在于边界值。
按照官方文档来说edge_order=2
就是利用边界处的二阶精确差计算梯度,具体啥意思呢?
网上博客也是千篇一律,都没有给出具体的计算过程。
这里我们对计算过程进行解析:
左边界 = 2*(edge_order=1时f的第一个梯度值) - (edge_order=1时f的第二个梯度值)
即:
(这里两撇表示edge_order=2时的梯度,表示f的第i个值)
大家可以自行跟二阶前向差分对比下,需要注意的是numpy里面求梯度这里中间部分的一阶差分是用的一阶中心差分。
右边界 = 2*(edge_order=1时f的最后一个梯度值) - (edge_order=1时f的倒数第二个梯度值)
即:
大家也可以自行推下这里,并跟二阶后向差分对比下。
本例中:
左边界 = 2*(-13) - (-6.5) = -19.5
左边界 = 2*(45) - (20) = 70
可以收藏下,日后你可能会用到。
微信扫码关注该文公众号作者