Коррекция весов для простейшей нейросети

Есть код простейшей нейросети на Python. Нейросеть обучается правильно рассчитать столбец матрицы. Просьба объяснить, что происходит в данной строке:

adjustments = np.dot( input_layer.T, err * (outputs * (1 - outputs)))

Мой основной вопрос звучит - ЗАЧЕМ мы это делаем и какой алгоритм работы с нейросетью преследуем? То есть, мы изначально произвели несколько действий, следуя теории работы с нейросетью перцептроном:

  1. перемножение входных значений на веса
  2. сделали нормирование этих значений через сигмоиду
  3. вычитая полученный массив из массива с правильными ответами мы получили ошибку err (на сколько наша нейросеть ошиблась в первой итерации)

А вот дальше мы должны сделать коррекцию весов. И это переменная adjustments, которую мы прибавим к старым весам. И вот как именно она посчитана - я не понимаю с точки зрения алгоритма вычислений этой коррекции. Что именно мы сделали, и почему мы именно это сделали? По каким правилам мы здесь шли?

Выдержка из теории: "Здесь мы должны следовать градиентному спуску, и рассчитать вектор градиента ошибки. Это вектор из частных производных функции по всем ее аргументам. Его размерность равна количеству всех искомых весов, а направлен он в этом пространстве в сторону локального возрастания функции ошибки. Это значит, что градиент со знаком «-» направлен в сторону локального убывания ошибки. И мы можем немного подвинуться вдоль анти-градиента в сторону новых весов, где ошибка уже будет меньше."

У нас есть наша ошибка err. Что мы дальше сделали с ней в этом длинном произведении, и почему именно так? Брали мы здесь производную от чего-то или нет? И зачем мы вычитаем нашу матрицу outputs из вектора, где все единицы?

Весь код:

import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

training_inputs = np.array([[0,0,1],
                            [1,1,1],
                            [1,0,1],
                            [0,1,1]])
training_outputs = np.array([[0],
                             [1],
                             [1],
                             [0]])
np.random.seed(1)
synaptic_weights = 2 * np.random.random((3,1)) - 1

print("Random weights: ")
print(synaptic_weights)

for i in range(20000):
    input_layer = training_inputs
    outputs = sigmoid( np.dot(input_layer, synaptic_weights) )

    err = training_outputs - outputs
    adjustments = np.dot( input_layer.T, err * (outputs * (1 - outputs)))

    synaptic_weights += adjustments

print( "Weights after study: " )
print(synaptic_weights)

print("Result: ")
print(outputs)

Спасибо!


Ответы (2 шт):

Автор решения: Константин

Сделал Вам получше код:

import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

training_inputs = np.array([[0,0,1],
                            [1,1,1],
                            [1,0,1],
                            [0,1,1]])
training_outputs_targets = np.array([[0],
                             [1],
                             [1],
                             [0]])
np.random.seed(1)
synaptic_weights = 2 * np.random.random((3,1)) - 1

print("Random weights: ")
print(synaptic_weights)
print('---')

err=-1
for i in range(100):
    for row in range(4):
      input_layer = training_inputs[row].reshape(1, 3)
    #   print('sh input_layer', input_layer.shape) # -> (1, 3)
      outputs = sigmoid( np.dot(input_layer, synaptic_weights) )
    #   print('sh outputs', outputs.shape) # -> (1, 1)

      err = training_outputs_targets[row].reshape(1, 1) - outputs # t - y_domic -> (1, 1)
      adjustments = np.dot( input_layer.T, err * (outputs * (1 - outputs)))

      synaptic_weights+= adjustments 
      print('err', err) # Oshibka po dannomu paketu

print( "Weights after study: " )
print(synaptic_weights)

