【问题标题】:Loss Not changing: Backpropagation in Python 3.6 with MNIST Dataset损失不变:Python 3.6 中的反向传播与 MNIST 数据集
【发布时间】:2018-12-23 22:08:37
【问题描述】:

我开始使用数学方法使用梯度下降来学习反向传播,以便在不使用 Keras 之类的任何库的情况下掌握事物的工作原理。

我从网上获取了一个示例程序,并确保我尝试理解每个步骤。它使用以下内容: 1)三层网络。输入有 784 列或特征,它们是 0-255 的像素值 2)1个隐藏节点,250个神经元 3)1个输出节点,1个神经元 4)两层的权重在-1和1之间随机生成 5) 整个批次在每个 epoch 中以 0.1 的学习率被输入到训练中

import numpy as np
dataset = np.loadtxt(open("train.csv", "rb"), delimiter=",",skiprows=1,dtype=float)
X = dataset[:,1:]
y = dataset[:,0]
print(X.shape,y.shape)
X = X/255
y = y/10
y = np.reshape(y,(len(y),1)) ## Necessary to avoid mismatching dimensions

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

# Define a learning rate
eta = 0.1
# Define the number of epochs for learning
epochs = 500000


w01 = np.random.uniform(low=-1, high=1, size=(784,250))
w12 = np.random.uniform(low=-1, high=1, size=(250,1))
# Start feeding forward and backpropagate *epochs* times.
for epoch in range(epochs):
   # Feed forward
   z_h = np.dot(X, w01)
   a_h = sigmoid(z_h)
   z_o = np.dot(a_h, w12)
   a_o = sigmoid(z_o)
   # Calculate the error
   a_o_error = ((1 / 2) * (np.power((a_o - y), 2)))
   #a_o_error = y-a_o
   # Backpropagation
   ## Output layer
   delta_a_o_error = a_o - y
   delta_z_o = sigmoid(a_o,derive=True)
   delta_w12 = a_h
   delta_output_layer = np.dot(delta_w12.T,(delta_a_o_error * delta_z_o))

   ## Hidden layer
   delta_a_h = np.dot(delta_a_o_error * delta_z_o, w12.T)
   delta_z_h = sigmoid(a_h,derive=True)
   delta_w01 = X
   delta_hidden_layer = np.dot(delta_w01.T, delta_a_h * delta_z_h)
   w01 = w01 - eta * delta_hidden_layer
   w12 = w12 - eta * delta_output_layer
   if epoch % 100 == 0:    
     print ("Loss at epoch "+str(epoch)+":"+str(np.mean(np.square(y - a_o))))


#Testing:
X_Test = X[129] 
Y_Test = y[129]  

z_h = np.dot(X_Test, w01)
a_h = sigmoid(z_h)
z_o = np.dot(a_h, w12)
a_o = sigmoid(z_o)

print("Expected Output:",Y_Test*10) 
print("Actual Output got:",a_o*10)

这是我的问题: 1) 我无法用 42k 样本为整个 MNIST 数据集提供数据,因为我相信神经网络更适合小批量,而且我需要用更小的数据集进行快速 POC 2)我将总输入减少到 500 行,并且 NN 正确预测从任何输入行馈送的数字 3)但是,当我将样本输入增加到接近 3k 时,损失根本没有变化。我尝试使用学习率或隐藏层神经元的数量,但没有变化

数据可以从以下位置下载: www.kaggle.com/c/digit-recognizer/data

我将 train.csv 文件修剪为大约 3k 行,以便我可以喂它。

有人可以帮助我更好地理解这一点,什么可以使它与我的示例数据集一起工作。我已经花了一个星期的时间,但仍然没有放弃,我唯一可以尝试和实现的就是在这个程序中创建小批量,但仍在评估如何做到这一点,因为我不是编程背景。

感谢您阅读我的问题和您的耐心。

问候 钱丹·贾

【问题讨论】:

  • 能否请您也添加输出?当损失没有改变时。
  • 嗨 Vikas,我从第一个时期开始反复看到以下消息: 时期 59800 的损失是:0.285596560373
  • 这也意味着程序仍在运行,最后它只是尝试使用我在程序中硬编码的随机行进行预测,现在只输出一个垃圾值。我知道很多人使用向量单位矩阵来进行这样的多类输出,但我尝试使用单个输出神经元,它适用于 500 个样本大小。

标签: python-3.x backpropagation mnist


【解决方案1】:

我认为可以改进您的实施的一些建议:

  1. 对于 MNIST 数据集,考虑在最后一层而不是 sigmoid 中使用softmax 回归函数。您有多个类(0、1、2、...9),给定的输入可能属于这些类。 Sigmoid - 在这种情况下,二元分类器没有用。使用 Softmax,您的输出将是 10 种可能性 (0-9) 中概率最大的数字。
  2. 将数据集的标签预处理为 one-hot 向量格式(其中每个标签都是大小为 10 的向量,唯一具有所需输出编号的索引将为 1,其余为 0)
  3. 除非您陷入使用普通批量梯度下降的局部最小值,否则您应该观察到迭代过程中的损失有所减少。 使用小批量可能有助于以稳健的方式收敛。 您可以使用上面提到的现有代码并放入如下结构: start_pos = 0 mini_batch_size = 64 #Use suitable batch size that would fit in your memory(Typically use #size that is a power of 2) num_complete_batches = int(len(X) / mini_batch_size) for epoch in range(epochs): for curr_batch in range(num_complete_batches): current_x = X[:, curr_batch*mini_batch_size : curr_batch*mini_batch_size + \ mini_batch_size] current_y = Y[:, curr_batch*mini_batch_size : curr_batch*mini_batch_size + \ mini_batch_size] #Forward-Backward pass #If you have left-over examples that did not fit in complete batches, now feed those #into the network
  4. 使用更深层次的网络。

【讨论】:

  • 谢谢贾迪普。我会尽快落实您的建议并更新。
猜你喜欢
  • 2016-03-21
  • 1970-01-01
  • 2020-09-10
  • 2019-11-14
  • 2022-01-18
  • 2018-04-02
  • 1970-01-01
  • 2017-06-20
  • 2018-06-14
相关资源
最近更新 更多