Неврон
Накратко: Невронът е сума от входовете, умножени по тегла, плюс отместване, пусната през активация като сигмоида или ReLU.
Проблем
Мрежата спря плащането. Защо?
Магазинът сменя старото правило за измами с „невронна мрежа“ от външна фирма. На първия ден клиент плаща 230 € от нова сметка с чужда карта, а плащането спира за ръчна проверка. Клиентът пише в поддръжката: „Защо?“
Никой не знае. За екипа мрежата е черна кутия: влизат признаците на плащането, излиза число. А докато не знаеш какво става вътре, не можеш да обясниш решението, да поправиш грешка или да кажеш дали числото изобщо е смислено.
Кутията се отваря. Вътре няма нищо, което не си виждал: умножение, събиране и една функция.
Идеята
Неврон: сума с тегла
Изкуственият неврон получава няколко числа (входовете). Всеки вход има свое тегло: колко силно влияе и в коя посока. Невронът умножава всеки вход по теглото му, събира и добавя още едно число, отместването (bias). Резултатът се казва z.
После z минава през функция, която решава какво излиза. Тя се казва функция на активация. Засега е сигмоидата: тя свива всяко z до число между 0 и 1.
Познато ли ти е? Това е логистичната регресия: претеглена сума, сигмоида, вероятност и праг. Един неврон със сигмоида е точно тя. Невронната мрежа е много такива неврони, свързани един след друг.
Виж го
Невронът в код
Трите функции: претеглената сума, сигмоидата и невронът, който ги свързва.
def weighted_sum(x, w, b): z = b # отместването for xi, wi in zip(x, w): z += xi * wi # вход × тегло return z
def sigmoid(z): return 1 / (1 + math.exp(-z))
def neuron(x, w, b): return sigmoid(weighted_sum(x, w, b))Плащанията имат три признака: сумата в стотици евро, нова сметка (1 или 0) и чужда карта (1 или 0). Теглата са сложени на ръка, за да се смятат наум. Как мрежата ги намира сама, е урокът за обратното разпространение.
# сума (стотици €), нова сметка, чужда картаw = [0.9, 1.4, 1.8]b = -4.0payments = [ [0.40, 0, 0], [1.20, 1, 0], [8.90, 1, 1], [0.60, 0, 1], [6.40, 0, 0], [2.30, 1, 1],]print(" сума € нова чужда z p")for x in payments: z = weighted_sum(x, w, b) p = sigmoid(z) verdict = "проверка" if p >= 0.5 else "ок" print(f"{x[0] * 100:8.0f} {x[1]:5.0f} {x[2]:7.0f} {z:6.2f} {p:6.3f} {verdict}") сума € нова чужда z p 40 0 0 -3.64 0.026 ок 120 1 0 -1.52 0.179 ок 890 1 1 7.21 0.999 проверка 60 0 1 -1.66 0.160 ок 640 0 0 1.76 0.853 проверка 230 1 1 1.27 0.781 проверкаСега можеш да отговориш на клиента. Плащането за 230 € е последният ред: z = −4 + 2,3 × 0,9 + 1 × 1,4 + 1 × 1,8 = −4 + 2,07 + 1,4 + 1,8 = 1,27. Сигмоидата дава 0,781, над прага 0,5. Новата сметка и чуждата карта добавиха 3,2 към сумата. Без тях z щеше да е −1,93, а вероятността около 0,13.
Виж го
Сигналът минава през неврона
def weighted_sum(x, w, b): z = b # отместването for xi, wi in zip(x, w): z += xi * wi # вход × тегло return z
def sigmoid(z): return 1 / (1 + math.exp(-z))
def neuron(x, w, b): return sigmoid(weighted_sum(x, w, b))Стъпка по стъпка, с думи
- Плащане за 230 € от нова сметка с чужда карта. Входовете са 2,30, 1 и 1.
- z започва от отместването: −4,00.
- Всеки вход по теглото си: 2,30 × 0,9 = 2,07, 1 × 1,4 = 1,40, 1 × 1,8 = 1,80.
- Сборът: z = −4 + 2,07 + 1,40 + 1,80 = 1,27.
- Сигмоидата свива z между 0 и 1: σ(1,27) = 0,781.
- 0,781 е над прага 0,5: плащането отива за проверка.
- 40 € от стара сметка с българска карта: z = −4 + 0,36 = −3,64, p = 0,026. Ок.
- Невронът: сума с тегла, отместване и сигмоида. Това е логистичната регресия.
Отместването е първо, после всеки вход добавя своя дял. Сигмоидата не променя реда: по-голямо z дава по-голямо p. Тя само го свива между 0 и 1, за да се чете като вероятност.
Пробвай
Намери грешката
Колега пише претеглената сума сам. С отместване −4 всяко плащане излиза с много по-малко z, отколкото трябва, и нищо не стига до проверка. На кой ред е грешката?
Избери реда с грешката.
Отместването се добавя за всеки вход, а не веднъж: при три входа то влиза три пъти. С b = −4 сумата е с 8 по-малка, отколкото трябва. Правилно е z да започва от b и в цикъла да се добавя само вход × тегло.
Проблем
Три неврона, а колкото един
Колега иска мрежата да хваща по-сложни правила. Слага два неврона, които четат плащането, и трети, който чете техните изходи. Активация няма никъде: всеки неврон връща самата сума z.
Програмата пресмята трите неврона и, отделно, един неврон, чиито тегла са смятани от техните:
# два неврона четат плащането, без активацияw1 = [0.5, 1.0, 1.5]b1 = -1.0w2 = [1.0, -0.5, 0.5]b2 = 0.5# трети неврон чете техните изходиv = [1.5, -0.5]c = 0.5# същото като един неврон с тези теглаw3 = [v[0] * w1[i] + v[1] * w2[i] for i in range(3)]b3 = v[0] * b1 + v[1] * b2 + cprint(f"w = [{w3[0]:.2f}, {w3[1]:.2f}, {w3[2]:.2f}], b = {b3:.2f}")
payments = [[0.40, 0, 0], [1.20, 1, 0], [8.90, 1, 1]]print(" сума € три неврона един неврон")for x in payments: a1 = weighted_sum(x, w1, b1) a2 = weighted_sum(x, w2, b2) out = weighted_sum([a1, a2], v, c) one = weighted_sum(x, w3, b3) print(f"{x[0] * 100:8.0f} {out:13.4f} {one:12.4f}")w = [0.25, 1.75, 2.00], b = -1.25 сума € три неврона един неврон 40 -1.1500 -1.1500 120 0.8000 0.8000 890 4.7250 4.7250Колоните съвпадат до последната цифра. Трите неврона са колкото един. Причината е училищна алгебра: сума от суми е пак сума. Каквото и да наредиш едно след друго, без активация резултатът е една права (по-точно равнина) с други тегла.
Идеята
Активацията пречупва правата
Новото идва едва когато между невроните има функция, която не е права. Двете най-честите:
- Сигмоида: свива z до между 0 и 1. Удобна е за изхода, когато искаш вероятност.
- ReLU (rectified linear unit): max(0, z). Положителното минава, отрицателното става 0. Това е най-честата активация в скритите неврони на днешните мрежи.
def relu(z): return max(0.0, z)zs = [-3.0, -1.0, 0.0, 1.0, 3.0]print(" z sigmoid ReLU")for z in zs: print(f"{z:6.2f} {sigmoid(z):8.4f} {relu(z):5.2f}") z sigmoid ReLU -3.00 0.0474 0.00 -1.00 0.2689 0.00 0.00 0.5000 0.00 1.00 0.7311 1.00 3.00 0.9526 3.00И двете са огънати. Сигмоидата е „S“, а ReLU е права с пречупване при нулата. Сума от пречупени линии вече не е права, затова неврони с активация един след друг могат да опишат правило, което един неврон не може. Такова правило идва в следващия урок.
Пробвай
Предвиди изхода
Неврон с ReLU оценява колко дни закъснение има доставката. Входовете са разстоянието в стотици километри и дали колетът е тежък. Закъснението не може да е отрицателно, затова ReLU. Какво ще отпечата?
w = [0.5, 1.0] # стотици км, тежък колет (1 или 0)b = -1.0near = relu(weighted_sum([1.5, 0], w, b))far = relu(weighted_sum([4.4, 0], w, b))heavy = relu(weighted_sum([3.0, 1], w, b))print(f"{near:.1f} {far:.1f} {heavy:.1f}")Близката доставка: 0,5 × 1,5 − 1 = −0,25, а ReLU я прави 0. Далечната: 0,5 × 4,4 − 1 = 1,2. Тежкият колет: 0,5 × 3 + 1 − 1 = 1,5. Със сигмоида щеше да излезе 0,4 0,8 0,8, а без ReLU първото число щеше да е отрицателно: −0,25.
Пробвай
Попълни
Довърши ReLU.
def relu(z):
return (0.0, z)max(0.0, z) връща по-голямото от 0 и z: положителното минава, отрицателното става 0.
Идеята
Кога един неврон стига, а кога вреди
- Правилото е почти право. Ако признаците сами по себе си казват отговора (по-голяма сума, повече риск), един неврон, тоест логистична регресия, прави колкото и голяма мрежа. Учи се по-бързо и иска по-малко данни.
- Данните са малко. Мрежа със стотици тегла и 200 примера ги наизустява. Това е преобучението.
- Трябва да обясниш решението. Теглата на един неврон се четат: „новата сметка добави 1,4“. В мрежа с много слоеве отговорът „защо“ е много по-труден, а при спряно плащане или отказан кредит той се иска.
- Правилото е известно и твърдо. „Над 5 000 € винаги ръчна проверка“ е
if, не модел. - Числата на входа са в различен мащаб. Сумата в евро (40, 890) до признаци 0 и 1 дава тегла, които трудно се учат. Затова сумата тук е в стотици евро. В истински модел входовете се нормират.
По-точно, за любопитните
Формулите. За неврон с входове x₁, x₂, x₃:
z = w₁·x₁ + w₂·x₂ + w₃·x₃ + b
p = σ(z) = 1 / (1 + e^(−z))
С думи: всеки вход по теглото си, плюс отместването, после сигмоидата. e е числото на Ойлер (около 2,718), а Math.exp(-z) е e на степен −z.
Защо три неврона без активация са един. Ако a₁ = w₁·x + b₁ и a₂ = w₂·x + b₂, то v₁·a₁ + v₂·a₂ + c = (v₁·w₁ + v₂·w₂)·x + (v₁·b₁ + v₂·b₂ + c). Това е един неврон с тегла v₁·w₁ + v₂·w₂. Точно това смята програмата с трите неврона.
Други активации: tanh (като сигмоида, но между −1 и 1), leaky ReLU (отрицателното не е 0, а малко, например 0,01·z), softmax (на изхода, когато класовете са повече от два: превръща няколко числа във вероятности със сбор 1). Има и много други, но ReLU и сигмоидата са достатъчни, за да разбереш всичко в модула.
С какво се правят мрежи в истинска работа. Тук всичко е цикли и масиви, за да виждаш всяко число. Истинските мрежи са с милиони тегла, а сметките са с матрици на видеокарта. Практиката на машинното обучение е предимно на Python: NumPy за масивите, scikit-learn за класическите модели, PyTorch за невронните мрежи. Има и други езици: ML.NET за C#, DJL и Tribuo за Java, TensorFlow.js и ONNX Runtime за JavaScript. Често моделът се учи на Python, а се ползва от програма на друг език (например през ONNX).
Името. „Неврон“ идва от биологията: клетка, която събира сигнали и „пали“, щом сборът мине прага. Приликата спира дотук. Изкуственият неврон е функция с числа.
Упражнение
Неврон за отзивите
Реши задачата в редактора си.
Магазинът иска да подреди отзивите на добри и лоши. За всеки отзив вече са преброени хубавите думи („бърза“, „качествен“) и лошите („счупен“, „закъсня“). Напиши неврон със сигмоида с тегла 1,1 за хубавите думи и −1,7 за лошите и отместване 0,2. Пусни го върху петте отзива (хубави, лоши): (3, 0), (1, 2), (0, 0), (2, 1), (0, 3). Отзивът е добър, ако p е поне 0,5.
хубави думи 3, лоши думи 0: p = 0.971 → добърхубави думи 1, лоши думи 2: p = 0.109 → лошхубави думи 0, лоши думи 0: p = 0.550 → добърхубави думи 2, лоши думи 1: p = 0.668 → добърхубави думи 0, лоши думи 3: p = 0.007 → лошОтзивът без нито една дума излиза добър с 0,550: това е само отместването. Тоест без други сведения моделът леко вярва, че отзивът е добър.
Още задачи
- Трети признак. Добави удивителните знаци като признак с тегло −0,3 и виж кои отзиви сменят решението си.
- Прагът. Сложи праг 0,7 вместо 0,5. Кои отзиви стават лоши?
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Какво е машинно учене · Линейна регресия · Класификация: измама или не · Преобучение: моделът, който наизустява
- Продължава в: Слоеве · Обратно разпространение · Обучението от начало до край · Цифрите от касовата бележка
- Задачи по темата: Невронна мрежа отвътре