print("Result: ")
print(outputs)
"""
->
err [[-0.2689864]]
err [[0.68524239]]
err [[0.71565815]]
err [[-0.45740598]]
err [[-0.29468088]]
err [[0.58215104]]
err [[0.62792284]]
err [[-0.49271104]]
err [[-0.31672956]]
err [[0.48206267]]
err [[0.54509714]]
err [[-0.50796975]]
err [[-0.32985954]]
err [[0.40700592]]
err [[0.47850366]]
err [[-0.50522817]]
err [[-0.33394559]]
err [[0.35824331]]
err [[0.42824858]]
err [[-0.49090853]]
err [[-0.33178149]]
err [[0.32720196]]
err [[0.3901854]]
err [[-0.47043509]]
err [[-0.32606839]]
err [[0.30648731]]
err [[0.36039409]]
err [[-0.44742464]]
err [[-0.3186301]]
err [[0.29157199]]
err [[0.33615854]]
err [[-0.42408456]]
err [[-0.31054225]]
err [[0.27992586]]
err [[0.31577132]]
err [[-0.40164931]]
err [[-0.30238799]]
err [[0.27018009]]
err [[0.29818436]]
err [[-0.38072082]]
err [[-0.29445836]]
err [[0.26160667]]
err [[0.28274387]]
err [[-0.3615178]]
err [[-0.28688227]]
err [[0.25382136]]
err [[0.26902386]]
err [[-0.3440456]]
err [[-0.27970356]]
err [[0.24662005]]
err [[0.25672973]]
err [[-0.32820306]]
err [[-0.272924]]
err [[0.23989093]]
err [[0.2456448]]
err [[-0.31384461]]
err [[-0.26652614]]
err [[0.23356866]]
err [[0.23560099]]
err [[-0.30081385]]
err [[-0.26048502]]
err [[0.22761095]]
err [[0.22646265]]
err [[-0.28896019]]
err [[-0.25477386]]
err [[0.22198699]]
err [[0.21811733]]
err [[-0.27814609]]
err [[-0.24936666]]
err [[0.21667177]]
err [[0.21047018]]
err [[-0.26824939]]
err [[-0.24423931]]
err [[0.21164347]]
err [[0.20344028]]
err [[-0.25916317]]
err [[-0.23936984]]
err [[0.20688227]]
err [[0.19695814]]
err [[-0.25079455]]
err [[-0.23473845]]
err [[0.20236981]]
err [[0.19096374]]
err [[-0.2430631]]
err [[-0.23032733]]
err [[0.19808898]]
err [[0.18540503]]
err [[-0.23589919]]
err [[-0.22612045]]
err [[0.19402385]]
err [[0.18023677]]
err [[-0.2292425]]
err [[-0.22210337]]
err [[0.19015957]]
err [[0.17541945]]
err [[-0.22304063]]
err [[-0.21826303]]
err [[0.18648239]]
err [[0.1709185]]
err [[-0.21724793]]
err [[-0.21458758]]
err [[0.18297956]]
err [[0.16670358]]
err [[-0.21182456]]
err [[-0.21106626]]
err [[0.1796393]]
err [[0.162748]]
err [[-0.20673558]]
err [[-0.20768924]]
err [[0.17645074]]
err [[0.15902818]]
err [[-0.20195026]]
err [[-0.20444756]]
err [[0.17340386]]
err [[0.15552325]]
err [[-0.1974415]]
err [[-0.20133296]]
err [[0.17048944]]
err [[0.15221469]]
err [[-0.19318532]]
err [[-0.19833789]]
err [[0.16769897]]
err [[0.149086]]
err [[-0.18916041]]
err [[-0.19545538]]
err [[0.16502461]]
err [[0.14612249]]
err [[-0.18534778]]
err [[-0.192679]]
err [[0.16245915]]
err [[0.14331096]]
err [[-0.18173049]]
err [[-0.1900028]]
err [[0.15999593]]
err [[0.14063961]]
err [[-0.17829334]]
err [[-0.18742129]]
err [[0.15762879]]
err [[0.13809781]]
err [[-0.17502268]]
err [[-0.18492935]]
err [[0.15535207]]
err [[0.13567597]]
err [[-0.1719062]]
err [[-0.18252224]]
err [[0.15316051]]
err [[0.13336545]]
err [[-0.16893281]]
err [[-0.18019556]]
err [[0.15104925]]
err [[0.13115838]]
err [[-0.16609243]]
err [[-0.1779452]]
err [[0.14901381]]
err [[0.12904764]]
err [[-0.16337595]]
err [[-0.17576731]]
err [[0.14704999]]
err [[0.12702677]]
err [[-0.16077504]]
err [[-0.17365833]]
err [[0.14515394]]
err [[0.12508984]]
err [[-0.15828215]]
err [[-0.17161491]]
err [[0.14332204]]
err [[0.12323147]]
err [[-0.15589035]]
err [[-0.16963392]]
err [[0.14155094]]
err [[0.12144672]]
err [[-0.15359332]]
err [[-0.16771242]]
err [[0.13983753]]
err [[0.11973105]]
err [[-0.15138524]]
err [[-0.16584767]]
err [[0.1381789]]
err [[0.1180803]]
err [[-0.14926077]]
err [[-0.16403707]]
err [[0.13657232]]
err [[0.11649064]]
err [[-0.14721502]]
err [[-0.1622782]]
err [[0.13501526]]
err [[0.11495856]]
err [[-0.14524344]]
err [[-0.16056878]]
err [[0.13350534]]
err [[0.11348078]]
err [[-0.14334186]]
err [[-0.15890666]]
err [[0.13204034]]
err [[0.11205429]]
err [[-0.14150641]]
err [[-0.1572898]]
err [[0.13061817]]
err [[0.11067631]]
err [[-0.13973349]]
err [[-0.1557163]]
err [[0.12923687]]
err [[0.10934424]]
err [[-0.1380198]]
err [[-0.15418435]]
err [[0.12789462]]
err [[0.10805569]]
err [[-0.13636223]]
err [[-0.15269225]]
err [[0.12658967]]
err [[0.10680841]]
err [[-0.13475792]]
err [[-0.15123839]]
err [[0.12532041]]
err [[0.10560032]]
err [[-0.13320418]]
err [[-0.14982124]]
err [[0.1240853]]
err [[0.10442949]]
err [[-0.13169852]]
err [[-0.14843935]]
err [[0.12288291]]
err [[0.10329409]]
err [[-0.1302386]]
err [[-0.14709136]]
err [[0.12171186]]
err [[0.10219244]]
err [[-0.12882224]]
err [[-0.14577598]]
err [[0.12057088]]
err [[0.10112295]]
err [[-0.12744741]]
err [[-0.14449196]]
err [[0.11945874]]
err [[0.10008414]]
err [[-0.12611218]]
err [[-0.14323814]]
err [[0.1183743]]
err [[0.0990746]]
err [[-0.12481476]]
err [[-0.14201341]]
err [[0.11731648]]
err [[0.09809304]]
err [[-0.12355347]]
err [[-0.14081671]]
err [[0.11628423]]
err [[0.09713823]]
err [[-0.12232672]]
err [[-0.13964703]]
err [[0.11527659]]
err [[0.09620899]]
err [[-0.12113301]]
err [[-0.13850342]]
err [[0.11429262]]
err [[0.09530426]]
err [[-0.11997095]]
err [[-0.13738497]]
err [[0.11333145]]
err [[0.094423]]
err [[-0.1188392]]
err [[-0.13629081]]
err [[0.11239225]]
err [[0.09356424]]
err [[-0.11773652]]
err [[-0.13522011]]
err [[0.11147421]]
err [[0.09272706]]
err [[-0.11666173]]
err [[-0.13417207]]
err [[0.11057658]]
err [[0.09191062]]
err [[-0.11561371]]
err [[-0.13314594]]
err [[0.10969865]]
err [[0.09111407]]
err [[-0.11459141]]
err [[-0.13214101]]
err [[0.10883972]]
err [[0.09033666]]
err [[-0.11359382]]
err [[-0.13115658]]
err [[0.10799914]]
err [[0.08957765]]
err [[-0.11261999]]
err [[-0.13019199]]
err [[0.1071763]]
err [[0.08883634]]
err [[-0.11166904]]
err [[-0.12924661]]
err [[0.1063706]]
err [[0.08811207]]
err [[-0.1107401]]
err [[-0.12831984]]
err [[0.10558146]]
err [[0.08740422]]
err [[-0.10983237]]
err [[-0.12741109]]
err [[0.10480836]]
err [[0.0867122]]
err [[-0.10894508]]
err [[-0.12651982]]
err [[0.10405076]]
err [[0.08603543]]
err [[-0.10807749]]
err [[-0.1256455]]
err [[0.10330818]]
err [[0.08537338]]
err [[-0.10722891]]
err [[-0.1247876]]
err [[0.10258015]]
err [[0.08472553]]
err [[-0.10639868]]
err [[-0.12394566]]
err [[0.1018662]]
err [[0.0840914]]
err [[-0.10558617]]
err [[-0.12311918]]
err [[0.1011659]]
err [[0.08347053]]
err [[-0.10479077]]
err [[-0.12230773]]
err [[0.10047884]]
err [[0.08286246]]
err [[-0.1040119]]
err [[-0.12151088]]
err [[0.09980463]]
err [[0.08226678]]
err [[-0.10324903]]
err [[-0.1207282]]
err [[0.09914286]]
err [[0.08168307]]
err [[-0.10250163]]
err [[-0.11995929]]
err [[0.09849319]]
err [[0.08111096]]
err [[-0.10176919]]
err [[-0.11920378]]
err [[0.09785525]]
err [[0.08055007]]
err [[-0.10105124]]
err [[-0.11846128]]
err [[0.09722871]]
err [[0.08000005]]
err [[-0.10034731]]
err [[-0.11773145]]
err [[0.09661324]]
err [[0.07946056]]
err [[-0.09965699]]
err [[-0.11701394]]
err [[0.09600854]]
err [[0.07893128]]
err [[-0.09897983]]
err [[-0.11630842]]
err [[0.09541429]]
err [[0.0784119]]
err [[-0.09831544]]
err [[-0.11561457]]
err [[0.09483021]]
err [[0.07790211]]
err [[-0.09766344]]
err [[-0.11493209]]
err [[0.09425602]]
err [[0.07740163]]
err [[-0.09702346]]
err [[-0.11426067]]
err [[0.09369146]]
err [[0.0769102]]
err [[-0.09639514]]
err [[-0.11360003]]
err [[0.09313626]]
err [[0.07642754]]
err [[-0.09577813]]
err [[-0.1129499]]
err [[0.09259018]]
err [[0.0759534]]
err [[-0.09517213]]
err [[-0.11231001]]
err [[0.09205297]]
err [[0.07548755]]
err [[-0.0945768]]
err [[-0.11168011]]
err [[0.09152441]]
err [[0.07502974]]
err [[-0.09399185]]
err [[-0.11105993]]
err [[0.09100427]]
err [[0.07457976]]
err [[-0.09341699]]
err [[-0.11044925]]
err [[0.09049234]]
err [[0.07413739]]
err [[-0.09285194]]
err [[-0.10984784]]
err [[0.08998841]]
err [[0.07370241]]
err [[-0.09229643]]
err [[-0.10925546]]
err [[0.08949228]]
err [[0.07327464]]
err [[-0.0917502]]
"""
→ Ссылка
Автор решения: Константин

