字幕组双语原文:深度学习基础:张量运算

英语原文:Tensor Operations — Basic Building Blocks of Deep Learning

2012-至今:深度学习爆炸时代

在2012年的Imagenet运动之后,深度学习取得了突飞猛进的发展。 深度学习现在已经成为我们日常生活中不可或缺的一部分,当我们与语音助手交谈、使用家庭自动化系统、写电子邮件等时,许多算法都在运行。事实上,它的影响是如此之大,以至于我们可以在亚马逊上看到名为“婴儿的神经网络”的书籍:D

“深度”学习是如何发生的?

就其核心而言,深度学习只不过是人脑工作方式的缩影(忽略了人脑中存在的实际复杂性,这种复杂性仍然很难复制)。 计算机使用成百上千个跨越深层的神经元连接从它的输入和输出中学习(因此有了“深度学习”这个词)。

每一个神经元连接都有与自身相关的不同重量。

在每次迭代中对权值进行优化,使预测损失最小化,并以最高精度预测输出。计算机是机器,机器只懂数字。因此,在底层,我们讨论的所有这些权重都是n维矩阵或张量。

由于每个权值都是一个n维矩阵或张量,权值的学习和优化涉及数百万个矩阵乘法。在过去的6-7年中,我们已经看到许多DL框架的出现,它们简化了这个任务。

五大深度学习框架(Pythorch、Tensorflow、Keras、CNTK、Caffe)

什么是Pytorch

Pytorch是一个流行的深度学习框架,由Facebook人工智能研究(FAIR)开发和维护,用于处理张力。自2016年1.0.0发布以来,由于使用的简单性和灵活性,它获得了极大的普及。在本文中,我们将主要关注使用Pytorch的一些核心张量运算。您可能想通过这个博客了解如何安装PyTorch的详细说明。

torch.size

torch.mm

torch.cat

torch.mul

torch.inverse

1.torch.size

Torch.size返回任何输入张量的维度。

x = torch.tensor([

[[1, 2, 3, 4],

[3, 4., 6, 7]],

[[10,20,30,40],

[20,30,40,50]],

[[5,6,7,8],

[9,10,11,12]]

])

x.size()

torch.Size([3, 2, 4])

在上面的示例中,我创建了一个3X2X4张量,torch.size返回3个维度。 我们的张量在外括号内有3个元素,每个元素都是一个矩阵。 每个矩阵同样有2个元素,每个元素都是一个包含4个元素的列表。

2.torch.mm

torch.mm返回任意两个输入矩阵matr1和mat2的矩阵乘法(不是元素一一对应相乘)

mat1 = torch.tensor([[1,2,3],

[4,5,6],

[6,7,8]])

mat2 = torch.tensor([[10,20,30],

[40,50,60],

[60,70,80]])

x = torch.mm(mat1, mat2)

y = mat1@mat2

x,y

(tensor([[ 270, 330, 390], [ 600, 750, 900], [ 820, 1030, 1240]]), tensor([[ 270, 330, 390], [ 600, 750, 900], [ 820, 1030, 1240]]))

在上面的示例中,mat1和mat2的大小均为3X3。 因此,torch.mm的输出大小也为3X3。 我们可以看到可以使用“ @”运算符代替torch.mm来执行相同的操作。

使用torch.mm()时要注意的几点

第一个输入矩阵的列大小应等于第二个输入矩阵的行大小

对于不是矩阵或大于2维的张量,torch.mm不起作用,我们可以使用torch.mul进行逐个元素的乘法

‘@运算符执行与torch.mm相同的操作

3.torch.cat

Torch.cat可以水平或垂直连接2个张量

#假设我们有以下2个张量,并尝试垂直连接它门x = torch.tensor([[1,3],

[2,5],

[3,6]])

y = torch.tensor([[10,30],

[20,50],

[30,60]])

z = torch.cat((x,y))

z

tensor([[ 1, 3], [ 2, 5], [ 3, 6], [10, 30], [20, 50], [30, 60]])

我们可以看到,张量y已经堆叠在张量x的下方。

# 现在我们尝试着将它们水平连接起来x = torch.tensor([[1,3],

[2,5],

[3,6]])

y = torch.tensor([[10,30],

[20,50],

[30,60]])

z = torch.cat((x,y), dim = 1)

z

tensor([[ 1, 3, 10, 30], [ 2, 5, 20, 50], [ 3, 6, 30, 60]])

通过使用dim参数并将其设置为1,我们可以水平连接2个张量。 默认设置为0,这将导致垂直串联。

使用torch.cat时的注意事项

使用dim = 1来水平连接张量

可以连接任意数量的张量,但是,请确保张量在串联方向上的大小应相同

