问题描述

这几天在用TensorFlow搭建一个神经网络来做一个binary classifier,搭建一个典型的神经网络的基本思路是:

  • 定义神经网络的layers(层)以及初始化每一层的参数
  • 然后迭代:
    • 前向传播(Forward propagation)
    • 计算cost(Compute cost)
    • 反向传播(Backward propagation)
    • 更新参数(Update parameters)
  • 使用训练好的参数去做预测

在训练的时候发现了一个很奇怪的现象:每一次迭代所有的cost都为0。一开始以为是参数初始化出了问题,花了好多时间在上面。后来仔细研究了一下发现是最后一层的输出函数用错了,我用的是tf.nn.softmax_cross_entropy_with_logits来计算cost。 我们知道softmax一般是用来做multiclass classifier的,也就是输出的类别要大于两个。对于一个binary classifier而言,很明显我们要用sigmoid函数也就是tf.nn.sigmoid_cross_entropy_with_logits来计算cost,于是问题解决。

为什么?

那么为什么在binary classifier中使用了softmax之后cost就一直是0呢?我们先来看一下softmax的公式:

s(z)j=ezj∑Kk=1ezks(z)j=ezj∑k=1Kezk

  • binary classifier的output是一维的(one-dimension 0/1),那么如果只有一个元素,那么s(z)就永远等于1,不管z的值是多少。
  • 恒定输出1之后,我们结合交叉熵的计算公式可知:
    • 如果true label是0,那么 -0*log(1) = 0
    • 如果true label是1,那么 -1*log(1) = 0

Tensorflow函数:tf.nn.softmax_cross_entropy_with_logits 讲解

 

首先把Tensorflow英文API搬过来:

tf.nn.softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, dim=-1, name=None)

Computes softmax cross entropy between logits and labels.

Measures the probability error in discrete classification tasks in which the classes are mutually exclusive (each entry is in exactly one class). For example, each CIFAR-10 image is labeled with one and only one label: an image can be a dog or a truck, but not both.

NOTE: While the classes are mutually exclusive, their probabilities need not be. All that is required is that each row oflabels is a valid probability distribution. If they are not, the computation of the gradient will be incorrect.

If using exclusive labels (wherein one and only one class is true at a time), seesparse_softmax_cross_entropy_with_logits.

WARNING: This op expects unscaled logits, since it performs a softmax on logits internally for efficiency. Do not call this op with the output of softmax, as it will produce incorrect results.

logits and labels must have the same shape [batch_size, num_classes] and the same dtype (either float16,float32, or float64).

Note that to avoid confusion, it is required to pass only named arguments to this function.

Args:

  • _sentinel: Used to prevent positional parameters. Internal, do not use.
  • labels: Each row labels[i] must be a valid probability distribution.
  • logits: Unscaled log probabilities.
  • dim: The class dimension. Defaulted to -1 which is the last dimension.
  • name: A name for the operation (optional).

这个函数至少需要两个参数:labels, logits.

labels:为神经网络期望的输出

logits:为神经网络最后一层的输出

警告:这个函数内部自动计算softmax,然后再计算交叉熵代价函数,也就是说logits必须是没有经过tf.nn.softmax函数处理的数据,否则导致训练结果有问题。建议编程序时使用这个函数,而不必自己编写交叉熵代价函数。

下面是两层CNN识别mnist的softmax回归实验:

  1. #coding=utf-8
  2. import tensorflow as tf
  3. from tensorflow.examples.tutorials.mnist import input_data
  4. mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
  5. def compute_accuracy(v_xs,v_ys):
  6. global prediction
  7. y_pre=sess.run(prediction,feed_dict={xs:v_xs,keep_prob:1}) #这里的keep_prob是保留概率,即我们要保留的RELU的结果所占比例
  8. correct_prediction=tf.equal(tf.argmax(y_pre,1),tf.argmax(v_ys,1))
  9. accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
  10. result=sess.run(accuracy,feed_dict={xs:v_xs,ys:v_ys,keep_prob:1})
  11. return result
  12. def weight_variable(shape):
  13. inital=tf.truncated_normal(shape,stddev=0.1)     #stddev爲標準差
  14. return tf.Variable(inital)
  15. def bias_variable(shape):
  16. inital=tf.constant(0.1,shape=shape)
  17. return tf.Variable(inital)
  18. def conv2d(x,W):    #x爲像素值,W爲權值
  19. #strides[1,x_movement,y_movement,1]
  20. #must have strides[0]=strides[3]=1
  21. #padding=????
  22. return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')#
  23. def max_pool_2x2(x):
  24. # strides[1,x_movement,y_movement,1]
  25. return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')#ksize二三维为池化窗口
  26. #define placeholder for inputs to network
  27. xs=tf.placeholder(tf.float32,[None,784])/255
  28. ys=tf.placeholder(tf.float32,[None,10])
  29. keep_prob=tf.placeholder(tf.float32)
  30. x_image=tf.reshape(xs, [-1,28,28,1]) #-1为这个维度不确定,变成一个4维的矩阵,最后为最里面的维数
  31. #print x_image.shape                 #最后这个1理解为输入的channel,因为为黑白色所以为1
  32. ##conv1 layer##
  33. W_conv1=weight_variable([5,5,1,32]) #patch 5x5,in size 1 是image的厚度,outsize 32 是提取的特征的维数
  34. b_conv1=bias_variable([32])
  35. h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)# output size 28x28x32 因为padding='SAME'
  36. h_pool1=max_pool_2x2(h_conv1)      #output size 14x14x32
  37. ##conv2 layer##
  38. W_conv2=weight_variable([5,5,32,64]) #patch 5x5,in size 32 是conv1的厚度,outsize 64 是提取的特征的维数
  39. b_conv2=bias_variable([64])
  40. h_conv2=tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)# output size 14x14x64 因为padding='SAME'
  41. h_pool2=max_pool_2x2(h_conv2)      #output size 7x7x64
  42. ##func1 layer##
  43. W_fc1=weight_variable([7*7*64,1024])
  44. b_fc1=bias_variable([1024])
  45. #[n_samples,7,7,64]->>[n_samples,7*7*64]
  46. h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64])
  47. h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1)
  48. h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob)  #防止过拟合
  49. ##func2 layer##
  50. W_fc2=weight_variable([1024,10])
  51. b_fc2=bias_variable([10])
  52. #prediction=tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)
  53. prediction=tf.matmul(h_fc1_drop,W_fc2)+b_fc2
  1. #h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob)  #防止过拟合
  2. #the errro between prediction and real data
  3. #cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys*tf.log(prediction),reduction_indices=[1]))
  1. cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=ys, logits=prediction)
  2. train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
  3. sess=tf.Session()
  4. sess.run(tf.global_variables_initializer())
  5. for i in range(1000):
  6. batch_xs,batch_ys=mnist.train.next_batch(100)
  7. sess.run(train_step,feed_dict={xs:batch_xs,ys:batch_ys,keep_prob:0.5})
  8. if i%50 ==0:
  9. accuracy = 0
  10. for j in range(10):
  11. test_batch = mnist.test.next_batch(1000)
  12. acc_forone=compute_accuracy(test_batch[0], test_batch[1])
  13. #print 'once=%f' %(acc_forone)
  14. accuracy=acc_forone+accuracy
  15. print '测试结果:batch:%g,准确率:%f' %(i,accuracy/10)

实验结果为:

  1. 测试结果:batch:0,准确率:0.090000
  2. 测试结果:batch:50,准确率:0.788600
  3. 测试结果:batch:100,准确率:0.880200
  4. 测试结果:batch:150,准确率:0.904600
  5. 测试结果:batch:200,准确率:0.927500
  6. 测试结果:batch:250,准确率:0.929800
  7. 测试结果:batch:300,准确率:0.939600
  8. 测试结果:batch:350,准确率:0.942100
  9. 测试结果:batch:400,准确率:0.950600
  10. 测试结果:batch:450,准确率:0.950700
  11. 测试结果:batch:500,准确率:0.956700
  12. 测试结果:batch:550,准确率:0.956000
  13. 测试结果:batch:600,准确率:0.957100
  14. 测试结果:batch:650,准确率:0.958400
  15. 测试结果:batch:700,准确率:0.961500
  16. 测试结果:batch:750,准确率:0.963800
  17. 测试结果:batch:800,准确率:0.965000
  18. 测试结果:batch:850,准确率:0.966300
  19. 测试结果:batch:900,准确率:0.967800
  20. 测试结果:batch:950,准确率:0.967700

迭代次数没有太多,否则准确率还会提高。

TensorFlow训练神经网络cost一直为0的更多相关文章

  1. 吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用滑动平均

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_NODE = 784 ...

  2. 吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用隐藏层

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_NODE = 784 ...

  3. 吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用激活函数

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_NODE = 784 ...

  4. 吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用指数衰减的学习率

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_NODE = 784 ...

  5. 吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用正则化

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_NODE = 784 ...

  6. 吴裕雄 python 神经网络——TensorFlow训练神经网络:全模型

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_NODE = 784 ...

  7. 吴裕雄 python 神经网络——TensorFlow训练神经网络:花瓣识别

    import os import glob import os.path import numpy as np import tensorflow as tf from tensorflow.pyth ...

  8. 吴裕雄 python 神经网络——TensorFlow训练神经网络:MNIST最佳实践

    import os import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_N ...

  9. Tensorflow训练神经网络

    以下代码摘自<Tensorflow实战Google 深度学习框架>. 由于这段代码包含了激活函数去线性化,多层神经网络,指数衰减学习率,正则化防止过拟合,滑动平均稳定模型等手段,涵盖了神经 ...

随机推荐

  1. 【LOJ】#2082. 「JSOI2016」炸弹攻击 2

    题解 想到n3发现思路有点卡住了 对于每个发射塔把激光塔和敌人按照极角排序,对于一个激光塔,和它转角不超过pi的激光塔中间夹的敌人总和就是答案 记录前缀和,用two-Points扫一下就行 代码 #i ...

  2. linux 安装redis4.0

    1.安装redis 第一步:下载redis安装包 wget http://download.redis.io/releases/redis-4.0.6.tar.gz 1 2 3 4 5 6 7 8 9 ...

  3. 命令:man

    简介 man命令,是manual的缩写,manual表示手册的意思.通过man命令,可以查询大多数shell外部命令的帮助手册. 语法格式 # man [[section] page ...] ... ...

  4. 使用ApiPost测试接口时需要先登录怎么办?利用Cookie模拟登陆!

    ApiPost简介: ApiPost是一个支持团队协作,并可直接生成文档的API调试.管理工具.它支持模拟POST.GET.PUT等常见请求,是后台接口开发者或前端.接口测试人员不可多得的工具 . 下 ...

  5. Ubuntu下登陆远程postgresql数据库

    登陆公司远程postgresql:psql -h <host or remote id> -p <port> dbdame 如: psql -h  aliyunsql_addr ...

  6. 初识thinkphp(2)

    thinkphp的url路径的表示格式为 http://ip/tp/public/index.php/模块/控制器/操作 这里url最后的操作就是类里面的函数. 0x01:url访问格式 官方文档中有 ...

  7. 懒人的福利?教你用set维护斜率优化凸包

    斜率优化题目大家肯定都做得不少了,有一些题目查询插入点的x坐标和查询斜率都不单调,这样就需要维护动态凸包并二分斜率.(例如bzoj1492) 常规的做法是cdq分治或手写平衡树维护凸包,然而如果我不愿 ...

  8. 【BZOJ5137】Standing Out from the Herd(后缀自动机)

    [BZOJ5137]Standing Out from the Herd(后缀自动机) 题面 BZOJ 洛谷 题解 构建广义后缀自动机 然后对于每个节点处理一下它的集合就好了 不知道为什么,我如果按照 ...

  9. bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列

    详见vfleaking在discuss里的题解. 收获: 当我们要顺序枚举一个序列,并且跳过某些元素,那么我们可以用并查集将要跳过的元素合并到一起,这样当一长串元素需要跳过时,可以O(1)跳过. 暴力 ...

  10. Git和Gitlab

    参考 http://www.cnblogs.com/clsn/p/7929958.html#auto_id_16https://backlog.com/git-tutorial/cn/intro/in ...