Pytorch Tutorial-Tensors
这是我学习Pytorch时记录的一些笔记 ,希望能对你有所帮助😊
- You will sometimes see a 1-dimensional tensor called a vector.
- Likewise, a 2-dimensional tensor is often referred to as a matrix.
- Anything with more than two dimensions is generally just called a tensor
Creating Tensors
- using factory methods
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20x = torch.empty(3, 4)
print(type(x)) # <class 'torch.Tensor'>
zeros = torch.zeros(2, 3)
print(zeros)
ones = torch.ones(2, 3)
print(ones)
torch.manual_seed(1729)
random = torch.rand(2, 3)
print(random)
# The output
tensor([[0., 0., 0.],
[0., 0., 0.]])
tensor([[1., 1., 1.],
[1., 1., 1.]])
tensor([[0.3126, 0.3791, 0.3087],
[0.0736, 0.4216, 0.0691]])
Random Tensors and Seeding
1 |
|
- 可以发现random1,2 与 3,4完全一致,随机数生成器的种子都是1729,这样可以保证“结果可复现”
- r1与r2的值不同,因为生成r1后随机数生成器的状态更新了,而r3相当于重置了,类似于execve
Tensor Shapes
- when you’re performing operations on two or more tensors, they will need to be of the same shape - that is, having the same number of dimensions and the same number of cells in each dimension. For that, we have the
torch.*_like()
methods:
1 |
|
- Below that, we call the
.empty_like()
,.zeros_like()
, and.rand_like()
methods. Using the.shape
property, we can verify that each of these methods returns a tensor of identical dimensionality and extent.
1 |
|
- Using
torch.tensor()
is the most straightforward way to create a tensor if you already have data in a Python tuple or list. As shown above, nesting the collections will result in a multi-dimensional tensor.(嵌套集合将产生多维张量)
Note:torch.tensor()
creates a copy of the data.
Tensor Data Types
默认是float32,
Available data types include:
torch.bool
torch.int8
torch.uint8
torch.int16
torch.int32
torch.int64
torch.half
torch.float
torch.double
torch.bfloat
设置数据类型有两种方式,一是在创建时设置,二是使用.to()
函数
1 |
|
Math & Logic with Tensors
- 大部分运算都和你的直觉差不多,而且比较“聪明”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31ones = torch.zeros(2, 2) + 1
twos = torch.ones(2, 2) * 2
threes = (torch.ones(2, 2) * 7 - 1) / 2
fours = twos ** 2
sqrt2s = twos ** 0.5
tensor([[1., 1.],
[1., 1.]])
tensor([[2., 2.],
[2., 2.]])
tensor([[3., 3.],
[3., 3.]])
tensor([[4., 4.],
[4., 4.]])
tensor([[1.4142, 1.4142],
[1.4142, 1.4142]])
powers2 = twos ** torch.tensor([[1, 2], [3, 4]])
print(powers2)
fives = ones + fours
print(fives)
dozens = threes * fours
print(dozens)
tensor([[ 2., 4.],
[ 8., 16.]])
tensor([[5., 5.],
[5., 5.]])
tensor([[12., 12.],
[12., 12.]])
In Brief: Tensor Broadcasting
1 |
|
The rules for broadcasting are:
- Each tensor must have at least one dimension - no empty tensors.
- Comparing the dimension sizes of the two tensors, going from last to first 从后往前:
- Each dimension must be equal, or
- One of the dimensions must be of size 1, or
- The dimension does not exist in one of the tensors
- some correct examples:For more information on broadcasting, see the PyTorch documentation on the topic.
1
2
3
4
5
6
7
8
9
10a = torch.ones(4, 3, 2)
b = a * torch.rand( 3, 2) # 3rd & 2nd dims identical to a, dim 1 absent
print(b)
c = a * torch.rand( 3, 1) # 3rd dim = 1, 2nd dim identical to a
print(c)
d = a * torch.rand( 1, 2) # 3rd dim identical to a, 2nd dim = 1
print(d)
More Math with Tensors
This is a small sample of For more details and the full inventory of math functions, have a look at the documentation.
给出一些经典示例:
1 |
|
Copying Tensors
- clone()
1
2
3
4
5
6
7
8a = torch.ones(2, 2)
b = a.clone()
assert b is not a # different objects in memory...
print(torch.eq(a, b)) # ...but still with the same contents!
a[0][1] = 561 # a changes...
print(b) # ...but b is still all ones - There is an important thing to be aware of when using
clone()
. If your source tensor has autograd, enabled then so will the clone.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19a = torch.rand(2, 2, requires_grad=True) # turn on autograd
print(a)
b = a.clone()
print(b)
c = a.detach().clone()
print(c)
print(a)
tensor([[0.5461, 0.5396],
[0.3053, 0.1973]], requires_grad=True)
tensor([[0.5461, 0.5396],
[0.3053, 0.1973]], grad_fn=<CloneBackward>)
tensor([[0.5461, 0.5396],
[0.3053, 0.1973]])
tensor([[0.5461, 0.5396],
[0.3053, 0.1973]], requires_grad=True) - The
detach()
method detaches the tensor from its computation history. It says, “do whatever comes next as if autograd was off.” It does this without changinga
- you can see that when we printa
again at the end, it retains itsrequires_grad=True
property.
Moving to GPU
引入:One of the major advantages of PyTorch is its robust acceleration on CUDA-compatible Nvidia GPUs. (“CUDA” stands for Compute Unified Device Architecture, which is Nvidia’s platform for parallel computing.) So far, everything we’ve done has been on CPU. How do we move to the faster hardware?
1 |
|
CPU在RAM中进行计算,而GPU提供了附加内存,用GPU计算时需要将数据迁移到GPU
创建时迁移
张量默认创建在CPU上,你可以使用
device
来制定设备1
2
3
4
5if torch.cuda.is_available():
gpu_rand = torch.rand(2, 2, device='cuda')
print(gpu_rand)
else:
print('Sorry, CPU only.')一个好的习惯是使用
my_device
来表征自己的设备,而不直接使用字符串1
2
3
4
5if torch.cuda.is_available():
my_device = torch.device('cuda')
else:
my_device = torch.device('cpu')
print('Device: {}'.format(my_device))
to()迁移
1 |
|
It is important to know that in order to do computation involving two or more tensors, all of the tensors must be on the same device.
Manipulating Tensor Shapes
PyTorch models generally expect batches of input.For example, imagine having a model that works on 3 x 226 x 226 images - a 226-pixel square with 3 color channels. When you load and transform it, you’ll get a tensor of shape (3, 226, 226)
. Your model, though, is expecting input of shape (N, 3, 226, 226)
, where N
is the number of images in the batch. So how do you make a batch of one?
1 |
|
- The
unsqueeze()
method adds a dimension of extent 1.unsqueeze(0)
adds it as a new zeroth dimension - now you have a batch of one!
1 |
|
- 其实增加或减少一个范围为1的维度,其实对数据本身并没有影响,这也能提示我们: Calls to
squeeze()
andunsqueeze()
can only act on dimensions of extent 1 because to do otherwise would change the number of elements in the tensor.
1 |
|
Sometimes you’ll want to change the shape of a tensor more radically, while still preserving the number of elements and their contents. One case where this happens is at the interface between a convolutional layer of a model and a linear layer of the model - this is common in image classification models. A convolution kernel will yield an output tensor of shape features x width x height, but the following linear layer expects a 1-dimensional input. reshape()
will do this for you, provided that the dimensions you request yield the same number of elements as the input tensor has:
1 |
|
NumPy Bridge
NumPy 有和张量比较想通的地方,比如Broadcast
,所以在二者之间转换很容易
1 |
|
- PyTorch 创建了一个与 NumPy 数组具有相同形状并包含相同数据的张量,甚至保留了 NumPy 默认的 64 位浮点数据类型。
1 |
|
这些都不重要,重要的是要知道这些转换后的对象使用与其源对象有相同的底层内存_ ,这意味着对一个对象的更改会反映在另一个对象中:
1 |
|