PyTorch中Tensor的基本用法与动手学深度学习的预备知识

同个人博客网站 : www.serendipper-x.cn
🐳🐳

  • 第一部分是PyTorch中有关Tensor的一些基本用法,因为之前并没有系统学习过PyTorch,所以现在看书的同时慢慢学习PyTorch的知识

  • 第二部分是原书的知识和一些自己的理解

    • 一、PyTorch 中的Tensor
      • 1.1 Tensor的创建
      • 1.2 Tensor的数据类型
        • 1.2.1 torch.FloatTensor
        • 1.2.2 torch.IntTensor
        • 1.2.3 torch.rand
        • 1.2.4 torch.randn
        • 1.2.5 torch.range
        • 1.2.6 torch.zeros
      • 1.3 Tensor的运算
        • 1.3.1 torch.abs
        • 1.3.2 torch.add
        • 1.3.3 torch.clamp
        • 1.3.4 torch.div
        • 1.3.5 torch.mul
        • 1.3.6 torch.pow
        • 1.3.7 torch.mm
        • 1.3.8 torch.mv
    • 二、原书
      • 2.1 数据操作
        • 2.1.1 索引
        • 2.1.2 改变形状
      • 2.2 线性代数
      • 2.3 广播机制
      • 2.4 运算内存开销
      • 2.5 Tensor和NumPy相互转换
      • 2.2.6 Tensor on GPU

张量 Tensor

张量包含了一个数据集合,这个数据集合就是原始值变形而来的,它可以是一个任何维度的数据。tensor的rank就是其维度。

Rank本意是矩阵的秩,不过Tensor Rank和Matrix Rank的意义不太一样,这里就还叫Rank。Tensor Rank的意义看起来更像是维度,比如Rank =1就是向量,Rank=2 就是矩阵了,Rank = 0 就是一个值。

一、PyTorch 中的Tensor

在PyTorch中,**torch.Tensor**是存储和变换数据的主要工具。TensorNumPy 的多维数组非常类似。

首先导入PyTorch

import torch

1.1 Tensor的创建

创建一个5x3的未初始化的 Tensor

x = torch.empty(5, 3)
print(x)
tensor([[5.4880e+23, 4.5886e-41, 2.7434e-24],[3.0915e-41, 4.4842e-44, 0.0000e+00],[4.4842e-44, 0.0000e+00, 2.7450e-24],[3.0915e-41, 5.4880e+23, 4.5886e-41],[4.2039e-45, 0.0000e+00, 4.6243e-44]])

创建一个5x3的随机初始化的 Tensor

x = torch.rand(5, 3)  # 这里rand的用法后面会讲到
print(x)
tensor([[0.7787, 0.8019, 0.3431],[0.1335, 0.3062, 0.2305],[0.6151, 0.5777, 0.2794],[0.4701, 0.6086, 0.9624],[0.6524, 0.6794, 0.8206]])

创建一个5x3的long类型全0的 Tensor

x = torch.zeros(5, 3, dtype=torch.long)
print(x)
tensor([[0, 0, 0],[0, 0, 0],[0, 0, 0],[0, 0, 0],[0, 0, 0]])

直接根据数据创建

x = torch.tensor([5.5, 3])
print(x)
tensor([5.5000, 3.0000])

通过现有的 Tensor 来创建,此方法会默认重用输入 Tensor 的一些属性,例如数据类型,除非自定义数据类型。

x = x.new_ones(5, 3, dtype=torch.float64)  # new_ones 返回一个与size大小相同的用1填充的张量,默认具有相同的torch.dtype和torch.device
print(x)x = torch.randn_like(x, dtype=torch.float) # randn_like形状与输入的张量相同,指定新的数据类型
print(x) 
tensor([[1., 1., 1.],[1., 1., 1.],[1., 1., 1.],[1., 1., 1.],[1., 1., 1.]], dtype=torch.float64)
tensor([[-0.9532,  0.4367, -0.1972],[ 2.1078,  0.3750, -0.2939],[-0.3682,  1.3246, -0.7197],[-0.4119,  0.2093, -0.3431],[-1.7094,  0.0638, -0.4597]])

通过 shape 或者size() 来获取 Tensor 的形状

print(x.size())
print(x.shape)
torch.Size([5, 3])
torch.Size([5, 3])

✨ 注意:返回的torch.Size其实就是一个tuple, 支持所有tuple的操作。

1.2 Tensor的数据类型

1.2.1 torch.FloatTensor

此变量用于生成数据类型为浮点型的 Tensor,传递给 torch.FloatTensor 的参数可以是一个列表,也可以是一个维度值。

a = torch.FloatTensor(2, 3)  # 两行三列
print(a)
tensor([[5.4880e+23, 4.5886e-41, 5.4880e+23],[4.5886e-41, 1.4584e-19, 7.8458e+17]])
b = torch.FloatTensor([[2, 3], [4, 5]])
print(b, b.shape, b.dtype)
tensor([[2., 3.],[4., 5.]]) torch.Size([2, 2]) torch.float32

1.2.2 torch.IntTensor

用于生成数据类型为整型的 Tensor,传递给 torch.IntTensor 的参数可以是一个列表,也可以是一个维度值。

a = torch.IntTensor(2, 3)
print(a)
tensor([[1726508320,      32745,  407958368],[     22062, 1953384789, 1701869908]], dtype=torch.int32)
b = torch.IntTensor([[2, 3], [4, 5]])
print(b, b.dtype)
tensor([[2, 3],[4, 5]], dtype=torch.int32) torch.int32

1.2.3 torch.rand

用于生成数据类型为浮点型且维度指定的随机 Tensor,和在 Numpy 中使用 numpy.rand 生成随机数的方法类似,随机生成的浮点数据在 0~1区间均匀分布。

a = torch.rand(2, 3)
print(a, a.dtype)
tensor([[0.8055, 0.3392, 0.5802],[0.3333, 0.7156, 0.3415]]) torch.float32

1.2.4 torch.randn

用于生成数据类型为浮点型且维度指定的随机 Tensor,和在 Numpy 中使用 numpy.randn生成随机数的方法类似,随机生成的浮点数的取值满足均值为0,方差为1的正态分布

a = torch.randn(2, 3)
print(a, a.dtype)
tensor([[ 0.4737,  0.3686, -1.1102],[ 0.9147, -0.3446, -0.7511]]) torch.float32

1.2.5 torch.range

用于生成数据类型为浮点型且自定义其实范围和结束范围的 Tensor,所以传递给 torch.range 的参数有三个,分别是范围的起始值,范围的结束值步长,其中,步长用于指定从起始值到结束值的每步的数据间隔。

a = torch.range(2, 8, 3)
print(a, a.dtype)
tensor([2., 5., 8.]) torch.float32/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:2: UserWarning: torch.range is deprecated in favor of torch.arange and will be removed in 0.5. Note that arange generates values in [start; end), not [start; end].

1.2.6 torch.zeros

用于生成数据类型为浮点型且维度指定的 Tensor,不过这个浮点型的 Tensor 中的元素值全部为0

a = torch.zeros(3, 4)
print(a, a.dtype)
tensor([[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.]]) torch.float32

1.3 Tensor的运算

这里通常对 Tensor 数据类型的变量进行运算,来组合一些简单或者复杂的算法,常用的 Tensor 运算如下:

1.3.1 torch.abs

将参数传递到 torch.abs 后返回输入参数的绝对值作为输出,输出参数必须是一个 Tensor 数据类型的变量

a = torch.randn(2, 3)
print(a)
b = torch.abs(a)
print(b)
tensor([[-1.5257,  0.1174, -0.2927],[ 0.4662,  0.7019,  0.2605]])
tensor([[1.5257, 0.1174, 0.2927],[0.4662, 0.7019, 0.2605]])

1.3.2 torch.add

将参数传递到 torch.add 后返回输入参数的求和结果作为输出,输入参数既可以全部是 Tensor 数据类型的变量,也可以是一个 Tensor 数据类型的变量,另一个是标量。

a = torch.randn(2, 3)
print(a)b = torch.randn(2, 3)
print(b)c = torch.add(a, b)
print(c)d = torch.randn(2, 3)
print(d)e = torch.add(d, 10)
print(e)
tensor([[-1.5090, -1.1659, -0.7795],[ 0.8453, -0.0334,  0.2251]])
tensor([[-1.5168, -1.2602,  0.8775],[ 1.8206, -0.0880, -1.1371]])
tensor([[-3.0258, -2.4261,  0.0980],[ 2.6659, -0.1213, -0.9120]])
tensor([[0.2818, 1.4852, 2.0287],[1.1209, 1.6720, 1.0154]])
tensor([[10.2818, 11.4852, 12.0287],[11.1209, 11.6720, 11.0154]])

可以指定输出

result = torch.empty(2, 3)
torch.add(a, b, out=result)
print(result)
tensor([[-3.0258, -2.4261,  0.0980],[ 2.6659, -0.1213, -0.9120]])

关于加法还有两种方式:

  • 第一种,+号
  • 第二种,inplace

✨ 注:PyTorch操作inplace版本都有后缀_, 例如x.copy_(y), x.t_()

print(a+b)
tensor([[-3.0258, -2.4261,  0.0980],[ 2.6659, -0.1213, -0.9120]])
b.add_(a)
print(b)
tensor([[-3.0258, -2.4261,  0.0980],[ 2.6659, -0.1213, -0.9120]])

1.3.3 torch.clamp

对输入参数按照自定义的范围进行裁剪,最后将参数裁剪的结果作为输出。所以输入参数一共有三个,分别是需要进行裁剪的Tensor数据类型的变量裁剪的上边界裁剪的下边界

具体的裁剪过程是:使用变量中的每个元素分别和裁剪的上边界及裁剪的下边界的值进行比较,如果元素的值小于裁剪的下边界的值,该元素就被重写成裁剪的下边界的值;

同理,如果元素的值大于裁剪的上边界的值,该元素就被重写成裁剪的上边界的值。

a = torch.randn(2, 3)
print(a)b = torch.clamp(a, -0.1, 0.1)
print(b)
tensor([[ 0.5965,  2.1073, -1.2866],[-0.1101, -1.6736, -2.2357]])
tensor([[ 0.1000,  0.1000, -0.1000],[-0.1000, -0.1000, -0.1000]])

1.3.4 torch.div

将参数传递到 torch.div 后返回输入参数的求商结果作为输出,同样,参与运算的参数可以全部是 Tensor 数据类型的变量,也可以是 Tensor 数据类型的变量和标量的组合。

a = torch.randn(2,3)
print(a)b = torch.randn(2,3)
print(b)c = torch.div(a,b)
print(c)d = torch.randn(2,3)
print(d)e = torch.div(d,10)
print(e)
tensor([[ 0.4518,  0.1334,  1.7579],[ 0.0349, -0.2346,  1.6790]])
tensor([[ 1.2516, -1.1198,  1.1351],[-0.6222, -0.6472, -0.0758]])
tensor([[  0.3610,  -0.1191,   1.5486],[ -0.0561,   0.3624, -22.1492]])
tensor([[ 0.2908,  0.0664, -1.4821],[ 0.4358,  0.3226,  1.0338]])
tensor([[ 0.0291,  0.0066, -0.1482],[ 0.0436,  0.0323,  0.1034]])

1.3.5 torch.mul

将参数传递到 torch.mul 后返回输入参数求积的结果作为输出,参与运算的参数可以全部是 Tensor 数据类型的变量,也可以是 Tensor 数据类型的变量和标量的组合。

a = torch.randn(2, 3)
print(a)b = torch.randn(2, 3)
print(b)c = torch.mul(a, b)
print(c)d = torch.randn(2, 3)
print(d)e = torch.mul(d, 10)
print(e)
tensor([[ 0.5851,  0.2113,  0.6891],[ 1.1177, -0.0177,  1.5595]])
tensor([[ 0.9094, -0.0707, -0.3900],[ 0.2990, -0.9827,  0.7165]])
tensor([[ 0.5321, -0.0149, -0.2687],[ 0.3342,  0.0174,  1.1174]])
tensor([[-0.7012,  1.2348,  1.6156],[ 0.5412,  0.2345, -0.5753]])
tensor([[-7.0115, 12.3478, 16.1558],[ 5.4116,  2.3447, -5.7526]])

