动手学深度学习,笔记
第一章:预备知识
第一节数据操作:
(1)入门操作:
1.首先导入torch库,我们使用pytorch主要使用这个库的函数
import torch
张量表示一个由数值组成的数组,这个数组可能有多个维度。具有一个轴的张量对应数学上的向量(vector); 具有两个轴的张量对应数学上的矩阵(matrix);具有两个轴以上的张量没有特殊的数学名称。
我们来创建一个张量,可以使用 arange 创建一个行向量 x。
这个行向量包含以0开始的前12个整数,它们默认创建为整 数。也可指定创建类型为浮点数。张量中的每个值都称为张量的 元素(element)。
x = torch.arange(12) print(x) ## tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
可以通过张量的shape属性来访问张量(沿每个轴的长度)的形状
print(x.shape) #结果:torch.Size([12])
如果只想知道张量中元素的总数,即形状的所有元素乘积,可以检查它的大小(size)。因为这里在处理的是 一个向量,所以它的shape与它的size相同。
print(x.numel()) #12
要想改变一个张量的形状而不改变元素数量和元素值,可以调用reshape函数。例如,可以把张量x从形状为 (12,)的行向量转换为形状为(3,4)的矩阵。这个新的张量包含与转换前相同的值,但是它被看成一个3行4列 的矩阵。要重点说明一下,虽然张量的形状发生了改变,但其元素值并没有变。注意,通过改变张量的形状, 张量的大小不会改变。
X = x.reshape(3, 4) print(X) # tensor([[ 0, 1, 2, 3], # [ 4, 5, 6, 7], # [ 8, 9, 10, 11]])
有时,我们希望使用全0、全1、其他常量,或者从特定分布中随机采样的数字来初始化矩阵。我们可以创建 一个形状为(2,3,4)的张量,其中所有元素都设置为0。代码如下:
x2 = torch.zeros((2, 3, 4)) print(x2) ''' 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.]]]) '''
同样,我们可以创建一个形状为(2,3,4)的张量,其中所有元素都设置为1。代码如下:
x3 = torch.ones((2, 3, 4)) print(x3) # 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.]]])
我们想要随机获取一些值,以下代码创建一个形状为(3,4)的张量。其中的 每个元素都从均值为0、标准差为1的标准高斯分布(正态分布)中随机采样。
x4 = torch.randn(3, 4) print(x4) # tensor([[-0.2421, -1.4333, 0.1154, -0.2187], # [-0.6590, -0.1766, 1.9008, -0.7222], # [ 1.2284, -0.5664, 0.6310, -1.3181]])
创建确定的张量内容,为张量内每个元素确定值
x5 = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(x5) # tensor([[1, 2, 3], # [4, 5, 6], # [7, 8, 9]])
(2)运算符
我们可以对张量进行加减乘除和幂运算
import torch x = torch.tensor([1.0, 2, 4, 8]) y = torch.tensor([2, 2, 2, 2]) print("x+y=", x + y) print("x-y=", x - y) print("x*y=", x * y) print("x/y=", x / y) print("x^y=", x**y) # x+y= tensor([ 3., 4., 6., 10.]) # x-y= tensor([-1., 0., 2., 6.]) # x*y= tensor([ 2., 4., 8., 16.]) # x/y= tensor([0.5000, 1.0000, 2.0000, 4.0000]) # x^y= tensor([ 1., 4., 16., 64.])
使用自然对数e^(x)的函数
print("exp(x)=", torch.exp(x)) # exp(x)= tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
将两个张量进行拼接在一起,cat函数
比如(1,4)和(1,4)的张量,cat中dim=0,拼接后的张量1+1=2 shape=(2,4)
比如(1,4)和(1,4)的张量,cat中dim=1,拼接后的张量4+4=8 shape=(1,8)
x1 = torch.cat((x, y), dim=0) x2 = torch.cat((x, y), dim=1) print("dim = 0 ", x1) print("dim = 1", x2) print("cat前的大小 x.shape=", x.shape, "y.shape=", y.shape) print("cat后的大小 x1.shape=", x1.shape, "x2.shape=", x2.shape) # dim = 0 tensor([[1, 2, 4, 8], # [2, 2, 2, 2]]) # dim = 1 tensor([[1, 2, 4, 8, 2, 2, 2, 2]]) # cat前的大小 x.shape= torch.Size([1, 4]) y.shape= torch.Size([1, 4]) # cat后的大小 x1.shape= torch.Size([2, 4]) x2.shape= torch.Size([1, 8])
对于张量的逻辑操作
比如x==y ,x!=y
x =[1, 2, 4, 8] y = [2, 2, 2, 2]x1 = x == y x2 = x != y print("x==y", x1) print("x!=y", x2) # x==y tensor([[False, True, False, False]]) # x!=y tensor([[ True, False, True, True]])
张量的降维,求和,计算张量的总和,变成一个标量 sum函数
x1 = x.sum() print(x1) print(type(x1)) # tensor(15) # <class 'torch.Tensor'>
(3) 广播机制
通过适当复制元素来扩展一个或者两个数组,以便转换之后,两个张量具有相同的形状,方便元素操作
例如x 和y张量 ,x张量复制出额外的列,元素012,变成3行2列。
y张量复制出额外的行,元素01,变成3行2列。
然后张量按照行列相加。
总而言之,矩阵x复制列,矩阵y复制行,然后按照元素相加。
x = torch.tensor([[0], [1], [2]]) y = torch.tensor([[0, 1]]) print(x + y) # tensor([[0, 1], # [1, 2], # [2, 3]])
(4) 节省内存
在pytorch中进行新的操作会为新结果分配内存,例如,如果我们用Y =Y+1,我们将取消引用Y指向的张量, 而是指向新分配的内存处的张量。
import torch Y = torch.tensor([[1], [2]]) before = id(Y) Y = Y + 1 flag = id(Y) == before print(flag)
这里的结果是False,表示内存位置不一样,Python的id()函数演示了这一点,它给我们提供了内存中引用对象的确切地址。运 行Y = Y + 1后,我们会发现id(Y)指向另一个位置。这是因为Python首先计算Y + 1,为结果分配新的内存, 然后使Y指向内存中的这个新位置。
这可能是不可取的,原因有两个: 1. 首先,我们不想总是不必要地分配内存。在机器学习中,我们可能有数百兆的参数,并且在一秒内多次 更新所有参数。通常情况下,我们希望原地执行这些更新; 2. 如果我们不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧 的参数。
执行原地址操作的代码
Z = torch.zeros_like(Y) print(id(Z)) Z[:] = Y + 1 print(id(Z)) # 2104847078848 # 2104847078848
或者
before = id(Y) Y += 1 print(before == id(Y)) # True
或者
before = id(Y) Y[:] = Y + 1 print(before == id(Y)) # True
这样就会在原内存地址操作,减少内存的开销。
标签:tensor,预备,torch,张量,动手,shape,深度,print,x1 From: https://www.cnblogs.com/AndreaDO/p/17812729.html