PyTorch不';似乎没有正确地进行优化
由于StackOverflow不支持LaTeX,我已经在Data Science StackExchange网站上发布了这个问题。链接到这里,因为这个网站可能更合适 正确渲染乳胶的问题如下: 我的想法是考虑不同相位的正弦波之和。在间隔[0,2pi]内,以一定的采样率PyTorch不';似乎没有正确地进行优化,pytorch,Pytorch,由于StackOverflow不支持LaTeX,我已经在Data Science StackExchange网站上发布了这个问题。链接到这里,因为这个网站可能更合适 正确渲染乳胶的问题如下: 我的想法是考虑不同相位的正弦波之和。在间隔[0,2pi]内,以一定的采样率s对波进行采样。我需要以这样一种方式来选择相位,任何采样点的波的总和都是最小的 下面是Python代码。优化的计算似乎不正确 将numpy导入为np 进口火炬 def相位优化(n,s=48000,nsteps=1000): 学习率=1
s
对波进行采样。我需要以这样一种方式来选择相位,任何采样点的波的总和都是最小的
下面是Python代码。优化的计算似乎不正确
将numpy导入为np
进口火炬
def相位优化(n,s=48000,nsteps=1000):
学习率=1e-3
θ=火炬。零([n,1],需要_grad=True)
l=torch.linspace(0,2*np.pi,s)
t=火炬烟囱([l]*n)
T=T+theta
对于范围内的jj(nsteps):
损耗=T.sin().sum(0).pow(2).sum()/s
loss.backward()
θ.data-=学习率*θ.grad.data
打印('最佳θ:\n\n',θ数据)
打印('\n\n最大值:',T.sin().sum(0.abs().max().item())
下面是一个示例输出
phaseOptimize(5,nsteps=100)
最佳θ:
张量([[1.2812e-07],
[1.2812e-07],
[1.2812e-07],
[1.2812e-07],
[1.2812e-07]],需要_grad=True)
最大值:5.0
我想这与中国的广播有关
T=T+theta
和/或我计算损失函数的方式
验证优化是否正确的一种方法是,简单地对数组$\theta\u 1、\dots、\theta\u n$的随机值计算损失函数,例如均匀分布在$[0,2\pi]$。这种情况下的最大值几乎总是远低于phaseOptimize()
报告的最大值。事实上,更容易考虑的是$N=2美元,并且简单地评估$\ theta a1=0 $和$\ theta a2=\pI$。在这种情况下,我们得到:
phaseOptimize(2,nsteps=100)
最佳θ:
张量([[2.8599e-08],
[2.8599e-08]]
最大值:2.0
另一方面,
theta=torch.FloatTensor([[0],[np.pi]])
l=torch.linspace(0,2*np.pi,48000)
t=火炬烟囱([l]*2)
T=T+theta
T.sin().sum(0.abs().max().item()
产生
3.2782554626464844e-07
您必须将计算
T
移动到循环内部,否则它将始终具有相同的常量值,从而导致常量损失
另一件事是在索引处将θ初始化为不同的值,否则由于问题的对称性,每个索引的梯度都是相同的
另一件事是,您需要将梯度设置为零,因为向后
只是将它们累加起来
这似乎有效:
def phaseOptimize(n, s = 48000, nsteps = 1000):
learning_rate = 1e-1
theta = torch.zeros([n, 1], requires_grad=True)
theta.data[0][0] = 1
l = torch.linspace(0, 2 * np.pi, s)
t = torch.stack([l] * n)
for jj in range(nsteps):
T = t + theta
loss = T.sin().sum(0).pow(2).sum() / s
loss.backward()
theta.data -= learning_rate * theta.grad.data
theta.grad.zero_()
你被PyTorch和math都咬了。首先,你需要
向后
步骤之前设置theta.grad=None
将梯度归零。否则,渐变将累积,而不是覆盖以前的渐变T
。PyTorch不是符号,与TensorFlow不同,T=T+theta
意味着“T等于当前T
和当前theta
之和”,而不是“T等于T
和theta
之和,无论它们在未来的任何时候的值是什么”def phaseOptimize(n, s = 48000, nsteps = 1000):
learning_rate = 1e-3
theta = torch.zeros(n, 1, requires_grad=True)
l = torch.linspace(0, 2 * np.pi, s)
t = torch.stack([l] * n)
T = t + theta
for jj in range(nsteps):
T = t + theta
loss = T.sin().sum(0).pow(2).sum() / s
theta.grad = None
loss.backward()
theta.data -= learning_rate * theta.grad.data
T = t + theta
print('Optimal theta: \n\n', theta.data)
print('\n\nMaximum value:', T.sin().sum(0).abs().max().item())
由于数学的原因,它仍然不会像你期望的那样工作
我们可以很容易地看到,损失函数的最小值是θ
在[0,2pi)
上均匀分布。问题是,您将参数初始化为火炬。零
,这导致所有这些值相等(这是等间距的极性相反!)。由于损失函数相对于θ
的排列是对称的,因此计算的梯度是相等的,梯度下降算法永远无法“区分它们”.用更数学的术语来说,你很不幸在鞍点上初始化了你的算法,所以它无法继续。如果你添加任何噪声,它就会收敛。例如
theta = torch.zeros(n, 1) + 0.001 * torch.randn(n, 1)
theta.requires_grad_(True)