1.3.6 torch.pow

将参数传递到 torch.pow 后返回输入参数的求幂结果作为输出,参与运算的参数可以全部是 Tensor 数据类型的变量,也可以是 Tensor 数据类型的变量和标量的组合。

a = torch.randn(2, 3)
print(a)b = torch.pow(a, 2)
print(b)
tensor([[-0.9387,  1.0499, -1.6718],[-0.3190, -1.1677, -0.0666]])
tensor([[0.8812, 1.1024, 2.7948],[0.1018, 1.3635, 0.0044]])

1.3.7 torch.mm

将参数传递到 torch.mm 后返回输入参数的求积结果作为输出,不过这个求积的方式和之前的 torch.mul运算方式不太样,

torch.mm 运用矩阵之间的乘法规则进行计算,所以被传入的参数会被当作矩阵进行处理,参数的维度自然也要满足矩阵乘法的前提条件,

前一个矩阵的行数必须和后一个矩阵的列数相等,否则不能进行计算。

a = torch.randn(2, 3)
print(a)b = torch.randn(3, 2)
print(b)b = torch.mm(a, b)
print(b)
tensor([[ 0.1701,  0.9539, -0.3128],[-0.2466,  2.4600, -1.6023]])
tensor([[-1.0573, -1.0292],[-0.2707,  0.2992],[-1.0913, -3.1058]])
tensor([[-0.0967,  1.0818],[ 1.3436,  5.9664]])

1.3.8 torch.mv

将参数传递到 torch.mv 后返回输入参数的求积结果作为输出,torch.mv 运用矩阵与向量之间的乘法规则进行计算,被传入的参数中的第1个参数代表矩阵,第2个参数代表向量,顺序不能颠倒。

a = torch.randn(2, 3)
print(a)b = torch.randn(3)
print(b)c = torch.mv(a, b)
print(c)
tensor([[ 1.7745,  0.8665, -0.5622],[-0.6072,  0.5540, -1.0647]])
tensor([ 0.0553, -0.5526, -1.0924])
tensor([0.2335, 0.8233])

二、原书

2.1 数据操作

部分操作已经在前面提及

2.1.1 索引

索引出来的结果与原数据共享内存,也即修改一个,另一个会跟着修改。

x = torch.randn(2, 4)
print(x)
y = x[:, :3]
print(y)
y += 1
print(y)
print(x[:, :3]) # 源tensor也被改了
print(x)
tensor([[ 0.5706,  0.3683,  1.4869,  1.2791],[-0.1592, -1.7226, -1.1192, -0.9729]])
tensor([[ 0.5706,  0.3683,  1.4869],[-0.1592, -1.7226, -1.1192]])
tensor([[ 1.5706,  1.3683,  2.4869],[ 0.8408, -0.7226, -0.1192]])
tensor([[ 1.5706,  1.3683,  2.4869],[ 0.8408, -0.7226, -0.1192]])
tensor([[ 1.5706,  1.3683,  2.4869,  1.2791],[ 0.8408, -0.7226, -0.1192, -0.9729]])

除了常用的索引选择数据之外,PyTorch还提供了一些高级的选择函数:

函数功能
index_select(input, dim, index)在指定维度dim上选取,比如选取某些行、某些列
masked_select(input, mask,out=None)根据布尔掩码 (boolean mask) 索引输入张量的 1D 张量
nonzero(input)非0元素的下标
gather(input, dim, index)根据index,在dim维度上选取数据,输出的size与index一样

index_select

index_select(input,dim,index
)

参数:

  • input:索引的对象
  • dim:表示从第几维挑选数据,类型为int值;0表示按行索引,1表示按列索引
  • index:表示从第一个参数维度中的哪个位置挑选数据,类型为torch.Tensor类的实例;
print(torch.index_select(x,0,torch.tensor([0, 1])))
print(torch.index_select(x,1,torch.tensor([0, 1])))
tensor([[ 1.5706,  1.3683,  2.4869,  1.2791],[ 0.8408, -0.7226, -0.1192, -0.9729]])
tensor([[ 1.5706,  1.3683],[ 0.8408, -0.7226]])

masked_select

masked_select(input,mask,out
)

参数:

  • input(Tensor) :需要进行索引操作的输入张量;
  • mask(BoolTensor) :要进行索引的布尔掩码
  • out(Tensor, optional) :指定输出的张量。比如执行 torch.zeros([2, 2], out = tensor_a),相当于执行 tensor_a = torch.zeros([2, 2]);

⚠️ 注意:「 masked_select 函数最关键的参数就是布尔掩码 mask,

传入 mask 参数的布尔张量通过 True 和 False (或 1 和 0) 来决定输入张量对应位置的元素是否保留,

既然是一一对应的关系,这就需要传入 mask 中的布尔张量和传入 input 中的输入张量形状要相同。

mask = x.ge(0.5)
print(mask)
print(torch.masked_select(x, mask))
tensor([[ True,  True,  True,  True],[ True, False, False, False]])
tensor([1.5706, 1.3683, 2.4869, 1.2791, 0.8408])
print(x)
print(torch.nonzero(x))
tensor([[ 1.5706,  1.3683,  2.4869,  1.2791],[ 0.8408, -0.7226, -0.1192, -0.9729]])
tensor([[0, 0],[0, 1],[0, 2],[0, 3],[1, 0],[1, 1],[1, 2],[1, 3]])

gather

gather(input, dim,index
)

参数:

  • input (Tensor) – 需要进行索引操作的输入张量;
  • dim (int) – 表示从第几维挑选数据,类型为int值;
  • index (LongTensor) – 要收集的元素的索引;
  • out (Tensor, optional) – 指定输出的张量。
print(torch.gather(x, dim=1, index=torch.LongTensor([[0, 1],[0, 0]])))  # dim为1说明按列索引,[0, 1]表示第一行的第0列和第1列,就是1.5706和1.3683,同理[0, 0]是0.8408和0.8408
print(torch.gather(x, dim=0, index=torch.LongTensor([[0,1,1,0],[0,0,0,0]])))   # dim为0说明按行索引,[0, 1, 1, 0]表示第0行,第1行,第1行,第0行
tensor([[1.5706, 1.3683],[0.8408, 0.8408]])
tensor([[ 1.5706, -0.7226, -0.1192,  1.2791],[ 1.5706,  1.3683,  2.4869,  1.2791]])

2.1.2 改变形状

view() 来改变 Tensor 的形状:

⚠️ 需要注意的是:-1所指的维度可以根据其他维度的值推出来,这个用法在很多地方都见过,应该要记住

y = x.view(8)
z = x.view(-1, 2)  # -1所指的维度可以根据其他维度的值推出来
print(x.size(), y.size(), z.size())
torch.Size([2, 4]) torch.Size([8]) torch.Size([4, 2])

🔥 view()返回的新 Tensor 与源 Tensor 虽然可能有不同的 size,但是是共享 data 的,也即更改其中的一个,另外一个也会跟着改变。(顾名思义,view 仅仅是改变了对这个张量的观察角度,内部数据并未改变)

x += 1
print(x)
print(y)
tensor([[2.5706, 2.3683, 3.4869, 2.2791],[1.8408, 0.2774, 0.8808, 0.0271]])
tensor([2.5706, 2.3683, 3.4869, 2.2791, 1.8408, 0.2774, 0.8808, 0.0271])

所以如果我们想返回一个真正新的副本(即不共享data内存)该怎么办呢?

Pytorch还提供了一个 reshape() 可以改变形状,但是此函数并不能保证返回的是其拷贝,所以不推荐使用。推荐先用 clone 创造一个副本然后再使用 view

x_cp = x.clone().view(8)
x -= 1
print(x)
print(x_cp)
tensor([[ 1.5706,  1.3683,  2.4869,  1.2791],[ 0.8408, -0.7226, -0.1192, -0.9729]])
tensor([2.5706, 2.3683, 3.4869, 2.2791, 1.8408, 0.2774, 0.8808, 0.0271])

✨ 使用 clone 还有一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源 Tensor

另外一个常用的函数就是 item(), 它可以将一个标量 Tensor 转换成一个Python number:

x = torch.randn(1)
print(x)
print(x.item())
tensor([1.0600])
1.059958815574646

2.2 线性代数

另外,PyTorch还支持一些线性函数,这里提一下,免得用起来的时候自己造轮子,具体用法参考官方文档。如下表所示:

函数功能
trace对角线元素之和(矩阵的迹)
diag对角线元素
triu/tril矩阵的上三角/下三角,可指定偏移量
mm/bmm矩阵乘法,batch的矩阵乘法
addmm/addbmm/addmv/addr/baddbmm…矩阵运算
t转置
dot/cross内积/外积
inverse求逆矩阵
svd奇异值分解

2.3 广播机制

当对两个形状不同的 Tensor 按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个 Tensor 形状相同后再按元素运算。

x = torch.arange(1, 3).view(1, 2)
print(x)
y = torch.arange(1, 4).view(3, 1)
print(y)
print(x + y)
tensor([[1, 2]])
tensor([[1],[2],[3]])
tensor([[2, 3],[3, 4],[4, 5]])

由于 xy 分别是1行2列和3行1列的矩阵,如果要计算 x + y,那么 x 中第一行的2个元素被广播(复制)到了第二行和第三行,

y 中第一列的3个元素被广播(复制)到了第二列。如此,就可以对2个3行2列的矩阵按元素相加。

2.4 运算内存开销

前面说了,索引操作是不会开辟新内存的,而像y = x + y 这样的运算是会新开内存的,然后将y指向新内存。

为了演示这一点,我们可以使用Python自带的 id 函数:如果两个实例的ID一致,那么它们所对应的内存地址相同;反之则不同。

x = torch.tensor([1, 2])
y = torch.tensor([3, 4])
id_before = id(y)
y = y + x
print(id(y) == id_before) # False 
False

如果想指定结果到原来的 y 的内存,我们可以使用前面介绍的索引来进行替换操作。在下面的例子中,我们把x + y的结果通过 [:] 写进 y 对应的内存中。

x = torch.tensor([1, 2])
y = torch.tensor([3, 4])
id_before = id(y)
y[:] = y + x
print(id(y) == id_before) # True
True

我们还可以使用运算符全名函数中的 out 参数或者自加运算符 += (也即 add_() )达到上述效果,例如 torch.add(x, y, out=y)y += x(y.add_(x))

x = torch.tensor([1, 2])
y = torch.tensor([3, 4])
id_before = id(y)
torch.add(x, y, out=y) # y += x, y.add_(x)
print(id(y) == id_before) # True
True

✨ 注:虽然 view 返回的 Tensor 与源 Tensor 是共享data的,但是依然是一个新的 Tensor(因为 Tensor 除了包含data外还有一些其他属性),二者id(内存地址)并不一致。

2.5 Tensor和NumPy相互转换

我们很容易用 numpy()from_numpy()TensorNumPy 中的数组相互转换。

但是需要注意的一点是: 这两个函数所产生的的 TensorNumPy 中的数组共享相同的内存(所以他们之间的转换很快),改变其中一个时另一个也会改变!!!

还有一个常用的将NumPy中的array转换成Tensor的方法就是torch.tensor(), 需要注意的是,此方法总是会进行数据拷贝(就会消耗更多的时间和空间),所以返回的Tensor和原来的数据不再共享内存。

Tensor转NumPy

使用 numpy()Tensor 转换成 NumPy 数组:

a = torch.ones(5)
b = a.numpy()
print(a, b)a += 1
print(a, b)
b += 1
print(a, b)
tensor([1., 1., 1., 1., 1.]) [1. 1. 1. 1. 1.]
tensor([2., 2., 2., 2., 2.]) [2. 2. 2. 2. 2.]
tensor([3., 3., 3., 3., 3.]) [3. 3. 3. 3. 3.]

NumPy数组转Tensor

使用from_numpy()NumPy 数组转换成 Tensor :

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
print(a, b)a += 1
print(a, b)
b += 1
print(a, b)
[1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
[2. 2. 2. 2. 2.] tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
[3. 3. 3. 3. 3.] tensor([3., 3., 3., 3., 3.], dtype=torch.float64)

所有在CPU上的 Tensor(除了 CharTensor)都支持与 NumPy 数组相互转换。

此外上面提到还有一个常用的方法就是直接用 torch.tensor()NumPy 数组转换成 Tensor

需要注意的是该方法总是会进行数据拷贝,返回的 Tensor 和原来的数据不再共享内存。

c = torch.tensor(a)
a += 1
print(a, c)
[4. 4. 4. 4. 4.] tensor([3., 3., 3., 3., 3.], dtype=torch.float64)

2.2.6 Tensor on GPU

用方法 to() 可以将 Tensor 在CPU和GPU(需要硬件支持)之间相互移动。

# 以下代码只有在PyTorch GPU版本上才会执行
if torch.cuda.is_available():device = torch.device("cuda")          # GPUy = torch.ones_like(x, device=device)  # 直接创建一个在GPU上的Tensorx = x.to(device)                       # 等价于 .to("cuda")z = x + yprint(z)print(z.to("cpu", torch.double))       # to()还可以同时更改数据类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/483392.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络——物理层设备

1.中继器 \qquad信号在传输过程中会有衰减,导致数据失真,所以我们需要对信号进行再生和还原,使其与原数据相同。这就需要中继器的发挥作用。 2.中继器的结构 \qquad中继器的两端:两端的网络部分是网段而不是子网,适用…

重磅!2020国家科学技术奖全名单公布!

来源:软科 2021年11月3日,2020年度国家科学技术奖励大会在人民大会堂正式召开。备受关注的国家最高科学技术奖,授予了中国航空工业集团有限公司顾诵芬院士和清华大学王大中院士。国家最高科学技术奖自2000年正式设立,是中国科技界…

PHP 常用数据库操作

1.建立与数据库服务器的连接(前提数据库服务器必须打开) 第一个参数:本地地址 第二个参数:数据库账户 第三个参数:数据库密码 第四个参数:数据库名称 $connection mysqli_connect(127.0.0.1, root, 密码, …

计算机网络——数据链路层的概述

1.数据链路层的基本概念 \qquad结点:主机、路由器 \qquad链路:网络中两个结点之间的物理通道,链路的传输介质主要有双绞线,光纤,微波。分为有线链路和无线链路。 \qquad数据链路:网络中两个结点之间的逻辑通…

中国科学家证明凯勒几何两大核心猜想

来源:中国科学报中国科学技术大学几何物理中心创始主任陈秀雄与合作者程经睿在偏微分方程和复几何领域取得“里程碑式结果”。他们解出了一个四阶完全非线性椭圆方程,成功证明了“强制性猜想”和“测地稳定性猜想”这两个国际数学界60多年悬而未决的核心…

基于交换机的PC端网络通信

1. 通信环境 \qquad两台电脑:一台是windows10操作系统,一台是Ubuntu操作系统; \qquad一个5口的交换机和配套的交换机电源线 \qquad两根网线 2.实现的目的 \qquad通过上述的通信环境,基于交换机,可以实现两台不同操作系…

深度学习发展下的“摩尔困境”,人工智能又将如何破局?

来源:AI科技大本营编译:禾木木前不久,微软和英伟达推出包含5300亿参数的语言模型MT-NLG,这是一款基于 Transformer 的模型被誉为“世界上最大、最强的生成语言模型”。毫无疑问,这是一场令人印象深刻的机器学习工程展示…

计算机网络——差错控制

1.传输过程中出现错误的原因? \qquad传输中的差错主要是由噪声引起的,噪声主要分为:全局性噪声,比如线路电气特性所产生的随机噪声;局部性噪声,比如短暂性的冲击噪声。 2.差错的原因? \qquad差…

Exp8 Web基础

一、实验过程 1.Web前端:HTML基础 (1)kali默认已安装Apache,使用 service apache2 start 命令打开Apache服务 (2)在浏览器输入 127.0.0.1 ,如果可以打开Apache的默认网页 (3&#xf…

linux的基础知识——协议和网络应用程序设计模式

1.什么是协议? 协议,即规则。网络通信中的协议,即数据传输和数据解释的规则。 2.一些典型的协议 传输层:常见的有TCP/UDP协议 应用层:HTTP协议,FTP协议 网络层:IP协议,ICMP协议&a…

linux的基础知识——模型结构和数据包的封装

1.OSI参考模型和TCP/IP参考模型 2.TCP/IP模型 TCP/IP网络协议分为四层:应用层,传输层,网络层,链路层 3.数据包的封装 数据要想传输必须经过封装。两台电脑通过TCP/IP协议通讯过程如下:

人工智能发展时间轴

来源:人机与认知实验室时间人物事件意义1633Rene Descartes发表著作《论人》提出灵魂存在于大脑的松果体中1714Gottfried Wilhelm Leibniz《单子论》一切知识都能通过理性思考获得。发现微积分,并开发了一套更为适用的记号方法。1739David Hume《人性论》…

linux的基础知识——以太网帧格式

1.路由器寻路 路由器根据自身的路由表,寻找下一个路由节点。 2.数据包的封装结构 3.以太网帧 以太网帧是在链路层,链路层的主要职能是检错和校验,以太网帧格式如下: 其中,目的地址和源地址是网卡中的硬件地址&#…

吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设置浮动和偏移

<!DOCTYPE html> <html><head><title>菜鸟教程(runoob.com)</title> <meta name"viewport" content"widthdevice-width, initial-scale1" charset"utf-8"><link rel"stylesheet" href"h…

生成式AI,引领AI从“换脸”到“造脸”

来源&#xff1a;中智观察头图来源&#xff1a;界面新闻记者&#xff1a;木易编辑&#xff1a;豆芽日前&#xff0c;Gartner发布了2022年重要战略技术趋势。其中&#xff0c;生成式人工智能&#xff08;Generative Artificial Intelligence&#xff09;位列12项重要战略之首。同…

linux的基础知识——IP,UDP和TCP

1.IP协议 IP协议处于网络层&#xff0c;格式如下&#xff1a; 2.UDP UDP协议处于传输层&#xff0c;传输层常用的协议有两种&#xff0c;一个就是UDP&#xff0c;另外一个就是TCP。

从世界数字大脑形成看元宇宙未来趋势

来源&#xff1a;腾云中国科学院虚拟经济与数据科学研究中心研究组成员、远望智库数字大脑研究院院长、腾云智库专家 刘 锋前言&#xff1a;21世纪&#xff0c;科技生态呈现出越来越多的类脑特征&#xff0c;各种前沿科技概念和技术正在形成一个世界规模的数字大脑&#xff0c…

profile 配置文件修改后如何生效?

1、profile生效命令 . /etc/profiel 或 source /etc/profile说明&#xff1a;source命令也称为“点命令”&#xff0c;也就是一个点符号&#xff08;.&#xff09;转载于:https://www.cnblogs.com/Small-sunshine/p/10895426.html

项目:如何快速实现电脑间大文件(lichee.tar.gz)互传?

1.电脑间大文件互传遇到问题 最简单是使用U盘进行大文件互传&#xff0c;但是可能会遇到这种问题&#xff0c;只能取消。 一般我们也可以借助云盘&#xff0c;进行互传。A电脑把电脑上传到百度云盘上&#xff0c;B电脑再下载&#xff0c;但是可能会遇到这种问题。 2.利用IP地…

《复杂》作者梅拉妮·米歇尔发文直指AI四大谬论,探究AI几度兴衰背后的根源...

来源&#xff1a;AI科技评论 作者&#xff1a;梅拉妮米歇尔 论文题目&#xff1a;Why AI is Harder Than We Think论文地址&#xff1a;https://arxiv.org/pdf/2104.12871.pdf关于作者&#xff1a;梅拉妮米歇尔&#xff0c;圣塔菲研究所客座教授&#xff0c;畅销书《复杂》作者…