IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> tf.keras.losses函数参数(from_logits、label_smoothing...) -> 正文阅读

[人工智能]tf.keras.losses函数参数(from_logits、label_smoothing...)

tf.keras.losses实例是用来计算真实标签( y_true )和预测标签之间( y_pred )的Loss损失。

参数

from_logits

是否将 y_pred 解释为 logit 值的张量。 默认情况下,假设 y_pred 包含概率(即 [0, 1] 中的值)。即默认情况下from_logits的值为False

解释一下logit值的含义:逻辑回归一般将因变量二分类变量的0-1转变为频率[0,1]也就是分类为1的概率,进而变成优势比odds( odds=P/(1-P) ,[0,+∞] ),然后log一下成为Logit值( 即?Logit=log(odds) ),值域为?[-∞,+∞]?),于是可以理解有时候我们遇到的 y_pred标签值为一些[0,1]之外的无穷大的数。例如:

y_pred = [-18.6, 0.51, 2.94, -12.8]

以P为因变量的Logit函数,反过来求概率P的反函数即为sigmoid函数(sigmoid(x)=1/1+e^(-x) ,即概率P=1/1+e^(-Logit) )。

在二分类中sigmoid函数较为常用,softmax函数常用于多分类任务。

对于多标签输入softmax函数能保证它们的映射之和为1,而sigmoid函数不能保证。
简单来说,from_logits的值为True的?y_pred的标签,首先应该使用sigmoid或者softmax函数计算后,再计算loss损失。

label_smoothing

即标签平滑,是一种正则化方法,用于分类问题,防止模型在训练时过拟合,改善泛化能力差的问题。

那么为什么需要标签平滑呢?以二分类为例,设训练数据为形如(x,y)的集合,其中x为数据,y为真实标签( y_true ),p(x)指预测标签 (y_pred) 即预测的概率,一般情况下真实标签( y_true )已经标注好样本所属类别

y_pred = [0.7, 0.5, 0.6, 0.8]
y_true = [0, 1, 0, 1] #样本0,1,2,3分别属于第0,1,0,1类

以BinaryCrossentropy损失函数为例,N代表样本的大小,如上代码中N=4:

Loss=-\frac{1}{N}\sum_{i=1}^{N}y_{i}\cdot log\left ( p(x_{i}) \right )+(1-y_{i})\cdot log\left ( 1-p(x_{i}) \right )

在训练期间,对于这些训练数据对应的 y_true 标签不能保证完全正确,如果恰好该样本的 y_true是错的,训练就会对模型产生消极影响。

不做出处理的话,这样的标签计算对于样本而言,无论属于类0还是1,都只计算了一种情况,就是说这样鼓励模型目标类别的概率趋近于1,非目标类别的概率趋近0。但事实上这样做产生的消极影响会模型过分自信的相信原训练数据集,遇到训练数据中没有覆盖的数据时,就无从下手,导致网络过拟合,泛化能力差。

为了处理这种情况,我们以1-α的概率认为原样本是对的,以α的概率认为原样本是错的(即α的概率(x,1-y)是对的)。

1-α的概率与(x,y)相同,即loss计算公式与上相同Loss1=-\frac{1}{N}\sum_{i=1}^{N}y\cdot log\left ( p(x) \right )+(1-y)\cdot log\left ( 1-p(x) \right )

有α的概率不同(即α的概率(x,1-y)是对的,将1-y取代y代入公式)。则公式为Loss2=-\frac{1}{N}\sum_{i=1}^{N}(1-y)\cdot log\left ( p(x) \right )+(1-(1-y))\cdot log\left ( 1-p(x) \right )=-\frac{1}{N}\sum_{i=1}^{N}(1-y)\cdot log\left ( p(x) \right )+y\cdot log\left ( 1-p(x) \right )

将两个式子进行概率的加权

Loss=(1-\alpha )\cdot Loss1+\alpha \cdot Loss2

=-(1-\alpha )\cdot\left \{ \frac{1}{N}\sum_{i=1}^{N}y\cdot log\left ( p(x) \right )+(1-y)\cdot log\left ( 1-p(x) \right )\right \}-\alpha \cdot \left \{ \frac{1}{N}\sum_{i=1}^{N}(1-y)\cdot log\left ( p(x) \right )+y\cdot log\left ( 1-p(x) \right ) \right \}

