tensorflow 基础学习三:损失函数讲解

交叉熵损失:

给定两个概率分布p和q,通过q来表示p的交叉熵为:

从上述公式可以看出交叉熵函数是不对称的,即H(p,q)不等于H(q,p)。

交叉熵刻画的是两个概率分布之间的距离,它表示通过概率分布q来表示概率分布p的困难程度。所以使用交叉熵作为

神经网络的损失函数时,p代表的是正确答案,q代表的是预测值。当两个概率分布越接近时,它们的交叉熵也就越小。

由于神经网络的输出并不是一个概率分布,所以需要先使用softmax将网络输出变成一个概率分布,再计算交叉熵。

比如,原始的神经网络输出为y1,y2,……,yn,那么经过softmax处理后的输出为:

小例子:

以一个三分类为例,比如某个样本正确答案为(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)))

其中y_代表正确结果,y代表预测结果。tf.clip_by_value函数可以将一个张量中的数值限制在一个范围内,这样可以避免

一些运算错误(比如log0是无效的)。下面讲解使用tf.clip_by_value函数的简单样例。

v=tf.constant([[1.0,2.0,3.0],[4.0,5.0,6.0]])
with tf.Session() as sess:
    print(tf.clip_by_value(v,2.5,4.5).eval())
'''
输出为
[[ 2.5  2.5  3. ]
 [ 4.   4.5  4.5]]
'''
# tensorflow中提供的直接计算交叉熵损失的函数,y代表神经网络的输出结果,y_表示真实类别
cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=y,y_)

均方误差(MSE,mean squared error):

常用于回归问题中。它的具体定义如下:

$MES(y,y^{'})=\frac{\sum _{i=1}^{n}(y_{i}-y_{i}^{'})^{2}}{n}$

   其中,yi表示一个batch中第i个样本的真实类别,yi'为神经网络输出的预测值。tensorflow代码实现如下:

mse=tf.reduce_mean(tf.square(y_-y))

 

自定义损失函数:

tensorlfow支持自定义损失函数,以下演示一个简单的示例:

首先定义一个分段损失函数,然后提供它的代码实现:

$Loss(y,y^{'})=\sum_{i=1}^{n}f(y_{i},y_{i}^{'}), f(x,y)=\left\{\begin{matrix}a(x-y)
 & x>y \\
 b(y-x) & x\leqslant y
\end{matrix}\right. $

loss=tf.recue_sum(tf.where(tf.greater(v1,v2),(v1-v2)*a,(v2-v1)*b))

tf.where和tf.greater函数用法如下:

# tf.where和tf.greater函数的用法
v1=tf.constant([1.0,2.0,3.0,4.0])
v2=tf.constant([4.0,3.0,2.0,1.0])

with tf.Session() as sess:
    print(tf.greater(v1,v2).eval())
    # 输出 [False False  True  True]
    print(.where(tf.greater(v1,v2),v1,v2).eval())
    # 输出 [ 4.  3.  3.  4.]

 使用自定义损失函数实现一个简单的神经网络

该网络只有两个输入节点和一个输出节点,相当于实现了一个回归。

import tensorflow as tf
from numpy.random import RandomState

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)

# 使用上述自己定义的损失函数
a=1;b=10
loss=tf.reduce_sum(tf.where(tf.greater(y,y_),(y-y_)*a,(y_-y)*b))

train_step=tf.train.AdamOptimizer(0.001).minimize(loss)

# 随机生成一个模拟数据集
rdm=RandomState(1)
dataset_size=128
X=rdm.rand(dataset_size,2)
# 设置随机噪声,范围在-0.05~0.05
Y = [[x1+x2+rdm.rand()/10.0-0.05] for (x1,x2) in X]

# 训练神经网路
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) % dataset_size
        end = min(start+batch_size,dataset_size)
        sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})
    print(sess.run(w1))

 

posted @ 2017-12-16 22:23  blackx  阅读(12474)  评论(2编辑  收藏  举报