Я использую линейную регрессию для многих оптимизаторов. Я заметил, что если первым активировать СГД, то остальные имеют хорошую точность. В противном случае Адам и 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),
}
Почему это происходит?
Проблема в том, что вы сохраняете одну и ту же модель для всех регрессий, а это означает, что когда первая оптимизация закончится, вы перейдете к следующей, используя обученную модель. Бывает, что скорость обучения работает только для 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
При описанной выше настройке вы получите следующую примерку, независимо от порядка выполнения.
Модель, используемая для разных прогонов, — это одно, но что более важно, этот ответ показывает, что только SGD хорошо соответствует точкам (с текущей скоростью обучения). Вот почему порядок тоже имеет значение.
Да, поскольку задача выпуклая. SGD всегда минимизирует, а другие алгоритмы — нет.
Предполагая, что вы действительно хотите продолжать оптимизировать свою модель с использованием различных оптимизаторов, ваша проблема заключается в том, что ваша проблема выпуклая.
Выпуклость означает, что у вас есть единственный минимум, который также является глобальным минимумом. Это также означает, что градиенты становятся все меньше и меньше по мере приближения к минимальной точке. В выпуклой обстановке разумной идеей является шаг в сторону градиента.
Итак, когда вы начинаете с SGD, вы приближаетесь к минимуму, и градиенты становятся небольшими. Тогда другие алгоритмы, которые делают неоптимальный шаг (когда задача выпуклая), не слишком сильно портят ситуацию, поскольку градиенты уже малы.
С другой стороны, если вы начнете, скажем, с Адама, вы начнете с плохих шагов, которые позже исправите с помощью SGD, поскольку для выпуклых задач SGD будет сходиться к минимуму независимо от начальной точки.
Возможно, ОП хотел сохранить одну и ту же модель для всех регрессий?