Python中的神经网络 - 在权重矩阵形状和背部支柱方面存在问题

时间:2017-05-11 02:13:08

标签: python matrix machine-learning neural-network backpropagation

我一直在努力用直线蟒蛇编写神经网络。我试图让它识别MNIST图像。

我认为在初始化体重时我一定做错了。

我的假设是,因为MNIST数据是形状28x28的数据,所以第一组的权重应该是形状(28,某事物),最后一组权重的形状应该是(X,1), X是数据集中的类数。

我很困惑的一件事是我的结束矩阵(下面的变量l5)具有形状(28,1)。 我需要做什么才能使输出的形状为(9,1)?我已经打印了形状,并且在我对NN和线性代数的理解中实现了差距:

l5 shape: (28, 1)
l4 shape: (28, 9)
l3 shape: (28, 14)
l2 shape: (28, 21)
l1 shape: (28, 28)

我认为我理论上可以做一个SVM(支持向量机)和多个(扁平化)形状(784,1)的图像,矩阵为(784,9),但我不确定这是否是唯一的这样做的方式,如果实际上,我与我所拥有的东西相差甚远。

以下代码,基于本教程:http://iamtrask.github.io/2015/07/12/basic-python-network/

    syn0 = np.random.random((28, 28))
    syn1 = np.random.random((28, 21))
    syn2 = np.random.random((21, 14)) 
    syn3 = np.random.random((14, 9)) 
    syn4 = np.random.random((9, 1))
    images, labels = mndata.load_training()
    print(len(images))
    for index, image in enumerate(images):
        X = np.array(image).reshape((28, 28))
        print(X)        
        y = np.zeros((9)) # getImageCategory(fileName)
        y[labels[index]] = 1

        print(y)

        l0 = X
        l1 = sigmoid(np.dot(l0, syn0)) # + bias?
        l2 = sigmoid(np.dot(l1, syn1)) # + bias?
        l3 = sigmoid(np.dot(l2, syn2)) # + bias?
        l4 = sigmoid(np.dot(l3, syn3)) # + bias?
        l5 = sigmoid(np.dot(l4, syn4)) # + bias?

        print("l5 shape: " + str(l5.shape))
        print("l4 shape: " + str(l4.shape))
        print("l3 shape: " + str(l3.shape))
        print("l2 shape: " + str(l2.shape))
        print("l1 shape: " + str(l1.shape))
        print("Y shape: " + str(y.shape))

        l5_error = y - l5

        if index % 10 == 0:
            print("Error: " + str(np.mean(np.abs(l5_error)))) # +" | Prediction: " + str(l5))

        l5_delta = l5_error * sigmoid(l5, True) # True = derivative of sigmoid

        l4_error = l5_delta.dot(syn4.T)
        l4_delta = l4_error * sigmoid(l4, True) # True = derivative of sigmoid

        l3_error = l4_delta.dot(syn3.T)
        l3_delta = l3_error * sigmoid(l3, True) # True = derivative of sigmoid

        l2_error = l3_delta.dot(syn2.T)
        l2_delta = l2_error * sigmoid(l2, True) # True = derivative of sigmoid

        l1_error = l2_delta.dot(syn1.T)
        l1_delta = l1_error * sigmoid(l1, True) # True = derivative of sigmoid

#             print("layer_4_delta shape: " + str(l4_delta.shape))
#             print("layer_3_delta shape: " + str(l3_delta.shape))
#             print("layer_2_delta shape: " + str(l2_delta.shape))
#             print("layer_1_delta shape: " + str(l1_delta.shape))

#             print("L1 Error" + str(layer_1_delta) + " | L2 Error: " + str(layer_2_delta) + " | L3 Error: " + str(layer_3_delta) + " | L4 Error: " + str(layer_4_delta))
        # update weights
        syn4 += l4.T.dot(l5_delta)
        syn3 += l3.T.dot(l4_delta)
        syn2 += l2.T.dot(l3_delta)
        syn1 += l1.T.dot(l2_delta)
        syn0 += l0.T.dot(l1_delta)            

另外,我知道反向传播是找到输出的梯度并根据适应度函数更新权重以最小化误差(我现在想到它可能会丢失它?)。 我不明白为什么在更新我的权重和计算图层错误时我必须转置图层。

我得到的当前错误低于,但我确定我的代码还有其他问题

Traceback (most recent call last):
  File "C:\Users\Username\Development\Python\updatedKernel.py", line 128, in <module>
    main()
  File "C:\Users\Username\Development\Python\updatedKernel.py", line 104, in main
    l4_error = l5_delta.dot(syn4.T)
ValueError: shapes (28,9) and (1,9) not aligned: 9 (dim 1) != 1 (dim 0) 

1 个答案:

答案 0 :(得分:1)

一般

输入的形状(MNIST数据)是(nb_samples_in_bacth,input_dimensions),其中input_dimensions = 784 = 28 * 28

第一组权重的形状是(input_dimensions,hidden_​​dimension),其中input_dimensions = 784 = 28 * 28,hidden_​​dimension由用户设置(通常应与input_dimension的数量级相同)。

第二个权重的形状是(hidden_​​dimension,nb_classes),其中nb_class = 10(对于MNIST中的10位数字)。

您的最终输出的形状应为(nb_samples_in_batch,nb_classes)