Зачем нужен bias‑нейрон? Наверняка вы сталкивались с какими‑то не особо понятными объяснениями типа «смещение в нейронных сетях корректирует точку пересечения границы принятия решений, помогая более точно подогнать данные». Так вот: это все говно. Сейчас я объясню вам все по‑Акакиевски!

Пусть у сети есть задача определить: число больше нуля или меньше. Ее может решить сеть с 2 нейронами. Вес умножит число на -1 и функцию активации (пусть будет логистическая сигмоида) и мы получим либо число < 0.5 (Нет) либо > 0.5 (Да).

Ок, тогда пусть будет задача определить: число больше 1 или меньше. Ну так вот, я открою вам секрет: не одна сеть ее не решит. Даже chatGPT, будь он без смещений, никогда бы точно не отличал числа > 1 и < 1 
Но почему? А потому что сеть не имеет доступа больше ни к каким данным, кроме тех, которые есть во входящих нейронах. В нашем случае — это число, которое мы должны отнести к классу >1 или <1. Каждый вес может масштабировать (умножать) величины, а нейроны потом складывают это и применяют функцию активации. т. е. сеть может оперировать только с зависимыми от вводимого числа данными. Но тупо сравнить с единицей сеть это число не может т. к. единица не зависит от этого вводимого числа и сеть буквально «Не е**т» что такое единица

Что бы точно убедиться в этом, я обучил громоздкую для такой простой задачи сеть: 4 слоя + всего 16 нейронов. По итогу, нейронка всегда выдает результат «больше 1». т. е. даже сложная сеть не справилась с этой простой задачей. Результат может стоять у границы к решению «меньше 1», но никогда его не выдаст

Код для реализации такой сети:


import pygame, numpy as np, random, math, copy
learning_speed = 0.1

with open('C:\\Users\\User\\Desktop\\Dataset.txt', 'r', encoding='utf-8') as file:
    content = file.read()   # Загружаем файл обучения
content = content.split('], [')
for elnum in range(len(content)):  # Преобразуем его в список, пригодный для обучения
    content[elnum] = content[elnum].split(', ')
    content[elnum][0] = int(content[elnum][0])
    content[elnum][1] = int(content[elnum][1])

def f_act(num):
    return 1 / (1 + math.exp(-num))

def df_act(num):
    return f_act(num) * (1 - f_act(num))

neura = []
neura.append(np.ones((1, 8)))
neura.append(np.ones((8, 6)))
neura.append(np.ones((6, 1)))
for layernum in range(len(neura)):   # Конструируем сеть: 2 скрытых слоя (первый с 8, а второй - с 6 нейронами)
    for neuronnum in range((neura[layernum].shape)[0]):
        for connect in range((neura[layernum].shape)[1]):
            neura[layernum][neuronnum, connect] -= 1
            while neura[layernum][neuronnum, connect] > -0.01 and neura[layernum][neuronnum, connect] < 0.01:
                neura[layernum][neuronnum, connect] = random.randint(-5000, 3000) / 10000

def go(scheme):   # Ввод данных и возвращение ответа сети
    global neura
    scheme = scheme[0]
    layer_1_result = np.dot(scheme, neura[0])
    for i in range((layer_1_result.shape)[1]):
        layer_1_result[0, i] = f_act(layer_1_result[0, i])
    layer_2_result = np.dot(layer_1_result, neura[1])
    for i in range((layer_2_result.shape)[1]):
        layer_2_result[0, i] = f_act(layer_2_result[0, i])
    layer_3_result = np.dot(layer_2_result, neura[2])
    for i in range((layer_3_result.shape)[1]):
        layer_3_result[0, i] = f_act(layer_3_result[0, i])
    return f_act(layer_3_result[0, 0])

def go_with(scheme):   # Возвращает z-ы для Back Propagation-а
    global neura
    scheme = scheme[0]
    layer_1_result = np.dot(scheme, neura[0])
    l1save = copy.deepcopy(layer_1_result)
    for i in range((layer_1_result.shape)[1]):
        layer_1_result[0, i] = f_act(layer_1_result[0, i])
    layer_2_result = np.dot(layer_1_result, neura[1])
    l2save = copy.deepcopy(layer_2_result)
    for i in range((layer_2_result.shape)[1]):
        layer_2_result[0, i] = f_act(layer_2_result[0, i])
    layer_3_result = np.dot(layer_2_result, neura[2])
    l3save = copy.deepcopy(layer_3_result)
    for i in range((layer_3_result.shape)[1]):
        layer_3_result[0, i] = f_act(layer_3_result[0, i])
    return scheme, l1save, l2save, l3save

