1

我一直在试图让下面的神经网络工作,作为一个简单的AND门,但它似乎并没有工作。以下是我的代码:用于AND逻辑门的单层神经网络(Python)

import numpy as np 

def sigmoid(x,derivative=False): 
    if(derivative==True): 
     return x*(1-x) 
    return 1/(1+np.exp(-x)) 

np.random.seed(1) 

weights = np.array([0,0,0]) 

training = np.array([[[1,1,1],1], 
        [[1,1,0],0], 
        [[1,0,1],0], 
        [[1,0,0],0]]) 

for iter in xrange(training.shape[0]): 
#forwardPropagation: 
     a_layer1 = training[iter][0] 
     z_layer2 = np.dot(weights,a_layer1) 
     a_layer2 = sigmoid(z_layer2) 
     hypothesis_theta = a_layer2 

#backPropagation: 
     delta_neuron1_layer2 = a_layer2 - training[iter][1] 
     Delta_neuron1_layer2 = np.dot(a_layer2,delta_neuron1_layer2) 
     update = Delta_neuron1_layer2/training.shape[0] 
     weights = weights-update 

x = np.array([1,0,1]) 

print weights 
print sigmoid(np.dot(weights,x)) 

上面的程序不断返回奇怪的值作为输出,输入X返回比数组[1,1,1]更高的值。每个培训/测试“输入”的第一个元素代表偏见单位。该代码是基于Andrew Ng在其Coursera Course上的机器学习课程视频:https://www.coursera.org/learn/machine-learning

在此先感谢您的帮助。

+0

我敢打赌,你的阵列形状会导致不需要的广播操作发生,导致学习全部搞砸。 –

回答

1

几个要点:

  1. NN的需要数据的不少。你不能传递一些样本,并期望它学到很多东西。
  2. 您正在使用列表和一维数组而不是二维数组。这对于numpy来说很危险,因为无论何种形状,都会盲目播放,这在某些情况下可能会很危险。
  3. 您没有使用乙状结肠衍生物您的反向传播应该像你

我重塑你的阵列,并且也增加了你的输入。

import numpy as np 

def sigmoid(x,derivative=False): 
    if(derivative==True): 
     return x*(1-x) 
    return 1/(1+np.exp(-x)) 

np.random.seed(1) 

weights = np.random.randn(1, 3) 

training = np.array([[np.array([0, 0, 0]).reshape(1, -1), 1], 
        [np.array([0,0,1]).reshape(1, -1), 0], 
        [np.array([0,1,0]).reshape(1, -1), 0], 
        [np.array([0,1,1]).reshape(1, -1), 0], 
        [np.array([1, 0, 0]).reshape(1, -1), 1], 
        [np.array([1,0, 1]).reshape(1, -1), 0], 
        [np.array([1,1,0]).reshape(1, -1), 0], 
        [np.array([1,1,1]).reshape(1, -1), 1], 

        ]) 

for iter in xrange(training.shape[0]): 
#forwardPropagation: 
     a_layer1 = training[iter][0] 
     z_layer2 = np.dot(weights,a_layer1.reshape(-1, 1)) 
     a_layer2 = sigmoid(z_layer2) 
     hypothesis_theta = a_layer2 

#backPropagation: 
     delta_neuron1_layer2 = (a_layer2 - training[iter][1]) * sigmoid(a_layer2 , derivative=True) 
     Delta_neuron1_layer2 = np.dot(delta_neuron1_layer2 , a_layer1) 
     update = Delta_neuron1_layer2 
     weights = weights - update 


x = np.array([0,0, 1]) 
print sigmoid(np.dot(weights,x.reshape(-1, 1))) 

x = np.array([0,1,1]) 
print sigmoid(np.dot(weights,x.reshape(-1, 1))) 

x = np.array([1,1,1]) 
print sigmoid(np.dot(weights,x.reshape(-1, 1))) 

输出:

[[ 0.34224604]] 
[[ 0.19976054]] 
[[ 0.52710321]] 

这是不干净的,肯定还有改进的余地。但至少,你现在有了一些东西。预计产生理论0的输入比理论1产生的输入更接近于0.

+0

这适用于我。我稍微改变了你的训练数组,并在main for循环之外添加了一个循环,以便我遍历数据10,000次。这实现的价值非常接近那些期望值。不过,我对此有疑问。重塑如何改善网络的培训方式?谢谢! – ashboy64

+0

哦,我明白了。你增加了时代。这正是我希望你会做的,而不是试图把它喂给你。另外,如果你使用np.dot,你需要确保你明确地形成你的数组。例如,如果您想要乘以尺寸为1,3 x 3x1的2个矩阵以获得1x1输出,则需要像这样调整它们。否则,你最终会乘以(3,)x(3,)得到你不想要的(3,)。这只是一个代表性的例子,但是你的代码中发生了类似的事情。 –