```python

import torch

import torch.nn as nn

import torch.optim as optim

# Определяем класс нейронной сети с Dropout

class DropoutNet(nn.Module):

def __init__(self, dropout_prob=0.5): # dropout_prob задаёт вероятность выключения нейрона

super(DropoutNet, self).__init__()

self.layer1 = nn.Linear(784, 256) # Первый полносвязный слой

self.dropout1 = nn.Dropout(dropout_prob) # Dropout после первого слоя

self.layer2 = nn.Linear(256, 128) # Второй полносвязный слой

self.dropout2 = nn.Dropout(dropout_prob) # Dropout после второго слоя

self.layer3 = nn.Linear(128, 10) # Выходной слой для 10 классов

def forward(self, x):

x = torch.relu(self.layer1(x))

x = self.dropout1(x) # Применение Dropout после активации

x = torch.relu(self.layer2(x))

x = self.dropout2(x) # Применение Dropout после активации

x = self.layer3(x) # Прямой выход

return x

# Пример создания модели и обучения

model = DropoutNet(dropout_prob=0.5) # Создаем модель с Dropout 50%

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

optimizer = optim.Adam(model.parameters(), lr=0.001) # Оптимизатор Adam

# Пример одного шага обучения

inputs = torch.randn(64, 784) # Входной батч из 64 изображений размером 28x28

labels = torch.randint(0, 10, (64,)) # Случайные метки классов

# Обнуление градиентов

optimizer.zero_grad()

# Прямой проход

outputs = model(inputs)

loss = criterion(outputs, labels)

# Обратное распространение и обновление весов

loss.backward()

optimizer.step()

print("Значение функции потерь:", loss.item())

```

Объяснение кода:

1. Dropout Layers:

`self.dropout1` и `self.dropout2` – слои Dropout, которые добавляются после каждого скрытого слоя. Значение `dropout_prob=0.5` означает, что в каждом проходе по данным будет отключаться 50% нейронов в каждом из этих слоев.

2. Dropout в обучении и оценке:

Dropout активен только во время обучения, при вызове `model.train()`. В режиме тестирования (`model.eval()`), Dropout отключается, и все нейроны остаются активными, чтобы обеспечить полную производительность модели.

3. Регуляризация:

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

Gradient Clipping – это метод, который ограничивает значения градиентов, предотвращая их чрезмерное увеличение. Этот подход особенно полезен для рекуррентных нейронных сетей (RNN), где градиенты могут быстро расти при распространении ошибки по временной оси, что приводит к взрыву градиентов и нестабильному обучению.

Ниже приведен пример кода в PyTorch, демонстрирующий использование Gradient Clipping:

```python

import torch

import torch.nn as nn

import torch.optim as optim

# Пример класса RNN с использованием Gradient Clipping

class SimpleRNN(nn.Module):

def __init__(self, input_size, hidden_size, output_size):

super(SimpleRNN, self).__init__()

self.hidden_size = hidden_size

self.rnn = nn.RNN(input_size, hidden_size, batch_first=True) # Однослойная RNN

self.fc = nn.Linear(hidden_size, output_size) # Полносвязный слой для предсказания

def forward(self, x):

h0 = torch.zeros(1, x.size(0), self.hidden_size) # Инициализация скрытого состояния

out, _ = self.rnn(x, h0) # Передача через RNN

out = self.fc(out[:, -1, :]) # Применение линейного слоя к выходу RNN

return out

# Параметры сети и данных

input_size = 10 # Размер входных данных

hidden_size = 50 # Размер скрытого состояния

output_size = 1 # Размер выхода

model = SimpleRNN(input_size, hidden_size, output_size)