Создание простой нейронной сети с использованием Pytorch с нуля

Узнайте об основах PyTorch, взглянув на подробную информацию о том, как работают нейронные сети. Начните работу с PyTorch сегодня.

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

Что такое нейронные сети? 

Нейронные сети также называют искусственными нейронными сетями (ИНС). Архитектура формирует основу глубокого обучения, which is merely a subset of machine learning concerned with algorithms that take inspiration from the structure and function of the human brain.  Put simply, neural networks form the basis of architectures that mimic how biological neurons signal to one another. 

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

Общая архитектура нейронной сети состоит из следующего:

  • Входной слой : данные подаются в сеть через входной слой. Количество нейронов во входном слое эквивалентно количеству признаков в данных. Входной уровень технически не рассматривается как один из уровней в сети, потому что в этой точке не происходит никаких вычислений.
  • Скрытый слой : Слои между входным и выходным слоями называются скрытыми слоями. Сеть может иметь произвольное количество скрытых слоев — чем больше скрытых слоев, тем сложнее сеть.
  • Выходной слой : выходной слой используется для прогнозирования.
  • Нейроны : каждый слой имеет набор нейронов, взаимодействующих с нейронами других слоев.
  • Функция активации : выполняет нелинейные преобразования, чтобы помочь модели изучить сложные закономерности на основе данных.

Трехслойная нейронная сеть

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

Как работают нейронные сети? 

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

Инициализация веса

Инициализация веса — это первый компонент в архитектуре нейронной сети. Начальные веса мы установили, чтобы определить начальную точку для процесса оптимизации модели нейронной сети. 

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

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

Вот несколько распространенных подходов к инициализации веса: 

Нулевая инициализация

Нулевая инициализация означает, что веса инициализируются как ноль. Это не очень хорошее решение, так как наша нейронная сеть не сможет нарушить симметрию — она не будет обучаться. 

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

Случайная инициализация:

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

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

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

Инициализация Ксавьера/Глорота 

Инициализация Ксавьера или Глорота (под любым названием) — это эвристический подход, используемый для инициализации весов. Обычно такой подход к инициализации можно увидеть всякий раз, когда к средневзвешенному значению применяется тангенсная или сигмовидная функция активации. Этот подход был впервые предложен в 2010 году в исследовательской статье Ксавьера Глорота и Йошуа Бенджио под названием « Понимание сложности обучения нейронных сетей с глубокой прямой связью». Этот метод инициализации направлен на поддержание одинаковой дисперсии в сети, чтобы предотвратить взрыв или исчезновение градиентов. 

He/Kaiming инициализация 

Инициализация He или Kaiming — еще один эвристический подход. Разница с эвристикой He и Xavier заключается в том, что при инициализации He используется другой коэффициент масштабирования для весов, учитывающий нелинейность функций активации. 

Таким образом, когда в слоях используется функция активации ReLU, рекомендуемым подходом является инициализация He. Вы можете узнать больше об этом подходе в книге «Погружаясь в выпрямители: превосходя производительность на уровне человека в классификации ImageNet » He et al.

Прямое распространение

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

Средневзвешенная сумма в нейронной сети.png

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

  • z - взвешенная сумма входных данных нейрона
  • Wn обозначает веса
  • Xn обозначает независимые переменные, а
  • b — погрешность.

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

Функции активации

Мы уже упоминали некоторые функции активации в разделе об инициализации веса , но теперь вы знаете их важность в архитектуре нейронной сети.

Давайте углубимся в некоторые общие функции активации, которые вы, вероятно, увидите, читая исследовательские работы и чужой код.  

сигмовидная

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

Вот как вы можете визуализировать свою собственную сигмовидную функцию с помощью Python: 

# Sigmoid function in Python
import matplotlib.pyplot as plt
import numpy as np




x = np.linspace(-5, 5, 50)
z = 1/(1 + np.exp(-x))




plt.subplots(figsize=(8, 5))
plt.plot(x, z)
plt.grid()
plt.show()

Линейный график сигмовидной функции

Тан

Гиперболический тангенс (tanh) имеет ту же S-образную кривую, что и сигмовидная функция, за исключением того, что значения ограничены между -1 и 1. Таким образом, небольшие входные данные отображаются ближе к -1, а большие входные данные отображаются ближе к 1. .

Выражение функции Тан

Вот пример функции tanh, визуализированный с помощью Python: 

# tanh function in Python
import matplotlib.pyplot as plt
import numpy as np




x = np.linspace(-5, 5, 50)
z = np.tanh(x)


plt.subplots(figsize=(8, 5))
plt.plot(x, z)
plt.grid()
plt.show()

Линейный график функции тангенса

Софтмакс

Функция softmax обычно используется в качестве функции активации в выходном слое. Это обобщение сигмовидной функции на несколько измерений. Таким образом, он используется в нейронных сетях для предсказания принадлежности к классу более чем по двум меткам. 

Выпрямленная линейная единица (ReLU)

Использование сигмовидной или тангенциальной функции для построения глубоких нейронных сетей рискованно, поскольку они, скорее всего, пострадают от проблемы исчезающего градиента. Функция активации выпрямленной линейной единицы (ReLU) стала решением этой проблемы и часто является функцией активации по умолчанию для нескольких нейронных сетей. 

 

Вот наглядный пример функции ReLU с использованием Python: 

# ReLU in Python
import matplotlib.pyplot as plt
import numpy as np


x = np.linspace(-5, 5, 50)
z = [max(0, i) for i in x]


plt.subplots(figsize=(8, 5))
plt.plot(x, z)
plt.grid()
plt.show()

Линейный график функции ReLU

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

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

Обратное распространение

В конце первого прямого прохода сеть делает прогнозы, используя инициализированные веса, которые не настраиваются. Таким образом, весьма вероятно, что прогнозы, которые делает модель, не будут точными. Используя потери, рассчитанные при прямом распространении, мы передаем информацию обратно через сеть для точной настройки весов в процессе, известном как обратное распространение. 

В конечном счете, мы используем функцию оптимизации, чтобы помочь нам определить веса, которые могут снизить частоту ошибок, сделать модель более надежной и повысить ее способность обобщать на новые случаи. Математика того, как это работает, выходит за рамки этой статьи, но заинтересованный читатель может узнать больше об обратном распространении в нашем курсе «Введение в глубокое обучение в Python» .

Учебное пособие по PyTorch: пошаговое руководство по созданию нейронной сети с нуля.

В этом разделе статьи мы создадим простую модель искусственной нейронной сети с использованием библиотеки PyTorch. Ознакомьтесь с этим рабочим пространством DataCamp , чтобы следовать коду.

PyTorch — одна из самых популярных библиотек для глубокого обучения. Он обеспечивает гораздо более прямой опыт отладки, чем TensorFlow. У него есть несколько других преимуществ, таких как распределенное обучение, надежная экосистема, облачная поддержка, позволяющая писать готовый к работе код и т. д. Вы можете узнать больше о PyTorch в разделе « Введение в глубокое обучение с помощью трека навыков PyTorch». 

Давайте перейдем к учебнику. 

Определение и подготовка данных 

Набор данных, который мы будем использовать в нашем руководстве, — это make_circles от scikit-learn — см . документацию . Это игрушечный набор данных, содержащий большой круг с меньшим кругом в двухмерной плоскости и две функции. Для нашей демонстрации мы использовали 10 000 выборок и добавили к данным стандартное отклонение 0,05 гауссовского шума. 

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

import matplotlib.pyplot as plt
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split

# Create a dataset with 10,000 samples.
X, y = make_circles(n_samples = 10000,
                    noise= 0.05,
                    random_state=26)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.33, random_state=26)

# Visualize the data.
fig, (train_ax, test_ax) = plt.subplots(ncols=2, sharex=True, sharey=True, figsize=(10, 5))
train_ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=plt.cm.Spectral)
train_ax.set_title("Training Data")
train_ax.set_xlabel("Feature #0")
train_ax.set_ylabel("Feature #1")

test_ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test)
test_ax.set_xlabel("Feature #0")
test_ax.set_title("Testing data")
plt.show()

Обучайте и тестируйте наборы данных

Следующим шагом является преобразование данных обучения и тестирования из массивов NumPy в тензоры PyTorch . Для этого мы собираемся создать собственный набор данных для наших учебных и тестовых файлов. Мы также собираемся использовать модуль PyTorch Dataloader , чтобы мы могли обучать наши данные партиями. Вот код: 

import warnings
warnings.filterwarnings("ignore")

!pip install torch -q

import torch
import numpy as np
from torch.utils.data import Dataset, DataLoader

# Convert data to torch tensors
class Data(Dataset):
    def __init__(self, X, y):
        self.X = torch.from_numpy(X.astype(np.float32))
        self.y = torch.from_numpy(y.astype(np.float32))
        self.len = self.X.shape[0]
       
    def __getitem__(self, index):
        return self.X[index], self.y[index]
   
    def __len__(self):
        return self.len
   
batch_size = 64

# Instantiate training and test data
train_data = Data(X_train, y_train)
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)

test_data = Data(X_test, y_test)
test_dataloader = DataLoader(dataset=test_data, batch_size=batch_size, shuffle=True)

# Check it's working
for batch, (X, y) in enumerate(train_dataloader):
    print(f"Batch: {batch+1}")
    print(f"X shape: {X.shape}")
    print(f"y shape: {y.shape}")
    break


"""
Batch: 1
X shape: torch.Size([64, 2])
y shape: torch.Size([64])
"""

Теперь перейдем к реализации и обучению нашей нейронной сети. 

Реализация нейронной сети и обучение модели

Мы собираемся реализовать простую двухслойную нейронную сеть, использующую функцию активации ReLU (torch.nn.functional.relu). Для этого мы собираемся создать класс NeuralNetwork, который наследуется от nn.Module, который является базовым классом для всех модулей нейронных сетей, созданных в PyTorch. 

Вот код: 

import torch
from torch import nn
from torch import optim

input_dim = 2
hidden_dim = 10
output_dim = 1

class NeuralNetwork(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(NeuralNetwork, self).__init__()
        self.layer_1 = nn.Linear(input_dim, hidden_dim)
        nn.init.kaiming_uniform_(self.layer_1.weight, nonlinearity="relu")
        self.layer_2 = nn.Linear(hidden_dim, output_dim)
       
    def forward(self, x):
        x = torch.nn.functional.relu(self.layer_1(x))
        x = torch.nn.functional.sigmoid(self.layer_2(x))

        return x
       
model = NeuralNetwork(input_dim, hidden_dim, output_dim)
print(model)


"""
NeuralNetwork(
  (layer_1): Linear(in_features=2, out_features=10, bias=True)
  (layer_2): Linear(in_features=10, out_features=1, bias=True)
)
"""

И это все. 

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

learning_rate = 0.1

loss_fn = nn.BCELoss()

optimizer = torch.optim.SGD(model.parameters(), lr=lea

Давайте обучим нашу модель

num_epochs = 100
loss_values = []


for epoch in range(num_epochs):
    for X, y in train_dataloader:
        # zero the parameter gradients
        optimizer.zero_grad()
       
        # forward + backward + optimize
        pred = model(X)
        loss = loss_fn(pred, y.unsqueeze(-1))
        loss_values.append(loss.item())
        loss.backward()
        optimizer.step()

print("Training Complete")

"""
Training Complete
"""

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

step = np.linspace(0, 100, 10500)

fig, ax = plt.subplots(figsize=(8,5))
plt.plot(step, np.array(loss_values))
plt.title("Step-wise Loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.show()

Модель обучения

Визуализация выше показывает потерю нашей модели за 100 эпох. Первоначально потери начинаются с 0,7 и постепенно уменьшаются — это говорит нам о том, что наша модель со временем улучшает свои прогнозы. Однако модель, кажется, выходит на плато около отметки 60 эпох, что может быть связано с рядом причин, например, модель может находиться в области локального или глобального минимума функции потерь. 

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

Прогнозы и оценка модели

Делать прогнозы с помощью нашей нейронной сети PyTorch довольно просто. 

"""
We're not training so we don't need to calculate the gradients for our outputs
"""
with torch.no_grad():
    for X, y in test_dataloader:
        outputs = model(X)
        predicted = np.where(outputs < 0.5, 0, 1)
        predicted = list(itertools.chain(*predicted))
        y_pred.append(predicted)
        y_test.append(y)
        total += y.size(0)
        correct += (predicted == y.numpy()).sum().item()

print(f'Accuracy of the network on the 3300 test instances: {100 * correct // total}%')

"""
Accuracy of the network on the 3300 test instances: 97%
"""

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

Приведенный выше код перебирает тестовые пакеты, которые хранятся в переменной test_dataloader, без вычисления градиентов. Затем мы прогнозируем экземпляры в пакете и сохраняем результаты в переменной с именем outputs. Затем мы устанавливаем все значения меньше 0,5 на 0 и те, которые равны или больше 0,5 на 1. Затем эти значения добавляются в список для наших прогнозов.

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

Чтобы рассчитать точность всей модели, мы умножаем количество правильных прогнозов на 100 (чтобы получить процент), а затем делим его на количество экземпляров в нашем тестовом наборе. Наша модель имела точность 97%. Мы копаем дальше, используя матрицу путаницы и классификационный_отчет scikit-learn, чтобы лучше понять, как работает наша модель.

from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix

import seaborn as sns


y_pred = list(itertools.chain(*y_pred))
y_test = list(itertools.chain(*y_test))


print(classification_report(y_test, y_pred))

"""
              precision    recall  f1-score   support

        0.0       0.98      0.97      0.98      1635
        1.0       0.98      0.98      0.98      1665

    accuracy                           0.98      3300
  macro avg       0.98      0.98      0.98      3300
weighted avg       0.98      0.98      0.98      3300

"""




cf_matrix = confusion_matrix(y_test, y_pred)

plt.subplots(figsize=(8, 5))

sns.heatmap(cf_matrix, annot=True, cbar=False, fmt="g")

plt.show()

Прогнозы нейронных сетей

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

В этом руководстве по PyTorch мы рассмотрели фундаментальные основы нейронных сетей и использовали PyTorch, библиотеку Python для глубокого обучения, для реализации нашей сети. Мы использовали набор данных круга из scikit-learn для обучения двухслойной нейронной сети классификации. Затем мы сделали прогнозы на основе данных и оценили наши результаты, используя показатель точности. 

Ссылка: https://www.datacamp.com/tutorial/pytorch-tutorial-building-a-simple-neural-network-from-scratch

#pytorch #python

What is GEEK

Buddha Community

Создание простой нейронной сети с использованием Pytorch с нуля

Создание простой нейронной сети с использованием Pytorch с нуля

Узнайте об основах PyTorch, взглянув на подробную информацию о том, как работают нейронные сети. Начните работу с PyTorch сегодня.

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

Что такое нейронные сети? 

Нейронные сети также называют искусственными нейронными сетями (ИНС). Архитектура формирует основу глубокого обучения, which is merely a subset of machine learning concerned with algorithms that take inspiration from the structure and function of the human brain.  Put simply, neural networks form the basis of architectures that mimic how biological neurons signal to one another. 

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

Общая архитектура нейронной сети состоит из следующего:

  • Входной слой : данные подаются в сеть через входной слой. Количество нейронов во входном слое эквивалентно количеству признаков в данных. Входной уровень технически не рассматривается как один из уровней в сети, потому что в этой точке не происходит никаких вычислений.
  • Скрытый слой : Слои между входным и выходным слоями называются скрытыми слоями. Сеть может иметь произвольное количество скрытых слоев — чем больше скрытых слоев, тем сложнее сеть.
  • Выходной слой : выходной слой используется для прогнозирования.
  • Нейроны : каждый слой имеет набор нейронов, взаимодействующих с нейронами других слоев.
  • Функция активации : выполняет нелинейные преобразования, чтобы помочь модели изучить сложные закономерности на основе данных.

Трехслойная нейронная сеть

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

Как работают нейронные сети? 

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

Инициализация веса

Инициализация веса — это первый компонент в архитектуре нейронной сети. Начальные веса мы установили, чтобы определить начальную точку для процесса оптимизации модели нейронной сети. 

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

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

Вот несколько распространенных подходов к инициализации веса: 

Нулевая инициализация

Нулевая инициализация означает, что веса инициализируются как ноль. Это не очень хорошее решение, так как наша нейронная сеть не сможет нарушить симметрию — она не будет обучаться. 

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

Случайная инициализация:

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

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

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

Инициализация Ксавьера/Глорота 

Инициализация Ксавьера или Глорота (под любым названием) — это эвристический подход, используемый для инициализации весов. Обычно такой подход к инициализации можно увидеть всякий раз, когда к средневзвешенному значению применяется тангенсная или сигмовидная функция активации. Этот подход был впервые предложен в 2010 году в исследовательской статье Ксавьера Глорота и Йошуа Бенджио под названием « Понимание сложности обучения нейронных сетей с глубокой прямой связью». Этот метод инициализации направлен на поддержание одинаковой дисперсии в сети, чтобы предотвратить взрыв или исчезновение градиентов. 

He/Kaiming инициализация 

Инициализация He или Kaiming — еще один эвристический подход. Разница с эвристикой He и Xavier заключается в том, что при инициализации He используется другой коэффициент масштабирования для весов, учитывающий нелинейность функций активации. 

Таким образом, когда в слоях используется функция активации ReLU, рекомендуемым подходом является инициализация He. Вы можете узнать больше об этом подходе в книге «Погружаясь в выпрямители: превосходя производительность на уровне человека в классификации ImageNet » He et al.

Прямое распространение

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

Средневзвешенная сумма в нейронной сети.png

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

  • z - взвешенная сумма входных данных нейрона
  • Wn обозначает веса
  • Xn обозначает независимые переменные, а
  • b — погрешность.

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

Функции активации

Мы уже упоминали некоторые функции активации в разделе об инициализации веса , но теперь вы знаете их важность в архитектуре нейронной сети.

Давайте углубимся в некоторые общие функции активации, которые вы, вероятно, увидите, читая исследовательские работы и чужой код.  

сигмовидная

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

Вот как вы можете визуализировать свою собственную сигмовидную функцию с помощью Python: 

# Sigmoid function in Python
import matplotlib.pyplot as plt
import numpy as np




x = np.linspace(-5, 5, 50)
z = 1/(1 + np.exp(-x))




plt.subplots(figsize=(8, 5))
plt.plot(x, z)
plt.grid()
plt.show()

Линейный график сигмовидной функции

Тан

Гиперболический тангенс (tanh) имеет ту же S-образную кривую, что и сигмовидная функция, за исключением того, что значения ограничены между -1 и 1. Таким образом, небольшие входные данные отображаются ближе к -1, а большие входные данные отображаются ближе к 1. .

Выражение функции Тан

Вот пример функции tanh, визуализированный с помощью Python: 

# tanh function in Python
import matplotlib.pyplot as plt
import numpy as np




x = np.linspace(-5, 5, 50)
z = np.tanh(x)


plt.subplots(figsize=(8, 5))
plt.plot(x, z)
plt.grid()
plt.show()

Линейный график функции тангенса

Софтмакс

Функция softmax обычно используется в качестве функции активации в выходном слое. Это обобщение сигмовидной функции на несколько измерений. Таким образом, он используется в нейронных сетях для предсказания принадлежности к классу более чем по двум меткам. 

Выпрямленная линейная единица (ReLU)

Использование сигмовидной или тангенциальной функции для построения глубоких нейронных сетей рискованно, поскольку они, скорее всего, пострадают от проблемы исчезающего градиента. Функция активации выпрямленной линейной единицы (ReLU) стала решением этой проблемы и часто является функцией активации по умолчанию для нескольких нейронных сетей. 

 

Вот наглядный пример функции ReLU с использованием Python: 

# ReLU in Python
import matplotlib.pyplot as plt
import numpy as np


x = np.linspace(-5, 5, 50)
z = [max(0, i) for i in x]


plt.subplots(figsize=(8, 5))
plt.plot(x, z)
plt.grid()
plt.show()

Линейный график функции ReLU

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

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

Обратное распространение

В конце первого прямого прохода сеть делает прогнозы, используя инициализированные веса, которые не настраиваются. Таким образом, весьма вероятно, что прогнозы, которые делает модель, не будут точными. Используя потери, рассчитанные при прямом распространении, мы передаем информацию обратно через сеть для точной настройки весов в процессе, известном как обратное распространение. 

В конечном счете, мы используем функцию оптимизации, чтобы помочь нам определить веса, которые могут снизить частоту ошибок, сделать модель более надежной и повысить ее способность обобщать на новые случаи. Математика того, как это работает, выходит за рамки этой статьи, но заинтересованный читатель может узнать больше об обратном распространении в нашем курсе «Введение в глубокое обучение в Python» .

Учебное пособие по PyTorch: пошаговое руководство по созданию нейронной сети с нуля.

В этом разделе статьи мы создадим простую модель искусственной нейронной сети с использованием библиотеки PyTorch. Ознакомьтесь с этим рабочим пространством DataCamp , чтобы следовать коду.

PyTorch — одна из самых популярных библиотек для глубокого обучения. Он обеспечивает гораздо более прямой опыт отладки, чем TensorFlow. У него есть несколько других преимуществ, таких как распределенное обучение, надежная экосистема, облачная поддержка, позволяющая писать готовый к работе код и т. д. Вы можете узнать больше о PyTorch в разделе « Введение в глубокое обучение с помощью трека навыков PyTorch». 

Давайте перейдем к учебнику. 

Определение и подготовка данных 

Набор данных, который мы будем использовать в нашем руководстве, — это make_circles от scikit-learn — см . документацию . Это игрушечный набор данных, содержащий большой круг с меньшим кругом в двухмерной плоскости и две функции. Для нашей демонстрации мы использовали 10 000 выборок и добавили к данным стандартное отклонение 0,05 гауссовского шума. 

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

import matplotlib.pyplot as plt
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split

# Create a dataset with 10,000 samples.
X, y = make_circles(n_samples = 10000,
                    noise= 0.05,
                    random_state=26)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.33, random_state=26)

# Visualize the data.
fig, (train_ax, test_ax) = plt.subplots(ncols=2, sharex=True, sharey=True, figsize=(10, 5))
train_ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=plt.cm.Spectral)
train_ax.set_title("Training Data")
train_ax.set_xlabel("Feature #0")
train_ax.set_ylabel("Feature #1")

test_ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test)
test_ax.set_xlabel("Feature #0")
test_ax.set_title("Testing data")
plt.show()

