Смысл смещения. Почему без bias невозможна сложная нейросеть?
Зачем нужен 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')
Скрытый текст
В этом посте много говнокода и формулировок типа , от которых, я думаю, у многих отвалятся глаза. Мои посты предназначены для новичков и тех, кто только начинает свой путь, как и я. Тем не менее, я всегда открыт к здравой критике и рад любым комментариям!😊
Вступайте в мою группу в telegram, где я собираю энтузиастов и новичков в AI и IT, которые искренне заинтересованы общением на эту тему: https://t.me/AkakyAIGroup