def train():   # Back Propagation
    global content, neura
    sample = random.choice(content)
    outputs = go_with(sample)
    output_local_gradient = df_act(outputs[3]) * (f_act(outputs[3]) - sample[1])
    layer_2_local_gradients = [0, 0, 0, 0, 0, 0]
    for connect in range(6):
        layer_2_local_gradients[connect] = output_local_gradient * neura[2][connect, 0] * df_act(outputs[2][0, connect])
        neura[2][connect, 0] -= output_local_gradient * learning_speed * f_act(outputs[2][0, connect])
    layer_1_local_gradients = [0, 0, 0, 0, 0, 0, 0, 0]
    for neuron in range(6):
        this_neuron_local_gradient = layer_2_local_gradients[neuron]
        for connect in range(8):
            layer_1_local_gradients[connect] += this_neuron_local_gradient * neura[1][connect, neuron] * df_act(outputs[1][0, connect])
            neura[1][connect, neuron] -= this_neuron_local_gradient * learning_speed * f_act(outputs[1][0, connect])
    for neuron in range(8):
        neura[0][0, neuron] -= layer_1_local_gradients[neuron] * learning_speed * outputs[0]

for i in range(100000):
    train()
    print('Процесс обучения ', (math.ceil(i / 100) - 1) / 10, '%')

while True:
    if go([int(input()), 0]) >= 0.5:
        print('больше 1')
    else:
        print('меньше 1')

Содержание Dataset.txt:

6, 1], [37, 1], [-46, 0], [14, 1], [44, 1], [78, 1], [-42, 0], [-62, 0], [-52, 0], [-72, 0], [64, 1], [93, 1], [98, 1], [-13, 0], [-41, 0], [-7, 0], [-77, 0], [15, 1], [52, 1], [84, 1], [-16, 0], [-56, 0], [61, 1], [98, 1], [-29, 0], [-79, 0], [-45, 0], [30, 1], [97, 1], [-19, 0], [33, 1], [-23, 0], [52, 1], [-6, 0], [11, 1], [-1, 0], [-52, 0], [-73, 0], [69, 1], [36, 1], [-58, 0], [-15, 0], [-29, 0], [38, 1], [97, 1], [-84, 0], [73, 1], [43, 1], [-67, 0], [-59, 0

Хорошо, добавим смещение. Пусть будет сеть, которая решила задачу со сравнением с нулем, но к выходному нейрону еще будет подключен bias. И вуаля, она решает эту задачу, как бы "отодвигая" ость сравнения на единицу, хотя громоздкая сеть без biasов не осилила эту задачу

Эта сеть:


import pygame, numpy as np, random, math, copy
learning_speed = 0.1

with open('C:\\Users\\User\\Desktop\\Аллахуакбар\\Dataset.txt', 'r', encoding='utf-8') as file:
    content = file.read()
content = content.split('], [')
for elnum in range(len(content)):
    content[elnum] = content[elnum].split(', ')
    content[elnum][0] = int(content[elnum][0])
    content[elnum][1] = int(content[elnum][1])

def f_act(num):
    return 1 / (1 + math.exp(-num))

def go(num):
    return f_act(num - 1)

while True:
    if go(int(input())) >= 0.5:
        print('больше 1')
    else:
        print('меньше 1')
Скрытый текст

В этом посте много говнокода и формулировок типа Σ(z), от которых, я думаю, у многих отвалятся глаза. Мои посты предназначены для новичков и тех, кто только начинает свой путь, как и я. Тем не менее, я всегда открыт к здравой критике и рад любым комментариям!😊

Вступайте в мою группу в telegram, где я собираю энтузиастов и новичков в AI и IT, которые искренне заинтересованы общением на эту тему: https://t.me/AkakyAIGroup