我们在上一章节介绍了关于 torch 的常用指令后, 现在来做一些简易的计算, 通过这些建议的运算指令, 可以更好的帮助我们理解 torch 中张量在运算中是怎么表现的.
Torch的基本运算
首先导入需要的包
要想启动Pytorch的功能,首先需要导入Pytorch的包
import torch
它包含torch的主要功能,而如果需要用到扩展功能,例如torch包含的公开数据集、通用的网络结构,或者一些图像矩阵工具等,就可以:
from torchvision import datasets
from torchvision import models
from torchvision import transforms
from torchvision import utils
通常情况下,我们可能还会用到 numpy 跟其他框架做数据交互, 比方说用 OpenCV 采集摄像头数据并且做一些简单的滤波后,再把数据传给 torch 做逻辑推理。 又比如说,我们可能还会用到 matplotlib 框架,把 torch 的计算结果绘制成科学插图的形式, 那么就可以导入这些包:
import numpy as np
import matplotlib as plt
创建一些简单的矩阵和向量
科学计算工具,最重要的一个工作就是具备处理矩阵和向量的能力。在 torch 没有指定具体的结构去处理向量和矩阵,所以我们需要通过规范的命名来避免矩阵和向量的混用。首先,我们先用不同的形式创建两组张量。
mat_1 = torch.tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
ndata_1 = np.array([[0, 2, 4, 6, 8], [11, 13, 15, 17, 19]])
mat_2 = torch.from_numpy(ndata_1)
然后,我们在创建两组由
(
i
,
j
,
k
)
(i, j, k)
(i,j,k) 组成的向量
vects_1 = torch.randn(4, 3)
vects_2 = torch.ones(4, 3)
好,对于所有的张量的加法、减法运算,都是一样的,而我们需要特别注意的是,对于向量、矩阵来说,乘法和除法则有很大的不同,具体的你可以看一些线性代数方面的资料了解一下。
加法运算 torch.add(…)
函数原型
torch.add(input, other, *, out=None) -> Tensor
o
u
t
=
i
n
p
u
t
+
o
t
h
e
r
out = input + other
out=input+other
如果是张量之间的加法,要求两个张量的大小、维度必须一致。而如果是张量对常数的加法,则遵循一般原则:
>>> a = torch.randn(4)
>>> a
tensor([ 0.0202, 1.0985, 1.3506, -0.6056])
>>> torch.add(a, 20)
tensor([ 20.0202, 21.0985, 21.3506, 19.3944])
此外,我们也可以直接用 + 运算符执行加法运算。
>>> mat_res = mat_1 + mat_2
>>> mat_res
tensor([[ 1, 4, 7, 10, 13],
[17, 20, 23, 26, 29]])
>>> mat_res = mat_1 + 5
>>> mat_res
tensor([[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
减法运算 torch.sub(…)
函数原型
torch.sub(input, other, *, alpha=1, out=None) -> Tensor
加法运算的逆运算,基本规则跟加法一样,只不过多了一个alpha,可以执行倍减运算。
o
u
t
i
=
i
n
p
u
t
i
?
a
l
p
h
a
×
o
t
h
e
r
i
out_i = input_i ? alpha × other_i
outi?=inputi??alpha×otheri?
>>> a = torch.tensor((1, 2))
>>> b = torch.tensor((0, 1))
>>> torch.sub(a, b, alpha=2)
tensor([1, 0])
同样,Python的减法运算符也被重栽,可以直接支持张量的减法运算。
>>> mat_res = mat_2 - mat_1
>>> mat_res
tensor([[-1, 0, 1, 2, 3],
[ 5, 6, 7, 8, 9]])
对于我们来说,乘法除了常量运算,还有向量乘法、矩阵乘法的运算,在 PyTorch 中也是一样的。
向量乘法运算
向量点乘(内积)torch.dot(…)
函数原型
torch.dot(input, other, *, out=None) -> Tensor
需要注意的是,这个函数只支持1维运算,而且两个张量的维度必须一样。
a
?
?
b
?
=
(
a
1
,
a
2
,
?
?
,
a
n
)
?
(
b
1
,
b
2
,
?
?
,
b
n
)
\vec{a} \cdot \vec{b} = (a_1, a_2, \cdots, a_n) \cdot (b_1, b_2, \cdots, b_n)
a
?b
=(a1?,a2?,?,an?)?(b1?,b2?,?,bn?)
=
a
1
b
1
+
a
2
b
2
+
?
+
a
n
b
n
= a_1 b_1 + a_2 b_2 + \cdots + a_n b_n
=a1?b1?+a2?b2?+?+an?bn?
>>> torch.dot(torch.tensor([1, 2, 3, 4]), torch.tensor([7, 8, 9, 0]))
tensor(50)
向量叉乘(外积)torch.cross(…)
函数原型
torch.cross(input, other, dim=None, *, out=None) -> Tensor
我第一次用 torch 的时候,想当然的觉得cross函数应该是矩阵外积,结果各种报错。 后来仔细看了文档,才发现torch另外定义了矩阵外积的函数名,而cross则是专用于向量外积的。 而且这个函数比较诡异的是,它可以支持多组向量外积, 而且要求进行计算的向量必须是三维的(也就意味着,如果你试图做二维向量外积,需要给第三维填充0)。
a
?
×
b
?
=
(
a
i
,
a
j
,
a
k
)
×
(
b
i
,
b
j
,
b
k
)
=
∣
i
j
k
a
i
a
j
a
k
b
i
b
j
b
k
∣
\vec{a} \times \vec{b} = (a_i, a_j, a_k) \times (b_i, b_j, b_k) = \begin{vmatrix} i & j & k \\ a_i & a_j & a_k \\ b_i & b_j & b_k \end{vmatrix}
a
×b
=(ai?,aj?,ak?)×(bi?,bj?,bk?)=∣∣∣∣∣∣?iai?bi??jaj?bj??kak?bk??∣∣∣∣∣∣?
>>> a = torch.randn(4, 3)
>>> a
tensor([[-0.3956, 1.1455, 1.6895],
[-0.5849, 1.3672, 0.3599],
[-1.1626, 0.7180, -0.0521],
[-0.1339, 0.9902, -2.0225]])
>>> b = torch.randn(4, 3)
>>> b
tensor([[-0.0257, -1.4725, -1.2251],
[-1.1479, -0.7005, -1.9757],
[-1.3904, 0.3726, -1.1836],
[-0.9688, -0.7153, 0.2159]])
>>> torch.cross(a, b, dim=1)
tensor([[ 1.0844, -0.5281, 0.6120],
[-2.4490, -1.5687, 1.9792],
[-0.8304, -1.3037, 0.5650],
[-1.2329, 1.9883, 1.0551]])
>>> torch.cross(a, b)
tensor([[ 1.0844, -0.5281, 0.6120],
[-2.4490, -1.5687, 1.9792],
[-0.8304, -1.3037, 0.5650],
[-1.2329, 1.9883, 1.0551]])
矩阵乘法运算
矩阵内积 无
在最新的版本里,貌似取消了矩阵内积的支持,但也并不意味着你不能做矩阵的内积了。 我们可以通过这些方法,实现矩阵的内积运算。
>>> ret = torch.mul(mat_1, mat_2)
>>> torch.sum(ret.view(-1))
tensor(700)
矩阵外积 torch.mm(…)
torch.mm(input, mat2, *, out=None) -> Tensor
PyTorch 提供了另外一个函数指令执行矩阵乘法,你需要注意的就是 两矩阵的纬度问题, 如果第一个矩阵的大小是
(
n
×
m
)
(n \times m)
(n×m) 第二个矩阵的纬度是
(
m
×
p
)
(m \times p)
(m×p), 得到的新矩阵是
(
n
×
p
)
(n \times p)
(n×p)。
A
23
×
B
32
=
[
a
00
a
01
a
02
a
10
a
11
a
12
]
×
[
b
00
b
01
b
10
b
11
b
20
b
21
]
A_{23} \times B_{32} = \begin{bmatrix} a_{00} & a_{01} & a_{02} \\ a_{10} & a_{11} & a_{12} \end{bmatrix} \times \begin{bmatrix} b_{00} & b_{01} \\ b_{10} & b_{11} \\ b_{20} & b_{21} \end{bmatrix}
A23?×B32?=[a00?a10??a01?a11??a02?a12??]×???b00?b10?b20??b01?b11?b21?????
>>> mat1 = torch.randn(2, 3)
>>> mat2 = torch.randn(3, 3)
>>> torch.mm(mat1, mat2)
tensor([[ 0.4851, 0.5037, -0.3633],
[-0.0760, -3.6705, 2.4784]])
矩阵哈达玛积 torch.mul(…)
torch.mul(input, other, *, out=None) -> Tensor
这是最常见的一种矩阵乘法运算,你可以理解为元素积。 如果你要使用两个张量执行哈达玛积,那么需要注意张量纬度以及大小的一致性。
A
°
B
=
[
a
00
?
b
00
,
a
01
?
b
01
,
?
a
0
j
?
b
0
j
a
10
?
b
10
,
a
11
?
b
11
,
?
a
1
j
?
b
1
j
?
?
?
?
a
i
0
?
b
i
0
,
a
i
1
?
b
i
1
,
?
a
i
j
?
b
i
j
]
A \circ B =\begin{bmatrix} a_{00} \cdot b_{00}, & a_{01} \cdot b_{01}, & \cdots &a_{0j} \cdot b_{0j} \\ a_{10} \cdot b_{10}, & a_{11} \cdot b_{11}, & \cdots & a_{1j} \cdot b_{1j} \\ \cdots & \cdots & \cdots & \cdots\\ a_{i0} \cdot b_{i0}, & a_{i1} \cdot b_{i1}, & \cdots & a_{ij} \cdot b_{ij} \end{bmatrix}
A°B=?????a00??b00?,a10??b10?,?ai0??bi0?,?a01??b01?,a11??b11?,?ai1??bi1?,??????a0j??b0j?a1j??b1j??aij??bij???????
>>> a = torch.randn(3)
>>> a
tensor([ 0.2015, -0.4255, 2.6087])
>>> torch.mul(a, 100)
tensor([ 20.1494, -42.5491, 260.8663])
除此以外,python的 * 运算符也重载了这个运算,不过我不推荐大家使用 * 做张量的运算。
>>> ret = torch.mul(mat_1, mat_2)
tensor([[ 0, 4, 12, 24, 40],
[ 66, 91, 120, 153, 190]])
>>> ret = mat_1 * mat_2
tensor([[ 0, 4, 12, 24, 40],
[ 66, 91, 120, 153, 190]])
除法运算 torch.div(…)
torch.div(input, other, *, rounding_mode=None, out=None) -> Tensor
除法运算,是torch中实现的一种特殊的运算,本质上是元素乘(哈达玛积)的逆运算。 支持张量对常数的除法。 如果想要实现两个张量之间的除法,要求作为input的张量
(
N
×
M
)
(N \times M)
(N×M) ,其对应的other张量 纬度应该是
(
1
×
M
)
(1 \times M)
(1×M),或者与input张量的纬度一致
(
N
×
M
)
(N \times M)
(N×M)。
o
u
t
i
=
i
n
p
u
t
i
o
t
h
e
r
i
out_i = \frac{input_i}{other_i}
outi?=otheri?inputi??
>>> x = torch.tensor([ 0.3810, 1.2774, -0.2972, -0.3719, 0.4637])
>>> torch.div(x, 0.5)
tensor([ 0.7620, 2.5548, -0.5944, -0.7438, 0.9274])
>>> a = torch.tensor([[-0.3711, -1.9353, -0.4605, -0.2917],
... [ 0.1815, -1.0111, 0.9805, -1.5923],
... [ 0.1062, 1.4581, 0.7759, -1.2344],
... [-0.1830, -0.0313, 1.1908, -1.4757]])
>>> b = torch.tensor([ 0.8032, 0.2930, -0.8113, -0.2308])
>>> torch.div(a, b)
tensor([[-0.4620, -6.6051, 0.5676, 1.2639],
[ 0.2260, -3.4509, -1.2086, 6.8990],
[ 0.1322, 4.9764, -0.9564, 5.3484],
[-0.2278, -0.1068, -1.4678, 6.3938]])
>>> torch.div(a, b, rounding_mode='trunc')
tensor([[-0., -6., 0., 1.],
[ 0., -3., -1., 6.],
[ 0., 4., -0., 5.],
[-0., -0., -1., 6.]])
>>> torch.div(a, b, rounding_mode='floor')
tensor([[-1., -7., 0., 1.],
[ 0., -4., -2., 6.],
[ 0., 4., -1., 5.],
[-1., -1., -2., 6.]])
|