tensorflow-深度学习之损失函数总结

本篇文章介绍一下tensorflow中必须要掌握的基础知识点,就是损失函数,因为最终训练迭代优化就是损失函数,那么总体来说它可以分为两大类:

1 以回归为主:MSE-均方根误差

2 以分类为主:SOFTMAX-交叉熵

3 根据特定场景:自定义损失函数

接下来我们具体来通过代码讲解每种具体的实例:

首先我们看一下均方根误差-MSE

import tensorflow as tf
session = tf.InteractiveSession()

y_ = tf.constant([1,2,3],dtype=tf.float32,shape=[3,1])
y1 = tf.constant([1,2,3],dtype=tf.float32,shape=[3,1])
y2 = tf.constant([3,5,5],dtype=tf.float32,shape=[3,1])

#先求差的平方,然后再求平均
mes = tf.reduce_mean(tf.square(y2-y_))

# reduce_sum 使用它的目的 如果当求差的平法之后是一个向量,需要先用这个函数求和
mes1 = tf.reduce_mean(tf.reduce_sum(tf.square(y2-y_)))

print(session.run(mes))
print(session.run(mes1))

关于交叉熵有两种使用方法,一种是自定义交叉熵,一种是使用tensorflow自带的几种,接下来分别来讲解

& 自定义交叉熵

import tensorflow as tf
session = tf.InteractiveSession()

y_ = tf.constant([[1.0, 0, 0]]) # 正确标签
y1 = tf.constant([[0.9, 0.06, 0.04]]) # 预测结果1
y2 = tf.constant([[0.5, 0.3, 0.2]]) # 预测结果2
# 自定义交叉熵
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y1, 1e-10, 1.0)))
print('cross_entropy',cross_entropy)

clib_by_value为了防止出现log0这种情况,还有不要忘记前面的'-',实际使用中建议使用tf自带的损失函数

& tensorflow自带实现的交叉熵

# -*- coding: utf-8 -*-
import tensorflow as tf
session = tf.InteractiveSession()

y_ = tf.constant([[1.0, 0, 0]]) # 正确标签
y3 = tf.constant([[10.0, 3.0, 2.0]])
y4 = tf.constant([[5.0, 3.0, 1.0]])

# 该操作应该施加在未经过Softmax处理的logits上,否则会产生错误结果
# labels为期望输出,且必须采用labels=y_, logits=y的形式将参数传入
cross_entropy_v2_1 = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y3)
cross_entropy_v2_2 = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y4)

print('v2_1', cross_entropy_v2_1.eval())
print('v2_2',cross_entropy_v2_2.eval())

我们举了其中的一个实现方法讲解,其实它提供了几大类,分别对应不同的场景实现:

# 基于单标签多分类
tf.nn.softmax_cross_entropy_with_logits()
#基于单标签单分类
tf.nn.sparse_softmax_cross_entropy_with_logits()
#基于多标签多分类
tf.nn.sigmoid_cross_entropy_with_logits()
# 基于权重的损失函数
tf.nn.weighted_cross_entropy_with_logits()
# 基于词向量的NCE
tf.nn.nce_loss()

注意:前4个函数,返回的不是一个具体的数值,而是一个向量,所以如果要求交叉熵需要使用tf.reduce_sum()进行求和,如果还想求解最终的loss,需要再使用tf.reduce_mean()....

& 自定义损失函数:这个根据业务场景可以很简单也可以很复杂,接下来我们看一个比较简单的使用场景

# -*- coding: utf-8 -*-

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)


#自己定义损失函数
# 如果y>y_ (y-y_)* 1
# 如果y<=y_ (y_-y)*10
# 根据loss结果可以自动调节这个计算方式和系数的值
loss=tf.reduce_sum(tf.where(tf.greater(y,y_),(y-y_)*1,(y_-y)*10))

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))
通过上面自定义的损失函数可以发现,最后的输出结果的参数会略大于1,而我们在定义实际的输出结果是x1+x2+随机数,参数值应该都为1。因为,我们在使用损失函数的时候,指定了当预测少的损失更大,所以预测值会比实际值要大一些。如果,我们指定损失函数的时候,指定预测多的损失更大,那么所求得的参数值将会略小于1。通过自定义损失函数,来更好的满足我们实际的模型需要,从中可以发现,损失函数对一个模型的重要性。

你可能感兴趣的:(tensorflow-深度学习之损失函数总结)