hidden_size = hidden_size,
num_layers = num_layers,
batch_first = True,
dropout = dropout,
bidirectional = True)
初始化定义lstm的模块,
隐藏层是一个元组形式,其第一个元素是LSTM的隐藏层输出,另一个元素维护了隐藏层的状态。
embeds.view(len(sentence), 1, -1), hidden)
输入inputs和隐藏层hidden的数据
将一个tensor按照变换size,注意变换前后数据是不变的,变化的只是维度,如果每个维度上是-1,则代表是根据其他维度推导而来的;如果维度不一致,比如原来是3*4,变化为(7,-1)是会报错的。
embeds = nn.Embedding(2, 5)
这里的2表示有2个词,5表示5维度,其实也就是一个2x5的矩阵,所以如果你有1000个词,每个词希望是100维,你就可以这样建立一个word embedding,nn.Embedding(1000, 100)
x = torch.tensor([[1,2,3],[4,5,6]])
output(x): tensor([[1, 2, 3],
[4, 5, 6]])
y = x.repeat(1,2)
output(y): tensor([[1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6]])
y.view(2,-1,3)
output: tensor([[[1, 2, 3],
[1, 2, 3]],
[[4, 5, 6],
[4, 5, 6]]])
y.view(4,-1,3)
output: tensor([[[1, 2, 3]],
[[1, 2, 3]],
[[4, 5, 6]],
[[4, 5, 6]]])
repeat函数在形成新的tensor时候,可以认为是在做各个维度上的乘法:
2×3.repeat(1,2) >>>> 2×6
所有view在重新排版tensor的时候,可以认为将所有数据拉成一个sequence,然后按照设置的维度从前往后进行切割,组成新的tensor。
为保证实验可重复,需要设定随机数
# args.seed就是预先设定的随机数种子
random.seed(args.seed)
np.random.seed(args.seed)
torch.manual_seed(args.seed)
if args.cuda:
torch.cuda.manual_seed(args.seed)
大多情况下是pytorch提供的模块与自定义参数的结合,那么就需要把自定义模块绑定到网络中,通过nn.Parameter()实现
pytorch提供的模块,如linear是默认绑定到net中
# 官方linear代码块形式
class Linear(Module):
def __init__(self, in_features, out_features, bias=True):
super(Linear, self).__init__()
self.in_features = in_features
self.out_features = out_features
self.weight = Parameter(torch.Tensor(out_features, in_features))
if bias:
self.bias = Parameter(torch.Tensor(out_features))
else:
self.register_parameter('bias', None)
self.reset_parameters()
def reset_parameters(self):
stdv = 1. / math.sqrt(self.weight.size(1))
self.weight.data.uniform_(-stdv, stdv)
if self.bias is not None:
self.bias.data.uniform_(-stdv, stdv)
def forward(self, input):
return F.linear(input, self.weight, self.bias)
cuda中很难看到错误,此时需要放到cpu上运行,才方便进行debug
如下错误是embedding的index维度错误,超过max_idx
error:RuntimeError: CUDA error: device-side assert triggered
CUDA_LAUNCH_BLOCKING=1 python script.py
CUDA_VISIBLE_DEVICES=1 python my_script.py
or:
os.environ["CUDA_VISIBLE_DEVICES"] = "0,1"
# 梯度裁剪
optimizer.zero_grad()
loss, hidden = model(data)
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm, norm_type=2) # 按范数裁剪
torch.nn.utils.clip_grad_value_(model.parameters(), clip_value) # 按值裁剪
optimizer.step()
# tensor 裁剪
torch.clamp(input, min, max, out=None)
with open('model.pkl', 'rb') as f:
model = pickle.load(f)
user_emb = model.User_Embedding.weight.detach().cpu().numpy() # to numpy
with open('weight.pkl', 'wb') as f:
pickle.dump(user_emb, f)
# load to a embedding
import torch
u = torch.nn.Embedding(nums. emb_dim) # 初始化相同规模
u.weight.data.copy_(torch.from_numpy(user_emb)) # 赋值权重
torch.gather(input, dim, index, out=None) → Tensor
一般说来,input和index都是相似维度的
具体案例:如何做到batch index select/gather
q_a_s = torch.randn(64, 30, 64)
q_i_s_exp = torch.randn(64, 30, 64)
q_a_s_sim = torch.topk(torch.sum(q_a_s * q_i_s_exp, dim=3), 30, dim=2)[1] # 计算相似性后,取相似度top 30 index, B * maxu_len * 30
dy_qas = q_a_s_sim.unsqueeze(3).expand(q_a_s_sim.size(0), q_a_s_sim.size(1), q_a_s_sim.size(2), x_ia_s.size(3)) # 按照计算出来的相似度,取原来tensor对应位置的信息
new_x_ia_s = torch.gather(x_ia_s, 2, dy_qas)
new_mask_s = torch.gather(mask_s, 2, q_a_s_sim)
import os
cpu_num = 4 # 这里设置成你想运行的CPU个数
# cpu_num = cpu_count() # 自动获取最大核心数目
os.environ ['OMP_NUM_THREADS'] = str(cpu_num)
os.environ ['OPENBLAS_NUM_THREADS'] = str(cpu_num)
os.environ ['MKL_NUM_THREADS'] = str(cpu_num)
os.environ ['VECLIB_MAXIMUM_THREADS'] = str(cpu_num)
os.environ ['NUMEXPR_NUM_THREADS'] = str(cpu_num)
torch.set_num_threads(cpu_num)