发布于2020-03-31 12:29 阅读(1659) 评论(0) 点赞(17) 收藏(4)
pytorch中有两个softmax,一个在torch.nn中,一个在torch.nn.functional中,顾明思想,torch.nn.functional.softmax就是一个函数,直接使用即可,torch.nn.Softmax和torch.nn.RNN一样是个类,需要先初始化,然后赋值
pytorch的损失函数都在torch.nn下面
pytorch优化方法都封装在torch.optim中,主要有以下(加粗和常用的):
import optim
ptimizer=optim.SGD(params=net.parameters(),lr=0.1)
optimizer.zero_grad() //梯度清零
output=net(input)
output.backward(output)
optimizer.step()
# 方法1
# 为不同子网络设置不同的学习率,在finetune中经常用到
# 如果对某个参数不指定学习率,就使用最外层的默认学习率(如feature层就使用1e-5)
optimizer =optim.SGD([
{'params': net.features.parameters()}, # 学习率为1e-5
{'params': net.classifier.parameters(), 'lr': 1e-2}
],
lr=1e-5)
# 方法2
# 只为两个全连接层设置较大的学习率,其余层的学习率较小
special_layers = nn.ModuleList([net.classifier[0], net.classifier[3]])
special_layers_params = list(map(id, special_layers.parameters()))
base_params = filter(lambda p: id(p) not in special_layers_params,
net.parameters())
optimizer = t.optim.SGD([
{'params': base_params},
{'params': special_layers.parameters(), 'lr': 0.01}
], lr=0.001 )
具体的可见下述代码
import torch
class TwoLayerNet(torch.nn.Module):
def __init__(self, d_input, d_hidden, d_output):
super(TwoLayerNet, self).__init__()
self.linear1 = torch.nn.Linear(d_input, d_hidden)
self.linear2 = torch.nn.Linear(d_hidden, d_output)
def forward(self, x):
h_relu = self.linear1(x).clamp(min=0)
Y_pred = self.linear2(h_relu)
Y_pred = torch.nn.functional.softmax(Y_pred, axis=1)
return Y_pred
n, d_input, d_hidden, d_output = 64, 1000, 100, 10
# Create random Tensors to hold inputs and outputs
X = torch.randn(n, d_input) # shape(64, 1000)
Y = torch.randn(n, d_output) # 10分类问题
model = TwoLayerNet(d_input, d_hidden, d_output)
criterion = torch.nn.CrossEntropyLoss(reduction='sum')
all_params = model.parameters()
print('all_params:', all_params)
weight_params = []
quant_params = []
print('model.named_parameters():', model.named_parameters())
# 根据自己的筛选规则 将所有网络参数进行分组
for pname, p in model.named_parameters():
print('pname', pname, 'p.shape:', p.shape)
if any([pname.endswith(k) for k in ['cw', 'dw', 'cx', 'dx', 'lamb']]):
quant_params += [p]
elif ('conv' or 'fc' in pname and 'weight' in pname):
weight_params += [p]
# 取回分组参数的id
params_id = list(map(id, weight_params)) + list(map(id, quant_params))
print('params_id:', params_id)
# 取回剩余分特殊处置参数的id
other_params = list(filter(lambda p: id(p) not in params_id, all_params))
print('other_params:', other_params)
# 构建不同学习参数的优化器
optimizer = torch.optim.SGD([
{'params': other_params},
{'params': quant_params, 'lr': 0.1*0.1},
{'params': weight_params, 'weight_decay': 0.1}],
lr=0.01,
momentum=0.1,
)
all_params: <generator object Module.parameters at 0x00000267D2565048>
model.named_parameters(): <generator object Module.named_parameters at 0x00000267E437FB48>
pname linear1.weight p.shape: torch.Size([100, 1000])
pname linear1.bias p.shape: torch.Size([100])
pname linear2.weight p.shape: torch.Size([10, 100])
pname linear2.bias p.shape: torch.Size([10])
params_id: [2645231002536, 2645231004048, 2645231004120, 2645231004192]
other_params: []
# 方法1
# 新建一个optimizer。对于使用动量的优化器(如Adam),会丢失动量等状态信息,可能会造成损失函数的收敛出现震荡等情况
old_lr = 0.1
optimizer1 =optim.SGD([
{'params': net.features.parameters()},
{'params': net.classifier.parameters(), 'lr': old_lr*0.1}
], lr=1e-5)
# 方法2: 调整学习率, 手动decay, 保存动量
for param_group in optimizer.param_groups:
param_group['lr'] *= 0.1 # 学习率为之前的0.1倍
optimizer
# 具体实现
def adjust_learning_rate(optimizer, epoch, lr):
"""Sets the learning rate to the initial LR decayed by 10 every 2 epochs"""
lr *= (0.1 ** (epoch // 2))
for param_group in optimizer.param_groups:
param_group['lr'] = lr
model = AlexNet(num_classes=2)
optimizer = optim.SGD(params = model.parameters(), lr=10)
plt.figure()
x = list(range(10))
y = []
lr_init = optimizer.param_groups[0]['lr']
for epoch in range(10):
adjust_learning_rate(optimizer, epoch, lr_init)
lr = optimizer.param_groups[0]['lr']
print(epoch, lr)
y.append(lr)
plt.plot(x,y)
上面代码用到了optimizer.param_groups
,这个到底是什么,可以见下
import torch
class TwoLayerNet(torch.nn.Module):
def __init__(self, d_input, d_hidden, d_output):
super(TwoLayerNet, self).__init__()
self.linear1 = torch.nn.Linear(d_input, d_hidden)
self.linear2 = torch.nn.Linear(d_hidden, d_output)
def forward(self, x):
h_relu = self.linear1(x).clamp(min=0)
Y_pred = self.linear2(h_relu)
return Y_pred
# 定义样本数,输入层维度,隐藏层维度,输出层维度
n, d_input, d_hidden, d_output = 64, 1000, 100, 10
# Create random Tensors to hold inputs and outputs
X = torch.randn(n, d_input) # shape(64, 1000)
Y = torch.randn(n, d_output) # 10分类问题
# Construct our model by instantiating the class defined above
model = TwoLayerNet(d_input, d_hidden, d_output)
# Construct our loss function and an Optimizer. The call to model.parameters()
# in the SGD constructor will contain the learnable parameters of the two
# nn.Linear modules which are members of the model.
criterion = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)
print(type(optimizer)) # SGD类型
print(optimizer)
print(dir(optimizer)) # 方法中有一个param_groups方法
for i in optimizer.param_groups:
print(type(i)) # param_groups中每一个元素都是字典
print(i.keys()) # 字典中共有6个key,其中有一个就是lr,记录了优化器的lr
print(i['lr']) # 目前lr的取值
print(type(i['params'])) # 记录了当前参数
print(i['params'][0].shape) # list中每个参数都是tensor
break
<class 'torch.optim.sgd.SGD'>
SGD (
Parameter Group 0
dampening: 0
lr: 0.0001
momentum: 0
nesterov: False
weight_decay: 0
)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'add_param_group', 'defaults', 'load_state_dict', 'param_groups', 'state', 'state_dict', 'step', 'zero_grad']
<class 'dict'>
dict_keys(['params', 'lr', 'momentum', 'dampening', 'weight_decay', 'nesterov'])
0.0001
<class 'list'>
torch.Size([100, 1000])
关于优化器学习率的调整,pytorch已经封装好了,可详见博客https://blog.csdn.net/weixin_43722026/article/details/103271611
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)
'''
参数:
step_size(int)
学习率下降间隔数,若为 30,则会在 30、 60、 90…个 step 时,将学习率调整为 lr*gamma。
gamma(float)
学习率调整倍数,默认为 0.1 倍,即下降 10 倍。
last_epoch(int)
上一个 epoch 数,这个变量用来指示学习率是否需要调整。当last_epoch 符合设定的间隔时,就会对学习率进行调整。当为-1 时,学习率设置为初始值。
# 按设定的间隔调整学习率。这个方法适合后期调试使用,观察 loss 曲线,
# 为每个实验定制学习率调整时机。
torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)
'''
参数:
milestones(list)
一个 list,每一个元素代表何时调整学习率, list 元素必须是递增的。如 milestones=[30,80,120]
gamma(float)
学习率调整倍数,默认为 0.1 倍,即下降 10 倍。
'''
# 按指数衰减调整学习率,调整公式: lr=l∗gamma∗∗epoch
torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1)
'''
参数:
gamma
学习率调整倍数的底,指数为 epoch,即 gamma**epoch
'''
torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1)
'''
参数:
T_max(int)
一次学习率周期的迭代次数,即 T_max 个 epoch 之后重新设置学习率。
eta_min(float)
最小学习率,即在一个周期中,学习率最小会下降到 eta_min,默认值为 0。
'''
torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
'''
参数:
mode(str)
模式选择,有 min 和 max 两种模式, min 表示当指标不再降低(如监测loss), max 表示当指标不再升高(如监测 accuracy)。
factor(float)
学习率调整倍数(等同于其它方法的 gamma),即学习率更新为 lr = lr * factor
patience(int)
忍受该指标多少个 step 不变化,当忍无可忍时,调整学习率。
verbose(bool)
是否打印学习率信息, print(‘Epoch {:5d}: reducing learning rate of group {} to {:.4e}.’.format(epoch, i, new_lr))
threshold_mode(str)
选择判断指标是否达最优的模式,有两种模式, rel 和 abs。
当 threshold_mode == rel,并且 mode == max 时, dynamic_threshold = best * ( 1 +threshold );
当 threshold_mode == rel,并且 mode == min 时, dynamic_threshold = best * ( 1 -threshold );
当 threshold_mode == abs,并且 mode== max 时, dynamic_threshold = best + threshold ;
当 threshold_mode == rel,并且 mode == max 时, dynamic_threshold = best - threshold;
threshold(float)
配合 threshold_mode 使用。
cooldown(int)
“冷却时间“,当调整学习率之后,让学习率调整策略冷静一下,让模型再训练一段时间,再重启监测模式。
min_lr(float or list)
学习率下限,可为 float,或者 list,当有多个参数组时,可用 list 进行设置。
eps(float)
学习率衰减的最小值,当学习率变化小于 eps 时,则不调整学习率。
lr=base_lr∗lmbda(self.last_epoch)
lr=base_lr∗lmbda(self.last_epoch)
fine-tune 中十分有用,我们不仅可为不同的层设定不同的学习率,还可以为其设定不同的学习率调整策略。
torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1)
'''
参数:
lr_lambda(function or list)
一个计算学习率调整倍数的函数,输入通常为 step,当有多个参数组时,设为 list。
#优化器针对loss进行参数更新,分三档
if (loss.item() <= 0.4) & lr_flag1:
for p in optimizer.param_groups:
p['lr'] = 3e-3
lr_flag1 = 0
if (loss.item() <= 0.2) & lr_flag1:
for p in optimizer.param_groups:
p['lr'] = 3e-4
lr_flag2 = 0
if (loss.item() <= 0.05) & lr_flag1:
for p in optimizer.param_groups:
p['lr'] = 3e-5
lr_flag3 = 0
torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None, norm_type=2.0, scale_grad_by_freq=False, sparse=False, _weight=None)
from torch import nn
from torch.autograd import Variable
# 定义词嵌入
embeds = nn.Embedding(2, 5) # 2 个单词,维度 5
# 得到词嵌入矩阵,开始是随机初始化的
torch.manual_seed(1)
embeds.weight
# 输出结果:
Parameter containing:
-0.8923 -0.0583 -0.1955 -0.9656 0.4224
0.2673 -0.4212 -0.5107 -1.5727 -0.1232
[torch.FloatTensor of size 2x5]
如果需要加载预训练好的向量,使用如下:
# FloatTensor containing pretrained weights
weight = torch.FloatTensor([[1, 2.3, 3], [4, 5.1, 6.3]])
embedding = nn.Embedding.from_pretrained(weight)
# Get embeddings for index 1
input = torch.LongTensor([1])
embedding(input)
tensor([[ 4.0000, 5.1000, 6.3000]])
x=x.cuda()
、model = model.cuda()
# 如果有cuda使用cuda,0表示第0块cuda,没有则使用cpu
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
model.to(device) # 加不加model=都可以
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
model = BiLSTMAttention(embedding_dim, num_classes, n_hidden, num_layers, weight) # 初始化BiLSTMAttention模型
if torch.cuda.device_count() > 1: # cuda个数
print('Use', torch.cuda.device_count(), 'gpus')
model = nn.DataParallel(model) # 模型并行
model.to(device) # 虽然并行,也需要将模型放到指定的一块cuda上
将数据从gpu转向cpu,只需要x.cpu()
x = tensor_input.numpy()
x = torch.from_numpy(numpy_data)
作者:imsorry
链接:https://www.pythonheidong.com/blog/article/292127/7ac522234551f4ecbbc6/
来源:python黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 python黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-1
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!