Загрузка данных


import numpy as np

class NeuralNetwork:
    def __init__(self, input_size, hidden_size, output_size, learning_rate=0.1):
        """
        Инициализация двухслойной нейросети.
        
        Параметры:
        - input_size: количество входных нейронов
        - hidden_size: количество нейронов в скрытом слое
        - output_size: количество выходных нейронов
        - learning_rate: скорость обучения (шаг градиентного спуска)
        """
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
        self.lr = learning_rate

        # Инициализируем веса случайными числами
        # Веса между входным и скрытым слоем
        self.weights_input_hidden = np.random.uniform(-1, 1, (self.input_size, self.hidden_size))
        # Веса между скрытым и выходным слоем
        self.weights_hidden_output = np.random.uniform(-1, 1, (self.hidden_size, self.output_size))

        # Инициализируем смещения (биосы) нулями
        self.bias_hidden = np.zeros((1, self.hidden_size))
        self.bias_output = np.zeros((1, self.output_size))

    def _sigmoid(self, x):
        """Функция активации Сигмоида"""
        return 1 / (1 + np.exp(-x))

    def _sigmoid_derivative(self, x):
        """Производная функции сигмоиды (нужна для обратного распространения ошибки)"""
        return x * (1 - x)

    def forward(self, X):
        """
        Прямое распространение сигнала через сеть.
        """
        # Вычисления для скрытого слоя: сумма (входы * веса) + смещение
        self.hidden_input = np.dot(X, self.weights_input_hidden) + self.bias_hidden
        # Активация скрытого слоя
        self.hidden_output = self._sigmoid(self.hidden_input)

        # Вычисления для выходного слоя: сумма (выходы скрытого * веса) + смещение
        self.output_input = np.dot(self.hidden_output, self.weights_hidden_output) + self.bias_output
        # Активация выходного слоя (финальное предсказание)
        self.output = self._sigmoid(self.output_input)
        
        return self.output

    def backward(self, X, y, output):
        """
        Обратное распространение ошибки и обновление весов.
        """
        # Ошибка выходного слоя: разница между реальным значением и предсказанием
        output_error = y - output
        # Градиент для выходного слоя
        output_delta = output_error * self._sigmoid_derivative(output)

        # Ошибка скрытого слоя (вклад весов выходного слоя в общую ошибку)
        hidden_error = output_delta.dot(self.weights_hidden_output.T)
        # Градиент для скрытого слоя
        hidden_delta = hidden_error * self._sigmoid_derivative(self.hidden_output)

        # Корректировка весов и смещений (градиентный спуск)
        self.weights_hidden_output += self.hidden_output.T.dot(output_delta) * self.lr
        self.bias_output += np.sum(output_delta, axis=0, keepdims=True) * self.lr

        self.weights_input_hidden += X.T.dot(hidden_delta) * self.lr
        self.bias_hidden += np.sum(hidden_delta, axis=0, keepdims=True) * self.lr

    def train(self, X, y, epochs=10000):
        """
        Метод обучения нейросети.
        """
        for epoch in range(epochs):
            # Шаг 1: Прямой ход
            output = self.forward(X)
            # Шаг 2: Обратный ход и корректировка весов
            self.backward(X, y, output)

            # Выводим ошибку каждые 1000 эпох для отслеживания прогресса
            if epoch % 1000 == 0:
                loss = np.mean(np.square(y - output))  # Среднеквадратичная ошибка (MSE)
                print(f"Эпоха {epoch:5d} | Среднеквадратичная ошибка (Loss): {loss:.6f}")


# --- Пример использования нейросети для решения задачи XOR (Исключающее ИЛИ) ---
if __name__ == "__main__":
    print("--- Обучение нейросети решению задачи XOR ---")

    # Входные данные (X) - 4 возможных комбинации для двух входов
    X = np.array([
        [0, 0],
        [0, 1],
        [1, 0],
        [1, 1]
    ])

    # Ожидаемые выходные данные (y) для XOR
    y = np.array([
        [0],
        [1],
        [1],
        [0]
    ])

    # Создаем нейросеть: 2 входа, 4 нейрона в скрытом слое, 1 выходной нейрон
    nn = NeuralNetwork(input_size=2, hidden_size=4, output_size=1, learning_rate=0.2)

    # Обучаем сеть на протяжении 10 000 эпох
    nn.train(X, y, epochs=10000)

    print("\n--- Результаты тестирования после обучения ---")
    for inputs in X:
        prediction = nn.forward(inputs)
        # Округляем предсказание до целого числа, чтобы получить четкий бинарный ответ
        binary_prediction = int(np.round(prediction[0]))
        print(f"Вход: {inputs} -> Предсказание сети: {prediction[0]:.4f} (Округленно: {binary_prediction})")