VisualPytorch beta发布了!

功能概述:通过可视化拖拽网络层方式搭建模型,可选择不同数据集、损失函数、优化器生成可运行pytorch代码

扩展功能:1. 模型搭建支持模块的嵌套;2. 模型市场中能共享及克隆模型;3. 模型推理助你直观的感受神经网络在语义分割、目标探测上的威力;4.添加图像增强、快速入门、参数弹窗等辅助性功能

修复缺陷:1.大幅改进UI界面,提升用户体验;2.修改注销不跳转、图片丢失等已知缺陷;3.实现双服务器访问,缓解访问压力

访问地址http://sunie.top:9000

发布声明详见https://www.cnblogs.com/NAG2020/p/13030602.html

一、权值初始化

1. 梯度消失与爆炸

\(E(XY)=E(X)E(Y)\)

\(D(X)=E(X^2)-E(X)^2\)

\(D(X+Y)=D(X)+D(Y)\)

\(\Longrightarrow D(XY) = D(X)D(Y)+D(X)E(Y)^2+D(Y)E(X)^2=D(X)D(Y)\)

\(H_{11}=\sum_{i=0}^n X_i*W_{1i}\)

\(\Longrightarrow D(H_{11})=\sum_{i=0}^n D(X_i)*D(W_{1i})=n*1*1=n\)

\(std(H_{11}=\sqrt n)\)

若仍使 \(D(H_1)=nD(X)D(W)=1\)

\(\Longrightarrow D(W)=\frac{1}{n}\)


import os
import torch
import random
import numpy as np
import torch.nn as nn
from common_tools import set_seed set_seed(3) # 设置随机种子 class MLP(nn.Module):
def __init__(self, neural_num, layers):
super(MLP, self).__init__()
self.linears = nn.ModuleList([nn.Linear(neural_num, neural_num, bias=False) for i in range(layers)])
self.neural_num = neural_num def forward(self, x):
for (i, linear) in enumerate(self.linears):
x = linear(x)
# x = torch.relu(x) print("layer:{}, std:{}".format(i, x.std()))
if torch.isnan(x.std()):
print("output is nan in {} layers".format(i))
break return x def initialize(self):
for m in self.modules():
if isinstance(m, nn.Linear):
nn.init.normal_(m.weight.data, std=1) layer_nums = 100
neural_nums = 256
batch_size = 16 net = MLP(neural_nums, layer_nums)
net.initialize() inputs = torch.randn((batch_size, neural_nums)) # normal: mean=0, std=1 output = net(inputs)
print(output)

将W设置为0均值,1标准差的标准正太分布,出现如下所示梯度爆炸现象。正如所料,每层std增加的倍数大概为\(\sqrt{256}=16\) ,将W的标准差设为 np.sqrt(1/self.neural_num) 则正常。

layer:0, std:16.0981502532959
layer:1, std:253.29345703125
layer:2, std:3982.99951171875
...
layer:30, std:2.2885405881461517e+37
layer:31, std:nan
output is nan in 31 layers
tensor([[ 4.9907e+37, -inf, inf, ..., inf,
-inf, inf],
[ -inf, inf, 2.1733e+38, ..., 9.1766e+37,
-4.5777e+37, 3.3680e+37],
[ 1.4215e+38, -inf, inf, ..., -inf,
inf, inf],
...,
[-9.2355e+37, -9.9121e+37, -3.7809e+37, ..., 4.6074e+37,
2.2305e+36, 1.2982e+38],
[ -inf, inf, -inf, ..., -inf,
-2.2394e+38, 2.0295e+36],
[ -inf, inf, 2.1518e+38, ..., -inf,
1.6132e+38, -inf]], grad_fn=<MmBackward>)

2. 激活函数初始化