4.torch.mul

torch.mul 可对2个张量进行逐元素乘法。

mat1 = torch.tensor([[[1,2,3],

[4,5,6]],

[[5,6,7],

[8,9,10]],

[[11,12,13],

[13,14,15]]])

mat2 = torch.tensor([[[10,20,30],

[40,50,60]],

[[50,60,70],

[80,90,100]],

[[110,120,130],

[130,140,150]]])

x = torch.mul(mat1, mat2)

y = mat1 * mat2

z = mat1.mul(mat2)

x,y,z

(tensor([[[ 10, 40, 90],

[ 160, 250, 360]],

[[ 250, 360, 490],

[ 640, 810, 1000]],

[[1210, 1440, 1690],

[1690, 1960, 2250]]]),

tensor([[[ 10, 40, 90],

[ 160, 250, 360]],

[[ 250, 360, 490],

[ 640, 810, 1000]],

[[1210, 1440, 1690],

[1690, 1960, 2250]]]),

tensor([[[ 10, 40, 90],

[ 160, 250, 360]],

[[ 250, 360, 490],

[ 640, 810, 1000]],

[[1210, 1440, 1690],

[1690, 1960, 2250]]]))

我们可以看到逐元素乘法适用于任何维度的张量。使用*运算符或者使用a.mul(b),其中a和b为输入张量,也可以实现torch.mul的功能。

mat1 = torch.randn(1,1,4)

mat2 = torch.randn(2,2,4)

x = torch.mul(mat1, mat2)

y = mat1 * mat2

z = mat1.mul(mat2)

x,y,z

(tensor([[[ 0.3923, 1.2011, -0.7222, -0.0097],

[-0.3082, -0.7667, 0.0777, -0.1011]],

[[-0.0289, 0.6919, 0.2720, -0.0952],

[-0.3427, -1.1867, -1.0518, -0.0562]]]),

tensor([[[ 0.3923, 1.2011, -0.7222, -0.0097],

[-0.3082, -0.7667, 0.0777, -0.1011]],

[[-0.0289, 0.6919, 0.2720, -0.0952],

[-0.3427, -1.1867, -1.0518, -0.0562]]]),

tensor([[[ 0.3923, 1.2011, -0.7222, -0.0097],

[-0.3082, -0.7667, 0.0777, -0.1011]],

[[-0.0289, 0.6919, 0.2720, -0.0952],

[-0.3427, -1.1867, -1.0518, -0.0562]]]))

Torch.mul can be used for broadcasting of tensors. For tensors to be broadcastable, the following conditions should be met:

Each tensor should have atleast one dimension

When iterating over the dimension sizes, starting at the trailing dimension,

the dimension sizes must either be equal,

one of them is 1, or

one of them does not exist.

使用torch.mul时要注意的几点

torch.mul类似于两个向量之间的点积。

“ *”运算符或a.mul(b)也执行与torch.mm相同的操作

输入张量应满足广播条件

5.torch.inverse

torch.inverse计算任意张量的逆

x = torch.rand(4, 4)

print(x)

y = torch.inverse(x)

print(y)

print(x@y)

tensor([[0.5113, 0.6916, 0.4692, 0.0154],

[0.3848, 0.3022, 0.0248, 0.9268],

[0.8846, 0.6778, 0.0108, 0.8708],

[0.2503, 0.9674, 0.8385, 0.3985]])

tensor([[ 5.4673, 3.9426, -2.8567, -3.1387],

[-7.0532, -7.4136, 6.1454, 4.0863],

[ 6.5743, 6.5758, -5.9237, -2.6038],

[-0.1456, 1.6838, -0.6596, 0.0402]])

tensor([[ 1.0000e+00, -5.8052e-07, -4.9533e-08, 2.9703e-09],

[ 2.4891e-07, 1.0000e+00, -2.3864e-08, -1.8278e-07],

[ 3.2888e-07, 2.2601e-08, 1.0000e+00, -1.5329e-07],

[ 3.5323e-07, -2.4265e-08, -4.5756e-07, 1.0000e+00]])

这里,我们通过使用randn函数来建立了一个由随机数组成的4x4张量。torch.inverse可计算x的逆。Inv(x) @ X 则会返回一个单位矩阵。

使用torch.inverse需要注意的几点:

只有在输入张量的各个维度的元素数量相同时才可以正常使用torch.inverse

torch.inverse 同样适用于3维张量。但是张量在各个方向上的维度需要相同或者为方阵张量。

总结

这篇文章里我主要提及了一下几点:

什么是深度学习?

Pytorch是啥?

什么是重要的张量运算?

如何实现执行上述张量运算的核心功能?

使用这些功能时要注意的几点是什么?