Я хочу реализовать MLP (MultiLayer Perceptron) для решения проблемы XOR. Я сокрушаю голову, потому что я не большой ученый, и я хочу быть уверенным в понимании каждой линии этой программы.Алгоритм обратной просадки застрял в MultiLayer Perceptron
Начну вопросы:
- Есть конкретный метод для отладки нейронной сети? (например, предопределенные известные веса, которые приводят к ожидаемому решению)
- Является следующим алгоритм обратного распространения (in pseodocode) ?
- Должно ли предубеждение быть в этом алгоритме? Если нет, является ли предубеждение необходимым для решения проблемы XOR? И если да, то должно быть смещение 1 на нейрон, 1 на слой или 1 на сеть?
- Правильно ли реализована моя реализация python? Если нет, то это касается обратного распространения, прямого распространения, отсутствия смещения или чего-то еще?
Каждый ответ очень приветствуется. Это не «домашнее задание», но если вы очень боитесь этого, я буду очень доволен только хорошими советами. Я все еще не использую должным образом numpy, потому что я более дева, чем ученый, и иногда имею проблемы с матричными уравнениями (в настоящее время я работаю над этим). Таким образом, мне очень сложно хорошо понять различные реализации, которые я нашел.
EDIT: Теперь отлично алгоритм работы, и я остановлюсь различные проблемы была в реализации псевдокод/Python:
Теория:
- pseudocode был неправильным при регулировке веса (я отредактировал код, чтобы отметить строку WRONG с исправлением). Я использовал выходы выходного уровня, где я должен использовать значения входов
- Фактически можно решить проблему XOR без предубеждений и только 1 скрытый слой. Интересно, что он работает только с 4-мя нейронами в скрытом слое или более, но не с 3. Однако после бенчмарков добавление смещения может значительно ускорить время оптимальной конвергенции (5x speeder или более)
реализация питон:
- веса были инициализированы в случайном порядке между 0 и 1, а не между -1 и 1, она не может работать, как это.
И, наконец, this resource был большой помощью, чтобы хорошо понять «волшебство нейронов». Это не помогло мне отладить backpropagation, но теперь это свидетельствует о том, что я никогда не смог бы заставить его работать без каких-либо теоретических знаний. Если, как я, вы больше дева, чем ученый, я настоятельно рекомендую вам проверить это.
на основе книги «Artifical интеллекта для разработчиков» по Виржини Матив, вот псевдокода для обратного распространения алгоритма (это французская книга, извините за плохой TRADUCTIONS):
While stop criteria is not achieved:
Initialize d(i)
For each example:
Compute output value s(i) #1
For each output neuron weight: #2
d(i) = s(i) * (1 - s(i)) * (y(i) - s(i))
EndFor
For each hidden neuron weight:
sum = 0
For each link towards output neuron k:
sum += d(k) * w(i->k)
EndFor
d(i) = o(i) * (1 - o(i)) * sum
EndFor
For each weight of the network:
If link towards output neuron:
w(i) += rate * d(i) * o(i)
Else
w(i) += rate * d(i) * s(i) # WRONG: s(i) should be input(i)
EndIf
EndFor
EndFor
EndWhile
В приведенном выше примере d(x)
являются дельтами, o(x)
являются выходы скрытого уровня, s(x)
- выходные выходы выходного уровня, y(x)
- ожидаемые выходы и w(x)
a re сетевые веса.
Я понимаю, что линия # 1 является прямым распространением, а линии после # 2 (включено) около обратного распространения. Таким образом, правильный алгоритм можно записать в виде:
While stop criteria is not achieved:
Initialize d(i)
For each example:
output = Forward propagation with example inputs #1
Backpropagation of the error between output and expected output #2
EndFor
EndWhile
Моя проблема заключается в том, что алгоритм, кажется, идет по кругу с алгоритмом обратного распространения и изменения весов, например, вот выходы для скрытого слоя:
[Epoch 0, inputs (1.0, 1.0)]: hidden outputs: None
[Epoch 0, inputs (0.0, 0.0)]: hidden outputs: [ 0.7755638 0.64556638 0.68163599]
[Epoch 0, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5]
[Epoch 0, inputs (0.0, 1.0)]: hidden outputs: [ 0.60747218 0.58975313 0.55246625]
[Epoch 1, inputs (1.0, 1.0)]: hidden outputs: [ 0.68911554 0.55079694 0.62718831]
[Epoch 1, inputs (1.0, 0.0)]: hidden outputs: [ 0.77449528 0.64107552 0.67770194]
[Epoch 1, inputs (0.0, 0.0)]: hidden outputs: [ 0.60728756 0.58957687 0.55230354]
[Epoch 1, inputs (0.0, 1.0)]: hidden outputs: [ 0.5 0.5 0.5]
[Epoch 2, inputs (0.0, 0.0)]: hidden outputs: [ 0.68877278 0.54872848 0.6254074 ]
[Epoch 2, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5]
[Epoch 2, inputs (1.0, 1.0)]: hidden outputs: [ 0.60700878 0.58812487 0.5509695 ]
[Epoch 2, inputs (0.0, 1.0)]: hidden outputs: [ 0.77344667 0.63591436 0.67311723]
[Epoch 3, inputs (0.0, 0.0)]: hidden outputs: [ 0.68856723 0.54708942 0.62400827]
[Epoch 3, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5]
Ввод примеров в случайном порядке ничего не меняет. Более того, я пробовал каждый курс обучения (от 0,05 до 0,95) с тем же результатом, поэтому я думаю, что это не о плохой конвергенции. Вот моя реализация Python:
def sigmoid(x):
return 1/(1 + np.exp(-x))
def dsigmoid(y):
return y * (1.0 - y)
class NeuralNetwork:
def __init__(self, nb_inputs, nb_hidden, nb_outputs, learning_rate):
self.nb_inputs = nb_inputs
self.nb_hidden = nb_hidden
self.nb_outputs = nb_outputs
self.learning_rate = learning_rate
self.output_deltas = None
self.output_weights = np.random.random((nb_outputs, nb_hidden)) # WRONG: should be between -1 and 1, not 0 and 1
self.outputs = None
self.hidden_deltas = None
self.hidden_weights = np.random.random((nb_hidden, nb_inputs)) # WRONG: should be between -1 and 1, not 0 and 1
self.hidden_outputs = None
def forward_propagation(self, inputs):
self.hidden_outputs = np.zeros((self.nb_hidden,))
self.outputs = np.zeros((self.nb_outputs,))
# get outputs for hidden layer
for i in range(self.nb_hidden):
aggregated = sum([inputs[j] * self.hidden_weights[i][j] for j in range(self.nb_inputs)])
self.hidden_outputs[i] = sigmoid(aggregated)
# get inputs for output layer
for i in range(self.nb_outputs):
aggregated = sum([self.hidden_outputs[j] * self.output_weights[i][j] for j in range(self.nb_hidden)])
self.outputs[i] = sigmoid(aggregated)
def backpropagation(self, expected_outputs):
# find deltas for output layer
for i in range(self.nb_outputs):
for j in range(self.nb_hidden):
self.output_deltas[i][j] = dsigmoid(self.outputs[i]) * (expected_outputs[i] - self.outputs[i])
# find deltas for hidden layer
for i in range(self.nb_hidden):
for j in range(self.nb_inputs):
total = 0.0
for k in range(self.nb_outputs):
total += self.output_deltas[k][i] * self.output_weights[k][i]
self.hidden_deltas[i][j] = dsigmoid(self.hidden_outputs[i]) * total
# change weights for output layer
for i in range(self.nb_outputs):
for j in range(self.nb_hidden):
self.output_weights[i][j] += self.learning_rate * self.output_deltas[i][j] * self.outputs[i] # WRONG: should be self.hidden_outputs[j]
# change weights for inputs layer
for i in range(self.nb_hidden):
for j in range(self.nb_inputs):
self.hidden_weights[i][j] += self.learning_rate * self.hidden_deltas[i][j] * self.hidden_outputs[i] # WRONG: should be inputs[j]
def train(self, data, nb_iterations):
for i in range(nb_iterations):
# Init deltas
self.output_deltas = np.zeros((self.nb_outputs, self.nb_hidden), dtype=np.float64)
self.hidden_deltas = np.zeros((self.nb_hidden, self.nb_inputs), dtype=np.float64)
# Train on examples with different orders
for inputs, expected_output in sorted(data.items(), key=lambda x: random.random()):
expected_outputs = np.array([expected_output])
self.forward_propagation(inputs)
self.backpropagation(expected_outputs) # WRONG: need inputs: backpropagation(inputs, expected_outputs)
def predict(self, inputs):
self.forward_propagation(inputs)
return self.outputs
'алгоритм, кажется, идет в circles' <- как правило, является показатель скорости обучения, который слишком высоко – inspectorG4dget
Спасибо за ваш ответ. К сожалению, я пробовал много обучающих курсов (от 0,05 до 0,95) с точно такими же результатами. Я отредактировал мое сообщение с этой точностью – Loheek
У вас может быть смещение для каждого узла и для каждого слоя, и также часто бывает, что вы добавляете эти смещения. Проблема XOR не может быть решена без предвзятости, кроме использования 3 скрытых нейронов, где один из них фактически действует как смещение. – Jodo