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

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

Шаг 1. Импорт библиотеки NumPy

import numpy as np

Шаг 2. Определите сетевую архитектуру

# Define the number of nodes in each layer
input_nodes = 3
hidden_nodes = 5
output_nodes = 1

# Define the weights for the input layer to hidden layer
weights_input_to_hidden = np.random.normal(0.0, input_nodes**-0.5, 
                                          (input_nodes, hidden_nodes))
# Define the weights for the hidden layer to output layer
weights_hidden_to_output = np.random.normal(0.0, hidden_nodes**-0.5, 
                                         (hidden_nodes, output_nodes))

На этом шаге мы определяем количество узлов в каждом слое и инициализируем веса входного слоя для скрытого слоя и скрытого слоя для соединений выходного слоя. Веса инициализируются случайными значениями с помощью функции NumPy random.normal.

Шаг 3. Определите функцию активации

# Define the activation function
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

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

Шаг 4. Внедрение алгоритма прямого распространения

def forward_propagation(inputs, weights_input_to_hidden, 
                        weights_hidden_to_output):
    # Compute the hidden layer inputs
    hidden_inputs = np.dot(inputs, weights_input_to_hidden)
    
    # Compute the hidden layer outputs
    hidden_outputs = sigmoid(hidden_inputs)
    
    # Compute the final layer inputs
    final_inputs = np.dot(hidden_outputs, weights_hidden_to_output)
    
    # Compute the final layer outputs
    final_outputs = sigmoid(final_inputs)
    
    return final_outputs, hidden_outputs

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

Шаг 5. Реализуйте алгоритм обратного распространения

def backward_propagation(inputs, targets, final_outputs, hidden_outputs, 
                         weights_hidden_to_output, 
                         weights_input_to_hidden):
    # Compute the error for the final layer
    error = targets - final_outputs
    
    # Compute the error for the hidden layer
    hidden_error = np.dot(error, weights_hidden_to_output.T)
    
    # Compute the gradients for the weights from the hidden layer to output layer
    output_grad = error * final_outputs * (1 - final_outputs)
    weights_hidden_to_output_grad = np.dot(hidden_outputs.T, output_grad)
    
    # Compute the gradients for the weights from the input layer to hidden layer
    hidden_grad = hidden_error * hidden_outputs * (1 - hidden_outputs)
    weights_input_to_hidden_grad = np.dot(inputs.T, hidden_grad)
    
    return weights_input_to_hidden_grad, weights_hidden_to_output_grad

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

Шаг 6. Обучение сети

def train(inputs, targets, weights_input_to_hidden, weights_hidden_to_output, 
          num_iterations=10000, learning_rate=0.1):
    for i in range(num_iterations):
        # Compute the final outputs and hidden outputs
        final_outputs, hidden_outputs = forward_propagation(inputs, 
                                                             weights_input_to_hidden, 
                                                             weights_hidden_to_output)
        
        # Compute the gradients for the weights
        weights_input_to_hidden_grad, weights_hidden_to_output_grad = backward_propagation(inputs, targets, 
                                                                                           final_outputs, 
                                                                                           hidden_outputs, 
                                                                                           weights_hidden_to_output, 
                                                                                           weights_input_to_hidden)
        
        # Update the weights
        weights_hidden_to_output += learning_rate * weights_hidden_to_output_grad
        weights_input_to_hidden += learning_rate * weights_input_to_hidden_grad

Шаг 7. Протестируйте сеть

def test(inputs, targets, weights_input_to_hidden, weights_hidden_to_output):
    final_outputs, _ = forward_propagation(inputs, weights_input_to_hidden, weights_hidden_to_output)
    return np.mean(np.square(targets - final_outputs))

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

Шаг 8: Запустите сеть

if __name__ == "__main__":
    # Define the inputs and targets
    inputs = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
    targets = np.array([[0], [1], [1], [0]])
    
    # Initialize the weights
    weights_input_to_hidden = np.random.rand(2, 2)
    weights_hidden_to_output = np.random.rand(2, 1)
    
    # Train the network
    train(inputs, targets, weights_input_to_hidden, weights_hidden_to_output)
    
    # Test the network
    error = test(inputs, targets, weights_input_to_hidden, weights_hidden_to_output)
    print("Mean Squared Error:", error)

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

Заключение

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