Обучайте и тестируйте наборы данных

Следующим шагом является преобразование данных обучения и тестирования из массивов NumPy в тензоры PyTorch . Для этого мы собираемся создать собственный набор данных для наших учебных и тестовых файлов. Мы также собираемся использовать модуль PyTorch Dataloader , чтобы мы могли обучать наши данные партиями. Вот код: 

import warnings
warnings.filterwarnings("ignore")

!pip install torch -q

import torch
import numpy as np
from torch.utils.data import Dataset, DataLoader

# Convert data to torch tensors
class Data(Dataset):
    def __init__(self, X, y):
        self.X = torch.from_numpy(X.astype(np.float32))
        self.y = torch.from_numpy(y.astype(np.float32))
        self.len = self.X.shape[0]
       
    def __getitem__(self, index):
        return self.X[index], self.y[index]
   
    def __len__(self):
        return self.len
   
batch_size = 64

# Instantiate training and test data
train_data = Data(X_train, y_train)
train_dataloader = DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)

test_data = Data(X_test, y_test)
test_dataloader = DataLoader(dataset=test_data, batch_size=batch_size, shuffle=True)

# Check it's working
for batch, (X, y) in enumerate(train_dataloader):
    print(f"Batch: {batch+1}")
    print(f"X shape: {X.shape}")
    print(f"y shape: {y.shape}")
    break


"""
Batch: 1
X shape: torch.Size([64, 2])
y shape: torch.Size([64])
"""

Теперь перейдем к реализации и обучению нашей нейронной сети. 

Реализация нейронной сети и обучение модели

