【发布时间】:2018-04-10 15:25:45
【问题描述】:
我开始使用神经网络和这类东西,我了解perceptron 的工作原理以及feed-forward and backpropagation 机制背后的逻辑,我现在正在尝试编写一个具有 3 个神经元的简单多层网络( 2 在隐藏层和 1 作为输出)应该足以执行xor operation。
我以这种方式在 Python 中实现它(现在使用 v3.6.1):
import numpy as np
class Neuron():
def __init__(self, n, w = None, b = None):
#np.random.seed(46144492)
#np.random.seed(23)
self.weights = 2 * np.random.random((n)) - 1 if w == None else np.array(w)
self.bias = 2 * np.random.random() - 1 if b == None else b
self.learning_rate = 0.1
self.weights_error = []
for i in range(n):
self.weights_error.append(0)
self.bias_error = 0
def learning_factor(self, output):
return output * (1 - output)
def fire(self, x):
return 1 / (1 + np.exp(-x))
def __call__(self, inputs):
weighted = []
for i in range(len(inputs)):
weighted.append(inputs[i] * self.weights[i])
weighted = np.array(weighted)
return self.fire(weighted.sum() + self.bias)
def adjust(self, n_weights):
for i in range(n_weights):
self.weights[i] -= self.weights_error[i]
self.bias -= self.bias_error
class HiddenNeuron(Neuron):
def calc_error(self, inputs, output, next_layer, number_in_layer):
error = 0
for n in range(len(next_layer)):
error += next_layer[n].delta * next_layer[n].weights[number_in_layer - 1]
derivative = self.learning_factor(output)
self.delta = error * derivative
self.weights_error = []
for i in range(len(inputs)):
self.weights_error.append(self.delta * inputs[i] * self.learning_rate)
self.bias_error = self.delta * self.learning_rate
class OutputNeuron(Neuron):
def calc_error(self, inputs, output, expected):
error = output - expected
derivative = self.learning_factor(output)
self.delta = error * derivative
self.weights_error = []
for i in range(len(inputs)):
self.weights_error.append(self.delta * inputs[i] * self.learning_rate)
self.bias_error = self.delta * self.learning_rate
# Network
n1, n2 = HiddenNeuron(2), HiddenNeuron(2)
n3 = OutputNeuron(2)
# Training data
training_set_in = [[0, 0], [0, 1], [1, 0], [1, 1]]
training_set_out = [0, 1, 1, 0]
# Training cycles
for i in range(10000):
for i in range(len(training_set_in)):
# Feed-forward
n1_out = n1(training_set_in[i])
n2_out = n2(training_set_in[i])
n3_in = [n1_out, n2_out]
n3_out = n3(n3_in)
# Backpropagation
n3.calc_error(n3_in, n3_out, training_set_out[i])
n2.calc_error(training_set_in[i], n2_out, [n3], 2)
n1.calc_error(training_set_in[i], n1_out, [n3], 1)
n1.adjust(2)
n2.adjust(2)
n3.adjust(2)
# "New" cases (test)
for new in [[0, 0], [0, 1], [1, 0], [1, 1]]:
print(n3([n1(new), n2(new)]))
如你所见,我使用 sigmoid 函数作为激活函数,但我还没有实现动量(我还需要了解它是如何工作的)。
在大多数情况下,网络都能正常工作。但我发现在某些情况下它会输出一些奇怪的值(例如,参见我在 Neuron 类构造函数中注释的两个随机种子)。如果我增加 Neuron.learning_rate(例如将其设置为 10),这两种情况就解决了,但仍然出现了一些其他异常(找不到这些的种子,对不起......但它们非常频繁,只需运行代码 10 或 20 次,您就会看到一些)。
问题是:为什么会这样?我的网络太“小”/简单吗?我认为 3 个神经元就足够了。还是只是“校准”的问题(不知道这个怎么称呼,我的意思是调整学习率因子和动量的过程,这里没有)?还是我什至犯了任何错误?实在想不通。
编辑:我正在用所有可能的情况训练网络,然后用相同的情况进行尝试,以验证它是否正常工作。
【问题讨论】:
标签: python python-3.x neural-network perceptron calibration