3.计算d(h+l,t)
它衡量了 h+l 与 t 的距离,可以采用 L1 或 L2 norm 来算,具体采用哪个由 __init__ 函数中的 self.norm 来决定:
class E(nn.Module):
def distance(self, h, r, t):
# 在 tensor 的指定维度操作就是对指定维度包含的元素进行操作,如果想要保持结果的维度不变,设置参数keepdim=True即可
# 如 下面sum中 r_norm * h 结果是一个1024 *50的矩阵(2维张量) sum在dim的结果就变成了 1024的向量(1位张量) 如果想和r_norm对应元素两两相乘
# 就需要sum的结果也是2维张量 因此需要使用keepdim= True报纸张量的维度不变
# 另外关于 dim 等于几表示张量的第几个维度,从0开始计数,可以理解为张量的最开始的第几个左括号,具体可以参考这个https://www.cnblogs.com/flix/p/11262606.html
head = self.ent_embedding(h)
rel = self.rel_embedding(r)
tail = self.ent_embedding(t)
distance = head + rel - tail
# dim = -1表示的是维度的最后一维 比如如果一个张量有3维 那么 dim = 2 = -1, dim = 0 = -3
score = torch.norm(distance, p = self.norm, dim=1)
return score
4.计算loss
class E(nn.Module):
def scale_loss(self, embedding):
return torch.sum(
torch.max(
torch.sum(
embedding ** 2, dim=1, keepdim=True
)-torch.autograd.Variable(torch.FloatTensor([1.0]).cuda()),
torch.autograd.Variable(torch.FloatTensor([0.0]).cuda())
))
(1)torch.sum(input, dim, keepdim=False, *, dtype=None):返回给定维度dim中输入张量的每一行的总和。如果dim是一个维度列表,则对所有维度进行缩小。如果keepdim为True,则输出张量的大小与输入的大小相同,但维度dim的大小为1。否则,dim会被挤压(参考torch.squeeze())。
参数:
input:输入张量
dim:[可选, int/tuple] 要减少的一个或多个维度。如果为None,则所有维度都将被裁剪。
keepdim:[bool] 输出张量是否保留了dim。
dtype:[可选, torch.dtype] 返回张量的所需数据类型。如果指定,则在执行操作之前将输入张量强制转换为dtype。这对于防止数据类型溢出非常有用,默认值为None。
https://blog.csdn.net/hy592070616/article/details/131967720
(2)torch.max(input, other, out=None) → Tensor
返回输入张量给定维度上每行的最大值,并同时返回每个最大值的位置索引。
即,( out_i=max(input_i,other_i) \)
参数:
input (Tensor) – 输入张量
other (Tensor) – 输出张量
out (Tensor, optional) – 结果张量
https://blog.csdn.net/ViatorSun/article/details/108909312
(3)autograd及Variable
Autograd:自动微分
autograd包是PyTorch中神经网络的核心,它可以为基于tensor的所有操作提供自动微分的功能,这是一个逐个运行的框架,意味着反向传播是根据你的代码来运行的,并且每一次的迭代运行都可能不同。
Variable:tensor是硬币的话,那Variable就是钱包,它记录着里面的钱的多少和钱的去向
autograd.Variable是包的中央类,它包裹着Tensor,支持几乎所有Tensor的操作,并附加额外的属性。
Tensor是存在Variable中的.data里的,而CPU和GPU的数据是通过.cpu()和.cuda()来转换的。
注:在 torch0.4 以后 torch.autograd.Variable 直接用 torch.tensor()就可以搞定所有啦!
https://zhuanlan.zhihu.com/p/34298983
5.forward函数
class E(nn.Module):
def forward(self, current_triples, corrupted_triples):
h, r, t = torch.chunk(current_triples, 3, dim=1)
h_c, r_c, t_c = torch.chunk(corrupted_triples, 3, dim=1)
h = torch.squeeze(h, dim=1).cuda()
r = torch.squeeze(r, dim=1).cuda()
t = torch.squeeze(t, dim=1).cuda()
h_c = torch.squeeze(h_c, dim=1).cuda()
r_c = torch.squeeze(r_c, dim=1).cuda()
t_c = torch.squeeze(t_c, dim=1).cuda()
# torch.nn.embedding类的forward只接受longTensor类型的张量
pos = self.distance(h, r, t)
neg = self.distance(h_c, r_c, t_c)
entity_embedding = self.ent_embedding(torch.cat([h, t, h_c, t_c]).cuda())
relation_embedding = self.rel_embedding(torch.cat([r, r_c]).cuda())
# loss_F = max(0, -y*(x1-x2) + margin)
# loss1 = torch.sum(torch.relu(pos - neg + self.margin))
y = Variable(torch.Tensor([-1])).cuda()
loss = self.loss_F(pos, neg, y)
ent_scale_loss = self.scale_loss(entity_embedding)
rel_scale_loss = self.scale_loss(relation_embedding)
return loss + self.C * (ent_scale_loss/len(entity_embedding) + rel_scale_loss/len(relation_embedding))
关于pytorch:
一、Pytorch是什么?
Pytorch是torch的python版本,是由Facebook开源的神经网络框架,专门针对 GPU 加速的深度神经网络(DNN)编程。Torch 是一个经典的对多维矩阵数据进行操作的张量(tensor )库,在机器学习和其他数学密集型应用有广泛应用。与Tensorflow的静态计算图不同,pytorch的计算图是动态的,可以根据计算需要实时改变计算图。但由于Torch语言采用 Lua,导致在国内一直很小众,并逐渐被支持 Python 的 Tensorflow 抢走用户。作为经典机器学习库 Torch 的端口,PyTorch 为 Python 语言使用者提供了舒适的写代码选择。
它主要提供了以下两种核心功能:
1.支持GPU加速的张量计算。
2.方便优化模型的自动微分机制。
二、Pytorch的主要优点:
1.简洁:
PyTorch的设计追求最少的封装,尽量避免重复造轮子。不像 TensorFlow 中充斥着session、graph、operation、name_scope、variable、tensor、layer等全新的概念,PyTorch 的设计遵循tensor→variable(autograd)→nn.Module 三个由低到高的抽象层次,分别代表高维数组(张量)、自动求导(变量)和神经网络(层/模块),而且这三个抽象之间联系紧密,可以同时进行修改和操作。 简洁的设计带来的另外一个好处就是代码易于理解。PyTorch的源码只有TensorFlow的十分之一左右,更少的抽象、更直观的设计使得PyTorch的源码十分易于阅读。有一个这样的段子,说TensorFlow的设计哲学是 Make it complicated, Keras 的设计哲学是 Make it complicated and hide it,而Pytorch的设计哲学是 Keep it simple and stupid。
2.速度:
PyTorch 的灵活性不以速度为代价,在许多评测中,PyTorch 的速度表现胜过 TensorFlow和Keras 等框架。框架的运行速度和程序员的编码水平有极大关系,但同样的算法,使用PyTorch实现的那个更有可能快过用其他框架实现的。
3.易用:
PyTorch 是所有的框架中面向对象设计的最优雅的一个。PyTorch的面向对象的接口设计来源于Torch,而Torch的接口设计以灵活易用而著称,Keras作者最初就是受Torch的启发才开发了Keras。PyTorch继承了Torch的衣钵,尤其是API的设计和模块的接口都与Torch高度一致。PyTorch的设计最符合人们的思维,Pytorch提供了非常丰富的模型组件,它让用户尽可能地专注于实现自己的想法,即所思即所得,不需要考虑太多关于框架本身的束缚。并且运行速度很快。目前大部分深度学习相关的Paper都是用Pytorch实现的。
4.活跃的社区:
PyTorch 提供了完整的文档,循序渐进的指南。Facebook 人工智能研究院对 PyTorch 提供了强力支持,作为当今排名前三的深度学习研究机构,FAIR的支持足以确保PyTorch获得持续的开发更新,不至于像许多由个人开发的框架那样昙花一现。
5.便于调试:
Pytorch采用动态图,可以像普通Python代码一样进行调试。不同于TensorFlow, Pytorch的报错说明通常很容易看懂。有一个这样的段子,说你永远不可能从TensorFlow的报错说明中找到它出错的原因。
参考: