200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 【深度学习】(4) 梯度下降 损失函数

【深度学习】(4) 梯度下降 损失函数

时间:2020-01-11 12:46:31

相关推荐

【深度学习】(4) 梯度下降 损失函数

各位同学好,今天和大家介绍一下TensorFlow2.0中的梯度下降、激活函数及其梯度、损失函数及其梯度。

(1) 梯度计算:GradientTape(),tape.watch(),tape.gradient()

(2) 损失函数及其梯度:MSE:tf.reduce_mean(tf.losses.MSE()),交叉熵:tf.losses.categorical_crossentropy()

1. 梯度下降

1.1 自动求导函数:

GradientTape(persistent=False, watch_accessed_variables=True)

persistent:布尔值,用来指定新创建的gradient tape是否是可持续性的。默认是False,意味着只能够调用一次GradientTape()函数。

watch_accessed_variables:布尔值,表明GradientTape()函数是否会自动追踪任何能被训练的变量。默认是True。要是为False的话,意味着你需要手动去指定你想追踪的那些变量。

1.2 监视非Variable变量

tape.watch(tensor)

tape.watch()用于跟踪指定的tensor变量。由于GradientTape()默认只对tf.Variable类型的变量进行监控。如果需要监控的变量是tensor类型,则需要tape.watch()来监控,若是没有watch函数则梯度计算结果会是None。 如果指定跟踪的是tf.Variable类型,这一句就不用写了。

1.3 梯度计算

tape.gradient(target, sources, unconnected_gradients)

根据指定监视的变量来计算梯度

target:求导的因变量

sources:求导的自变量

unconnected_gradients:无法求导时,返回的值,有两个可选值[none, zero],默认none。

import tensorflow as tfw = tf.constant(1.) # 创建全连接层x = tf.constant(2.) # 创建输入特征# 自动求导with tf.GradientTape() as tape:tape.watch([w]) # 监视wy = x*w # 计算梯度,因变量y,自变量wgrad1 = tape.gradient(y,[w])# 结果为: [<tf.Tensor: shape=(), dtype=float32, numpy=2.0>]

创建的权重w是tensor类型,需要tape.watch()函数,如果改成w = tf.Variable(tf.constant(1.)),将w变成Variable类型,就不需要tape.watch()函数来监视w。y=x*w,y对w求导结果为x,即为2.0。

3. 损失函数及其梯度

3.1 均方误差MSE

计算公式:

y代表训练集的真实值,pred代表训练输出的预测结果,N通常指的是batch_size,也有时候是指特征属性个数。

MSE函数表示:

(1)tf.reduce_mean(tf.square(y - pred))

(2)tf.reduce_mean(tf.losses.MSE(y, pred))

一般而言,均方误差损失函数比较适用于回归问题中,对于分类问题,特别是目标输出为One-hot向量的分类任务中,交叉熵损失函数要合适的多。

import tensorflow as tf# 设有一组训练集的目标值y = tf.constant([1,2,3,0,2]) y = tf.one_hot(y, depth=4) # 目标为四种分类y = tf.cast(y,dtype=tf.float32)# 设有一组模型输出的预测结果数据out = tf.random.normal([5,4])# 三种方法计算,预测结果out和真实值y之间的损失MSEloss1 = tf.reduce_mean(tf.square(y-out)) # 1.2804947loss2 = tf.square(tf.norm(y-out))/(5*4) # 1.2804947 #二范数方法loss3 = tf.reduce_mean(tf.losses.MSE(y,out)) # 1.2804947# 返回shape为[b]的tensor

3.2 MSE的梯度

使用tf.reduce_mean(tf.losses.MSE())计算真实值和预测结果的均方差,需要对真实值y进行one-hot编码tf.one_hot(),对应索引位置的值为1,分成三个类别depth=3。prob输出的也是图片属于三种分类的概率。使用tape.gradient()函数对跟踪的变量求梯度,grads[0]因变量为loss,自变量为w。

import tensorflow as tf#(1)均方差MSEx = tf.random.normal([2,4]) # 创建输入层,2张图片,各有4个特征w = tf.random.normal([4,3]) #一层全连接层,输出每张图片属于3个分类的结果b = tf.zeros([3]) # 三个偏置y = tf.constant([2,0]) # 真实值,第一个样本属于2类别,第2个样本属于0类别#梯度计算with tf.GradientTape() as tape:tape.watch([w,b]) # 指定观测w和b,如果w和b时variable类型,就不需要watch了prob = tf.nn.softmax(x@w+b, axis=1) #将实数转为概率,得到属于3个节点的概率# 计算两个样本损失函数的均方差loss = tf.reduce_mean(tf.losses.MSE(tf.one_hot(y,depth=3),prob))# 求梯度grads = tape.gradient(loss,[w,b])grads[0] # loss对w的梯度grads[1] # loss对b的梯度

