Tensorflow实现神经网络

  • Post author:
  • Post category:其他


#主要根据一个神经网络来讲解基础的tensorflow的应用。在实现一个神经网络的过程,来讲解tensorflow的应用。具体讲了每个函数的作用和意义。
#还有就是讲解了dropout的作用,非线性激励函数,损失函数,还有优化算法。

# Parameters,开始的时候,这个设施大一点,然后慢慢的修改
learning_rate = 0.001

#训练的循环次数,用来提高准确率,降低错误率.也是更新w和b.在这里,由于数据小,这个一次epoch会循环一次数据
#在训练中,我们在每个 epoch 送入单个数据点。这被称为随机梯度下降(stochastic gradient descent)。随机梯度下降
# 我们也可以在每个 epoch 送入一堆数据点,这被称为 mini-batch 梯度下降(这里采用的是mini-batch),
# 或者甚至在一个 epoch 一次性送入所有的数据点,这被称为 batch 梯度下降。batch梯度下降
training_epochs = 30

#设置每次输入数据的大小
batch_size = 100

#无关,主要是显示作用
display_step = 5

# Network Parameters,有784 神经元输入(输入数据的维数),第一个隐藏层有256个神经元,第二个隐藏层有512个神经元,10个神经元输出(label 个数)
n_hidden_1 = 256 # 1st layer number of features第一隐藏层
n_hidden_2 = 512 # 2nd layer number of features第二隐藏层
n_input = 784 # MNIST data input (img shape: 28*28)输入层
n_classes = 10 # MNIST total classes (0-9 digits)输出层

# tf Graph input 占位符
x = tf.placeholder("float", [None, n_input])
y = tf.placeholder("float", [None, n_classes])

# Create model,建造二神经网络包括两个隐藏层
def multilayer_perceptron(x, weights, biases):
    # Hidden layer with RELU activation
    layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
    #这里采用非线性激励函数,是解决非线性数据问题.对于非线性激励函数,四种选择(可能更多)
    #1 sigmoid

    #2 tahn

    #3 ReLU(常用,因为特征度足够多,可以损失一些函数)

    #4 Leaky ReLU

    
    #非线性激励函数:正向截断负值,损失大量特征
    layer_1 = tf.nn.relu(layer_1)
    # Hidden layer with RELU activation
    layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
    #非线性激励函数:正向截断负值,损失大量特征
    layer_2 = tf.nn.relu(layer_2)

    # we can add dropout layer参数太多,有时候随机设为0,维数变.用剩余的参数进行计算。
    # overfitting的表现形式:可能就是一些weight特别的大,然后其他一些weight特别的小或者为0。
    # 想要的的参数尽量均衡,让来的数据都有贡献.随机设为0。当随机设为0的之后,若预测结果并没有太大的改变,说明weight较为均衡。
    drop_out = tf.nn.dropout(layer_2, 0.75)

    # Output layer with linear activation输出层,只是线性的输出
    out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
    return out_layer

# Store layers weight & biases 设置权重和斜偏率.
# 对于weight函数,这里设置为随机的,因为如果weight设置为相等的,这回造成所有的输入数据就有类似的效果.
weights = {
    'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes]))
}
biases = {
    'b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_classes]))
}

# 让模型训练做分类
pred = multilayer_perceptron(x, weights, biases)

# Define loss and optimizer  loggits为预测的结果,labels为实际label
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))

#扩展:TensorFlow四种Cross Entropy算法实现和应用
#交叉熵介绍(文献2)

#交叉熵(Cross Entropy)是Loss函数的一种(也称为损失函数或代价函数),用于描述模型预测值与真实值的差距大小,
# 常见的Loss函数就是均方平方差(Mean Squared Error)平方差很好理解,预测值与真实值直接相减,
# 为了避免得到负数取绝对值或者平方,再做平均就是均方平方差。注意这里预测值需要经过sigmoid激活函数,得到取值范围在0到1之间的预测值。
# 平方差可以表达预测值与真实值的差异,但在分类问题种效果并不如交叉熵好.

