
Нейронная сеть представляет собой набор нейронных узлов, которые взаимосвязаны друг с другом. Эти связи распространяются не только на соседние нейроны, но и на удаленные.
Фундаментальная концепция нейронных сетей заключается в том, что каждый нейрон в слое получает входные значения и генерирует выходные значения с помощью определенных математических операций, применяемых к входным данным. Эти выходы затем служат входами для следующего слоя нейронов.
Однослойная нейронная сеть, также известная как однослойный персептрон, представляет собой архитектуру нейронной сети только с одним слоем узлов (нейронов). Этот слой часто называют выходным слоем. В однослойной нейронной сети каждый нейрон в скрытом слое получает входные данные, обрабатывает их с использованием определенных весов и применяет функцию активации для получения выходных данных. Выходы нейронов скрытого слоя напрямую связаны с выходным слоем, который генерирует конечный результат сети.
Ключевой характеристикой однослойных нейронных сетей является то, что они могут изучать только линейно разделимые шаблоны. Это означает, что они ограничены задачами, в которых данные могут быть классифицированы с использованием прямой линии или плоскости во входном пространстве. Для задач, требующих нелинейных границ решения, однослойных нейронных сетей недостаточно, и необходимы более сложные архитектуры, такие как многослойные нейронные сети или глубокие нейронные сети.
В этом уроке мы рассмотрим:
- Создание однослойной нейронной сети с помощью 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!
ДОПОЛНИТЕЛЬНЫЕ РЕСУРСЫ:
Ознакомьтесь с некоторыми другими статьями, которые я написал о нейронных сетях: