import math
import random
# --- 1. ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ (Вместо формул) ---
def activation(x):
"""Сглаживает любое число в диапазон от 0 до 1 (функция Сигмоида)"""
return 1 / (1 + math.exp(-x))
def activation_derivative(x):
"""Показывает, насколько сильно нужно изменить вес при ошибке"""
return x * (1 - x)
# --- 2. ДАННЫЕ ДЛЯ ОБУЧЕНИЯ ---
# Задача: выдать 1, только если ОДИН из входов равен 1. Если оба 0 или оба 1 -> выдать 0.
training_inputs = [[0, 0], [0, 1], [1, 0], [1, 1]]
training_outputs = [[0], [1], [1], [0]]
# --- 3. ИНИЦИАЛИЗАЦИЯ СЕТИ (Случайные веса) ---
random.seed(1) # Задаем фиксацию случайности для повторяемости
# Веса между входным слоем (2 входа) и скрытым слоем (3 нейрона)
weights_input_hidden = [
[random.uniform(-1, 1) for _ in range(3)] for _ in range(2)
]
# Веса между скрытым слоем (3 нейрона) и выходным слоем (1 выход)
weights_hidden_output = [
[random.uniform(-1, 1) for _ in range(1)] for _ in range(3)
]
learning_rate = 0.5 # Скорость обучения
# --- 4. ЦИКЛ ОБУЧЕНИЯ (20 000 повторений) ---
for epoch in range(20000):
for inputs, correct_output in zip(training_inputs, training_outputs):
# ---- ШАГ А: ПРЯМОЙ ХОД (Сигнал идет вперед) ----
# Считаем сигналы для 3-х нейронов в скрытом слое
hidden_layer_outputs = []
for j in range(3):
sum_j = inputs[0] * weights_input_hidden[0][j] + inputs[1] * weights_input_hidden[1][j]
hidden_layer_outputs.append(activation(sum_j))
# Считаем финальный прогноз на выходе
final_sum = 0
for j in range(3):
final_sum += hidden_layer_outputs[j] * weights_hidden_output[j][0]
prediction = activation(final_sum)
# ---- ШАГ Б: ОБРАТНЫЙ ХОД (Исправление ошибок) ----
# 1. Считаем ошибку на самом выходе
output_error = correct_output[0] - prediction
output_delta = output_error * activation_derivative(prediction)
# 2. Переносим ошибку назад на скрытый слой
hidden_deltas = []
for j in range(3):
hidden_error = output_delta * weights_hidden_output[j][0]
hidden_deltas.append(
hidden_error * activation_derivative(hidden_layer_outputs[j])
)
# 3. Корректируем веса между скрытым и выходным слоями
for j in range(3):
weights_hidden_output[j][0] += (
learning_rate * output_delta * hidden_layer_outputs[j]
)
# 4. Корректируем веса между входным и скрытым слоями
for i in range(2):
for j in range(3):
weights_input_hidden[i][j] += (
learning_rate * hidden_deltas[j] * inputs[i]
)
print("Обучение многослойной сети завершено!\n")
# --- 5. ПРОВЕРКА РЕЗУЛЬТАТОВ ---
print("--- ТЕСТИРОВАНИЕ СЕТИ ---")
for inputs in training_inputs:
# Повторяем только ПРЯМОЙ ХОД для проверки
hidden_layer_outputs = []
for j in range(3):
sum_j = inputs[0] * weights_input_hidden[0][j] + inputs[1] * weights_input_hidden[1][j]
hidden_layer_outputs.append(activation(sum_j))
final_sum = 0
for j in range(3):
final_sum += hidden_layer_outputs[j] * weights_hidden_output[j][0]
prediction = activation(final_sum)
print(
f"Входы: {inputs} -> Прогноз сети: {prediction:.4f} (Округляем до {round(prediction)})"
)