Я строю свою первую однослойную сеть персептрона и обучаю ее имитировать поведение простейших логических элементов (И и ИЛИ) с двумя входами.
Сеть состоит из двух входовузлы и уклон.Используется алгоритм обучения дельта-правила для однослойного персептрона с функцией tanh в качестве функции активации.
При обучении на наборе данных AND сеть должна давать ответ, близкий к 1
при вводе данных(1, 1)
и 0 для любого другого входа, такого как (0, 1)
, (1, 0)
или (1, 1)
.Когда он обучен набору данных OR, он должен возвращать ответ, близкий к 1
, если дан любой ввод, отличный от (0, 0)
.
Однако он демонстрирует поведение, которое я не мог понять.Он хорошо сходится (т. Е. Частота ошибок довольно низкая - 0.01
или меньше), когда я обучил его на наборе данных OR:
$ python nn.py
[0 0]: (actual result = [[0.00051257]]). (expected result from training set=0, error rate=[[-0.00051257]])
[0 1]: (actual result = [[0.98865851]]). (expected result from training set=1, error rate=[[0.01134149]])
[1 0]: (actual result = [[0.98865222]]). (expected result from training set=1, error rate=[[0.01134778]])
[1 1]: (actual result = [[0.99993485]]). (expected result from training set=1, error rate=[[6.51512784e-05]])
Однако, он не очень хорошо сходится на наборе данных AND:
$ python nn.py
[0 0]: (actual result = [[-0.28911014]]). (expected result from training set=0, error rate=[[0.28911014]])
[0 1]: (actual result = [[0.23984154]]). (expected result from training set=0, error rate=[[-0.23984154]])
[1 0]: (actual result = [[0.28911014]]). (expected result from training set=0, error rate=[[-0.28911014]])
[1 1]: (actual result = [[0.68570095]]). (expected result from training set=1, error rate=[[0.31429905]])
Я пытался настроить epoch
для различных чисел между 500
- 10000
безрезультатно.И от eta
до любого значения от 0.1
до 1.0
.
Глядя на график конвергенции ниже, вы увидите, как нейронная сеть значительно лучше сходится для набора данных OR, чем набор данных AND, как показановечно «прореживающимся» оранжевым сюжетом.
Я думал, что вентили OR и AND противоположны друг другу, и если сеть работает на одном, то это определенно должно работать на другом.Что мне здесь не хватает?
Здесь я приложил исходный код nn.py
.
ПРИМЕЧАНИЕ. Когда вы посмотрите, вы увидите, что я инициализировал матрицу весов для1 вместо некоторых случайных значений.Это просто потому, что я хочу, чтобы какой-то детерминизм помог мне решить проблему.Насколько я понимаю, это не должно влиять на правильность алгоритма (хотя это может замедлить его сходимость). Вес теперь правильно инициализирован для некоторых случайных значений, следуя предложению @Dennis Soemers.Проблема все еще существует.
import numpy as np
def tanh(x):
return (1.0 - np.exp(-2*x))/(1.0 + np.exp(-2*x))
def tanh_derivative(x):
return (1 + tanh(x))*(1 - tanh(x))
# AND dataset
training_set = [
(np.array([0, 0]), 0),
(np.array([0, 1]), 0),
(np.array([1, 0]), 0),
(np.array([1, 1]), 1)
]
# # OR dataset
# training_set = [
# (np.array([0, 0]), 0),
# (np.array([0, 1]), 1),
# (np.array([1, 0]), 1),
# (np.array([1, 1]), 1)
# ]
weight = np.random.rand(3, 1)
# fit
eta = 0.2
epoch = 5000
for i in range(0, len(training_set)*epoch):
input_, expected_output = training_set[np.random.randint(0, len(training_set))]
input_with_bias = np.concatenate((input_, np.ones(1))).reshape(3, 1)
sum_weights_of_input = np.dot(input_with_bias.T, weight)
actual_output = tanh(sum_weights_of_input)
error = expected_output - actual_output
delta = np.multiply(eta, np.multiply(error, np.multiply(input_with_bias, tanh_derivative(sum_weights_of_input))))
weight = weight + delta
# print
for input_, expected_output in training_set:
input_with_bias = np.concatenate((input_, np.ones(1))).reshape(3, 1)
actual_output = tanh(np.dot(input_with_bias.T, weight))
error = expected_output - actual_output
print("{}: (actual result = {}). (expected result from training set={}, error rate={})".format(input_, actual_output, expected_output, error))