PyTorch 基础(1) 张量 Tensor

使用张量处理数据

张量(Tensors)类似于numpy中的ndarrays,Tensors可以在GPU中加速运算。
我们首先导入torch

from __future__ import print_function # python2中使用print()的输出函数
import torch

然后我们创建一个3行和4列的2D数组(通常也叫矩阵),并且把每个元素初始化成0

x = torch.zeros(3, 4)
print(x)

0 0 0 0
0 0 0 0
0 0 0 0
[torch.FloatTensor of size 3x4]

类似的,我们可以创建数组每个元素被初始化成1。

x = torch.ones(3, 4)
print(x)

1 1 1 1
1 1 1 1
1 1 1 1
[torch.FloatTensor of size 3x4]

或者从数组直接构造

x = torch.FloatTensor([[1,2],[3,4]])
print(x)

1 2
3 4
[torch.FloatTensor of size 2x2]

我们经常需要创建随机数组,就是说每个元素的值都是随机采样而来,这个经常被用来初始化模型参数。下面创建数组,它的元素服从均值0方差1的正态分布。

y = torch.randn(3, 4)
print(y)

1.8000 -1.2639 -0.5560 0.4861
-0.7101 -0.1594 -0.8752 -0.1776
-0.5662 -0.1355 -1.0900 -0.1244
[torch.FloatTensor of size 3x4]

每个数组的形状可以通过.shape来获取

print(x.size()) 

(3L, 4L)

它的总元素个数,是形状的累乘。

x_num = x.size(0) * x.size(1)
print(x_num)

12

操作符

PyTorch支持大量的数学操作符,例如按元素加法:

x = torch.FloatTensor([[1,2],[3,4]])
y = torch.FloatTensor([[5,6],[7,8]])
print(x + y) # 或者print(torch.add(x, y))

6 8
10 12
[torch.FloatTensor of size 2x2]

乘法:

print(x * y)

5 12
21 32
[torch.FloatTensor of size 2x2]

指数运算:

print(torch.exp(x))

2.7183 7.3891
20.0855 54.5981
[torch.FloatTensor of size 2x2]

也可以转置一个矩阵然后计算矩阵乘法:

x = torch.FloatTensor([[1,2,3],[4,5,6]])
y = torch.FloatTensor([[7,8,9],[10,11,12]])
print(torch.matmul(x, torch.t(y)))

50 68
122 167
[torch.FloatTensor of size 2x2]

可以索引数组:

x = torch.FloatTensor([[1,2],[3,4]])
print(x[:,1]) #提取第2列

2
4
[torch.FloatTensor of size 2]

形状转换(Broadcasting)

当二元操作符左右两边Tensor形状不一样时,系统会尝试将其复制到一个共同的形状。例如a的第0维是3, b的第0维是1,那么a+b时会将b沿着第0维复制3遍:

a = torch.arange(0, 3).resize_(3, 1)
b = torch.arange(0, 2).resize_(1, 2)
print(a)
print(b)
print(a + b)

0
1
2
[torch.FloatTensor of size 3x1]
0 1
[torch.FloatTensor of size 1x2]
0 1
1 2
2 3
[torch.FloatTensor of size 3x2]

跟NumPy的转换

Tensor可以很方便同numpy进行转换

x = np.ones((2, 3)).astype(np.float32)
y = torch.from_numpy(x) # numpy -> tensor
z = y.numpy() # tensor -> numpy
print(x)
print(y)
print(z)

[[ 1. 1. 1.]
[ 1. 1. 1.]]
1 1 1
1 1 1
[torch.FloatTensor of size 2x3]
[[ 1. 1. 1.]
[ 1. 1. 1.]]

替换操作(In-place)

在前面的样例中,我们为每个操作新开内存来存储它的结果。例如,如果我们写y = x + y, 我们会把y从现在指向的实例转到新建的实例上去。我们可以用Python的id()函数来看这个是怎么执行的:

x = torch.ones(3,4)
y = torch.ones(3,4)
before = id(y)
y = y + x
print(id(y) == before)

False

我们可以把结果通过[:]写到一个之前开好的数组里:

x = torch.ones(3,4)
y = torch.ones(3,4)
z = torch.zeros(x.size())
before = id(z)
z[:] = x + y
print(id(z) == before)

True

但是这里我们还是为x+y创建了临时空间,然后再复制到z。需要避免这个开销,我们可以使用操作符的全名版本中的out参数:

torch.add(x, y, out=z)

如果现有的数组不会复用,我们也可以用y.add_(x)达到这个目的,类似的操作还有x.copy_(y)x.t_()

x = torch.ones(3,4)
y = torch.ones(3,4)
before = id(y)
y.add_(x)
print(id(y) == before)

True

截取(Slicing)

截取x的第2、3行:

x = torch.arange(0,9).resize_(3,3)
print(x)
print(x[1:3])

0 1 2
3 4 5
6 7 8
[torch.FloatTensor of size 3x3]
3 4 5
6 7 8
[torch.FloatTensor of size 2x3]

截取x的第2、3列:

x = torch.arange(0,9).resize_(3,3)
print(x)
print(x[:,1:3])

0 1 2
3 4 5
6 7 8
[torch.FloatTensor of size 3x3]
1 2
4 5
7 8
[torch.FloatTensor of size 3x2]

以及直接写入指定位置:

x[1,2] = 9.0
print(x)

0 1 2
3 4 9
6 7 8
[torch.FloatTensor of size 3x3]

多维截取:

print(x[1:2,1:3])

4 9
[torch.FloatTensor of size 1x2]

多维写入:

x[1:2,1:3] = 9.0
print(x)

0 1 2
3 9 9
6 7 8
[torch.FloatTensor of size 3x3]

GPU计算

通过在张量后加上.cuda()可以把Tensors移动到GPU上

x = torch.arange(0,9).resize_(3,3)
y = torch.arange(1,10).resize_(3,3)
print(x)
print(y)
if torch.cuda.is_available():
    x = x.cuda()
    y = y.cuda()
print(x)
print(y)
print(x+y)

0 1 2
3 4 5
6 7 8
[torch.cuda.FloatTensor of size 3x3 (GPU 0)]
1 2 3
4 5 6
7 8 9
[torch.cuda.FloatTensor of size 3x3 (GPU 0)]
1 3 5
7 9 11
13 15 17
[torch.cuda.FloatTensor of size 3x3 (GPU 0)]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容