损失不变:使用MNIST数据集在Python 3.6中反向传播



我开始学习使用梯度下降的反向传播,使用数学方法,在不使用任何库(如Keras(的情况下了解事情是如何工作的。

我从网上取了一个示例程序,确保我试着理解每一步。它使用以下内容:1( 3层网络。输入具有784列或特征,这些列或特征是0-255之间的像素值2( 1个具有250个神经元的隐藏节点3( 具有1个神经元的1个输出节点4( 在-1和1之间随机生成的两个层的权重5( 整个批次被馈送到每个时期的训练中,学习率为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数据集,因为我相信神经网络在小批量时效果更好,而且我需要用较小的数据集进行快速POC2( 我将总输入减少到500行,NN正确预测从任何输入行馈送的数字3( 然而,当我将样本输入增加到接近3k时,损失根本没有改变。我试着玩学习率或隐藏层神经元的数量,但没有改变

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

我把train.csv文件修剪到大约3k行,这样我就可以馈送它了。

有人能帮助我更好地理解这一点吗?是什么让我的样本数据集发挥作用。我已经花了一周的时间,仍然没有放弃,我唯一能尝试和实现的就是在这个程序中创建小批量,但仍在评估如何做到这一点,因为我不是编程背景。

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

问候Chandan Jha

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

  1. 对于MNIST数据集,考虑在最后一层使用softmax回归函数,而不是sigmoid。给定的输入可能属于多个类(0,1,2,…9(。Sigmoid-二进制分类器在这种情况下没有用处。使用Softmax,您的输出将是10种可能性中概率最大的数字(0-9(
  2. 将数据集的标签预处理为一个热向量格式(其中每个标签都是大小为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 
  1. 使用更深层次的网络

最新更新