本文介绍: (1)首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。(2)如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。例如,如果我们用Y = X + Y,我们将取消引用Y指向的张量, 而是指向新分配的内存处的张量。1. 通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状;可以指定范围以包含第一个元素和最后一个之前的元素。第一个元素 的索引是0,最后一个元素索引是‐1;
一、数据操作
1、基础
import torch
x = torch.arange(12)
# x:tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
x.shape
# torch.Size([12])
x.numel()
# 12
x = x.reshape(3, 4)
# tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
torch.zeros((2, 3, 4))
# tensor([[[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]],
# [[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]]])
torch.ones((2, 3, 4))
# tensor([[[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]],
# [[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]]])
# 从某个特定的概率分布中随机采样来得到张量中每个元素的值。
# 随机初始化参数的值。
torch.randn(3, 4)
# tensor([[-0.0135, 0.0665, 0.0912, 0.3212],
# [ 1.4653, 0.1843, -1.6995, -0.3036],
# [ 1.7646, 1.0450, 0.2457, -0.7732]])
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
# tensor([[2, 1, 4, 3],
# [1, 2, 3, 4],
# [4, 3, 2, 1]])
2、运算符
在相同形状的两个张量上执行按元素操作
import torch
+-*/**运算
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y # **运算符是求幂运算
#(tensor([ 3., 4., 6., 10.]),
# tensor([-1., 0., 2., 6.]),
# tensor([ 2., 4., 8., 16.]),
# tensor([0.5000, 1.0000, 2.0000, 4.0000]),
# tensor([ 1., 4., 16., 64.]))
计算e^x
torch.exp(x)
#tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
张量连结,端对端地叠形成一个更大的张量
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((X, Y), dim=0)
# tensor([[ 0., 1., 2., 3.],
# [ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.],
# [ 2., 1., 4., 3.],
# [ 1., 2., 3., 4.],
# [ 4., 3., 2., 1.]])
torch.cat((X, Y), dim=1)
# tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],
# [ 4., 5., 6., 7., 1., 2., 3., 4.],
# [ 8., 9., 10., 11., 4., 3., 2., 1.]])
通过逻辑运算符构建二元张量
X == Y
# tensor([[False, True, False, True],
# [False, False, False, False],
# [False, False, False, False]])
对张量中的所有元素进行求和,会产生一个单元素张量。
X.sum()
# tensor(66.)
3、广播机制
在不同形状的两个张量上执行操作
1. 通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状;
2. 对生成的数组执行按元素操作。
import torch
a = torch.arange(3)
#tensor([0, 1, 2])
a = torch.arange(3).reshape((3, 1))
#tensor([[0],
# [1],
# [2]])
b = torch.arange(2)
#tensor([0, 1])
b = torch.arange(2).reshape((1, 2))
#tensor([[0, 1]])
a和b分别是3×1和1×2矩阵,如果让它们相加,它们的形状不匹配,可以将两个矩阵广播为一个更大的3×2矩阵。
矩阵a将复制列,矩阵b将复制行(这个过程程序自动执行),然后再按元素相加。
a
# tensor([[0, 0],
# [1, 1],
# [2, 2]])
b
# tensor([[0, 1],
# [0, 1],
# [0, 1]])
a+b
# tensor([[0, 1],
# [1, 2],
# [2, 3]])
4、索引和切片
张量中的元素可以通过索引访问
第一个元素 的索引是0,最后一个元素索引是‐1;
可以指定范围以包含第一个元素和最后一个之前的元素。
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
print(X)
# tensor([[ 0., 1., 2., 3.],
# [ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.]])
print(X[-1])
# tensor([ 8., 9., 10., 11.])
print(X[1:3])
# tensor([[ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.]])
X[1, 2] = 9
print(X)
# tensor([[ 0., 1., 2., 3.],
# [ 4., 5., 9., 7.],
# [ 8., 9., 10., 11.]])
X[0:2, :] = 12
print(X)
# tensor([[12., 12., 12., 12.],
# [12., 12., 12., 12.],
# [ 8., 9., 10., 11.]])
5、节省内存
运行一些操作可能会导致为新结果分配内存。
例如,如果我们用Y = X + Y,我们将取消引用Y指向的张量, 而是指向新分配的内存处的张量。
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
#Python的id()函数提供了内存中引用对象的确切地址。
before = id(Y)
Y = Y + X
print(id(Y) == before)
# False
这可能是不可取的,原因有两个:
(1)首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新;
(2)如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数。
执行原地操作非常简单,使用切片表示法将操作的结果分配给先前分配的数组。
例如Z[:] = <expression>
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
Z = torch.zeros_like(Y) #创建一个新的矩阵Z,其形状与X/Y相同
print('id(Z):', id(Z))
# id(Z): 140070288237104
Z[:] = X + Y
print('id(Z):', id(Z))
# id(Z): 140070288237104
如果在后续计算中没有重复使用X,可以使用X[:] = X + Y或X += Y来减少操作的内存开销。
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
before = id(X)
X += Y
print(id(X) == before)
# True
6、转换为其他Python对象
张量tensor转换为数组张量numpy很容易,反之也同样容易。
torch张量和numpy数组将共享它们的底层内存,就地操作更改一个张量也会同时更改另一个张量。
import torch
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
# tensor([[ 0., 1., 2., 3.],
# [ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.]])
tensor转numpy
A = X.numpy()
# array([[ 0., 1., 2., 3.],
# [ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.]], dtype=float32)
numpy转tensor
B = torch.tensor(A)
# tensor([[ 0., 1., 2., 3.],
# [ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.]])
print(type(A))
# <class 'numpy.ndarray'>
print(type(B))
# <class 'torch.Tensor'>
两者之间的区别
- PyTorch Tensors:PyTorch 中的 tensor 是这个深度学习框架的基础数据结构,可以在GPU上运行以加速计算。
- NumPy Arrays:NumPy 的 ndarray 是 Python 中用于科学计算的一个基本库的核心组件。它们被广泛用于各种数值计算任务,并且通常在 CPU 上运行。
- PyTorch tensors 支持自动微分,这对于训练神经网络来说是非常重要的。而 NumPy arrays 没有内建的自动微分功能。
原文地址:https://blog.csdn.net/weixin_43409127/article/details/135816139
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_61553.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。