Нейронная сеть представляет собой набор нейронных узлов, которые взаимосвязаны друг с другом. Эти связи распространяются не только на соседние нейроны, но и на удаленные.
Фундаментальная концепция нейронных сетей заключается в том, что каждый нейрон в слое получает входные значения и генерирует выходные значения с помощью определенных математических операций, применяемых к входным данным. Эти выходы затем служат входами для следующего слоя нейронов.
Однослойная нейронная сеть, также известная как однослойный персептрон, представляет собой архитектуру нейронной сети только с одним слоем узлов (нейронов). Этот слой часто называют выходным слоем. В однослойной нейронной сети каждый нейрон в скрытом слое получает входные данные, обрабатывает их с использованием определенных весов и применяет функцию активации для получения выходных данных. Выходы нейронов скрытого слоя напрямую связаны с выходным слоем, который генерирует конечный результат сети.
Ключевой характеристикой однослойных нейронных сетей является то, что они могут изучать только линейно разделимые шаблоны. Это означает, что они ограничены задачами, в которых данные могут быть классифицированы с использованием прямой линии или плоскости во входном пространстве. Для задач, требующих нелинейных границ решения, однослойных нейронных сетей недостаточно, и необходимы более сложные архитектуры, такие как многослойные нейронные сети или глубокие нейронные сети.
В этом уроке мы рассмотрим:
- Создание однослойной нейронной сети с помощью PyTorch
- Обучение однослойной нейронной сети
- Использование нейронной сети для классификации данных
ПОДГОТОВКА ДАННЫХ
Мы напишем код, который генерирует синтетические данные X
и присваивает соответствующие метки Y
для задачи классификации с тремя классами. Метки назначаются на основе определенных диапазонов значений в X
, где элементы меньше или равные -10 получают метку 1,0, элементы между -10 и 10 (исключительно) получают метку 0,5, а элементы больше 10 получают метку 0.
import torch import matplotlib.pyplot as plt # Generate synthetic data for X ranging from -30 to 29 with a step size of 1 X = torch.arange(-30, 30, 1).view(-1, 1).type(torch.FloatTensor) # Initialize an empty tensor Y to store the labels (target values) Y = torch.zeros(X.shape[0]) # Assign label 1.0 to elements in Y where the corresponding X value is less than or equal to -10 Y[X[:, 0] <= -10] = 1.0 # Assign label 0.5 to elements in Y where the corresponding X value falls between -10 and 10 (exclusive) Y[(X[:, 0] > -10) & (X[:, 0] < 10)] = 0.5 # Assign label 0 to elements in Y where the corresponding X value is greater than 10 Y[X[:, 0] > 10] = 0
Понимание тензоров:
Тензор — это фундаментальная структура данных, используемая в PyTorch для глубокого обучения. В простейшей форме тензор можно представить как многомерный массив. Это обобщение скаляров (0-мерных), векторов (1-мерных) и матриц (2-мерных) на более высокие измерения. Тензоры могут иметь произвольное количество измерений, что делает их универсальными для представления и обработки данных различной формы и размера.
Вот некоторые распространенные типы тензоров:
- Скаляр (0-мерный тензор): одно числовое значение, например действительное число.
- Вектор (одномерный тензор): упорядоченный набор значений по одному измерению, часто представляющий собой список чисел.
- Матрица (двумерный тензор): упорядоченный набор значений, расположенных в строках и столбцах, представляющий двумерную таблицу чисел.
- Многомерные тензоры: тензоры с более чем двумя измерениями, такие как трехмерные тензоры, четырехмерные тензоры и т. д. Они используются для представления более сложных структур данных, таких как изображения (трехмерные тензоры) или видеоданные (четырехмерные тензоры).
Давайте теперь построим данные, которые мы сгенерировали:
import matplotlib.pyplot as plt # Create a plot of X against Y plt.plot(X, Y) # Add X and Y labels to the plot plt.xlabel('X') plt.ylabel('Y') # Display the plot plt.show()
СОЗДАЙТЕ МОДЕЛЬ С ПОМОЩЬЮ PYTORCH nn.MODULE
nn.Module
— это фундаментальный класс в PyTorch, используемый для создания пользовательских архитектур нейронных сетей. Это базовый класс для всех модулей нейронных сетей в PyTorch, который предоставляет несколько важных функций для создания нейронных сетей и управления ими.
При создании пользовательской нейронной сети в PyTorch вы обычно создаете подкласс nn.Module
и определяете архитектуру, указывая слои и операции, из которых состоит ваша нейронная сеть.
Вот как ваша однослойная нейронная сеть выглядит в коде:
class SingleLayerNet(nn.Module): def __init__(self, input_size, hidden_neurons, output_size): super(SingleLayerNet, self).__init__() # Define the hidden layer with input_size input features and hidden_neurons neurons self.hidden_layer = nn.Linear(input_size, hidden_neurons) # Define the output layer with hidden_neurons input features and output_size neurons self.output_layer = nn.Linear(hidden_neurons, output_size) #Define a Prediction Function def forward(self, x): # Pass the input through the hidden layer and apply the sigmoid activation function hidden_output = torch.sigmoid(self.hidden_layer(x)) # Pass the hidden layer output through the output layer and apply the sigmoid activation function y_pred = torch.sigmoid(self.output_layer(hidden_output)) return y_pred
Разобьем этот код построчно:
- Код определяет класс однослойной нейронной сети с именем
SingleLayerNet
. - Класс наследуется от
nn.Module
, который является базовым классом для модулей нейронной сети PyTorch. - Конструктор (метод
__init__
) инициализирует архитектуру нейронной сети с размером ввода, размером скрытого слоя и размером вывода. - Он создает скрытый слой (
self.hidden_layer
), используяnn.Linear
с указанными входными данными и размером скрытого слоя. - Он создает выходной слой (
self.output_layer
), используяnn.Linear
со скрытым размером слоя и выходным размером. - Метод
forward
реализует прямой проход нейронной сети. - Входные данные (
x
) проходят через скрытый слой и применяют сигмовидную функцию активации, получаяhidden_output
. - Затем
hidden_output
проходит через выходной слой и применяет сигмовидную функцию активации, создавая окончательный прогнозy_pred
. - Метод
forward
возвращает прогнозy_pred
в качестве вывода нейронной сети.
Создайте экземпляр объекта модели:
# create the model model = SingleLayerNet(1, 2, 1) # 2 represents two neurons in one hidden layer
ОБУЧЕНИЕ ВАШЕЙ МОДЕЛИ
Определим функцию потерь и оптимизатор для модели. Вы напишете функцию потерь для перекрестной потери энтропии и используете стохастический градиентный спуск для оптимизации параметров.
# Define the loss function (criterion) def criterion(y_pred, y_true): # Binary Cross Entropy Loss # y_pred: predicted probabilities, y_true: true labels (0 or 1) # Compute the negative log likelihood loss using binary cross-entropy formula # (y * log(y_pred) + (1 - y) * log(1 - y_pred)) loss = -1 * (y_true * torch.log(y_pred) + (1 - y_true) * torch.log(1 - y_pred)) # Calculate the mean loss over the batch mean_loss = torch.mean(loss) return mean_loss # Assuming 'model' is an instance of your custom neural network # Create an optimizer (Stochastic Gradient Descent - SGD) optimizer = optim.SGD(model.parameters(), lr=0.01)
Функция criterion
вычисляет потерю двоичной перекрестной энтропии, обычно используемую функцию потерь для задач двоичной классификации.
Функция принимает два аргумента:
y_pred
: Предсказанные вероятности по модели (выход сигмовидной функции).y_true
: Истинные метки (наземная правда) для соответствующих входов.
Внутри функции бинарная кросс-энтропийная потеря вычисляется по формуле - (y * log(y_pred) + (1 - y) * log(1 - y_pred))
, где y
представляет истинные метки, а y_pred
представляет предсказанные вероятности.
Затем потери усредняются по партии путем вычисления среднего значения, которое является конечным результатом функции.
Оптимизатор создается с использованием стохастического градиентного спуска (SGD) для обновления параметров model
в процессе обучения. В качестве аргументов он принимает параметры модели (model.parameters()
) и скорость обучения (lr=0.01
). Скорость обучения определяет размер шага во время оптимизации.
Теперь у вас есть все компоненты для обучения модели. Давайте обучим модель на 5000 эпох. Вы увидите график того, как нейронная сеть аппроксимирует функцию через каждые 1000 эпох.
# Define the training loop epochs = 5000 cost = [] # List to store the total loss at each epoch for epoch in range(epochs): total_loss = 0 # Variable to store the total loss for the current epoch epoch = epoch + 1 # Increment the epoch count for x, y in zip(X, Y): # Forward pass: Calculate the predicted output (yhat) using the model yhat = model(x) # Calculate the loss between the predicted output (yhat) and the actual target (y) loss = criterion(yhat, y) # Backpropagation: Compute gradients of the model parameters with respect to the loss loss.backward() # Update the model parameters using the computed gradients optimizer.step() # Zero out the gradients for the next iteration to avoid accumulation optimizer.zero_grad() # Accumulate the loss for this batch of data total_loss += loss.item() # Append the total loss for this epoch to the cost list cost.append(total_loss) if epoch % 1000 == 0: print(f"Epoch {epoch} done!") # Print status after every 1000 epochs # Plot the result of the function approximator predicted_values = model(X).detach().numpy() plt.plot(X.numpy(), predicted_values) # Plot the predicted values plt.plot(X.numpy(), Y.numpy(), 'm') # Plot the ground truth data (Y) plt.xlabel('x') plt.ylabel('y') plt.legend(['Predicted', 'Ground Truth']) plt.title(f'Epoch {epoch} - Function Approximation') plt.show()
Как видите, нейронная сеть довольно хорошо аппроксимирует функции. Если функция более сложная, вам может понадобиться больше скрытых слоев или больше нейронов в скрытом слое, т. е. более сложная модель.
График снижения потерь во время обучения:
# Plot the cost (loss) over epochs plt.plot(cost, marker='o', linestyle='-', color='b', label='Training Loss') # Set labels and title plt.xlabel('Epochs') plt.ylabel('Cross Entropy Loss') plt.title('Training Progress - Cross Entropy Loss') # Add grid for better readability plt.grid(True) # Show legend plt.legend() # Display the plot plt.show()
Вот оно! Вы создали свою первую нейронную сеть с помощью PyTorch!
ДОПОЛНИТЕЛЬНЫЕ РЕСУРСЫ:
Ознакомьтесь с некоторыми другими статьями, которые я написал о нейронных сетях: