Простой перцептрон состоит из нескольких входов inp_t[1], inp_t[2] ... inp_t[n].
Каждому входу соответствует некий вес w[1], w[2] ... w[n].
Также имеется вход активации inp_b с весом w_b.
На вход активации постоянно подается единица, а вес на входе активации задает порог срабатывания перцептрона.
На выходе перцептрона может быть либо единица 1 либо -1 в зависимости от входных сигналов и весовых коэффициентов.
Условие срабатывания перцептрона ( когда на выходе появляется единица) :
w_b + w[1] * inp_t[1] + w[2] * inp_t[2] + ...+ w[n] * inp_t[n] > 0
Но можно и не различать входы inp_t и inp_b, а просто предположить, что у перцептрона есть еще один вход inp_t[0], на который всегда подается единица, а w_b записать как w[0].
Тогда условие срабатывания перцептрона можно записать так:
w[0] * inp_t[0] + w[1] * inp_t[1] + w[2] * inp_t[2] + ...+ w[n] * inp_t[n] > 0
Обучение перцептрона сводится к такому подбору весов w[0]...w[n] , при которых для всех
входных наборов данных (inp_t[1], inp_t[2] ... inp_t[n]), (inp_t[1], inp_t[2] ... inp_t[n]) ... (inp_t[1], inp_t[2] ... inp_t[n]), на выходе появлялось бы требуемое целевое значение out_t , соответствующее каждому входному набору.
Если реальное выходное значение перцептрона out_r отличается от требуемого целевого значения out_t, то необходимо подправить веса w[0]....w[n] перцептрона.
На каждом шаге обучения веса w[0]....w[n] должны изменяться в соответствии с правилом:
w[i] += t * (out_t - out_r) * inp_t[i]
где t - это небольшая константа (обычно 0,05 - 0,2) , которая задает скорость обучения.
Например обучим перцептрон логической функции дизъюнкции (операции ИЛИ).
inp_t[1] inp_t[2] out_t
0 0 -1
0 1 1
1 0 1
1 1 1
На вход алгоритму подаем скорость обучения t = 0,1
и входной вектор из четырех тестовых наборов [[0,0,-1],[0,1,1],[1,0,1],[1,1,1]]
в соответствии с таблицей истинности логической операции ИЛИ.
на выходе должны получить вектор весовых коэффициентов w[0]....w[n]
Алгоритм обучения простого перцептрона:
import random
def PerTrain(t, v):
w = []
# инициализируем начальные веса маленькими случайными значениями
for i in range(len(v[0])):
w.append((random.randrange(-5,5))/50.0)
chw = True
while (chw == True):
chw = False
for tst_n in v:
# получаем входные значения из тесового набора
# единицу добавляем для входа активации ( inp_t[0] = 1)
inp_t = [1] + tst_n[0:len(tst_n) - 1]
# получаем целевое выходное значение из тестового набора
out_t = tst_n[len(tst_n) - 1]
# реальное выходное значение будет вычислено позже
out_r = 0
# вычисляем выходное значение перцептрона (out_r)
for i in range(len(w)):
out_r += w[i] * inp_t[i]
if out_r > 0:
out_r = 1
else:
out_r = -1
if (out_r != out_t):
chw = True
# если на каком либо тестовом наборе перцептрон не сработал, то пересчитываем веса
for i in range(len(w)):
w[i] += t * (out_t - out_r) * inp_t[i]
break
return w
rez = PerTrain(0.1,[[0,0,-1],[0,1,1],[1,0,1],[1,1,1]])
print(rez)
Например получили такие веса:
[-0.1, 0.14, 0.16]
Проверяем:
print(1*-0.1 + 0*0.14 + 0*0.16)
print(1*-0.1 + 0*0.14 + 1*0.16)
print(1*-0.1 + 1*0.14 + 0*0.16)
print(1*-0.1 + 1*0.14 + 1*0.16)
в результате получаем:
-0.1
0.06
0.04000000000000001
0.2
что действительно соответствует дизъюнкции:
-1
1
1
1