Tensorflow交叉熵计算错误
2016-07-29 17:48
781 查看
转载请标明出处:小帆的帆的专栏
当a = y = 0.0, y * np.log(a) = 0 * -inf = nan
当a = y = 1.0, (1 - y) * np.log(1 - a) = 0 * -inf = nan
出现nan的核心原因是log(0.0) = -inf, 所以a的取值才是关键
而通常情况下a趋向0时, y多数就会等于0, 所以0 * -inf = nan
不过a=0, y=1也是有可能出现的, 就是初始化时, a就与y截然相反.之后就不会再出现了, 因为优化总是往好的方向走.
方法1. a加上一个极小值
方法2. 当a接近0时, 给a一个极小值
方法3. 出现nan时, 设置成本为0
出现错误的原因
-y * np.log(a) - (1-y) * np.log(1 - a)当a = y = 0.0, y * np.log(a) = 0 * -inf = nan
当a = y = 1.0, (1 - y) * np.log(1 - a) = 0 * -inf = nan
出现nan的核心原因是log(0.0) = -inf, 所以a的取值才是关键
而通常情况下a趋向0时, y多数就会等于0, 所以0 * -inf = nan
不过a=0, y=1也是有可能出现的, 就是初始化时, a就与y截然相反.之后就不会再出现了, 因为优化总是往好的方向走.
Tensorflow的处理方法
下面的代码中, 用了三种方法解决这个问题, 并对比了速度和精确度方法1. a加上一个极小值
方法2. 当a接近0时, 给a一个极小值
方法3. 出现nan时, 设置成本为0
结论
方法1速度最快, 并且精确度与另两种方法相当分析代码
# coding=utf-8 import tensorflow as tf import time NEAR_0 = 1e-10 ZERO = tf.constant(0.0) def cross_entropy(y, a): return sess.run(-(y * tf.log(a) + (1 - y) * tf.log(1 - a))) def method1(y, a): return sess.run(-(y * tf.log(a + NEAR_0) + (1 - y) * tf.log(1 - a + NEAR_0))) def method2(y, a): return sess.run(-(y * tf.log(nan_to_num(a)) + (1 - y) * tf.log(nan_to_num(1 - a)))) def method3(y, a): return sess.run(nan_to_zero(-(y * tf.log(a) + (1 - y) * tf.log(1 - a)))) def nan_to_num(n): return tf.clip_by_value(n, NEAR_0, 1) def nan_to_zero(c): # tensorflow 条件语法 https://www.tensorflow.org/versions/r0.7/api_docs/python/control_flow_ops.html#cond # 后面两个参数要是方法 return tf.cond(tf.is_nan(c), lambda: ZERO, lambda: c) sess = tf.Session() # 会出现nan的主要有两处 # 1. y和a都是0 # 2. y和a都是1 # 也就是loss很小的时候 # 而y=1, a=0, 或者a=1, y=1, 只有开刚开始优化的时候可能出现, 后面loss都会往好的方向走. # log(0.0) = -inf 负无穷 print '交叉熵:' print cross_entropy(0.0, 0.0) # y * tf.log(a) : 0.0 * -inf = nan print cross_entropy(1.0, 1.0) # (1 - y) * tf.log(1 - a) : 0.0 * -inf = nan print '\n方法一:' # 方法1: 加上一个接近0的数 print method1(0.0, 0.0) print method1(1.0, 1.0) print '\n方法二:' # 方法2: 当a比1e-10还小时, 等于1e-10 print method2(0.0, 0.0) print method2(1.0, 1.0) print '\n方法三:' # 方法3: 出现nan, 赋值为0 print method3(0.0, 0.0) print method3(1.0, 1.0) # 哪种方法更好 # 1. 速度, 方法1, 胜 # 方法1, 每次都加一个数 # 方法2, 每次都要比较大小 # 方法3, 不好说 # 结论, 加一个数计算成本更低, 所有速度更快 start_time = time.time() for i in xrange(100): method1(0.0, 0.0) duration = time.time() - start_time print '\n方法1用时: {0}'.format(duration) start_time = time.time() for i in xrange(100): method2(0.0, 0.0) duration = time.time() - start_time print '\n方法2用时: {0}'.format(duration) start_time = time.time() for i in xrange(100): method3(0.0, 0.0) duration = time.time() - start_time print '\n方法3用时: {0}'.format(duration) # 2. 精确度 # 方法1, 无论什么数, 都要加个1e-10 # 方法2, 只有小于1e-10时, 才会起作用 # 方法3, 出现nan, 才会起作用 # 总结, 理论上方法二, 三肯定是更精确, 但是实际看不到任何差别 print '\n' print '%.100f' % (0.5 + 1e-10) print '%.100f' % sess.run(tf.clip_by_value(0.5, 1e-10, 1)) print '\n' print '%.100f' % method1(1.0, 0.5) print '%.100f' % method2(1.0, 0.5) print '%.100f' % method3(1.0, 0.5)
相关文章推荐
- TensorFlow 的简单例子
- 用Python从零实现贝叶斯分类器的机器学习的教程
- My Machine Learning
- 机器学习---学习首页 3ff0
- Spark机器学习(一) -- Machine Learning Library (MLlib)
- CUDA搭建
- 反向传播(Backpropagation)算法的数学原理
- 稀疏自动编码器 (Sparse Autoencoder)
- 白化(Whitening):PCA vs. ZCA
- softmax回归
- 卷积神经网络初探
- 关于SVM的那点破事
- 也谈 机器学习到底有没有用 ?
- #ML-SDN
- TensorFlow人工智能引擎入门教程之九 RNN/LSTM循环神经网络长短期记忆网络使用
- TensorFlow人工智能引擎入门教程之十 最强网络 RSNN深度残差网络 平均准确率96-99%
- 人工智能扫盲漫谈篇 & 2018年1月新课资源推荐
- 人工智能唐宇迪老师专题团购~史无前例最低优惠~
- 【超大福利】 4.18-4.20日IT充电节,超级讲师带来免费技术公开课盛宴