对于不同的激活函数,对W的标准差初始化也不同,保持数据尺度维持在恰当范围,通常方差为1

  1. Sigmoid, tanh------Xavier

  2. Relu------Kaiming

    \(D(W)=\frac{2}{n_i}\)

    \(D(W)=\frac{2}{(1+a^2) n_i}\) , LeakyRelu

    a = np.sqrt(6 / (self.neural_num + self.neural_num))
    tanh_gain = nn.init.calculate_gain('tanh')
    a *= tanh_gain
    nn.init.uniform_(m.weight.data, -a, a)
    # 同 nn.init.xavier_uniform_(m.weight.data, gain=tanh_gain) nn.init.normal_(m.weight.data, std=np.sqrt(2 / self.neural_num))
    # 同 nn.init.kaiming_normal_(m.weight.data)

3. 十种初始化方法

  1. Xavier均匀分布

  2. Xavier正态分布

  3. Kaiming均匀分布

  4. Kaiming正态分布

  5. 均匀分布

  6. 正态分布

  7. 常数分布

  8. 正交矩阵初始化

  9. 单位矩阵初始化

  10. 稀疏矩阵初始化

nn.init.calculate_gain(nonlinearity, param=None)

x = torch.randn(10000)
out = torch.tanh(x)
gain = x.std() / out.std() # 1.5909514427185059 tanh_gain = nn.init.calculate_gain('tanh') # 1.6666666666666667
# 相当于每经过一层tanh,x的标准差缩小1.6倍

主要功能:计算激活函数的方差变化尺度

主要参数

  • nonlinearity: 激活函数名称
  • param: 激活函数的参数,如Leaky ReLU的negative_slop

二、损失函数

0. 损失函数、熵

损失函数(Loss Function):衡量模型输出与真实标签的差异

\(Loss=f(\hat y , y)\)

代价函数(Cost Function):

\(Cost = \frac{1}{N}\sum_i^N f(\hat y_i, y)\)

目标函数(Objective Function):

\(Obj=Cost+Regularization\)

1. nn.CrossEntropyLoss

nn.CrossEntropyLoss调用过程:

用步进(Step into)的调试方法从loss_functoin = nn.CrossEntropyLoss() 语句进入函数,观察从nn.CrossEntropyLoss()到class Module(object)一共经历了哪些类,记录其中所有进入的类及函数。

  1. CrossEntropyLoss.__init__: super(CrossEntropyLoss, self).__init__

  2. _WeightedLoss.__init__: super(_WeightedLoss,self).__init__

  3. _Loss.__init__: super(_Loss, self).__init__()

    def __init__(self, size_average=None, reduce=None, reduction='mean'): # 前两个不再使用
    super(_Loss, self).__init__()
    if size_average is not None or reduce is not None:
    self.reduction =_Reduction.legacy_get_string(size_average, reduce)
    else:
    self.reduction = reduction
  4. Module.__init__: _construct

功能:nn.LogSoftmax ()与nn.NLLLoss ()结合,进行交叉熵计算

主要参数:

  • weight:各类别的loss设置权值
  • ignore_index:忽略某个类别
  • reduction :计算模式,可为none/sum/mean
    • none 逐个元素计算
    • sum 所有元素求和,返回标量
    • mean 加权平均,返回标量
