【2】激活函数与Loss函数求导_loss求导_Clichong的博客-程序员宅基地

技术标签: 深度学习  激活函数  

影响找到全局极小值点的几个主要的影响因素:

1)初始点的设置

2)学习率的设置,可能会影响收敛的精度与速度

ps : 处于一个全局极小值或者是鞍点的状态时,往往会影响实验效果

import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
# Jupyter notebook 中的魔法命令
%matplotlib inline                            # 在下面的代码模块里面都可以不用写 plt.show()
%config InlineBackend.figure_format = "png"   # 设置矢量图的方式来提高图片显示质量
# 常用的设置图片分辨率的有以下几个:
# %config InlineBackend.figure_format = “png"
# %config InlineBackend.figure_format = “svg"
# %config InlineBackend.figure_format = “retina"

1.常见的激活函数与梯度

Sign函数

在这里插入图片描述

# 使用函数的运行速度较慢
# def Single_layer(x):
#     if x <= 0:  return 0
#     else:       return 1

X = torch.linspace(-10,10,100)
Y = torch.tensor([0 if x<=0 else 1 for x in X])
plt.plot(X,Y),plt.xlabel('X_value'),plt.ylabel('Y_value'),plt.title('$sign$')
([<matplotlib.lines.Line2D at 0x296e3813c88>],
 Text(0.5, 0, 'X_value'),
 Text(0, 0.5, 'Y_value'),
 Text(0.5, 1.0, '$sign$'))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IyR6jWHi-1616917324044)(output_7_1.png)]

Sigmoid函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gRt4yOan-1616917324046)(attachment:image.png)]

X = torch.linspace(-3,3,100)
Y = F.sigmoid(X)
plt.plot(X,Y),plt.xlabel('X_value'),plt.ylabel('Y_value'),plt.title('$sigmoid$')
([<matplotlib.lines.Line2D at 0x296e1e1d1c8>],
 Text(0.5, 0, 'X_value'),
 Text(0, 0.5, 'Y_value'),
 Text(0.5, 1.0, '$sigmoid$'))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uQmX6Pae-1616917324051)(output_10_2.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X8s6dzB2-1616917324055)(attachment:image.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5iqa5Xuo-1616917324057)(attachment:image-2.png)]

由此可见,sigmoid函数的特性,可以根据现有的值相乘以下便可以完成导数的求解情况。而且其是连续光滑的,解决了sign函数不能求导的情况。但是,在正无穷或者是负无穷的情况中,导数接近为0。而根据梯度下降法,这会导致梯度长时间得不到更新,这种情况称为梯度弥散现象

Tanh函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r9CJnFc0-1616917324058)(attachment:image.png)]

在这里插入图片描述

X = torch.linspace(-3,3,100)
Y = F.tanh(X)
plt.plot(X,Y),plt.xlabel('X_value'),plt.ylabel('Y_value'),plt.title('$tanh$')
([<matplotlib.lines.Line2D at 0x296e3903688>],
 Text(0.5, 0, 'X_value'),
 Text(0, 0.5, 'Y_value'),
 Text(0.5, 1.0, '$tanh$'))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6LYxcRUn-1616917324061)(output_17_2.png)]

ReLU函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sFM8JkG6-1616917324063)(attachment:image.png)]

优点,导数计算起来十分的简单,不会放大也不会缩小,梯度会保持变,所以很大情况下会减小出现梯度弥散或者是梯度爆炸的情况

X = torch.linspace(-3,3,100)
Y = F.relu(X)
plt.plot(X,Y),plt.xlabel('X_value'),plt.ylabel('Y_value'),plt.title('$ReLU$')
([<matplotlib.lines.Line2D at 0x296e3f2e6c8>],
 Text(0.5, 0, 'X_value'),
 Text(0, 0.5, 'Y_value'),
 Text(0.5, 1.0, '$ReLU$'))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZjlh3Bq-1616917324064)(output_21_1.png)]

Softmax函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oS98SBqI-1616917324067)(attachment:image.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v3BmaL7J-1616917324069)(attachment:image.png)]

Leaky ReLU函数

Leaky ReLU函数是在ReLU函数上面做出一个改进,用于对于ReLU函数函数来说,当x<0的时候,其梯度是为0的,而这种情况也可能会导致梯度长时间得不到更新,所以Leaky ReLU函数会在x<0的时候做一个小小的偏移,让其有一个比较小的梯度

X = torch.arange(-10,10,0.1)
Y = F.leaky_relu(X)
plt.xticks(range(-10,10,1))
plt.plot(X,Y),plt.xlabel('X_value'),plt.ylabel('Y_value'),plt.title('$Leaky ReLU$')
([<matplotlib.lines.Line2D at 0x1c1caaff9c8>],
 Text(0.5, 0, 'X_value'),
 Text(0, 0.5, 'Y_value'),
 Text(0.5, 1.0, '$Leaky ReLU$'))

在这里插入图片描述

SELU函数

在这里插入图片描述

同样的,SeLU函数也是ReLU函数的改进,对于x<0的情况,SELU函数是一个指数函数,也就是相当于是两个函数的拼接

X = torch.arange(-10,10,0.1)
Y = F.selu(X)
#cplt.xticks(range(-10,10,1))
plt.plot(X,Y),plt.xlabel('X_value'),plt.ylabel('Y_value'),plt.title('$SeLU$')
([<matplotlib.lines.Line2D at 0x1c1cacac2c8>],
 Text(0.5, 0, 'X_value'),
 Text(0, 0.5, 'Y_value'),
 Text(0.5, 1.0, '$SeLU$'))

在这里插入图片描述

Softplus函数

Softplus函数的表达式为在这里插入图片描述
其也是在ReLU函数上面作了一个改进,使得在x=0的时候使得函数比较的平滑一些,如下图所示:

X = torch.arange(-10,10,0.1)
Y = F.softplus(X)
plt.plot(X,Y),plt.xlabel('X_value'),plt.ylabel('Y_value'),plt.title('$Softplus$')
([<matplotlib.lines.Line2D at 0x1c1cabedc48>],
 Text(0.5, 0, 'X_value'),
 Text(0, 0.5, 'Y_value'),
 Text(0.5, 1.0, '$Softplus$'))

在这里插入图片描述

2.常见的Loss与梯度

Mean Squared Error均方误差

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zUunqKK-1616917324070)(attachment:image.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qpYPn3F9-1616917324071)(attachment:image.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4bOQ8a8Z-1616917324073)(attachment:image.png)]

# 代码表示为
torch.norm(y-pred,2).pow(2)
1)torch.autograd.grad的使用
# 现在使用torch.autograd.grad实现求导的过程
# torch.autograd.grad的使用方法
# 现在假设需要解决的任务方程是简单的一元函数:y = xw + b
# 所以其loss function为 loss = ∑[(xw + b) - y]**2

# 第一个例子:
x = torch.tensor(5)     # 设置x为5
w = torch.full([1],10.)  # 设置斜率w为10
b = torch.tensor(2)     # 设置bios为2
y = torch.rand(1)+50    # 设置真实值为50附近的随机数,输出为50.6296
loss = F.mse_loss(x*w+b,y)  
# 输出结果为:  tensor([1.8779]))
# 现在进行验证一下:(5*10+2-50.6296)**2=1.8779
# 对此时的w进行求导,但是出出现一个报错
## torch.autograd.grad(loss,[w])  
# RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
# 表示w此时是不需要求导,错误原因是一开始的w没有设置好导数信息,所以pytorch自动标注了w不需要求导
# 修改的方法是,可以使用requires_grad_函数更正标注
w.requires_grad_()
# RuntimeError: only Tensors of floating point dtype can require gradients
# 又出现了一个错误,表示w需要是浮点数值,现在重新将w修改为w = torch.full([1],10.)
# 此时想再来求导,但是还是出现了错误
# torch.autograd.grad(loss,[w])
# RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
# 出现错误的原因是:前一步已经更新了w,但pytorch的这个动态图还是没有更新,所以需要重新更新一个图
loss = F.mse_loss(x*w+b,y) 
# 此时输出下数值:w,y,loss
# (tensor([10.], requires_grad=True),
#  tensor([50.5761]),
#  tensor(1.8779, grad_fn=<MseLossBackward>),
# 完成这个过程之后,就可以对w进行求导了
torch.autograd.grad(loss,[w])
# 输出为(tensor([13.7037]),)
# 验证一下
# 2*5*(5*10+2-50.6296)=13.7037 与输出结果一致