3.3 交叉熵

交叉熵(Cross Entropy)主要用于度量两个概率分布间的差异性信息,交叉熵越小,两者之间差异越小,当交叉熵等于0时达到最佳状态,也即是预测值与真实值完全吻合。

公式为:

式中,p(x)是真实分布的概率,q(x)是模型输出的预测概率。log的底数为2。

(1) 多分类问题交叉熵

tf.losses.categorical_crossentropy(y_true, y_pred, from_logits=False)

y_true:真实值,需要one-hot编码

y_pred:预测值,模型输出结果

from_logits:为True时,会使用softmax函数将y_pred从实数转化为概率值,通常情况下用True结果更稳定

# 多分类# 真实值和预测概率,预测结果均匀,交叉熵1.38很大tf.losses.categorical_crossentropy([0,1,0,0],[0.25,0.25,0.25,0.25])# 预测错了,交叉熵2.3tf.losses.categorical_crossentropy([0,1,0,0],[0.1,0.1,0.7,0.1])# 预测对了,交叉熵为0.35tf.losses.categorical_crossentropy([0,1,0,0],[0.1,0.7,0.1,0.1])

(2) 二分类问题交叉熵

tf.losses.binary_crossentropy()

参数见:TF2.0—tf.keras.losses.BinaryCrossentropy_哎呦-_-不错的博客-CSDN博客

# 二分类# 预测对了,0.1tf.losses.binary_crossentropy([1,0],[0.9,0.1])# 预测错了,2.3tf.losses.categorical_crossentropy([1,0],[0.1,0.9])

(3) logits层直接计算交叉熵

模型的输出结果可能不是概率形式,通过softmax函数转换为概率形式,然后计算交叉熵,但有时候会出现数据不稳定的情况,即输出结果是NAN或者inf。

这种情况下可以通过logits层直接计算交叉熵,不过要给categorical_crossentropy()方法传递一个from_logits=True参数。

# 计算网络损失时,一定要加数值稳定处理参数from_logits=True,防止softmax和crossentropy之间的数值不稳定import tensorflow as tfx = tf.random.normal([1,784]) # 1张图片784个特征w = tf.random.normal([784,2]) # 全连接层,分为2类b = tf.zeros([2]) # 2个偏置logits = x@w + b # 计算logits层# 不推荐使用下面这种,会出现数值不稳定# 输出结果映射到0-1,且概率和为1,(这一步由from_logits=True代替)# prob = tf.math.softmax(logits,axis=1)# tf.losses.categorical_crossentropy([[0,1]],prob)# 计算交叉熵,一定要对y_true进行onehot编码tf.losses.categorical_crossentropy([[0,1]],logits,from_logits=True)

3.4 交叉熵的梯度

损失函数为计算交叉熵的平均值,一定要对训练集真实值y_true进行one-hot编码,分三类,tf.one_hot(y,depth=3),跟踪权重w和偏置b,grads[0]为以loss为因变量,w为自变量计算梯度。grads[1]为以loss为因变量,b为自变量计算梯度

#(2)交叉熵cross entropy# softmax,使logits数值最大的所在的所有作为预测结果的labelx = tf.random.normal([2,4]) # 输入层,2张图片,4个特征w = tf.random.normal([4,3]) # 一层全连接层,输出三个分类b = tf.zeros([3]) # 三个偏置y = tf.constant([2,0]) # 第一个样本属于2类别,第2个样本属于0类别# 梯度计算with tf.GradientTape() as tape:tape.watch([w,b]) # 跟踪w和b的梯度logits = x @ w + b # 计算logits层# 计算损失,不要先softmax再使用交叉熵,会导致数据不稳定,categorical_crossentropy会自动执行softmax操作再计算损失loss = tf.reduce_mean(tf.losses.categorical_crossentropy(tf.one_hot(y,depth=3),logits,from_logits=True))# 计算损失函数梯度grads = tape.gradient(loss,[w,b])grads[0] #shape为[4,3]grads[1] #shape为[3]# 结果为grads[0]:array([[ 0.05101332, 0.08121025, -0.13222364],[ 0.1871956 , -0.02524163, -0.16195397],[-1.6817021 , 0.17055441, 1.5111479 ],[-0.08085182, 0.06344394, 0.01740783]], dtype=float32)># grads[1]:<tf.Tensor: shape=(3,), dtype=float32, numpy=array([-0.12239906, 0.08427953, 0.03811949], dtype=float32)>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。