Снова переделал немного ваш код,построил график(надо всегда делать график, чтобы видеть что ошибка падает), ошибка действительно падает:

import numpy as np
import matplotlib.pyplot as plt

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

training_inputs = np.array([[0,0,1],
                            [1,1,1],
                            [1,0,1],
                            [0,1,1]])
training_outputs_targets = np.array([[0],
                             [1],
                             [1],
                             [0]])
np.random.seed(1)
synaptic_weights = 2 * np.random.random((3,1)) - 1

print("Random weights: ")
print(synaptic_weights)
print('---')

err=-1
epochs=10
errs=[]
for i in range(epochs):
    for row in range(4):
      input_layer = training_inputs[row].reshape(1, 3)
    #   print('sh input_layer', input_layer.shape) # -> (1, 3)
      outputs = sigmoid(np.dot(input_layer, synaptic_weights))
    #   print('sh outputs', outputs.shape) # -> (1, 1)

      err=outputs - training_outputs_targets[row].reshape(1, 1)# y_domic - t-> (1, 1)
      
      adjustments = np.dot(input_layer.T, err * (outputs * (1 - outputs)))

      synaptic_weights-= adjustments 
      print('err', err) # Oshibka po dannomu paketu
    errs.append(err[0][0])    

# print( "Weights after study: " )
# print(synaptic_weights)

# print("Result: ")
# print(outputs)
fig, ax = plt.subplots()

ax.plot(range(epochs), errs)
ax.grid()

#  Добавляем подписи к осям:
ax.set_xlabel('Эпохи')
ax.set_ylabel('Ошибка')

plt.show()

ошибка падает с эпохами

→ Ссылка