# 补充:
# 以上过程进行中出现的问题,也就是w不能丘梯度的问题,其实可以从开始初始化的时候直接进行解决
w = torch.full([1],10.).requires_grad_()
w = torch.tensor(10.,requires_grad=True)  
# 以上的两个写法是等价的


# 第二个例子:
# 同时可以对多个未知量进行求导
x = torch.tensor(5)     # 设置x为5
w = torch.full([1],10.).requires_grad_()   # 设置斜率w为10
b = torch.tensor(2.).requires_grad_()      # 设置bios为2
y = torch.rand(1)+50    # 设置真实值为50附近的随机数,输出为50.6296
loss = F.mse_loss(x*w+b,y) 
# autograd.grad的函数中如果对多个未知量进行求导,需要设置参数retain_graph=True,否则相关的结果内存会被释放
dw = torch.autograd.grad(loss,[w],retain_graph=True)
db = torch.autograd.grad(loss,[b])
print(y,x*w+b-y,loss)
# 输出为:tensor([50.6393]) tensor([1.3607], grad_fn=<SubBackward0>) tensor(1.8514, grad_fn=<MseLossBackward>)
dw,db
# 输出为:((tensor([13.6066]),), (tensor(2.7213),))  验证结果是正确的
(tensor([13.7037]),)
2)loss.backward的使用
# 还是以这个例子为例,其实backward函数会自动的对所有的参数进行求导,但是不会输出结果而是将结果保存在每一个未知量x.grad中
x = torch.tensor(5)     # 设置x为5
w = torch.full([1],10.).requires_grad_()   # 设置斜率w为10
b = torch.tensor(2.).requires_grad_()      # 设置bios为2
y = torch.rand(1)+50    # 设置真实值为50附近的随机数,输出为50.6296
loss = F.mse_loss(x*w+b,y) 
print("loss:",loss,"[(x*w+b)-y]**2:",((x*w+b)-y)**2)
# 输出为:loss: tensor(3.1575, grad_fn=<MseLossBackward>) [(x*w+b)-y]**2: tensor([3.1575], grad_fn=<PowBackward0>)
# 使用backward自动求导函数
loss.backward()
w.grad,b.grad
# 输出为:(tensor([17.7694]), tensor(3.5539))
# 验证一下
loss = F.mse_loss(x*w+b,y) 
dw = torch.autograd.grad(loss,[w],retain_graph=True)
db = torch.autograd.grad(loss,[b],retain_graph=True)
dw,db
# ((tensor([17.7694]),), (tensor(3.5539),))
# 可见,两种方法的输出结果一样
loss: tensor(3.1575, grad_fn=<MseLossBackward>) [(x*w+b)-y]**2: tensor([3.1575], grad_fn=<PowBackward0>)
3)Softmax的使用
a = torch.rand(3,requires_grad=True)
# 输出为:tensor([0.2001, 0.6048, 0.0787], requires_grad=True)
p = F.softmax(a,dim=0)
# 输出为:tensor([0.2954, 0.4429, 0.2617], grad_fn=<SoftmaxBackward>)
# 预测值:
# tensor([0.2954, 0.4429, 0.2617], grad_fn=<SoftmaxBackward>)
# (-0.13083266, 0.24673958999999998, -0.11590693)
torch.autograd.grad(p[1],[a])
# 输出为:(tensor([-0.1308,  0.2467, -0.1159]),),符合预测值
tensor([0.2001, 0.6048, 0.0787], requires_grad=True)
Cross Entropy Loss交叉熵损失