=-\frac{1}{N}\sum_{i=1}^{N}\left \{ ((1-\alpha )y+\alpha (1-y))\cdot log\left ( p(x) \right )+((1-\alpha )(1-y)+\alpha y)\cdot log\left ( 1-p(x) \right ) \right \}

{y}'=(1-\alpha )y+\alpha (1-y)

Loss=-\frac{1}{N}\sum_{i=1}^{N}\left \{ {y}'\cdot log\left ( p(x) \right )+(1-{y}')\cdot log\left ( 1-p(x) \right ) \right \}

可以看到,和原公式相比,仅有?{y}'替换了?y。y的值为0或1,则:

{y}'=\left\{\begin{matrix} \alpha ,y=0\\ 1-\alpha ,y=1 \end{matrix}\right.

即将标签0和1转换为α和1-α,以上是标签平滑的基本思路。未平滑前,模型预测输出尽可能逼近0或1,这个过程可以说是过拟合,正则化就是平滑后的处理,平滑后模型预测输出尽可能逼近α或1-α,逼近后不再向0或1逼近优化,即不再极端化。注意:这里的α并不是label_smoothing值(1-{y}')\cdot log\left ( 1-p(x) \right )的大小,继续往下看。

在二分类中,计算损失时考虑到了每个样本属于0和1两种类别的情况,即{y}'\cdot log\left ( p(x) \right )+(1-{y}')\cdot log\left ( 1-p(x) \right )

前面的{y}'\cdot log\left ( p(x) \right )是属于0类的情况

后面的(1-{y}')\cdot log\left ( 1-p(x) \right )是属于1类的情况

暂且将这样写,其中f(p(x))是不同的Loss函数对应的函数,k指的是类别数目

{y}'\cdot log\left ( p(x) \right )+(1-{y}')\cdot log\left ( 1-p(x) \right )=\sum_{j=1}^{K} {y}'\cdot log\left ( p(x) \right )=\sum_{j=1}^{K} {y}'\cdot f\left ( p(x) \right )

损失函数Loss可以表示为

Loss=-\frac{1}{N}\sum_{i=1}^{N}\sum_{j=1}^{K} {y}'\cdot f\left ( p(x) \right )

你可能会问二元交叉熵对应的概率α是清楚的,那多元的呢?

y_true = [[0, 1, 0], [0, 0, 1]]
y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]  #两个样本

#三分类问题,即样本[0, 1, 0]属于第1类(从第0类开始数)

TensorFlow中,官方API这样说:如果 label_smoothing为 0.1,则对非目标标签使用 0.1 / num_classes,对目标标签使用 0.9 + 0.1 / num_classes。这是Szegedy等人提出了inception v2的模型(论文:Rethinking the inception architecture for computer vision.),是以均匀分布为前提,采取的概率公式是这样的:

{y}'=y\cdot (1-\alpha )+\frac{\alpha }{K}

y_true = [[0, 1, 0], [0, 0, 1]]
y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]  #两个样本

# label_smoothing=β为0.1时
# y=[0, 1, 0],则y’=y*(1-β)+β/K=[0, 1, 0]*0.9+0.1/3=[0.033333, 0.933333, 0.033333]
# 即以0.033333概率选择类别0,以 0.933333概率选择类别1, 以 0.033333概率选择类别2

同理,也满足二分类的情况,即β=2α时

{y}'=\left\{\begin{matrix} \frac{\beta }{2} ,y=0\\ 1-\frac{\beta }{2},y=1 \end{matrix}\right.

下面用代码实验一下:

#BinaryCrossentropy二分类问题
import tensorflow as tf
import math
ls=0.1   #平滑后类别对应的不再是[0,1],而是[0.05,0.95]