inputs = torch.tensor([[1, 2], [1, 3], [1, 3]], dtype=torch.float)
target = torch.tensor([0, 1, 1], dtype=torch.long) # --------- CrossEntropy loss: reduction ------------
# def loss function
loss_f_none = nn.CrossEntropyLoss(weight=None, reduction='none')
loss_f_sum = nn.CrossEntropyLoss(weight=None, reduction='sum')
loss_f_mean = nn.CrossEntropyLoss(weight=None, reduction='mean') # forward
loss_none = loss_f_none(inputs, target) # tensor([1.3133, 0.1269, 0.1269])
loss_sum = loss_f_sum(inputs, target) # tensor(1.5671)
loss_mean = loss_f_mean(inputs, target) # tensor(0.5224) '''
若设置:
weights = torch.tensor([1, 2], dtype=torch.float)
结果变为:
tensor([1.3133, 0.2539, 0.2539]) tensor(1.8210) tensor(0.3642)
后面两项因为类别为1,故有权2
'''

2. nn.NLLLoss



功能:实现负对数似然函数中的负号功能

3. nn.BCELoss(逐神经元求Loss)



功能:二分类交叉熵

注意事项:输入值取值在[0,1]

inputs = torch.tensor([[1, 2], [2, 2], [3, 4], [4, 5]], dtype=torch.float)
target = torch.tensor([[1, 0], [1, 0], [0, 1], [0, 1]], dtype=torch.float)
# 注意这里输出端的两个神经元都需要分别计算Loss target_bce = target # itarget
inputs = torch.sigmoid(inputs) weights = torch.tensor([1, 1], dtype=torch.float) loss_f_none_w = nn.BCELoss(weight=weights, reduction='none')
loss_f_sum = nn.BCELoss(weight=weights, reduction='sum')
loss_f_mean = nn.BCELoss(weight=weights, reduction='mean') # forward
loss_none_w = loss_f_none_w(inputs, target_bce)
loss_sum = loss_f_sum(inputs, target_bce)
loss_mean = loss_f_mean(inputs, target_bce) '''
BCE Loss tensor([[0.3133, 2.1269],
[0.1269, 2.1269],
[3.0486, 0.0181],
[4.0181, 0.0067]]) tensor(11.7856) tensor(1.4732)
'''

4. nn.BCEWithLogitsLoss(逐神经元求Loss)

功能:结合Sigmoid与二分类交叉熵

注意事项:网络最后不加sigmoid函数

添加参数:pos_weight 正样本的权值

5. 18种损失函数总结

参数即调用方式详见:

下面仅列出各损失函数功能及表达式

注意:以下公式中出现下标n则表示该函数是对所有神经元进行的逐神经元操作。

函数名 功能 表达式
CrossEntropyLoss LogSoftmax 与NLLLoss 结合,进行交叉熵计算 \(weight[class](-x[class]+log(\sum_j e^{x[j]}))\)
NLLLoss 负对数似然函数中的负号功能 \(-\omega_{y_n} x_{n,y_n}\)
BCELoss 二分类交叉熵 \(-\omega_n [y_nlogx_n+(1-y_n)log(1-x_n)]\)
BCEWithLogitsLoss 结合Sigmoid与二分类交叉熵 \(-\omega_n [y_nlog\sigma(x_n)+(1-y_n)log(1-\sigma(x_n))]\)
L1Loss 差的绝对值 \(\|x_n-y_n\|\)
MSELoss 差的平方 \((x_n-y_n)^2\)
SmoothL1Loss 在L1基础上平滑 $$ \left{ \begin{array}{lr} 0.5(x_n-y_n)^2 & : |x_n-y_n| < 1\ |x_n-y_n|-0.5 & : otherwise \end{array} \right. $$
PoissonNLLLoss 泊松分布的负对数似然损失函数 $$ \left{ \begin{array}{lr} e^{x_n}-y_n x_n & : log(input)\ x_n-y_nlog(x_n+eps) & : otherwise \end{array} \right. $$
KLDivLoss 计算KLD(divergence),KL散度,相对熵(x必须是对数) \(y_n(logy_n-x_n)\)
MerginRankingLoss 计算两个向量之间的相似度,用于排序任务 \(max(0, -y(x^{(1)}-x^{(2)})+margin)\)
MultiLabelMarginLoss 多标签边界损失 \(\sum_j^{len(y)}\sum_{i\neq y_j}^{len(x)}\frac{max(0, 1-(x_{y_j}-x_i))}{len(x)}\)
SoftMarginLoss 二分类logistic损失 \(\frac{1}{len(x)}\sum_i log(1+e^{-y_i x_i})\)
MultiLabelSoftMarginLoss 上述多标签版本 \(-\frac{1}{C}\sum_i (y_i log(1+e^{-x_i^{-1}})+(1-y_i)log\frac{e^{-x}}{1+e^{-x}})\)
MultiMarginLoss 计算多分类的折页损失 \(\frac{1}{len(x)}\sum_i max(0, margin-x_y+x_i)^p\)
TripletMarginLoss 计算三元组损失,人脸验证中常用 \(max(d(a_i, p_i)-d(a_i,n_i)+margin, 0)\)
HimgeEmbeddingLoss 计算两个输入的相似性,常用于非线性embedding和半监督学习 $$ \left{ \begin{array}{lr} x_n & : y_n=1\ max(0, margin-x_n) & : y_n=-1 \end{array} \right. $$
CosineEmbeddingLoss 余弦相似度 $$ \left{ \begin{array}{lr} 1-cos(x_1,x_2) & : y=1\ max(0,cos(x_1,x_2)-margin) & : y=-1 \end{array} \right. $$
CTCLoss 计算CTC损失,解决时序类数据的分类 详见CTC loss 理解

三、优化器

pytorch的优化器:管理更新模型中可学习参数的值,使得模型输出更接近真实标签

导数:函数在指定坐标轴上的变化率

方向导数:指定方向上的变化率

梯度:一个向量,方向为方向导数取得最大值的方向

1. Optimizer基本属性

defaults:优化器超参数

state:参数的缓存,如momentum的缓存

params_groups:管理的参数组,字典的list

_step_count:记录更新次数,学习率调整中使用

# ========================= step 4/5 优化器 ==========================
optimizer = optim.SGD(net.parameters(), lr=LR, momentum=0.9) # 选择优化器
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1) # 设置学习率下降策略 # ============================ step 5/5 训练 ========================
for epoch in range(MAX_EPOCH):
...
for i, data in enumerate(train_loader):
...
# backward
optimizer.zero_grad()
loss = criterion(outputs, labels)
loss.backward() # update weights
optimizer.step()

2. 基本方法

zero_grad():清空所管理参数的梯度,pytorch特性:张量梯度不自动清零,而是累加

step():执行一步更新

add_param_group():添加参数组

state_dict():获取优化器当前状态信息字典

load_state_dict() :加载状态信息字典

weight = torch.randn((2, 2), requires_grad=True)
weight.grad = torch.ones((2, 2)) optimizer = optim.SGD([weight], lr=0.1) # --------------------------- step -----------------------------------
optimizer.step() # 修改lr=1 0.1观察结果
'''
weight before step:tensor([[0.6614, 0.2669],
[0.0617, 0.6213]])
weight after step:tensor([[ 0.5614, 0.1669],
[-0.0383, 0.5213]])
''' # ------------------------- zero_grad --------------------------------
print("weight in optimizer:{}\nweight in weight:{}\n".format(id(optimizer.param_groups[0]['params'][0]), id(weight)))
print("weight.grad is {}\n".format(weight.grad)) optimizer.zero_grad()
'''
weight in optimizer:1598931466208
weight in weight:1598931466208 与上一句相同,说明params存储的是指向数据的指针 weight.grad is tensor([[1., 1.],
[1., 1.]]) after optimizer.zero_grad(), weight.grad is
tensor([[0., 0.],
[0., 0.]])
''' # --------------------- add_param_group --------------------------
print("optimizer.param_groups is\n{}".format(optimizer.param_groups))
w2 = torch.randn((3, 3), requires_grad=True)
optimizer.add_param_group({"params": w2, 'lr': 0.0001})
print("optimizer.param_groups is\n{}".format(optimizer.param_groups)) # ------------------- state_dict ----------------------
optimizer = optim.SGD([weight], lr=0.1, momentum=0.9)
opt_state_dict = optimizer.state_dict() for i in range(10):
optimizer.step() torch.save(optimizer.state_dict(), os.path.join(BASE_DIR, "optimizer_state_dict.pkl")) # -----------------------load state_dict ---------------------------
optimizer = optim.SGD([weight], lr=0.1, momentum=0.9)
state_dict = torch.load(os.path.join(BASE_DIR, "optimizer_state_dict.pkl")) optimizer.load_state_dict(state_dict)

3. 学习率

梯度下降:

+ = − ( )

+ = − LR * ()

学习率(learning rate)控制更新的步伐

采用不同学习率进行训练,注意在lr>0.3时出现梯度爆炸

iteration = 100
num_lr = 10
lr_min, lr_max = 0.01, 0.2 # .5 .3 .2 lr_list = np.linspace(lr_min, lr_max, num=num_lr).tolist()
loss_rec = [[] for l in range(len(lr_list))]
iter_rec = list() for i, lr in enumerate(lr_list):
x = torch.tensor([2.], requires_grad=True)
for iter in range(iteration): y = func(x)
y.backward()
x.data.sub_(lr * x.grad) # x.data -= x.grad
x.grad.zero_() loss_rec[i].append(y.item()) for i, loss_r in enumerate(loss_rec):
plt.plot(range(len(loss_r)), loss_r, label="LR: {}".format(lr_list[i]))
plt.legend()
plt.xlabel('Iterations')
plt.ylabel('Loss value')
plt.show()

4. momentum

Momentum(动量,冲量):结合当前梯度与上一次更新信息,用于当前更新

指数加权平均: $$v_t=\beta v_{t-1}+(1-\beta)\theta_t = \sum_i{N}(1-\beta)\betai\theta_{N-1}$$

pytorch中更新公式:

\(v_i=mv_{i-1}+g(w_i)\)

\(w_{i+1}=w_i-lr*v_i\)

1.optim.SGD

主要参数:

• params:管理的参数组

• lr:初始学习率

• momentum:动量系数,贝塔

• weight_decay:L2正则化系数

• nesterov:是否采用NAG

def func(x):
return torch.pow(2*x, 2) # y = (2x)^2 = 4*x^2 dy/dx = 8x iteration = 100
m = 0.9 # .9 .63 lr_list = [0.01, 0.03] momentum_list = list()
loss_rec = [[] for l in range(len(lr_list))]
iter_rec = list() for i, lr in enumerate(lr_list):
x = torch.tensor([2.], requires_grad=True) momentum = 0. if lr == 0.03 else m
momentum_list.append(momentum) optimizer = optim.SGD([x], lr=lr, momentum=momentum) for iter in range(iteration): y = func(x)
y.backward() optimizer.step()
optimizer.zero_grad() loss_rec[i].append(y.item())



上述情况出现弹簧现象,因为在loss接近0的位置仍然有极大的动量,应当适当减小。

其他9个优化器详见PyTorch 学习笔记(七):PyTorch的十个优化器

Pytorch_Part4_损失函数的更多相关文章

  1. 数据预处理中归一化(Normalization)与损失函数中正则化(Regularization)解惑

    背景:数据挖掘/机器学习中的术语较多,而且我的知识有限.之前一直疑惑正则这个概念.所以写了篇博文梳理下 摘要: 1.正则化(Regularization) 1.1 正则化的目的 1.2 正则化的L1范 ...

  2. svm损失函数

    作者:杜客链接:https://zhuanlan.zhihu.com/p/20945670来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. SVM的损失函数定义如下: 举 ...

  3. 损失函数(Loss Function) -1

    http://www.ics.uci.edu/~dramanan/teaching/ics273a_winter08/lectures/lecture14.pdf Loss Function 损失函数 ...

  4. 损失函数(Loss Function)

    转载请注明出自BYRans博客:http://www.cnblogs.com/BYRans/ 线性回归中提到最小二乘损失函数及其相关知识.对于这一部分知识不清楚的同学可以参考上一篇文章<线性回归 ...

  5. Gradient Boost Decision Tree(GBDT)中损失函数为什么是对数形式

    由于最近要经常用到XGBOOST的包,不免对相关的GBDT的原理又重新学习了一遍, 发现其中在考虑损失函数的时候,是以对数log进行度量的,囿于误差平方和函数的印象 那么为什么是对数呢?可能是下面的原 ...

  6. 惩罚因子(penalty term)与损失函数(loss function)

    penalty term 和 loss function 看起来很相似,但其实二者完全不同. 惩罚因子: penalty term的作用是把受限优化问题转化为非受限优化问题. 比如我们要优化: min ...

  7. MATLAB 损失函数画图

    损失函数画图 Hinge loss function: \[H(z) = max(0,1-z)\] $\psi$-learning loss function: \[{\phi _s}(z) = \l ...

  8. 损失函数(loss function) 转

    原文:http://luowei828.blog.163.com/blog/static/310312042013101401524824 通常而言,损失函数由损失项(loss term)和正则项(r ...

  9. 逻辑回归损失函数(cost function)

    逻辑回归模型预估的是样本属于某个分类的概率,其损失函数(Cost Function)可以像线型回归那样,以均方差来表示:也可以用对数.概率等方法.损失函数本质上是衡量”模型预估值“到“实际值”的距离, ...

随机推荐

  1. Bonuses on a Line Gym - 102569B

    题目链接:https://vjudge.net/problem/Gym-102569B 题意:数轴上有N个点,从0出发最多走t步问最多经过几个点. 思路:分开存负数点和整数点,然后枚举每个端点,某个点 ...

  2. 一键自签本地 TLSv3 多域名 SAN 域名证书工具 HTTPS(最新版 Chrome 浏览器策略测试通过)

    一键自动生成本地自签名SAN域名证书工具 原生OpenSSL生成自签名SAN CA域名(V3签名),在Linux.MacOS系统下签发测试通过. 用于一键快速生成开发和测试场景证书,内部平台授权和私有 ...

  3. 【Azure 云服务】在Cloud Service的代码中如何修改IIS Application Pool的配置呢? 比如IdleTimeout, startMode, Recycling.PeriodicRestart.Time等

    什么是 PaaS?Platform as a Service 平台即服务 (PaaS) 是云中的完整开发和部署环境,你可以使用其中资源交付内容,从基于云的简单应用到启用云的复杂企业应用程序皆可.你以即 ...

  4. 力扣 - 剑指 Offer 09. 用两个栈实现队列

    目录 题目 思路 代码 复杂度分析 题目 剑指 Offer 09. 用两个栈实现队列 思路 刚开始想的是用stack1作为数据存储的地方,stack2用来作为辅助栈,如果添加元素直接push入stac ...

  5. JMeter元件作用域实践指南

    从一个问题说起 对于以下测试脚本: 为了能调用进入房间接口,需要从考场接口获取考场token.为了调用考场接口,需要从登陆接口获取登陆token.元件说明如下: 学生登录,提取登录${token}传入 ...

  6. [深搜]C. 【例题3】虫食算

    C . [ 例 题 3 ] 虫 食 算 题目解析 正解 : Dfs + 剪枝 依题意,把样例以加法的形式展现出来. 根据加法的性质,可以得出有两种情况:有进位和没有进位的. 而从百位到最高位的结果,又 ...

  7. [树形DP]加分二叉树

    加 分 二 叉 树 加分二叉树 加分二叉树 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第j ...

  8. Egress-Assess-出口数据安全功能测试

    简介 Egress-Assess是一款用于测试出口数据检测功能的工具,该工具可辅助完成数据安全模型测试. 在各种情况下,我们的团队都会尝试从我们正在运行的网络中提取数据,并将其移至另一个位置以进行脱机 ...

  9. OO_Unit2 多线程电梯总结

    OO_Unit2 多线程电梯总结 相比于Unit1的表达式求导,Unit2的多线程电梯听上去似乎显得更加"高大上".但在完成了3个task的迭代后再回过头去比较这两个单元,我发现其 ...

  10. 如何查看spark版本

    使用spark-shell命令进入shell模式