cross_entropy = -tf.reduce_mean( y_* tf.log(tf.clip_by_value(y,1e-10,1.0)))#交叉熵含义

转载:https://blog.csdn.net/weixin_38195506/article/details/75302445

神经网络模型的效果以及优化目标是通过损失函数(loss function)来定义的。分类问题和回归问题有很多经典的损失函数。 
分类问题和回归问题是监督学习的两大种类。 
分类问题希望解决的是将不同的样本分到事先定义好的类别中。再这种问题下,需要将样本二分类(多分类)。手写字体识别就是一个十分类的问题。 
再判断二分类问题的时候,可以定义一个有单个输出节点的神经网络,当这个节点输出越接近1(或者设定的其他条件)就越可能是合格这类(或定义的其他类),越接近0(或其他条件),就越可能是另一个类。为了给出具体的分类,通常需要给出一个阈值。然而这样的做法并不容易推广到多分类的问题,虽然设置多个阈值理论上是可能的,但是实际问题上并不容易操作。 
通过神经网络解决多分类问题最常用的方法是设置n个输出节点,其中n为类别的个数,每一个样例,神经网络可以得到一个n维数组作为输出结果。数组终端每一个维度(也就是每一个输出节点)对应一个类别。 
以识别数字为例: 
再理想情况下,如果一个样本属于类别k,那么这个类别所对应输出结果越接近[0,0,0,0,1,0,0,0,0,0]越好。那么如何判断一个输出向量和期望的向量有多接近呢? 
答案是交叉熵(cross entropy)。 
交叉熵是常用的评判方法之一。交叉熵刻画了两个概率分布之间的距离,他是分类问题中使用比较广泛的损失函数。 
交叉熵是信息论中的概念,它原本是用来估算平均编码长度的。 
给定两个概率分布p和q,用q来表示p的交叉熵为: 
 
注意交叉熵刻画的是两个概率分布之间的距离,然而神经网络的输出却不一定是一个概率分布。概率分布刻画了不同事件发生的概率。当事情总数是有限的情况下,概率分布函数p(X=x)满足: 
 
也就是说,任意事件发生的概率都在[0,1]之间,且总有某一个事件发射那个(概率和为1)。如果将分类问题中“一个样例属于某一类别”看成一个概率事件,那么训练数据的正确答案就符合一个概率分布。因为事件“一个样例属于不正确的类别”的概率为0,而“一个样例属于正确的类别”概率为1. 
如何将神经网络前向传播得到的结果也变成概率分布呢?Softmax回归就是一个很常用的方法。 
Softmax回归本身可以作为一个学习算法来优化分类结果,但在tensorflow中,Softmax回归的参数被去掉了,它至少一层额外的处理层,将神经网络的输出变成一个概率分布。 
 
 
原始神经网络的输出被用作置信度来生成新的输出,而新的输出满足概率分布的所有要求。这个新的输出可以理解为经过神经网络的推导,一个样例为不同类别的概率分别是多大。这样就把一个神经网络的输出变成一个概率分布,从而可以通过交叉熵(loss function)来计算预测的概率分布和真实答案的概率分布之间的距离了。 
从交叉熵的公式中可以看出交叉熵函数不是对称的(H(p,q)≠H(q,p)),它刻画的是通过概率分布q来表达概率分布p的困难程度。因为正确答案是希望得到的结果,所以当交叉熵作为神经网络的损失函数时,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.1 
从直观上就可以容易地知道第二个预测答案是要优于第一个的。通过交叉熵计算得到的结果也是一致的(第二个交叉熵的值更小) 
tf.clip_by_value(t, clip_value_min, clip_value_max, name=None) 
基于定义的min与max对tesor数据进行截断操作,目的是为了应对梯度爆发或者梯度消失的情况.

Tensorflow中交叉熵代码形式是: 
cross_entropy=-tf.reduce_mean( 
                y_*tf.log(tf.clip_by_value(y,1e-10,1.0))) 
