Порядок работы оптимизаторов влияет на прогнозы в PyTorch

Я использую линейную регрессию для многих оптимизаторов. Я заметил, что если первым активировать СГД, то остальные имеют хорошую точность. В противном случае Адам и RMSprop вносят ужасные изменения.

# Generate synthetic data
X_numpy, y_numpy = datasets.make_regression(n_samples=100, n_features=1, noise=20, random_state=15)

X = torch.from_numpy(X_numpy.astype(np.float32))
y = torch.from_numpy(y_numpy.astype(np.float32))
y = y.view(y.shape[0], 1)

# Define the model
n_samples, n_features = X.shape
input_size = n_features
output_size = 1
model = nn.Linear(input_size, output_size)

# Define learning rate
learning_rate = 0.01

# Define criteria
criterion = nn.MSELoss()

# Define different optimizers
optimizers = {    
    "Adam": torch.optim.Adam(model.parameters(), lr=learning_rate),
    "RMSprop": torch.optim.RMSprop(model.parameters(), lr=learning_rate),
    "SGD": torch.optim.SGD(model.parameters(), lr=learning_rate),
}

# Training loop for each optimizer
num_epochs = 100
predictions = {}
for optimizer_name, optimizer in optimizers.items():
    print(f"Optimizer: {optimizer_name}")
    predictions[optimizer_name] = []
    for epoch in range(num_epochs):        
        y_predicted = model(X)
        loss = criterion(y_predicted, y)
        loss.backward()
        optimizer.step() #update wights
        optimizer.zero_grad() #zero the gradients
    predictions[optimizer_name] = model(X).detach().numpy()

# Plotting predictions with different colors
plt.figure(figsize=(10, 6))
plt.plot(X_numpy, y_numpy, 'ro', label='Original Data')
for optimizer_name, prediction in predictions.items():
    plt.plot(X_numpy, prediction, label=optimizer_name)
plt.legend()
plt.show()

Приведенный выше код генерирует прогнозы:

Если я сначала запущу SGD, произойдет следующее:

optimizers = {    
    "Adam": torch.optim.Adam(model.parameters(), lr=learning_rate),
    "RMSprop": torch.optim.RMSprop(model.parameters(), lr=learning_rate),
    "SGD": torch.optim.SGD(model.parameters(), lr=learning_rate),
}

Почему это происходит?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблема в том, что вы сохраняете одну и ту же модель для всех регрессий, а это означает, что когда первая оптимизация закончится, вы перейдете к следующей, используя обученную модель. Бывает, что скорость обучения работает только для SGD (для двух других оптимизаторов она кажется слишком большой), поэтому суммируем оба случая:

  • если вы начнете с двух других, модель не будет работать хорошо и не будет соответствовать критериям. На третьем обучении (SGD) модель будет обучена правильно и будет соответствовать баллам.

  • если вы начнете с SGD, он будет тренировать модель, а последующие две тренировки не приведут к значительному изменению весов, что приведет к аналогичным результатам.

Вместо этого вам следует сбросить свою модель и определить скорость обучения для конкретного оптимизатора:

optimizers = dict(    
    RMSprop=(torch.optim.RMSprop, 0.3),
    SGD=(torch.optim.SGD, 0.01),
    Adam=(torch.optim.Adam, 0.5),
)

for optimizer_name, (klass,lr) in optimizers.items():
    model = copy.deepcopy(model_)
    optimizer = klass(model.parameters(), lr=lr)
    ## Proceed with your training loop

При описанной выше настройке вы получите следующую примерку, независимо от порядка выполнения.

Возможно, ОП хотел сохранить одну и ту же модель для всех регрессий?

Yakov Dan 08.04.2024 17:46

Модель, используемая для разных прогонов, — это одно, но что более важно, этот ответ показывает, что только SGD хорошо соответствует точкам (с текущей скоростью обучения). Вот почему порядок тоже имеет значение.

Ivan 08.04.2024 17:49

Да, поскольку задача выпуклая. SGD всегда минимизирует, а другие алгоритмы — нет.

Yakov Dan 08.04.2024 17:52

Предполагая, что вы действительно хотите продолжать оптимизировать свою модель с использованием различных оптимизаторов, ваша проблема заключается в том, что ваша проблема выпуклая.

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

Итак, когда вы начинаете с SGD, вы приближаетесь к минимуму, и градиенты становятся небольшими. Тогда другие алгоритмы, которые делают неоптимальный шаг (когда задача выпуклая), не слишком сильно портят ситуацию, поскольку градиенты уже малы.

С другой стороны, если вы начнете, скажем, с Адама, вы начнете с плохих шагов, которые позже исправите с помощью SGD, поскольку для выпуклых задач SGD будет сходиться к минимуму независимо от начальной точки.

Другие вопросы по теме