Мы собираемся реализовать простую двухслойную нейронную сеть, использующую функцию активации ReLU (torch.nn.functional.relu). Для этого мы собираемся создать класс NeuralNetwork, который наследуется от nn.Module, который является базовым классом для всех модулей нейронных сетей, созданных в PyTorch. 

Вот код: 

import torch
from torch import nn
from torch import optim

input_dim = 2
hidden_dim = 10
output_dim = 1

class NeuralNetwork(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(NeuralNetwork, self).__init__()
        self.layer_1 = nn.Linear(input_dim, hidden_dim)
        nn.init.kaiming_uniform_(self.layer_1.weight, nonlinearity="relu")
        self.layer_2 = nn.Linear(hidden_dim, output_dim)
       
    def forward(self, x):
        x = torch.nn.functional.relu(self.layer_1(x))
        x = torch.nn.functional.sigmoid(self.layer_2(x))

        return x
       
model = NeuralNetwork(input_dim, hidden_dim, output_dim)
print(model)


"""
NeuralNetwork(
  (layer_1): Linear(in_features=2, out_features=10, bias=True)
  (layer_2): Linear(in_features=10, out_features=1, bias=True)
)
"""

И это все. 

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

learning_rate = 0.1

loss_fn = nn.BCELoss()

optimizer = torch.optim.SGD(model.parameters(), lr=lea

Давайте обучим нашу модель

num_epochs = 100
loss_values = []


for epoch in range(num_epochs):
    for X, y in train_dataloader:
        # zero the parameter gradients
        optimizer.zero_grad()
       
        # forward + backward + optimize
        pred = model(X)
        loss = loss_fn(pred, y.unsqueeze(-1))
        loss_values.append(loss.item())
        loss.backward()
        optimizer.step()

print("Training Complete")

"""
Training Complete
"""

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

step = np.linspace(0, 100, 10500)

fig, ax = plt.subplots(figsize=(8,5))
plt.plot(step, np.array(loss_values))
plt.title("Step-wise Loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.show()

Модель обучения

Визуализация выше показывает потерю нашей модели за 100 эпох. Первоначально потери начинаются с 0,7 и постепенно уменьшаются — это говорит нам о том, что наша модель со временем улучшает свои прогнозы. Однако модель, кажется, выходит на плато около отметки 60 эпох, что может быть связано с рядом причин, например, модель может находиться в области локального или глобального минимума функции потерь. 

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

Прогнозы и оценка модели

Делать прогнозы с помощью нашей нейронной сети PyTorch довольно просто. 

"""
We're not training so we don't need to calculate the gradients for our outputs
"""
with torch.no_grad():
    for X, y in test_dataloader:
        outputs = model(X)
        predicted = np.where(outputs < 0.5, 0, 1)
        predicted = list(itertools.chain(*predicted))
        y_pred.append(predicted)
        y_test.append(y)
        total += y.size(0)
        correct += (predicted == y.numpy()).sum().item()

print(f'Accuracy of the network on the 3300 test instances: {100 * correct // total}%')

"""
Accuracy of the network on the 3300 test instances: 97%
"""

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

Приведенный выше код перебирает тестовые пакеты, которые хранятся в переменной test_dataloader, без вычисления градиентов. Затем мы прогнозируем экземпляры в пакете и сохраняем результаты в переменной с именем outputs. Затем мы устанавливаем все значения меньше 0,5 на 0 и те, которые равны или больше 0,5 на 1. Затем эти значения добавляются в список для наших прогнозов.

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

Чтобы рассчитать точность всей модели, мы умножаем количество правильных прогнозов на 100 (чтобы получить процент), а затем делим его на количество экземпляров в нашем тестовом наборе. Наша модель имела точность 97%. Мы копаем дальше, используя матрицу путаницы и классификационный_отчет scikit-learn, чтобы лучше понять, как работает наша модель.

from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix

import seaborn as sns


y_pred = list(itertools.chain(*y_pred))
y_test = list(itertools.chain(*y_test))


print(classification_report(y_test, y_pred))

"""
              precision    recall  f1-score   support

        0.0       0.98      0.97      0.98      1635
        1.0       0.98      0.98      0.98      1665

    accuracy                           0.98      3300
  macro avg       0.98      0.98      0.98      3300
weighted avg       0.98      0.98      0.98      3300

"""




cf_matrix = confusion_matrix(y_test, y_pred)

plt.subplots(figsize=(8, 5))

sns.heatmap(cf_matrix, annot=True, cbar=False, fmt="g")

plt.show()

Прогнозы нейронных сетей

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

В этом руководстве по PyTorch мы рассмотрели фундаментальные основы нейронных сетей и использовали PyTorch, библиотеку Python для глубокого обучения, для реализации нашей сети. Мы использовали набор данных круга из scikit-learn для обучения двухслойной нейронной сети классификации. Затем мы сделали прогнозы на основе данных и оценили наши результаты, используя показатель точности. 

Ссылка: https://www.datacamp.com/tutorial/pytorch-tutorial-building-a-simple-neural-network-from-scratch

#pytorch #python

PyTorch For Deep Learning 

What is Pytorch ?

Pytorch is a Deep Learning Library Devoloped by Facebook. it can be used for various purposes such as Natural Language Processing , Computer Vision, etc

Prerequisites

Python, Numpy, Pandas and Matplotlib

Tensor Basics

What is a tensor ?

A Tensor is a n-dimensional array of elements. In pytorch, everything is a defined as a tensor.

#pytorch #pytorch-tutorial #pytorch-course #deep-learning-course #deep-learning

Facebook Gives Away This PyTorch Library For Differential Privacy

Recently, Facebook AI open-sourced a new high-speed library for training PyTorch models with differential privacy (DP) known as Opacus. The library is claimed to be more scalable than existing state-of-the-art methods.

According to the developers at the social media giant, differential privacy is a mathematically rigorous framework for quantifying the anonymisation of sensitive data. With the growing interest in the machine learning (ML) community, this framework is often used in analytics and computations.

Differential privacy constitutes a strong standard for privacy guarantees for algorithms on aggregate databases. It is usually defined in terms of the application-specific concept of adjacent databases. The framework has several properties that make it particularly useful in applications, such as group privacy, robustness to auxiliary information, among others.

#developers corner #differential privacy #facebook ai research #facebook differential privacy #opacus #pytorch #pytorch library #pytorch library opacus

Justyn  Ortiz

Justyn Ortiz

1610436416

Guide to Conda for TensorFlow and PyTorch

Learn how to set up anaconda environments for different versions of CUDA, TensorFlow, and PyTorch

It’s a real shame that the first experience that most people have with deep learning is having to spend days trying to figure out why the model they downloaded off of GitHub just… won’t… run….

Dependency issues are incredibly common when trying to run an off-the-shelf model. The most problematic of which is needing to have the correct version of CUDA for TensorFlow. TensorFlow has been prominent for a number of years meaning that even new models that are released could use an old version of TensorFlow. This wouldn’t be an issue except that it feels like every version of TensorFlow needs a specific version of CUDA where anything else is incompatible. Sadly, installing multiple versions of CUDA on the same machine can be a real pain!

#machine-learning #pytorch #tensorflow #pytorch

Регуляризация отсева с использованием PyTorch в Python

Как реализовать регуляризацию отсева с помощью PyTorch в Python

Узнайте о важности регуляризации отсева и о том, как ее применять в среде глубокого обучения PyTorch на Python.

Вступление

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

В этом уроке мы представим регуляризацию отсева для нейронных сетей. Сначала мы изучим предысторию и мотивацию внедрения отсева, а затем опишем, как теоретически работает отсев и как его реализовать в библиотеке Pytorch на Python.

Мы также увидим график потерь на тестовом наборе во времени в нейронной сети с отсевом и без него.

Содержание:

  • Вступление
  • Настройка всего
  • Обучение нейронной сети без отсева
  • Общие проблемы в нейронных сетях
    • Переоснащение
    • Бэгинг
  • Представляем отсев
    • Случайное удаление узлов
    • Уровень отсева
    • Практические советы по регуляризации отсева
    • Отсев при выводе
    • Примеры использования Dropout
  • Обучение нейронной сети с помощью Dropout
  • Вывод

Настройка всего

Для демонстрации мы будем использовать набор данных MNIST, доступный в библиотеке torchvision. Давайте установим все зависимости этого руководства:

$ pip install matplotlib==3.4.3 numpy==1.21.5 torch==1.10.1 torchvision

Если вы используете Colab, вам не нужно ничего устанавливать, так как все предустановлено. Импорт необходимых библиотек:

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np

Давайте удостоверимся, что мы тренируемся с использованием GPU, если CUDA доступна:

# defining our device, 'cuda:0' if CUDA is available, 'cpu' otherwise
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
device
device(type='cuda', index=0)

Давайте создадим конвейер преобразования для нашего набора данных MNIST:

# make the transform pipeline, converting to tensor and normalizing
transform = transforms.Compose([
  transforms.ToTensor(),
  transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
# the batch size during training
batch_size = 64

Затем загружаем обучающий набор данных:

train_dataset = torchvision.datasets.CIFAR10(root="./data", train=True, 
                                             download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size,
                                           shuffle=True, num_workers=2)
Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
170499072/? [00:06<00:00, 29640614.08it/s]
Extracting ./data/cifar-10-python.tar.gz to ./data

Мы переходим Trueк, trainчтобы указать обучающий набор данных, и мы также устанавливаем download, чтобы Trueзагрузить набор данных в указанную dataпапку. После этого мы делаем наш DataLoader, передаем batch_sizeи shuffleустанавливаем True.

Аналогично для тестового набора:

test_dataset = torchvision.datasets.CIFAR10(root="./data", train=False, 
                                             download=True, transform=transform)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size,
                                           shuffle=False, num_workers=2)
Files already downloaded and verified

На этот раз мы собираемся trainполучить Falseтестовый набор.

Ниже приведены доступные классы в наборе данных MNIST:

# the MNIST classes
classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

Обучение нейронной сети без отсева

Теперь, когда у нас есть набор данных, готовый к обучению, давайте создадим нейронную сеть без отсева:

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

net = Net()
# switch to GPU if available
net.to(device)

Инициализация кросс-энтропийной потери и оптимизатора SGD :

import torch.optim as optim

# defining the loss and the optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

Далее создадим функцию, которая принимает нейронную сеть, потери и загрузчик данных для расчета общих потерь:

def get_test_loss(net, criterion, data_loader):
  """A simple function that iterates over `data_loader` to calculate the overall loss"""
  testing_loss = []
  with torch.no_grad():
    for data in data_loader:
      inputs, labels = data
      # get the data to GPU (if available)
      inputs, labels = inputs.to(device), labels.to(device)
      outputs = net(inputs)
      # calculate the loss for this batch
      loss = criterion(outputs, labels)
      # add the loss of this batch to the list
      testing_loss.append(loss.item())
  # calculate the average loss
  return sum(testing_loss) / len(testing_loss)

Эта функция нам понадобится во время обучения. Приступаем к обучению прямо сейчас:

training_loss, testing_loss = [], []
running_loss = []
i = 0
for epoch in range(150): # 150 epochs
  for data in train_loader:
    inputs, labels = data
    # get the data to GPU (if available)
    inputs, labels = inputs.to(device), labels.to(device)
    optimizer.zero_grad()
    # forward pass
    outputs = net(inputs)
    # backward pass
    loss = criterion(outputs, labels)
    loss.backward()
    # update gradients
    optimizer.step()
    running_loss.append(loss.item())
    i += 1
    if i % 1000 == 0:
      avg_train_loss = sum(running_loss) / len(running_loss)
      avg_test_loss = get_test_loss(net, criterion, test_loader)
      # clear the list
      running_loss.clear()
      # for logging & plotting later
      training_loss.append(avg_train_loss)
      testing_loss.append(avg_test_loss)
      print(f"[{epoch:2d}] [it={i:5d}] Train Loss: {avg_train_loss:.3f}, Test Loss: {avg_test_loss:.3f}")

print("Done training.")

Выход:

[ 1] [it= 1000] Train Loss: 2.273, Test Loss: 2.118
[10] [it= 8000] Train Loss: 1.312, Test Loss: 1.326
[20] [it=16000] Train Loss: 1.031, Test Loss: 1.120
[30] [it=24000] Train Loss: 0.854, Test Loss: 1.043
[40] [it=32000] Train Loss: 0.718, Test Loss: 1.051
[51] [it=40000] Train Loss: 0.604, Test Loss: 1.085
[60] [it=47000] Train Loss: 0.521, Test Loss: 1.178
[70] [it=55000] Train Loss: 0.425, Test Loss: 1.370
[80] [it=63000] Train Loss: 0.348, Test Loss: 1.518
[93] [it=73000] Train Loss: 0.268, Test Loss: 1.859
[99] [it=78000] Train Loss: 0.248, Test Loss: 2.036
[109] [it=86000] Train Loss: 0.200, Test Loss: 2.351
[120] [it=94000] Train Loss: 0.161, Test Loss: 2.610
[130] [it=102000] Train Loss: 0.142, Test Loss: 2.976
[140] [it=110000] Train Loss: 0.117, Test Loss: 3.319
[149] [it=117000] Train Loss: 0.095, Test Loss: 3.593
Done training.

Общие проблемы в нейронных сетях

Переоснащение

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

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

Бэгинг

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

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

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

Представляем отсев

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

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

На обучающих данных нейроны учатся исправлять ошибки, допущенные их сверстниками, — процесс, известный как коадаптация. Следовательно, способность сети соответствовать обучающим данным резко улучшается. Поскольку коадаптации адаптированы к особенностям обучающих данных, они не будут обобщаться на тестовые данные; следовательно, он становится более изменчивым.

Нитиш Сривастава, Илья Суцкевер, Джеффри Хинтон, Алекс Крижевский и Руслан Салахутдинов были первыми, кто предложил отсев, чтобы минимизировать эффекты нейронной коадаптации.
 

 

выпадающий слой

Источник:  газета .

Случайное удаление узлов

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

Выпадение относится к удалению единиц (как скрытых, так и явных) из нейронной сети. Удаление устройства означает временное удаление его из сети, включая все его входящие и исходящие соединения. Dropout имитирует разреженную активацию с заданного уровня, что подталкивает сеть к изучению разреженного представления в качестве побочного эффекта. Его можно использовать вместо регуляризации активности для поощрения разреженных представлений в моделях автокодировщика.

Уровень отсева

Dropout добавляет новый гиперпараметр: вероятность сохранения единицы p. Этот гиперпараметр управляет степенью отсева.

Отсева нет, когда p = 1, а низкие значения p указывают на то, что отсева много. Для скрытых блоков типичные значения p находятся в диапазоне от 0,5 до 0,8.

Тип ввода влияет на выбор входных слоев. Типичное значение для входных данных с действительным знаком (изображения или звуковые кадры) равно 0,8.

Выбор p для скрытых слоев связан с количеством скрытых единиц n. Меньшее p требует большего n, что замедляет обучение и приводит к недообучению.

Когда p велико, Dropout может быть недостаточно, чтобы избежать переобучения. На определенном уровне единицы будут иметь 70%-й шанс оставаться активным и 30%-й риск быть удаленным, если вероятность удержания на этом уровне составляет 0,7%.

Обратите внимание, что PyTorch и другие фреймворки для глубокого обучения используют коэффициент отсева вместо коэффициента сохранения p, коэффициент сохранения 70% означает коэффициент отсева 30% и т. д.

Практические советы по регуляризации отсева

  • Частота отсева : значение гиперпараметра отсева по умолчанию — это вероятность обучения определенного узла в слое, где 1,0 означает отсутствие отсева, а 0,0 — отсутствие выходных данных слоя.
  • Использование более широкой сети : более крупные сети (с большим количеством слоев или узлов) более склонны к переоснащению обучающих данных. При использовании регуляризации отсева можно использовать более крупные сети с меньшей опасностью переобучения.
  • Grided Search Parameters : методически тестируйте различные показатели, а не предполагайте разумный процент отсева для вашей сети. Методично тестируйте различные скорости. Вы можете тестировать значения в диапазоне от 1,0 до 0,1 с шагом 0,1.
  • Используйте ограничение по весу : веса сети будут расти из-за вероятностного устранения активаций слоев. Значительный размер веса может указывать на нестабильную сеть. Чтобы противодействовать этому эффекту, может применяться ограничение по весу, чтобы заставить норму (величину) всех весов в слое быть меньше определенного значения.

Отсев при выводе

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

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

Таким образом, нейроны в последующем слое будут перевозбуждены, если вы используете 50-процентный коэффициент отсева во время обучения и удаляете два из каждых четырех нейронов в слое. Таким образом, значения, выдаваемые этими нейронами, будут на 50% больше, чем необходимо. Вероятность удержания (1 — показатель отсева) используется для уменьшения веса сверхактивированных нейронов во время тестирования и вывода. На рисунке ниже, созданном участником  Datascience Stackexchange Дмитрием Прилипко , прекрасно показано, как это работает:

выбывать

Примеры использования Dropout

Впервые представленный Джеффри Хинтоном и его коллегами в их статье 2012 года под названием « Улучшение нейронных сетей путем предотвращения совместной адаптации детекторов признаков », отсев был применен к широкому кругу типов задач, включая классификацию фотографий (CIFAR-10), распознавание рукописных цифр (MNIST). ) и распознавание речи (TIMIT).

В этой статье можно вывести некоторые интересные факты о приложениях отсева в наборе данных MNIST.
 

  • MNIST, широко используемый тест для систем машинного обучения, был использован для изучения эффективности отсева. В базу данных включены 60 000 обучающих фотографий рукописных цифр размером 28x28 и 10 000 тестовых изображений.
  • Улучшение обучающих данных с помощью преобразованных изображений или подключение знаний о пространственном преобразовании к сверточной нейронной сети или использование генеративного предварительного обучения для извлечения полезных функций из обучающих изображений без использования меток может значительно повысить производительность на тестовом наборе.
  • Наилучшая оценка для обычной нейронной сети с прямой связью составляет 160 ошибок на тестовом наборе без применения какой-либо из этих стратегий.
    При удалении случайных 20 процентов пикселей количество ошибок может быть снижено примерно до 130 и даже до 110 за счет применения отдельных ограничений L2 к входящим весам каждой скрытой единицы.
  • Отсев сочетался с генеративным предварительным обучением, но использовалась лишь небольшая скорость обучения. Никаких ограничений по весу не применялось, чтобы предотвратить потерю детекторов признаков, определенных в ходе предварительной подготовки. После точной настройки с использованием обычного обратного распространения общедоступная предварительно обученная сеть глубокого убеждения допустила 118 ошибок и в общей сложности 92 ошибки после точной настройки с использованием 50-процентного отсева скрытых единиц.
  • На приведенном ниже рисунке представлены нейронные сети, обученные с использованием обратного распространения с использованием 50% отсева для всех скрытых слоев в тестовом наборе MNIST, а отсев составляет 20% для самого низкого набора строк. На горизонтальной линии отображается лучший ранее зарегистрированный результат с использованием обратного распространения без предварительной тренировки, распределения веса или обновлений тренировочной сессии. 
     

 

мнист

Когда отсев был представлен в журнальной публикации 2014 года под названием « Отсев: простой способ предотвращения переобучения нейронных сетей» , он был опробован на широком спектре задач распознавания голоса, компьютерного зрения и классификации текста и обнаружил, что он повышает производительность во всех из них. . В данной статье описана процедура обучения отсевающих нейронных сетей.

Используя глубокие сверточные нейронные сети с регуляризацией отсева, Алекс Крижевский и др. В своей публикации 2012 года « Классификация ImageNet с глубокими свёрточными нейронными сетями » получили самые современные результаты для классификации изображений в наборе данных ImageNet.

Обучение нейронной сети с помощью Dropout

Подход Dropout — отличная иллюстрация того, как PyTorch сделал программирование простым и понятным.

С помощью двух строк кода мы можем достичь нашей цели, которая поначалу кажется сложной. Нам просто нужно добавить дополнительный слой исключения при разработке нашей модели. torch.nn.Dropout()Для этого будет использоваться класс .

Некоторые элементы входного тензора деактивируются этим классом случайным образом во время обучения. Параметр p дает вероятность деактивации нейрона. Эта опция имеет значение по умолчанию 0,5, что означает, что половина нейронов выпадет. Выходные данные масштабируются с коэффициентом 1/1-p, что указывает на то, что модуль просто вычисляет функцию идентичности во время оценки.

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

В этом сценарии отсев применяется после каждого шага в порядке убывания.

class NetDropout(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.do1 = nn.Dropout(0.2)  # 20% Probability
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.do2 = nn.Dropout(0.2)  # 20% Probability
        self.fc2 = nn.Linear(120, 84)
        self.do3 = nn.Dropout(0.1)  # 10% Probability
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = self.do1(x)
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.relu(self.fc1(x))
        x = self.do2(x)
        x = F.relu(self.fc2(x))
        x = self.do3(x)
        x = self.fc3(x)
        return x


net_dropout = NetDropout()
net_dropout.to(device)

Проведем тренировку как раньше:

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net_dropout.parameters(), lr=0.001, momentum=0.9)
training_loss_d, testing_loss_d = [], []
running_loss = []
i = 0
for epoch in range(150): # 10 epochs
  for data in train_loader:
    inputs, labels = data
    # get the data to GPU (if available)
    inputs, labels = inputs.to(device), labels.to(device)

    optimizer.zero_grad()
    # forward pass
    outputs = net_dropout(inputs)
    # backward pass
    loss = criterion(outputs, labels)
    loss.backward()
    # update gradients
    optimizer.step()
    running_loss.append(loss.item())
    i += 1
    if i % 1000 == 0:
      avg_train_loss = sum(running_loss) / len(running_loss)
      avg_test_loss = get_test_loss(net_dropout, criterion, test_loader)
      # clear the list
      running_loss.clear()
      # for logging & plotting later
      training_loss_d.append(avg_train_loss)
      testing_loss_d.append(avg_test_loss)
      print(f"[{epoch:2d}] [it={i:5d}] Train Loss: {avg_train_loss:.3f}, Test Loss: {avg_test_loss:.3f}")

print("Done training.")
[ 1] [it= 1000] Train Loss: 2.302, Test Loss: 2.298
[10] [it= 8000] Train Loss: 1.510, Test Loss: 1.489
[20] [it=16000] Train Loss: 1.290, Test Loss: 1.318
[30] [it=24000] Train Loss: 1.167, Test Loss: 1.214
[40] [it=32000] Train Loss: 1.085, Test Loss: 1.154
[49] [it=39000] Train Loss: 1.025, Test Loss: 1.141
[60] [it=47000] Train Loss: 0.979, Test Loss: 1.113
[70] [it=55000] Train Loss: 0.936, Test Loss: 1.082
[80] [it=63000] Train Loss: 0.902, Test Loss: 1.088
[90] [it=71000] Train Loss: 0.880, Test Loss: 1.087
[99] [it=78000] Train Loss: 0.856, Test Loss: 1.090
[109] [it=86000] Train Loss: 0.843, Test Loss: 1.094
[120] [it=94000] Train Loss: 0.818, Test Loss: 1.102
[130] [it=102000] Train Loss: 0.805, Test Loss: 1.090
[140] [it=110000] Train Loss: 0.796, Test Loss: 1.094
[149] [it=117000] Train Loss: 0.785, Test Loss: 1.115
Done training.

Теперь давайте построим тестовую потерю обеих сетей (с отсевом и без):

import matplotlib.pyplot as plt

# plot both benchmarks
plt.plot(testing_loss, label="no dropout")
plt.plot(testing_loss_d, label="with dropout")
# make the legend on the plot
plt.legend()
plt.title("The Cross-entropy loss of the MNIST test data with and w/o Dropout")
plt.show()

Выход:

С выпадением VS без выпадения

Вывод

Как видите, потери при тестировании нейронной сети без отсева начали увеличиваться примерно через 20 эпох, явно переобучая. В то время как при введении отсева он со временем продолжает уменьшаться.

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

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

Оригинальный источник статьи на https://www.thepythoncode.com

#pytorch #python #глубокоеобучение