#首先是交叉熵得到的值一定是正数,其次是预测结果越准确值越小,注意这里用于计算的“a” 也是经过sigmoid激活的,取值范围在0到1。
#如果label是1,预测值也是1的话,前面一项y * ln(a)就是1 * ln(1)等于0,后一项(1 - y) * ln(1 - a)也就是0 * ln(0)等于0,Loss函数为0,
#反之Loss函数为无限大非常符合我们对Loss函数的定义。这里多次强调sigmoid激活函数,是因为在多目标或者多分类的问题下有些函数是不可用的,
#而TensorFlow本身也提供了多种交叉熵算法的实现。

#tf.nn.sigmoid_cross_entropy_with_logits
# sigmoid_cross_entropy_with_logits,因为它的实现和前面的交叉熵算法定义是一样的
# 输入是logits和targets,logits就是神经网络模型中的 W * X矩阵,注意不需要经过sigmoid,而targets的shape和logits相同,
# 就是正确的label值,例如这个模型一次要判断100张图是否包含10种动物,这两个输入的shape都是[100, 10]。
# 注释中还提到这10个分类之间是独立的、不要求是互斥,这种问题我们成为多目标,例如判断图片中是否包含10种动物,label值可以包含多个1或0个1,


#tf.nn.softmax_cross_entropy_with_logits
#上面的函数不能解决多分类问题,例如我们对年龄特征分为5段,只允许5个值有且只有1个值为1,
#Softmax本身的算法很简单,就是把所有值用e的n次方计算出来,求和后算每个值占的比率,保证总和为1,一般可以认为Softmax出来的就是confidence也就是概率
#softmax_cross_entropy_with_logits和sigmoid_cross_entropy_with_logits很不一样,输入是类似的logits和lables的shape一样,但这里要求分类的结果是互斥的,
# 保证只有一个字段有值,例如CIFAR-10中图片只能分一类而不像前面判断是否包含多类动物。想一下问什么会有这样的限制?在函数头的注释中我们看到,
# 这个函数传入的logits是unscaled的,既不做sigmoid也不做softmax,因为函数实现会在内部更高效得使用softmax,
# 对于任意的输入经过softmax都会变成和为1的概率预测值,这个值就可以代入变形的Cross Entroy算法- y * ln(a) - (1 - y) * ln(1 - a)算法中,
# 得到有意义的Loss值了。如果是多目标问题,经过softmax就不会得到多个和为1的概率,而且label有多个1也无法计算交叉熵,
# 因此这个函数只适合单目标的二分类或者多分类问题
#再补充一点,对于多分类问题,例如我们的年龄分为5类,并且人工编码为0、1、2、3、4,因为输出值是5维的特征,
# 因此我们需要人工做onehot encoding分别编码为00001、00010、00100、01000、10000,才可以作为这个函数的输入。
# 理论上我们不做onehot encoding也可以,做成和为1的概率分布也可以,但需要保证是和为1,和不为1的实际含义不明确,

#tf.nn.sparse_softmax_cross_entropy_with_logits
#sparse_softmax_cross_entropy_with_logits是softmax_cross_entropy_with_logits的易用版本,除了输入参数不同,作用和算法实现都是一样的。
# 前面提到softmax_cross_entropy_with_logits的输入必须是类似onehot encoding的多维特征,
# 但CIFAR-10、ImageNet和大部分分类场景都只有一个分类目标,label值都是从0编码的整数,每次转成onehot encoding比较麻烦,有没有更好的方法呢?
# 答案就是用sparse_softmax_cross_entropy_with_logits,它的第一个参数logits和前面一样,shape是[batch_size, num_classes],
# 而第二个参数labels以前也必须是[batch_size, num_classes]否则无法做Cross Entropy,
# 这个函数改为限制更强的[batch_size],而值必须是从0开始编码的int32或int64,而且值范围是[0, num_class),如果我们从1开始编码或者步长大于1,
# 会导致某些label值超过这个范围,代码会直接报错退出。这也很好理解,TensorFlow通过这样的限制才能知道用户传入的3、6或者9对应是哪个class,
# 最后可以在内部高效实现类似的onehot encoding,这只是简化用户的输入而已,
# 如果用户已经做了onehot encoding那可以直接使用不带“sparse”的softmax_cross_entropy_with_logits函数。