相对熵(relative entropy)就是KL散度(Kullback–Leibler divergence),用于衡量两个概率分布之间的差异。
对于两个概率分布p(x)和q(x) ,其相对熵的计算公式为:
在这里插入图片描述
需要注意:p(x)和q(x)在公式中的地位不是相等的,所以:在这里插入图片描述
相对熵的特点,是只有p(x)=q(x)时,其值为0。若p(x)和q(x)略有差异,其值就会大于0。其证明利用了负对数函数(-lnx)是严格凸函数(strictly convex function)的性质。
相对熵公式的前半部分就是交叉熵(cross entropy)。既

  • 相对熵
    在这里插入图片描述

  • 交叉熵
    在这里插入图片描述
    若p(x) 是数据的真实概率分布,q(x)是由数据计算得到的概率分布。机器学习的目的就是希望p(x)尽可能地逼近甚至等于p(x),从而使得相对熵接近最小值0. 由于真实的概率分布是固定的,相对熵公式的后半部分就成了一个常数。其后半部分为:在这里插入图片描述
    那么相对熵达到最小值的时候,也意味着交叉熵达到了最小值。对q(x)的优化就等效于求交叉熵的最小值。另外,对交叉熵求最小值,也等效于求最大似然估计(maximum likelihood estimation)。

1)cross_entropy的使用
x = torch.randn(1,28*28)
w = torch.randn(10,28*28)
# 矩阵相乘
logit = x@w.t()
# logit.shape为:torch.Size([1, 10])
# 直接求出交叉熵
F.cross_entropy(logit,torch.tensor([3]))
# 输出为:tensor(17.2760)
2)nll_loss的使用

nll_loss函数其实就是最大似然函数

x = torch.randn(1,28*28)
w = torch.randn(10,28*28)
# 矩阵相乘
logit = x@w.t()
# softmax 处理,即将 input 转换成概率分布的形式
pred = F.softmax(logit , dim=1)
# softmax 处理处理后取对数
pred = torch.log(pred)
# 最大似然计算,其中pred是预测值,torch.tensor([3])是真是值也就是label值,这位置是不能换的
F.nll_loss(pred,torch.tensor([3]))

输出结果同上面一样,所以实际上,可以认为:

CrossEntropyLoss = log_sofrmax + NLLLoss

实际意义为:
在对图片进行分类时,通常会一次性输入n张图片,最后得出一个n*c的tensor,c是此次分类的类别数:比如:n=10,c=2,表示一共10张图片,类别为2类;接下来对每一行使用softmax函数,得到每张图片每个类别的概率分布:结果如下:可以看出来,每一行的值加起来和为1
在这里插入图片描述
然后再对给概率分布取对数:输出如下:
在这里插入图片描述
最后,CrossEntropyLoss的结果就是将这10个图像输出中与label对应值拿出来,累加再对结果取负值。先假设label如下所示:
在这里插入图片描述
则最后结果为:

loss = -(-0.0178 + -0.3859 + -0.8744 + /
-1.3443 + -0.3392 + -2.7229 + -0.2614 + /
-0.2736 + -1.3477 + -2.0514) / 10 = 0.96186

使用代码来计算可以表示为:

print(torch.nn.CrossEntropyLosss(output, label)))

参考链接:
1.如何通俗的解释交叉熵与相对熵
2.NLL_Loss & CrossEntropyLoss(交叉熵)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44751294/article/details/115281926

智能推荐

东京天气预测——隐马可夫链_维特比算法东京天气-程序员宅基地

隐马可夫模型 维特比算法代码实现import numpy as npimport mathimport operators=np.array([0.4,0.6]) #初始概率,S=0.4 R=0.6e=np.array([[0.6,0.1],#发射概率 S1 R1 [0.4,0.3],# S2 R2 [0.5,0.1]])# S3 R3t=np.array([[0.4,0.6],#_维特比算法东京天气

ks.cfg使用于HPC和ORACLE单机,系统版本:RHEL6.2,硬件平台:X86全系列 .-程序员宅基地