其中y_代表真确结果,y代表预测结果。通过tf.clip_by_value()函数将一个张量中是数值限制在一个范围之内,避免一些错误运算。下面是tf.clip_by_value()函数的一个例子: 
 
从样例中我们可以看到小于2.5的都被替换成了2.5,大于4.5的都被替换成了4.5,这样通过tf.clip_by_value()函数就可以保证在进行log运算时,不会出现log0这样的错误或者大于1的概率。 
tf.log函数,这个函数完成了对张量所有元素依次求对数的功能。 
 
值得注意的是,在tensorflow中,*代表的是矩阵元素相乘,而想要实现矩阵乘法需要用到tf.matmul()函数。

通过tf.clip_by_value、tf.log、*、三个运算后,得到了一个n×m的二维矩阵,其中n为一个batch中样例的数量,m为分类的类别数量。根据交叉熵公式,应该将每行中的m个结果相加得到的所有样例的交叉熵,然后在取平均值,得到一个batch的平均交叉熵。 
因为分类问题的类别数量是不变的,所以可以直接对整个矩阵做平均而并不改变计算结果的意义。 
tf.reduce_mean()函数使用方法为: 
 
因为交叉熵一般会与softmax回归一起使用,所以Tensorflow对这两个功能进行了同一封装,并提供了tf.nn.softmax_cross_entropy_with_logits()函数。比如可以直接通过下面的代码实现使用softmax回归之后的交叉熵损失函数: 
 
其中y代表了原始神经网络的输出结果,而y_给出了标准答案。这样通过一个命令就可以使用softmax回归之后的交叉熵了。在只有一个正确答案的分类问题中,Tensorflow提供了tf.nn.sparse_softmax_cross_entropy_with_logits函数来进一步加速计算过程。

与分类问题不同,回归问题解决的是对具体数值的预测。这些问题需要预测的不是一个事先定义好的类别,而是一个任意实数。解决回归问题的神经网络一般只有一个输出节点,这个节点的输出值是预测值。对于回归问题,最常用的损失函数是均方误差(MSE,mean squared error): 
 
其中y是正确数据,而y’是神经网络给的预测值。 
mse=tf.reduce_mean(tf.square(y_-y)),其中y代表了神经网络的输出答案,y_代表了标准答案。
--------------------- 
作者:魂小猫 
来源:CSDN 
原文:https://blog.csdn.net/weixin_38195506/article/details/75302445 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

以下是一个代码测试:

import tensorflow as tf

from numpy.random import RandomState

batch_size = 8

w1 = tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2 = tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))

# x = tf.constant([[0.7,0.9]])
x = tf.placeholder(tf.float32,shape=(None,2),name='x-input')
y_ = tf.placeholder(tf.float32,shape=(None,1),name='y-input')

a = tf.matmul(x,w1)
y = tf.matmul(a,w2)

cross_entropy = -tf.reduce_mean(
    y_* tf.log(tf.clip_by_value(y,1e-10,1.0)))#交叉熵
train_step = tf.train.AdadeltaOptimizer(0.001).minimize(cross_entropy)

rdm =RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size,2)

Y = [[int(x1+x2 <1)] for (x1,x2) in X]

with tf.Session() as sess:
    init_op = tf.initialize_all_variables()
    sess.run(init_op)
    print(sess.run(w1))
    print(sess.run(w2))
    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]})
        if i % 1000 == 0:
            total_cross_entropy = sess.run(
                cross_entropy, feed_dict={x: X, y_: Y}
            )
            print("After %d training step(s),cross entropy on all data is %g" %
                  (i, total_cross_entropy))
    print(sess.run(w1))
    print(sess.run(w2))

 

你可能感兴趣的:(cross_entropy = -tf.reduce_mean( y_* tf.log(tf.clip_by_value(y,1e-10,1.0)))#交叉熵含义)