ГРОКАЕМ ТРАСКА. ГЛАВА 3: FORWARD PROPAGATION
Кот в Коде | @kot_research_botПОЧЕМУ МЫ ЗДЕСЬ?
Первые две главы — это теория. Но Дирижёру важно понимать, как устроены шестерни. Мы прыгаем в Главу 3, чтобы увидеть, как ИИ перестает быть магией и становится математикой. Наша цель — разобраться, как данные летят сквозь слои и превращаются в прогноз. Вайб-кодинг — это когда ты знаешь базу настолько хорошо, что можешь дирижировать ею с закрытыми глазами.
ПЕРЕДАЧА ОДНОЙ ТОЧКИ ДАННЫХ
Входы — это наши датчики. Мы берем текущее состояние перед началом каждой из четырёх игр в сезоне. Это массив чисел: среднее число игр, сыгранных игроками, доля побед и число болельщиков. Просто цифры, которые мы скармливаем системе.
# ПРОСТАЯ НЕЙРОННАЯ СЕТЬ, ДЕЛАЮЩАЯ ПРОГНОЗ
# 1. Чистая сеть
weight=0.1
def neural_network(input, weight):
prediction = input*weight # умножение входного значения на весовой коэффициент
return prediction
# 2. Передача одной точки данных
number_of_toes=[8.5, 9.5, 10, 9]
input = number_of_toes[0]
prediction=neural_network(input, weight) # получение прогноза
print(prediction)
ПОЛУЧЕНИЕ ПРОГНОЗА
Самая важная операция — взвешенная сумма (`w_sum`). Веса — это наши «ручки настройки» (knobs). Если мы считаем, что параметр важен, мы подкручиваем вес. Прогноз получается путем перемножения входа на вес. Функция w_sum берет каждый вход, умножает на соответствующий вес и складывает всё в один результат.
# ПРОГНОЗИРОВАНИЕ С НЕСКОЛЬКИМИ ВХОДАМИ
# 1. Вычисление взвешенной суммы входов
def w_sum(a, b):
assert len(a) == len(b)
output = 0
for i in range(len(a)):
output += (a[i] * b[i])
# поэлементная операция - попарно объединение
# значений соответствующих элементов вектором
# с равной длиной
return output
# 2. Чистая сеть с несколькими входами
weights = [0.1, 0.2, 0]
# 0.1 - данные игр
# 0.2 - победа/поражение
# 0 - данные болельщиков
# 2. Нейронная сеть
def neural_network(input, weights):
pred = w_sum(input, weights)
return pred
# 3. Передача одной точки данных
toes = [8.5, 9.5, 9.9, 9.0] # текущее среднее число игр
wlrec = [0.65, 0.8, 0.8, 0.9] # текущая доля побед
nfans = [1.2, 1.3, 0.5, 1.0] # число болельщиков (в миллионах)
input = [toes[0], wlrec[0], nfans[0]] # данные первой игры
# 4. Прогноз
pred = neural_network(input, weights)
print("Прогноз:", pred) # взвешенная сумма входов/взвешенная сумма/скалярное произведение
ПРОГНОЗИРОВАНИЕ НА ОСНОВЕ ПРОГНОЗОВ
Нейросеть становится «глубокой», когда между входом и выходом появляются скрытые слои. Данные не идут сразу на результат. Сначала сеть формирует «внутреннее мнение» (скрытый слой) о промежуточных состояниях, а уже на их основе выдает финальный пакет прогнозов: будет ли победа, будут ли травмы и не накроет ли команду печаль.
# ПРОГНОЗИРОВАНИЕ НА ОСНОВЕ ПРОГНОЗОВ
# ВХОДЫ - # игр % побед # болельщиков
ih_wgt = [ [ 0.1, 0.2,-0.1], # hid[0]
[-0.1, 0.1, 0.9], # hid[1]
[ 0.1, 0.4, 0.1]] # hid[2]
# СКРЫТЫЙ СЛОЙ - # hid[0] # hid[1] # hid[2]
hp_wgt = [[ 0.3, 1.1, -0.3], # травмы? | ПРОГНОЗ
[ 0.1, 0.2, 0.0], # победа? | ПРОГНОЗ
[ 0.0, 1.3, 0.1]] # печаль? | ПРОГНОЗ
# для каждого выхода вычисляется взвешенная сумма входов
# w_sum - последовательно находит 3 взвешенных суммы
# и сохраняет результаты в векторе output
def w_sum(a,b):
assert(len(a) == len(b)) # ОТЛАДКА
output = 0
for i in range(len(a)):
output += (a[i] * b[i])
return output
def vect_mat_mul(vect, matrix):
assert(len(vect) == len(matrix))
output=[0,0,0]
for i in range (len(vect)):
output[i]=w_sum(vect,matrix[i])
return output
def neural_network(input, weights):
hid = vect_mat_mul(input, weights[0])
pred = vect_mat_mul(hid, weights[1])
return pred
# Передача одной точки данных
toes = [8.5, 9.5, 9.9, 9.0] # текущее среднее число игр, сыгранных игроками
wlrec = [0.65, 0.8, 0.8, 0.9] # текущая доля игр, окончившихся победой (%)
nfans = [1.2, 1.3, 0.5, 1.0] # число болельщиков (млн)
# текущее состояние перед началом каждой из четырёх игр в сезоне:
input = [toes[0], wlrec[0], nfans[0]]
# Получение прогноза
pred = neural_network(input, weights)
print(pred)
ИСПРАВЛЕННЫЙ ВАРИАНТ GPT
Книжный код иногда слишком жесткий. Чтобы не ограничивать себя фиксированными списками и сделать систему гибкой, мы используем .append(). Дирижёр не просто копирует из книги — он рефакторит костыли, чтобы инструмент работал чисто на любых данных.
# ИСПРАВЛЕННЫЙ ВАРИАНТ GPT
# вход → скрытый слой
ih_wgt = [
[0.1, 0.2, -0.1], # hid[0]
[-0.1, 0.1, 0.9], # hid[1]
[0.1, 0.4, 0.1] # hid[2]
]
# скрытый слой → выход
hp_wgt = [
[0.3, 1.1, -0.3],
[0.1, 0.2, 0.0],
[0.0, 1.3, 0.1]
]
def w_sum(a, b):
assert len(a) == len(b)
output = 0
for i in range(len(a)):
output += a[i] * b[i]
return output
def vect_mat_mul(vect, matrix):
output = []
for i in range(len(matrix)):
output.append(w_sum(vect, matrix[i]))
return output
def neural_network(input, weights):
hid = vect_mat_mul(input, weights[0])
pred = vect_mat_mul(hid, weights[1])
return pred
toes = [8.5, 9.5, 9.9, 9.0]
wlrec = [0.65, 0.8, 0.8, 0.9]
nfans = [1.2, 1.3, 0.5, 1.0]
input = [toes[0], wlrec[0], nfans[0]]
weights = [ih_wgt, hp_wgt]
pred = neural_network(input, weights)
print(pred)
ВЕРСИЯ С NUMPY
В 2026 году никто не пишет циклы вручную — это медленно и впадлу. Библиотека NumPy делает то же самое одной командой .dot() (скалярное произведение). Это стандарт: быстро, эффективно и по-взрослому. Мы просто трансформируем наши списки в матрицы (array) и пробрасываем данные через них.
ГЛАВНЫЙ ВЫВОД
Forward Propagation (прямое распространение) — это процесс превращения сигналов в прогноз через цепочку фильтров-весов.
1. Веса — это накопленные знания системы (наши knobs).
2. Скрытый слой — промежуточная логика, где рождается «глубина».
3. NumPy — инструмент, превращающий громоздкие циклы в элегантную математику одной строки.
Мы научились получать прогноз. Но пока мы задаем веса вручную. В следующей части мы разберем, как заставить сеть саму находить ошибки и исправлять свои веса, чтобы прогнозы стали точными.
Кот в Коде| @kot_research_bot