Слоеве
Накратко: Слоевете свързват неврони един след друг: скритият слой позволява на мрежата да научи правила, които една права не може да начертае, като XOR.
Проблем
Правилото, което една права не чертае
Екипът по измамите иска ново правило: плащането е подозрително, когато държавата на картата и държавата на връзката (по IP адреса) се разминават. Българска карта от чужд IP: някой ползва открадната карта в чужбина. Чужда карта от български IP: открадната карта, ползвана тук. Българска карта от България и чужда карта от чужбина (клиент, който живее там) са наред.
Признаците са два, по 0 или 1, където 1 е чужбина. Случаите са четири, а подозрителни са (1, 0) и (0, 1). Програмата пробва 15 000 неврона: всяко тегло от −6 до 6 през 0,5 и отместване от −5,75 до 5,75. За всеки брои колко случая познава при праг 0,5:
cases = [[0, 0], [1, 0], [0, 1], [1, 1]]labels = [0, 1, 1, 0] # 1 = подозрителноtried, best = 0, 0best_w, best_b = [0.0, 0.0], 0.0for i in range(-12, 13): for j in range(-12, 13): for k in range(-12, 12): w = [i / 2, j / 2] b = k / 2 + 0.25 tried += 1 right = 0 for x, label in zip(cases, labels): guess = 1 if neuron(x, w, b) >= 0.5 else 0 if guess == label: right += 1 if right > best: best, best_w, best_b = right, w, bprint(f"опитани неврони: {tried}, най-добрият: {best} от 4")print(f"w = [{best_w[0]:.2f}, {best_w[1]:.2f}], b = {best_b:.2f}")for x, label in zip(cases, labels): p = neuron(x, best_w, best_b) right = (1 if p >= 0.5 else 0) == label print(f"{x[0]} {x[1]}: p = {p:.3f} {'вярно' if right else 'грешно'}")опитани неврони: 15000, най-добрият: 3 от 4w = [-6.00, 0.50], b = -0.250 0: p = 0.438 вярно1 0: p = 0.002 грешно0 1: p = 0.562 вярно1 1: p = 0.003 вярноНай-добрият познава 3 от 4, а чуждата карта от български IP казва „ок“. Никой от 15 000 не познава четирите. И не е, защото решетката от тегла е рядка: следващата карта показва защо.
Идеята
Защо една права не стига
Нарисувай случаите като точки на квадрат: картата е хоризонталата, връзката е вертикалата. Подозрителните (1, 0) и (0, 1) са в два срещуположни ъгъла, а наред са другите два.
Невронът казва „да“, когато z е над нулата. Границата z = 0, тоест w₁·карта + w₂·IP + b = 0, е права. От едната ѝ страна невронът казва „да“, от другата „не“. А права, която оставя двата подозрителни ъгъла от едната страна, оставя с тях поне един от другите два. Опитай с молив: не става.
Логистичната регресия от урока за класификацията има същата граница, затова и тя не може. Трябват две прави.
Идеята
Два неврона по средата
Между входа и изхода слагаме два неврона. Всеки чертае своя права:
- h1: „поне едното е от чужбина“. Тегла 6 и 6, отместване −3: z е над нулата, щом поне един вход е 1.
- h2: „и двете са от чужбина“. Тегла 6 и 6, отместване −9: z е над нулата само когато и двата входа са 1.
Изходът чете h1 и h2 с тегла 10 и −10 и отместване −5: „поне едното, но не и двете“. Подозрителното е ивицата между двете прави.
Невроните по средата са скрит слой. Скрит, защото никой не им дава верен отговор: входът е от данните, изходът има етикет, а какво смятат междинните, мрежата решава сама. Тук теглата са избрани на ръка, за да значат нещо, което се казва с думи. Научените обикновено не се казват така лесно.
Пресмятането отляво надясно, слой по слой, е проходът напред (forward pass):
W = [[6.0, 6.0], [6.0, 6.0]]B = [-3.0, -9.0]V = [10.0, -10.0]C = -5.0
def forward(x): # поне едното е от чужбина h1 = neuron(x, W[0], B[0]) # и двете са от чужбина h2 = neuron(x, W[1], B[1]) h = [h1, h2] # скритият слой return neuron(h, V, C)forward ги чете направо.Виж го
Проходът напред, число по число
Един случай: чужда карта от български IP, (1, 0). Всяка стъпка печата своето z и изхода си:
x = [1, 0] # чужда карта, IP от Българияz1 = weighted_sum(x, W[0], B[0])h1 = sigmoid(z1)print(f"h1: z = {z1:.2f}, h1 = {h1:.4f}")z2 = weighted_sum(x, W[1], B[1])h2 = sigmoid(z2)print(f"h2: z = {z2:.2f}, h2 = {h2:.4f}")h = [h1, h2]z = weighted_sum(h, V, C)p = sigmoid(z)print(f"изход: z = {z:.2f}, p = {p:.4f}")h1: z = 3.00, h1 = 0.9526h2: z = -3.00, h2 = 0.0474изход: z = 4.05, p = 0.9829h1: 6 × 1 + 6 × 0 − 3 = 3, а сигмоидата дава 0,9526. h2: 6 × 1 + 6 × 0 − 9 = −3, тоест 0,0474. Изходът: 10 × 0,9526 − 10 × 0,0474 − 5 = 4,05, а сигмоидата дава 0,9829. Подозрително.
Четирите случая с forward:
cases = [[0, 0], [1, 0], [0, 1], [1, 1]]print("карта IP p")for x in cases: p = forward(x) verdict = "подозрително" if p >= 0.5 else "ок" print(f"{x[0]:5.0f} {x[1]:3.0f} {p:7.4f} {verdict}")карта IP p 0 0 0.0107 ок 1 0 0.9829 подозрително 0 1 0.9829 подозрително 1 1 0.0107 окЧетири от четири. Същите тегла, същата сигмоида, само един слой повече.
Виж го
Две прави и сигналът през мрежата
W = [[6.0, 6.0], [6.0, 6.0]]B = [-3.0, -9.0]V = [10.0, -10.0]C = -5.0
def forward(x): # поне едното е от чужбина h1 = neuron(x, W[0], B[0]) # и двете са от чужбина h2 = neuron(x, W[1], B[1]) h = [h1, h2] # скритият слой return neuron(h, V, C)Стъпка по стъпка, с думи
- Четири случая: карта и IP, 1 е чужбина. Подозрителни са (1, 0) и (0, 1).
- Най-добрият един неврон чертае една права и улучва 3 от 4: (1, 0) остава от грешната страна.
- Скритият слой: две прави, h1 „поне едното“ и h2 „и двете“. Подозрителното е между тях.
- Преминаването напред за чужда карта от българско IP: x = (1, 0).
- h1: 6 × 1 + 6 × 0 − 3 = 3,00, σ дава 0,9526. h2: 6 × 1 + 6 × 0 − 9 = −3,00, σ дава 0,0474.
- Изходът чете h: 10 × 0,9526 − 10 × 0,0474 − 5 = 4,05, σ дава 0,9829.
- 0,9829 е над 0,5: подозрително.
- Четирите случая през същата мрежа: 0,0107; 0,9829; 0,9829; 0,0107. Четири от четири.
Горе са четирите случая. Една права винаги оставя един грешен. Двете прави на скрития слой затварят ивица, а изходът казва „подозрително“ само в нея.
Пробвай
Предвиди изхода
Същото правило с ReLU вместо сигмоида: h1 = ReLU(карта + IP), h2 = ReLU(карта + IP − 1), изход h1 − 2·h2. Какво ще отпечата за четирите случая?
cases = [[0, 0], [1, 0], [0, 1], [1, 1]]out = []for x in cases: h1 = relu(x[0] + x[1]) h2 = relu(x[0] + x[1] - 1) out.append(h1 - 2 * h2)print(" ".join(f"{o:.0f}" for o in out))(0, 0): 0 − 0 = 0. (1, 0) и (0, 1): h1 = 1, h2 = ReLU(0) = 0, изходът е 1. (1, 1): h1 = 2, h2 = 1, изходът е 2 − 2 = 0. С ReLU правилото излиза точно, без закръгляне. Без h2 последното число щеше да е 2.
Пробвай
Намери грешката
Колега пише forward сам. Мрежата отговаря както един неврон: три от четири. На кой ред е грешката?
Избери реда с грешката.
Изходът чете входа x, а не скрития слой h. Скритите неврони се смятат и не се ползват, а мрежата се свива до един неврон с правата си. Изходът трябва да получи h.
Пробвай
Попълни
Какво получава изходният неврон?
h = [h1, h2]
return neuron(, V, C)Изходът чете h: изходите на скрития слой. Всеки слой получава изходите на предишния.
Идеята
Кога скритият слой помага и кога вреди
- Помага, когато признаците си влияят. „Чужда карта“ сама не значи нищо, „чужд IP“ сам също. Значи съчетанието. Скритият слой учи такива съчетания, без да му ги казваш.
- Ако знаеш съчетанието, напиши го. Признакът „картата ≠ връзката“ е един ред код. С него стига един неврон или
if. Мрежа, която учи нещо, което можеш да напишеш, е по-бавна, иска данни и греши повече. - Повече неврони са повече тегла. Тук са 9 числа. Скрит слой от 100 неврона върху 20 признака е 2 201 числа. Повече тегла значи повече данни, иначе мрежата наизустява.
- Всеки слой струва при всяко плащане. Проходът напред минава през всички тегла за всяка заявка. При голяма мрежа и много плащания това е време и пари.
- Скритите неврони не са длъжни да значат нещо. Тук значат, защото теглата са избрани на ръка. Научените обикновено са смес, която не се казва с думи.
По-точно, за любопитните
С формули. Скритият слой е h = σ(W·x + b): W е таблица (матрица) 2 × 2 с теглата, b е двете отмествания, а σ се прилага за всеки елемент. Изходът е p = σ(v·h + c). Проходът напред е тези две реда един след друг. Затова в истинските библиотеки слоят е умножение на матрица по вектор.
Дълбоко учене. Мрежа с много скрити слоеве се казва дълбока (deep). Всеки слой строи върху предишния: първите хващат прости съчетания, следващите съчетават тях.
Колко неврона стигат. Доказано е, че един скрит слой с достатъчно неврони може да доближи колкото искаш всяка непрекъсната функция (в ограничена област). Само че „достатъчно“ може да са много, и никой не казва как да намериш теглата. Затова на практика слоевете са няколко.
Малко история. През 1969 г. Мински и Пейпърт показват, че един слой (перцептрон) не може да научи точно това правило (XOR, „или едното, или другото“). Интересът към невронните мрежи спада за години. Решението със скрит слой е известно, но не и как да се учат теглата му. Това идва с обратното разпространение.
Упражнение
Един слой за всички
Реши задачата в редактора си.
forward от урока знае, че скритите неврони са два. Напиши общ layer(x, w, b): получава входовете, таблица с теглата (по един ред за всеки неврон) и отместванията, и връща масив с изхода на всеки неврон. После построй същата мрежа като два слоя: скритият с теглата от урока и изходният с един неврон (тегла 10 и −10, отместване −5). Пусни четирите случая през layer(layer(x, w1, b1), w2, b2).
карта IP p 0 0 0.0107 ок 1 0 0.9829 подозрително 0 1 0.9829 подозрително 1 1 0.0107 окСъщата таблица като в урока: layer е общото, а мрежата е два реда с тегла.
Още задачи
- Трети скрит неврон. Добави неврон с тегла 0 и 0 и отместване 0 в скрития слой (и тегло 0 за него в изхода). Изходът не трябва да се промени.
- ReLU в скрития слой. Направи
layerс активация като параметър и сглоби мрежата от „Предвиди изхода“.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Ламбди · Какво е машинно учене · Класификация: измама или не · Неврон
- Продължава в: Обратно разпространение · Обучението от начало до край · Цифрите от касовата бележка
- Задачи по темата: Невронна мрежа отвътре