Search
Write a publication
Pull to refresh

Смысл смещения. Почему без bias невозможна сложная нейросеть?

Level of difficultyMedium

Зачем нужен 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

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.