渐变下降优化器TensorFlow

时间:2018-03-10 11:04:00

标签: python tensorflow neural-network deep-learning mnist

我是这个深度学习世界的新人。这些天我正在试图理解神经网络是如何工作的,所以我正在进行不同的测试。到目前为止,我正在使用MNIST数据库,其数字从0到9.我已经应用了一个没有隐藏层的完全连接的网络。这是代码:

from keras.datasets import mnist # subroutines for fetching the MNIST dataset
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
from keras.utils import np_utils # utilities for one-hot encoding of ground truth values
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

x_train = mnist.train.images
y_train = mnist.train.labels
x_test = mnist.test.images
y_test = mnist.test.labels

test = np.reshape(x_train,[-1,28,28]) #THRESHOLDING
x_train = np.zeros([55000,28,28])
x_train[test > 0.5] = 1


print(x_train.shape)

x_train = np.reshape(x_train,[55000,784])
y_train = np_utils.to_categorical(y_train, 10) # One-hot encode the labels

print(x_train.shape)
print(y_train.shape)

x_test = np.reshape(x_test,[10000,784])

input = tf.placeholder(tf.float32, name='Input')
output = tf.placeholder(tf.float32, name = 'Output')

syn0 = tf.Variable(2*tf.random_uniform([784,10],seed=1)-1, name= 'syn0')
#syn0 = tf.Variable(tf.zeros([784,10], dtype = tf.float32), name= 'syn0')


b1 = tf.Variable(2*tf.random_uniform([10],seed=1)-1, name= 'b1')
#b1 = tf.Variable(tf.zeros([10],dtype = tf.float32), name= 'syn0')

init = tf.global_variables_initializer()

#model

l1 = tf.nn.softmax((tf.matmul(input,syn0) + b1),name='layer1')

error = tf.square(tf.subtract(l1,output),name='error')
loss = tf.reduce_sum(error, name='cost')

#optimizer
with tf.name_scope('trainning'):
    optimizer = tf.train.GradientDescentOptimizer(0.01)
    train = optimizer.minimize(loss)


#session
sess = tf.Session()
sess.run(init)

syn0_ini = sess.run(syn0)

#trainning
for i in range (10000):
    batch_xs, batch_ys = mnist.train.next_batch(128)
    _,lossNow =  sess.run([train,loss],{input: batch_xs,output: batch_ys})

    if i%10 == 0:
        print("Loss in iteration " , i, " is: ", lossNow )

#print debug 

y_pred = sess.run(l1,{input: x_test,output: y_test})

correct_prediction = tf.equal(tf.argmax(y_pred,1), tf.argmax(y_test,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

print()
print("Final Accuracy: ", sess.run(accuracy))

我已经打印了重量(syn0),我什么也看不见。但如果我将它们初始化为零,我可以看到数字的形状。这是逻辑,因为没有隐藏层,它就像是一种相关性。

所以在第一种情况下,我可以假设我可以看到任何东西,因为权重没有被修改,它们被初始化为随机值。

我不明白的是为什么培训功能只修改了一些权重,因为我只用一个数字来减少它。因此,在我看来,所有权重必须以相同的方式进行修改。

这里有随机初始化的权重: weigths for 0 weights for 1

现在我把权重置于零初始化:

weigths for 0 weigths for 1

正如你所看到的,有一些权重在开始时仍然存在,但有些权重会发生变化。这是怎么可能的,因为损失函数只是一个标量数?

希望我的问题很明确。如果不是只是告诉我。

非常感谢。

1 个答案:

答案 0 :(得分:0)

  

我不明白的是为什么培训功能只修改了一些权重,因为我只用一个数字来减少它。因此,在我看来,所有权重必须以相同的方式进行修改。

这不完全正确。

在单个训练样本的情况下考虑线性激活:

Z = W*X + b    #(tf.matmul(input,syn0) + b1

这里你正在执行W和X之间的点积。基本上,你正在做:

Z = sum(W[j] * X[j]) + b

oss:matmul有效,因为你的权重是行向量,而要素是列向量。

之后,应用非线性激活功能,即softmax功能。这将为您提供预测,您将用它来计算损失,即您所说的标量。

现在,当执行反向传播步骤时,TF将计算相对于W的每个分量的损失的导数。显式:

dW[j] = dL/dZ * dZ/dW[j]

其中:

  • dL/dZ是Z
  • 损失的衍生物
  • dZ/dW[j]是Z wrt到W
  • 的衍生物

上一个公式来自链式规则。

事实证明:

dZ/dW[j] = x[j]

这就是为什么你最终得到每个组件的不同值。

有关进一步分析,请参阅this问题。基本上,将所有神经元的所有权重初始化为0会使您的网络冗余,因为所有神经元都具有相同的W值。但是,在每个神经元中,W的分量将是不同的。