y_true = [0, 1, 0]    #这里是3个样本
y_pred = [0.6, 0.3, 0.6]
bce = tf.keras.losses.BinaryCrossentropy(label_smoothing=ls)
print(bce(y_true, y_pred).numpy())
#输出:0.9845474
a = -0.05*math.log(0.6)-0.95*math.log(1-0.6)
b = -0.95*math.log(0.3)-0.05*math.log(1-0.3)
c = -0.05*math.log(0.6)-0.95*math.log(1-0.6)
print((a+b+c)/3)
#输出:0.9845476214146899,大概因为保留的精度不一致,所以最后1位不同

有兄弟可能会问,在预测标签 y_pred 中第三类[0.05, 0.95, 0]中的0,计算log时怎么办,这个情况似乎是TensorFlow以一个极小的正数代替了0,如使用0.000001(我也不清楚,瞎猜的,代入公式推算是正确的)。

#CategoricalCrossentropy多分类问题
import tensorflow as tf
import math
ls=0.1

y_true = [0, 1, 0]  #取三分类,一个样本,第0,1,2类平滑后[0.033333, 0.933333, 0.033333]
y_pred = [0.05, 0.95, 0]
cce = tf.keras.losses.CategoricalCrossentropy(label_smoothing=ls)
print(cce(y_true, y_pred).numpy())  #输出:0.6850014
a1 = -0.1/3*math.log(0.05)
b1 = -(0.9+0.1/3)*math.log(0.95)
c1 = -0.1/3*math.log(0.0000001)
print(a1+b1+c1)   #输出:0.6850013389121242,结果一致,仅有一个样本就没有1-N的求和了

标签平滑后相当于在真实分布中加入了噪声,避免模型对于正确标签过于自信,使得预测正负样本的输出值差别不那么大,从而避免过拟合,提高模型的泛化能力。

axis

计算loss的轴(特征轴)。 默认为 -1(-1表示为最后一个维度)。

reduction

适用于损失的 tf.keras.losses.Reduction 类型。 默认值为AUTO。一共AUTO、NONE、SUM、SUM_OVER_BATCH_SIZE四种值

  • NONE:分别计算每个样本的损失,不进行求和
import tensorflow as tf
import math

y_true = [[0, 1, 0], [0, 0, 1]]  #两个样本 1个batch
y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]
cce = tf.keras.losses.CategoricalCrossentropy(reduction=tf.keras.losses.Reduction.NONE)
print(cce(y_true, y_pred).numpy())  
#输出:[0.05129331 2.3025851 ],分开计算每个[](一个小样本)内的Loss
a1 = -0*math.log(0.05)  #未进行平滑
b1 = -1*math.log(0.95)
c1 = -0*math.log(0.0000001)

a2 = -0*math.log(0.1)
b2 = -0*math.log(0.8)
c2 = -1*math.log(0.1)

print(a1+b1+c1,a2+b2+c2)   #输出:0.05129329438755058 2.3025850929940455
  • SUM指加权损失的标量和。
cce = tf.keras.losses.CategoricalCrossentropy(reduction=tf.keras.losses.Reduction.SUM)
print(cce(y_true, y_pred).numpy())  #输出:2.3538785

print(a1+b1+c1+a2+b2+c2)   #输出:2.353878387381596
  • AUTO 表示reduction将由上下文确定。几乎所有情况,默认为 SUM_OVER_BATCH_SIZE一样的操作。 当与 tf.distribute.Strategy 一起使用时,在内置训练循环(例如 tf.keras compile and fit)之外,reduction值为 SUM 或 NONE。 在这种情况下使用 AUTO 会引发错误。?
  • SUM_OVER_BATCH_SIZE:标量 SUM 除以损失中的元素数,也就是所有样本的平均损失。
cce = tf.keras.losses.CategoricalCrossentropy(reduction=tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE)
print(cce(y_true, y_pred).numpy())  #输出:1.1769392

print((a1+b1+c1+a2+b2+c2)/2)   #输出:1.176939193690798

当与 tf.distribute.Strategy 一起使用时,在 tf.keras compile and fit 等内置训练循环之外,使用 AUTO 或 SUM_OVER_BATCH_SIZE 将引发错误。

name

操作的名称。 即使用的Loss函数名称。

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-08-22 13:32:41  更:2021-08-22 13:34:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 18:29:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码