from torchvision import datasets, transforms

# Определяем простую нейронную сеть

class SimpleNet(nn.Module):

def __init__(self):

super(SimpleNet, self).__init__()

self.fc1 = nn.Linear(28*28, 128) # Первый полносвязный слой

self.fc2 = nn.Linear(128, 10) # Второй слой для классификации (10 классов)

def forward(self, x):

x = x.view(-1, 28*28) # Преобразуем изображение в одномерный вектор

x = torch.relu(self.fc1(x)) # Применяем ReLU активацию

x = self.fc2(x) # Выходной слой

return x

# Загружаем данные MNIST

transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])

train_data = datasets.MNIST(root='./data', train=True, download=True, transform=transform)

train_loader = DataLoader(train_data, batch_size=64, shuffle=True) # Мини-батч градиентный спуск (batch size = 64)

# Создаем модель, функцию потерь и оптимизатор

model = SimpleNet()

criterion = nn.CrossEntropyLoss() # Функция потерь для многоклассовой классификации

optimizer = optim.SGD(model.parameters(), lr=0.01) # Стохастический градиентный спуск

# Обучение

epochs = 1 # Одно обучение (можно увеличить количество эпох)

for epoch in range(epochs):

for data, target in train_loader: # Для каждого мини-батча

optimizer.zero_grad() # Обнуляем градиенты перед вычислением новых

output = model(data) # Прямой проход

loss = criterion(output, target) # Вычисляем потери

loss.backward() # Обратное распространение ошибок

optimizer.step() # Обновляем веса

print(f'Эпоха {epoch+1}, Потери: {loss.item()}')

# Пример завершения обучения

print("Обучение завершено.")

```

Объяснение:

1. Нейронная сеть:

– Мы снова используем простую нейронную сеть `SimpleNet`, состоящую из двух полносвязных слоев.

2. Мини-батч градиентный спуск:

– В `train_loader` установлен параметр `batch_size=64`, что означает, что данные делятся на батчи по 64 примера. Мы обновляем веса после обработки каждого батча данных.

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

3. Процесс обучения:

– Для каждого батча (по 64 примера) выполняется прямой проход через модель, вычисляются потери, а затем обновляются веса. Этот процесс повторяется для каждого батча в течение эпохи.

Преимущества мини-батч градиентного спуска:

– Стабильность: В отличие от стохастического градиентного спуска, где обновления могут сильно колебаться, мини-батчи приводят к более стабильному обучению.

– Эффективность: Этот метод хорошо работает с большими наборами данных и позволяет эффективно использовать ресурсы GPU.

– Баланс: Мини-батч градиентный спуск обладает всеми преимуществами как пакетного, так и стохастического градиентного спуска, давая стабильное и быстрое обучение.


2.4.2. Современные алгоритмы оптимизации

Современные алгоритмы оптимизации, такие как Adam, RMSprop, Adagrad и другие, используются для улучшения процесса обучения нейронных сетей. Эти методы предлагают более быстрые и устойчивые способы обновления весов по сравнению с традиционным градиентным спуском, улучшая сходимость и уменьшая зависимость от начальных условий.

1. Adam (Adaptive Moment Estimation)

Описание: Adam – один из самых популярных и широко используемых алгоритмов оптимизации. Он сочетает в себе идеи Momentum и RMSprop. Использует адаптивные шаги обучения, основанные на первых (среднее значение градиента) и вторых моментах (квадраты градиентов), что позволяет корректировать скорость обучения для каждого параметра.