Линейная регрессия в Pytorch – исчезающие градиенты с Softmax

Вопрос или проблема

Я реализую нелинейную регрессию с использованием нейронных сетей с одним слоем в Pytorch. Однако при использовании активационной функции, такой как ReLu или Softmax, потеря застревает, значение не уменьшается по мере увеличения выборки, и предсказание остается постоянным. Поэтому я заменил ReLu на LeakyReLU, и потеря существенно уменьшилась, а предсказания больше не были постоянными, они даже отслеживали исходную функцию.

Тем не менее, в контексте, в котором я работаю, функция Softmax была бы более подходящей. Однако проблема исчезающего градиента сохраняется. Я пробовал инициализировать с небольшими весами, но это не сработало. Мне интересно, может ли кто-нибудь дать мне идею о том, как увеличить крутизну функции Softmax в Pytorch, так как это сработало с LeakyReLU.

class NeuralNetwork(nn.Module):
    def __init__(self,inputsize,outputsize):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(inputsize, outputsize),
            nn.Softmax(),
        )

        nn.init.uniform_(w,a=-1,b=1)

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

Гиперпараметры, которые я использую, следующие:

inputDim = 1        # принимает переменную 'x' 
outputDim = 1       # принимает переменную 'y'
learningRate = 0.001 
epochs = 100000
weight=torch.empty(3)
model = NeuralNetwork(inputDim, outputDim)
if torch.cuda.is_available():
    model.cuda()

Если нужно, я могу предоставить смоделированные данные.

criterion = torch.nn.MSELoss() 
optimizer = torch.optim.SGD(model.parameters(), lr=learningRate)
for epoch in range(epochs):
    # Преобразование входов и меток в переменные
    if torch.cuda.is_available():
        inputs = Variable(torch.from_numpy(vS0).cuda().float())
        labels = Variable(torch.from_numpy(vC).cuda().float())
    else:
        inputs = Variable(torch.from_numpy(vS0).float())
        labels = Variable(torch.from_numpy(vC).float())

  
    optimizer.zero_grad()

    # получение выхода из модели, учитывая входы
    outputs = model(inputs)

    # получение потерь для предсказанного выхода
    loss = criterion(outputs, labels)

    # получение градиентов по параметрам
    loss.backward()

    # обновление параметров
    optimizer.step()

    print('эпоха {}, потеря {}'.format(epoch, loss.item()))

Softmax – это многоклассовая версия потерь перекрестной энтропии, о которой известно, что она имеет проблемы исчезающего градиента. Измените активацию Softmax на ReLU.

Ответ или решение

Линейная Регрессия в Пайтоне: Проблемы Исчезающих Градиентов при Использовании Softmax

Введение

Проблема исчезающих градиентов – это одна из основных трудностей, с которыми сталкиваются разработчики нейронных сетей, особенно при использовании функций активации, таких как Softmax. В вашем случае обнаружилась проблема, когда при использовании Softmax сеть не тренируется должным образом и предсказания становятся статичными. Это может быть связано с тем, что Softmax, как функция активации, применяется не совсем корректно в контексте вашей задачи.

Основные Причины Проблемы

1. Неправильное Применение Softmax

Softmax обычно используется в задачах классификации для нормализации значений логитов в диапазоне от 0 до 1. Если вы используете Softmax в задачах регрессии, это может привести к неэффективному обучению, так как это преобразование не сохраняет информацию о расстояниях между значениями, что критично для регрессии.

2. Исчезающие Градиенты

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

3. Инициализация Веса

Если инициализация весов не достаточна для обеспечения разнообразия активации, это может усугубить проблему исчезающих градиентов.

Решения и Рекомендации

1. Примените Другую Функцию Активации

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

2. Настройка Модели

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

3. Измените Инициализацию Весов

Попробуйте инициализацию весов с помощью torch.nn.init.xavier_uniform_ или torch.nn.init.kaiming_uniform_, так как эти методы хорошо работают с ReLU и его производными, предотвращая исчезающие градиенты.

4. Мониторинг Градиентов

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

5. Нормализация Данных

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

Пример Корректировки Вашей Модели

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

import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable

class NeuralNetwork(nn.Module):
    def __init__(self, inputsize, outputsize):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(inputsize, 128),  # Используем больше нейронов
            nn.LeakyReLU(),
            nn.Linear(128, outputsize)   # Выходной слой
        )
        nn.init.xavier_uniform_(self.parameters())  # Инициализация весов

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

# Установка параметров
inputDim = 1          
outputDim = 1         
learningRate = 0.001 
epochs = 100000

model = NeuralNetwork(inputDim, outputDim)
optimizer = optim.SGD(model.parameters(), lr=learningRate)
criterion = nn.MSELoss()

# Обучение модели
for epoch in range(epochs):
    if torch.cuda.is_available():
        inputs = Variable(torch.from_numpy(vS0).cuda().float())
        labels = Variable(torch.from_numpy(vC).cuda().float())
    else:
        inputs = Variable(torch.from_numpy(vS0).float())
        labels = Variable(torch.from_numpy(vC).float())

    optimizer.zero_grad()
    outputs = model(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()

    print('epoch {}, loss {}'.format(epoch, loss.item()))

Заключение

Несмотря на то что Softmax является мощным инструментом для определённых задач, в вашем случае использование функций активации, предназначенных для регрессии, таких как ReLU или LeakyReLU, может привести к лучшим результатам. Проверяйте, корректно ли вы используете функции активации в зависимости от типа вашей задачи, и следите за тем, как инициализируются веса модели. Настройка модели и изменение архитектуры могут существенно повлиять на её производительность.

Оцените материал
Добавить комментарий

Капча загружается...