Загрузка данных
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})")