由于AMD 6200系列和INTEL E5系列等新架构CPU的大量推广,传统的SUSE10和RHEL5在新的硬件平台上已经不能发挥出良好的性能。经大量测试发现,在RHEL6.2 x64平台上,infiniband网络和计算软件能得到最佳性能。由于RHEL6.2 x64在系统安装时有很多32位软件包被自动忽略,同时使用UUID方式挂载硬盘不方便克隆和修复。现发布一个新测...

java.lang.NoClassDefFoundError 报错原因-程序员宅基地

我在一个软件包中有两个一模一样的类,为了类名不重复,我将类名setDefault改为了SetDefault(只变换了首字母的大小写),然后一直报错java.lang.NoClassDefFoundError,最后我将SetDefault改为了Set_Default,之后报错就停止了。 尽管我不知道原因是什么,但是此项报错是因为类名相似度太高,所以改一下类名就好。...

etlpy: 并行爬虫和数据清洗工具(开源)-程序员宅基地

etlpy是python编写的网页数据抓取和清洗工具,核心文件etl.py不超过500行,具备如下特点爬虫和清洗逻辑基于xml定义,不需手工编写基于python生成器,流式处理,对内存无要求内置线程池,支持串行和并行处理内置正则解析,html转义,json转换等数据清洗功能,直接输出可用文件插件式设计,能够非常方便地增加其他文件和数据库格式..._etl爬虫

K8S_Google工作笔记0006---通过kubeadm方式_部署master节点_谷歌master内的工作流程-程序员宅基地

技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152这个是k8s的架构图然后就是要安装docker,这个docker是在pod中的容器,用来装咱们的web应用等应用的首先去下载docker的镜像wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.发现没有wget 命令,然后去安装wgetyum _谷歌master内的工作流程

海思编译链编译出现__aeabi_unwind_cpp_pr1重定义怎么回事-程序员宅基地

1.用arm-hisiv100nptl-linux-gcc编译代码,结果发现报错,__aeabi_unwind_cpp_pr1重定义,在librt.a先定义,使用的海思芯片是hi3520d。 2.本来以为是编译...

随便推点

Spring MVC的web.xml配置详解-程序员宅基地

看本文之间建议先看——https://blog.csdn.net/u010796790/article/details/52098258我的web.xml&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="...

BZOJ 1008--[HNOI2008]越狱(容斥&快速幂)-程序员宅基地

1008: [HNOI2008]越狱Time Limit:1 SecMemory Limit:162 MBSubmit:12593Solved:5439[Submit][Status][Discuss]Description  监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发...

struts2 ognl 标签输出-程序员宅基地

public class TestAction extends BaseAction { private String testAttr; private Map attrMap; public Map getAttrMap() { return attrMap; } public void setAttrMap(Map attrMap) { this....

微信跳一跳高分系列三:用 adb 破解微信跳一跳小程序-程序员宅基地

写在前面:网上关于微信跳一跳的文章已有很多,写这篇的目的是对 adb 工具的一个熟悉过程,也是对未入门的新朋友的一个引导步骤: 1、保存当前跳一跳页的截图到手机 adb shell screencap /sdcard/jump.png 2、推送图片到PC adb pull /sdcard/jump.png d://jump 3、通过 PS 等工具,测量出两个方块要点击位置的距离(还可

倒计时炸弹11.2.0.4前版本DB Link必须在2019年4月升级真相-程序员宅基地

在 Oracle 官方支持站点 MOS 上,最近发布了两篇告警文章,引发了用户的广泛关注,这两篇文章分别是:Oracle Databases Need to be Patched to a Minimum Patchset/PSU/RU levelbefore April 2019(Doc ID 2361478.1)MandatoryPatching Requirement for ...

VBA:把一个或者多个word表格转移到1个word里面_vba将指定路径的word文档插入到指定word中-程序员宅基地

https://www.datanumen.com/blogs/4-methods-to-extract-tables-from-one-word-document-to-another/原文地址如上我这里主要是为了记录下来,怕以后忘了出处。Batch Extract All Tables from Multiple Documents批量处理表格数据Sub ExtractTablesFromMu..._vba将指定路径的word文档插入到指定word中