#tf.nn.weighted_cross_entropy_with_logits
#weighted_sigmoid_cross_entropy_with_logits是sigmoid_cross_entropy_with_logits的拓展版,输入参数和实现和后者差不多,
# 可以多支持一个pos_weight参数,目的是可以增加或者减小正样本在算Cross Entropy时的Loss。
# 实现原理很简单,在传统基于sigmoid的交叉熵算法上,正样本算出的值乘以某个系数接口.

#这就是TensorFlow目前提供的有关Cross Entropy的函数实现,用户需要理解多目标和多分类的场景,
# 根据业务需求(分类目标是否独立和互斥)来选择基于sigmoid或者softmax的实现,
# 如果使用sigmoid目前还支持加权的实现,如果使用softmax我们可以自己做onehot coding
# 或者使用更易用的sparse_softmax_cross_entropy_with_logits函数。
#TensorFlow提供的Cross Entropy函数基本cover了多目标和多分类的问题,但如果同时是多目标多分类的场景,
# 肯定是无法使用softmax_cross_entropy_with_logits,如果使用sigmoid_cross_entropy_with_logits
# 我们就把多分类的特征都认为是独立的特征,而实际上他们有且只有一个为1的非独立特征,计算Loss时不如Softmax有效。

# Define optimizer
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

# SGD(文献5,6)
#x+= -learning_rate*dx

# optimizer = tf.train.GradientDescentOptimizer(learning_rate=self.learning_rate)
#
# Momentum
#
# optimizer = tf.train.MomentumOptimizer(lr, 0.9)
#
# AdaGrad
#
# optimizer = tf.train.AdagradientOptimizer(learning_rate=self.learning_rate)
#
# RMSProp
#
# optimizer = tf.train.RMSPropOptimizer(0.001, 0.9)
#
# ADAM
#
# optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate, epsilon=1e-08)


# Initializing the variables初始化化所有变量
init = tf.global_variables_initializer()

# Launch the graph
with tf.Session() as sess:
    #初始化化所有变量
    sess.run(init)

    # Training cycle
    for epoch in range(training_epochs):
        avg_cost = 0.
        total_batch = int(mnist.train.num_examples/batch_size)
        # Loop over all batches one by one,把数据分块做训练
        for i in range(total_batch):
            batch_x, batch_y = mnist.train.next_batch(batch_size)
            # Run optimization op (backprop) and cost op (to get loss value),feed_dict,是把数据喂给分类器
            _, c = sess.run([optimizer, cost], feed_dict={x: batch_x,
                                                          y: batch_y})
            # Compute average loss
            avg_cost += c / total_batch
        # Display logs per epoch step
        if epoch % display_step == 0:
            print("Epoch:", '%04d' % (epoch+1), "cost=", \
                "{:.9f}".format(avg_cost))
    print("Optimization Finished!")

    # Test model测试数据,找出pred的最大好
    correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))


#http://www.jiqizhixin.com/article/1440 基础tensorflow
#http://weibo.com/ttarticle/p/show?id=2309404047468714166594  TensorFlow四种Cross Entropy算法实现和应用
#https://www.tensorflow.org/versions/master/api_docs/python/nn.html#sparse_softmax_cross_entropy_with_logits 官方文档
#https://jamesmccaffrey.wordpress.com/2013/11/05/why-you-should-use-cross-entropy-error-instead-of-classification-error-or-mean-squared-error-for-neural-network-classifier-training/  为什么: 平方差表达预测值与真实值的差异,但在分类问题种效果并不如交叉熵好
#http://blog.csdn.net/csyanbin/article/details/53460627 优化方法
#http://sebastianruder.com/optimizing-gradient-descent/index.html#gradientdescentvariants 优化算法
#图片来自小象学院ptt




版权声明:本文为yuzhou164原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。