PyTorch, похоже, не оптимизирует правильно

Простым решением является установка опции с пустым значением "". Я обнаружил, что это исключает дополнительную неопределенную опцию.

1
задан wny 27 March 2019 в 04:06
поделиться

2 ответа

Вы должны переместить вычисления T внутри цикла, иначе они всегда будут иметь одно и то же постоянное значение, то есть постоянные потери.

Другое дело - инициализировать theta различными значениями по индексам, в противном случае из-за симметричной природы задачи градиент одинаков для каждого индекса.

Другое дело, что вам нужен нулевой градиент, потому что backward просто накапливает их.

Это, кажется, работает:

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_()
0
ответ дан Sergey Dymchenko 27 March 2019 в 04:06
поделиться

Вас укусила и Питорч, и математика. Во-первых, вам нужно

  1. обнулить градиент, установив theta.grad = None перед каждым шагом backward. В противном случае градиенты накапливаются вместо того, чтобы перезаписывать предыдущие
  2. . Вам нужно пересчитывать 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())

, который все равно не будет работать так, как вы ожидаете из-за математики.

Легко видеть, что минимум вашей функции потерь - это когда theta также равномерно распределены по [0, 2pi). Проблема в том, что вы инициализируете свои параметры как torch.zeros, что приводит к тому, что все эти значения равны (это полярная противоположность equispaced!). Поскольку ваша функция потерь симметрична относительно перестановок из theta, вычисленные градиенты равны, и алгоритм градиентного спуска никогда не сможет «дифференцировать их». В более математических терминах вам не повезло инициализировать ваш алгоритм точно в седловой точке, поэтому он не может продолжаться. Если вы добавите какой-либо шум, он будет сходиться. Например, с

theta = torch.zeros(n, 1) + 0.001 * torch.randn(n, 1)
theta.requires_grad_(True)
0
ответ дан Jatentaki 27 March 2019 в 04:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: