TensorFlow损失函数(loss function) 2017-08-14 11:32 125人阅读 评论(0) 收藏 举报 分类: 深度学习及TensorFlow实现(10) 版权声明:
2017-09-24 21:21
891 查看
TensorFlow损失函数(loss function)
2017-08-14 11:32 125人阅读 评论(0) 收藏 举报分类:
深度学习及TensorFlow实现(10)
版权声明:本文为博主原创文章,未经博主允许不得转载。
目录(?)[+]
神经网络模型的效果及优化的目标是通过损失函数来定义的。
1、经典损失函数
分类问题和回归问题是监督学习的两大种类。
分类问题
常用方法:交叉熵(cross_entropy),它描述了两个概率分布之间的距离,当交叉熵越小说明二者之间越接近。它是分类问题中使用比较广的一种损失函数。 给定两个概率分布p和q,通过q来表示p的交叉熵为:
H(p,q)=−∑xp(x)logq(x)
交叉熵刻画的是两个概率分布之间的距离,但是神经网络的输出却不一定是一个概率分布。概率分布刻画了不同事件发生的概率。当事件总数是有限的情况下,概率分布函数p(X=x)满足:
∀x p(X=x)∈[0,1]且∑xp(X=x)=1
如何将神经网络前向传播得到的结果变成概率分布,Softmax回归就是一个非常常用的办法。
Softmax回归本身可以作为一个学习算法来优化分类结果,但在TensorFlow中,Softmax回归的参数被去掉了,它只是一层额外的处理层,将神经网络的输出变成一个概率分布。下图展示了加上Softmax回归的神经网络结构图。
交叉熵作为神经网络的损失函数时,p代表的是正确答案,q代表的是预测值。交叉熵刻画的是两个概率分布的距离,交叉熵值越小,两个概率分布越接近。
案例:
有个三分类问题,样例正确答案(1,0,0)。
某模型经过Softmax回归之后的预测答案是(0.5,0.4,0.1),那么这个预测和正确答案之间的交叉熵为:
H((1,0,0),(0.5,0.4,0.1))=−(1×log0.5+0×log0.4+0×log0.1)≈0.3
另一个模型的预测是(0.8,0.1,0.1),那么这个预测和真实值之间的交叉熵是:
H((1,0,0),(0.8,0.1,0.1))=−(1×log0.8+0×log0.1+0×log0.1)≈0.1
从直观上可以很容易地知道第二个预测答案要优于第一个。通过交叉熵计算得到的结果也是一致的(第二个交叉熵的值更小)。
TensorFlow实现交叉熵,代码如下:
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))1
tf.clip_by_value函数可以将一个张量中的数值限制在一个范围内,这样就避免了一些运算错误(比如log0是无效的)。
y_:正确结果
y :预测结果
TensorFlow对交叉熵和softmax回归进行了统一封装,我们可以直接使用如下代码实现使用softmax回归后的交叉熵损失函数:
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(y,y_)1
回归问题
回归问题解决的是对具体数值的预测。比如房价预测、销量预测等都是回归问题。这些问题需要预测的不是一个事先定义好的类别,而是一个任意实数。解决回顾问题的神经网络一般只有一个输出节点,这个节点的输出值就是预测值。对于回归问题,最常用的损失函数是均方误差(MSE,mean squared error )。它的定义如下: MSE(y,y′)=∑ni=1(yi−y′i)2n
其中yi为一个batch中第i个数据的正确答案,而yi′为神经网络给出的预测值。
如下代码展示了如何通过TensorFlow实现均方误差损失函数:
mse = tf.reduce_sum(tf.square(y_ - y))1
其中y代表了神经网络的输出答案,y_代表了标准答案。
2、自定义损失函数
例:如果一个商品的成本是1元,但是利润是10元,那么少预测一个就少赚10元,而多预测一个少赚1元。 为了最大化预期利润,需要将损失函数和利润直接联系起来。下面公式给出了一个当预测多于真实值和预测少于真实值时有不同损失系数的损失函数:
Loss(y,y′)=∑i=1nf(yi,y′i),f(x,y)={a(x−y)x>yb(y−x)x≤y
yi为一个batch中第i个数据的正确答案,y′i为神经网络得到的预测值,
a(x−y)x>y表示正确答案多于预测答案的情况
b(y−x)x≤y表示正确答案少于预测答案的情况
TensorFlow实现这个损失函数:
a= 10 b= 1 loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_) * a, (y_ - y) * b))1
2
3
(tf.select已被舍弃,使用tf.where替代)
再看一个tf.where和tf.greater使用的例子
import tensorflow as tf v1 = tf.constant([1.0,2.0,3.0,4.0]) v2 = tf.constant([4.0,3.0,2.0,1.0]) sess = tf.InteractiveSession() print(tf.greater(v1,v2).eval()) print(tf.where(tf.greater(v1,v2),v1,v2).eval())1
2
3
4
5
6
7
8
输出:
[False False True True] [ 4. 3. 3. 4.]1
2
损失函数对训练结果的影响
下面通过一个简单的神经网络程序来讲解损失函数对模型训练结果的影响。下面代码实现了一个拥有两个输入节点、一个输出节点,没有隐藏层的神经网络。import tensorflow as tf from numpy.random import RandomState1
2
1.定义神经网络的相关参数和变量。
batch_size = 8 #两个输入节点 x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input") #回归问题一般只有一个输出节点 y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input') #定义了一个单层的神经网络前向传播过程,这里就是简单加权和 w1= tf.Variable(tf.random_normal([2, 1], stddev=1, seed=1)) y = tf.matmul(x, w1)1
2
3
4
5
6
7
8
2.设置自定义的损失函数。
#定义损失函数使得预测少了的损失大,于是模型应该偏向多的方向预测。 loss_less = 10 loss_more = 1 loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_) * loss_more, (y_ - y) * loss_less)) train_step = tf.train.AdamOptimizer(0.001).minimize(loss)1
2
3
4
5
3.生成模拟数据集。
#通过随机数生成一个模拟数据集 rdm = RandomState(1) X = rdm.rand(128,2) #设置回归的正确值为两个输入的和加上一个随机量。之所以要加上一个随机量是为了加入不可预测的噪音,否则不同#损失函数的意义就不大了,因为不同损失函数都会在能完全预测正确的时候最低。一般来说噪音为一个均值为0的小#量,所以这里的噪音设置为-0.05 ~ 0.05的随机数 Y = [[x1+x2+(rdm.rand()/10.0-0.05)] for (x1, x2) in X]1
2
3
4
5
4.训练模型。
with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS = 5000 for i in range(STEPS): start = (i*batch_size) % 128 end = (i*batch_size) % 128 + batch_size sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]}) if i % 1000 == 0: print("After %d training step(s), w1 is: " % (i)) print(sess.run(w1), "\n") print("Final w1 is: \n", sess.run(w1))1
2
3
4
5
6
7
8
9
10
11
12
输出:
Final w1 is: [[ 1.01934695] [ 1.04280889]]1
2
3
5.重新定义损失函数,使得预测多了的损失大,于是模型应该偏向少的方向预测。
loss_less = 11
loss_more = 10
loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_) * loss_more, (y_ - y) * loss_less))
train_step = tf.train.AdamOptimizer(0.001).minimize(loss)
with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS = 5000 for i in range(STEPS): start = (i*batch_size) % 128 end = (i*batch_size) % 128 + batch_size sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]}) if i % 1000 == 0: print("After %d training step(s), w1 is: " % (i)) print(sess.run(w1), "\n") print("Final w1 is: \n", sess.run(w1))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
输出:
Final w1 is: [[ 0.95525807] [ 0.9813394 ]]1
2
3
6.定义损失函数为MSE。
loss = tf.losses.mean_squared_error(y, y_) train_step = tf.train.AdamOptimizer(0.001).minimize(loss) with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS = 5000 for i in range(STEPS): start = (i*batch_size) % 128 end = (i*batch_size) % 128 + batch_size sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]}) if i % 1000 == 0: print("After %d training step(s), w1 is: " % (i)) print( sess.run(w1), "\n") print ("Final w1 is: \n", sess.run(w1))1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
输出:
Final w1 is: [[ 0.97437561] [ 1.0243336 ]]1
2
3
从上面三种不同的运行结果可看出,对于相同的神经网络,不同的损失函数会对训练得到的模型产生重要影响。
相关文章推荐
- 关于如何在java中实现中文首字母索引排序的问题 2016-08-25 15:14 86人阅读 评论(0) 收藏 举报 分类: Java(19) 版权声明:本文为博主原创文章,未经博主允许不得转载
- 基于live555的rtsp 客户端模块优化 标签: live555rtsp客户端 2014-11-14 09:24 980人阅读 评论(0) 收藏 举报 分类: 流媒体(16) 版权声明:本文
- 单例模式八种写法比较 2017-07-04 15:30 25人阅读 评论(0) 收藏 举报 分类: Android移动互联(19) 版权声明:本文为博主原创文章,未经博主允许不得转载。 目录
- EventBus使用详解(二)——EventBus使用进阶 2014-11-04 16:45 88833人阅读 评论(81) 收藏 举报 分类: 5、andriod开发(149) 版权声明:本文
- WINDOWS中NEXUS的安装使用【ATCO整理】 2016-06-20 15:52 367人阅读 评论(0) 收藏 举报 分类: 项目管理(11) 版权声明:本文为博主原创文章,未经博主允许
- STM32 use microlib是干什么的 2016-04-25 23:13 1298人阅读 评论(0) 收藏 举报 分类: STM32(15) 版权声明:本文为博主原创文章,未经博主允许
- Gradle命令和配置 标签: AndroidGradle命令配置 2016-03-11 09:32 17174人阅读 评论(5) 收藏 举报 分类: 开发工具(9) 版权声明:本文为博主原创文
- iOS大文件分片上传和断点续传 标签: iOS大文件分片断点续传获取视频获取图片 2016-05-17 15:52 4881人阅读 评论(8) 收藏 举报 分类: 技术—iOS 版权声明:本文为博
- 关于悲观锁和乐观锁的区别(最直观理解) 2015-11-23 11:59 5105人阅读 评论(1) 收藏 举报 分类: 数据库(20) 版权声明:本文为博主原创文章,未经博主允许不得转载。
- 系统学习深度学习(七)--主流深度学习开源框架对比 2017-01-23 11:05 2292人阅读 评论(0) 收藏 举报 分类: 深度学习(30) 目录(?)[+] 转自:http://b
- Python实现基于朴素贝叶斯的垃圾邮件分类 标签: python朴素贝叶斯垃圾邮件分类 2016-04-20 15:09 2750人阅读 评论(1) 收藏 举报 分类: 机器学习(19) 听说
- 如何辨别密码安全糟糕的网站 分类: 软件插件学习 2015-05-08 11:32 54人阅读 评论(0) 收藏
- 关于Android 5.1限制外置SD卡写入权限的破解方法 标签: Android 5.1SD卡写入权限 2017-06-15 10:06 1374人阅读 评论(0) 收藏 举报 版权声明:本文为
- Android 中查看内存的使用情况集常用adb命令 标签: Androidadb 2014-06-28 10:55 57206人阅读 评论(0) 收藏 举报 分类: Android(9) 版权声
- 函数名function是一个数据类型,可以赋值 分类: python基础学习 2013-09-12 11:01 366人阅读 评论(0) 收藏
- 深度学习基础(五)Softmax Regression 分类: 深度学习 2015-02-28 10:28 42人阅读 评论(0) 收藏
- django-mysql 中的金钱计算事务处理 分类: 小技巧 python学习 mysql 2015-07-27 16:52 10人阅读 评论(0) 收藏
- 深度学习基础(一)神经网络 分类: 深度学习 2015-01-19 21:29 84人阅读 评论(0) 收藏
- 关于c语言中的复杂原型声明 分类: 嵌入式开发学习 2011-07-18 23:04 534人阅读 评论(1) 收藏
- android屏幕页面实现滚动,页面跳… 分类: Android开发 2014-05-30 10:58 58人阅读 评论(0) 收藏