Tensor数据操作

* torch.Tensor 存储和变换数据的工具

* Tensor与Ndarray多维数组类似,可提供GPU计算和自动求梯度

* 标量:0纬张量,一个数字

* 向量:1纬张量,[ ]

* 矩阵:2纬张量,[ [ ] ]

首先导入torch,查看版本号

import torch

#打印torch版本
print(torch.__version__)

#查看是否支持GPU
torch.cuda.is_avaliable()
代码运行后的结果是:
1.4.0
True

1.创建Tensor

1.11 直接创建

* torch.tensor(value)
* value:可以是任何维度的张量

print("创建一个标量5")
x = torch.tensor(5)
print("创建一个向量[]")
y = torch.tensor([2,3])
print("创建一个矩阵[ [ ] ]")
z = torch.tensor([[1,2],
                 [2,3]])
print(x)
print(y)
print(z)
输出结果是:
创建一个标量5
创建一个向量[]
创建一个矩阵[ [ ] ]
tensor(5)
tensor([2, 3])
tensor([[1, 2],
        [2, 3]])

1.2使用方法创建

* torch.empty(shape,dtype = type):创建未初始化的Tensor,可指定数据类型,dtype参数可省略
* torch.rand(shape) :创建随机矩阵
* torch.zeros(shape):创建0矩阵
* 创建维度均为2纬矩阵

print("创建二维未初始化矩阵")
A = torch.empty((2,2))
print(A)
print("创建随机矩阵")
B = torch.rand((2,2))
print(B)
print("创建0矩阵")
C = torch.zeros((2,2))
print(C)
输出结果是:
创建二维未初始化矩阵
tensor([[ 0.0000e+00,  1.4279e+00],
        [-9.3980e-11,  4.5908e-41]])
创建随机矩阵
tensor([[0.3857, 0.0058],
        [0.1388, 0.9339]])
创建0矩阵
tensor([[0., 0.],
        [0., 0.]])

1.3通过现有的Tensor创建

* matrix.new_ones(shape,dtype) 可以改变维度
* torch.randn_like(matirx,dtype)

print("将原本2*2未初始化矩阵进行重新创建")
B = B.new_ones(5,3)
print(B)
print("将原本2*2未初始化矩阵进行重新创建")
A = torch.randn_like(A, dtype = torch.float)
print(A)
输出结果是:
将原本2*2未初始化矩阵进行重新创建
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
将原本2*2未初始化矩阵进行重新创建
tensor([[ 0.1454, -0.1173],
        [-0.7503,  0.5255]])

1.4Tensor的基本方法

* matrix.shape: 获取Tensor形状
* matirx.size():获取Tensor形状 返回一个tuple,支持tuple的所有操作

print("获取B矩阵形状")
print(B.shape)
print(B.size())
输出结果是:
获取B矩阵形状
torch.Size([5, 3])
torch.Size([5, 3])

2 Tensor操作

2.1 算法操作

2.11 加法操作

* matrix1 + matirx2
* torch.add(matrix1, matrix2, out = A) out指定输出参数,可省略
* inplace matrix1.add_(matrix2) == (matirx1 += matrix2)

print("使用 + 完成加法操作")
print(A + C)
print("使用torch.add完成加法操作")
print(torch.add(A,C))
print("使用inplace完成加法操作")
print(C.add_(A))
输出结果是:
使用 + 完成加法操作
tensor([[ 0.1454, -0.1173],
        [-0.7503,  0.5255]])
使用torch.add完成加法操作
tensor([[ 0.1454, -0.1173],
        [-0.7503,  0.5255]])
使用inplace完成加法操作
tensor([[ 0.1454, -0.1173],
        [-0.7503,  0.5255]])

2.1.2 索引

* 类似于Numpy
* 索引结果与原数据共享内存

A = torch.rand(5,5)
print('查看创建Tensor')
print(A[1][1])
A[1][1] = 5
print("查看A矩阵第一行第一列是否为5")
print(A[1][1])
输出结果是:
查看创建Tensor
tensor(0.6124)
查看A矩阵第一行第一列是否为5
tensor(5.)

2.1.3 改变形状

* marix.clone() 克隆新副本,解决共享内存带来的问题
* matrix.view(shape) view() 前后共享data
* matrix.reshape(shape)

#查看clone与变量赋值的区别
print("查看A变量地址")
print(id(A))
A_cl = A.clone()
print('查看克隆新副本地址')
print(id(A_cl))
A_an = A
print('查看变量重新赋值后的地址')
print(id(A_an))
输出结果是:
查看A变量地址
2337547400576
查看克隆新副本地址
2337538344512
查看变量重新赋值后的地址
2337547400576

note:这里主要是解释共享data的问题。直接view()的话维度改变,操作的是同一内存的数据。不会生成新的维度的数据。

* 变量赋值相当于引用,地址不变,只想同一块内存
* clone()操作会重新申请内存空间
* matrix.item() 将标量Tensor转化为number

* https://pytorch.org/docs/stable/tensors.html     Tensor操作链接

2.1.4 Tensor的广播机制

* 自动使得运算的Tensor相同的操作
* 首先会比较最靠右的维度,如果最靠右的维度相等或其中一个为 1,则认为此维度相等;
* 再继续向左比较,如果一直满足,则认为两者兼容;
* 最后,分别在对应维度上发生广播,以此补齐直到维度一致;

x = torch.rand(4 , 6)
y = torch.rand(4,  1)
print(torch.add(x , y))
输出结果是:
tensor([[0.6108, 0.1842, 0.9873, 0.9042, 0.2456, 0.4298],
        [1.0251, 0.6726, 1.2724, 1.2861, 1.1256, 0.5654],
        [1.0223, 0.3473, 0.5952, 0.3701, 0.4500, 0.4993],
        [0.0542, 0.9524, 0.1668, 0.5762, 0.0671, 0.4689]])

2.1.5 Tensor与Numpy的相互转换

* tensor.numpy() 可将Tensor转为ndarray数据

a = torch.rand(3,2)
print(id(a))
b = a.numpy()
print(id(b))
print(a)
print(b)
输出结果为:
2337547166400
2337547429088
tensor([[0.3145, 0.9862],
        [0.7604, 0.9342],
        [0.3104, 0.7312]])
[[0.31446308 0.9861587 ]
 [0.7603721  0.9341993 ]
 [0.31042498 0.73123205]]

Numpy转为Tensor

* torch.from_numpy(array)
* torch.Tensor()

import numpy as np
c = torch.from_numpy(b)
d = torch.Tensor(b)
print(type(c))
print(type(d))
<class 'torch.Tensor'>
<class 'torch.Tensor'>

2.1.6 Tensor on GPU

* .to("cuda") 将Tensor在GPU上运算
    x.to("cuda")
* .to(device) 将Tensor在GPU运算
    torch.device("cuda")
    x.to(device)
* .to("cpu") 将Tensor在CPU上运算

验证GPU的运算速度

%%time #jupyter notebook中的魔法语句,可以输出当前代码块的运行速度
print("使用device")
device = torch.device("cuda")
x = torch.rand(200,100).to(device)
y = torch.rand(200,100).to(device)
print(x + y)
输出结果是:
使用device
tensor([[1.3311, 1.7433, 1.1089,  ..., 0.8775, 1.1430, 0.4877],
        [1.1953, 0.3628, 0.6479,  ..., 0.4781, 0.9154, 1.3447],
        [1.2134, 0.5482, 1.7713,  ..., 0.9025, 1.1786, 0.2083],
        ...,
        [0.9276, 0.8605, 0.9905,  ..., 0.9992, 1.1613, 0.8636],
        [1.2191, 0.6350, 0.9921,  ..., 1.7540, 1.0139, 1.2921],
        [1.2137, 0.9510, 0.9126,  ..., 0.8433, 0.5871, 1.0881]],
       device='cuda:0')
Wall time: 6.45 s

验证CPU运算速度

%%time
print("使用CPU")
x = torch.rand(200,100).to("cpu")
y = torch.rand(200,100).to("cpu")
print(x + y)
输出结果是:
使用CPU
tensor([[1.4920, 1.1891, 0.0936,  ..., 0.5056, 1.6395, 1.0162],
        [1.4211, 0.9837, 1.1501,  ..., 1.2990, 0.7121, 0.3505],
        [1.1503, 1.0263, 1.4055,  ..., 0.6856, 0.3320, 0.7620],
        ...,
        [0.4615, 1.0520, 1.3409,  ..., 1.1014, 1.0806, 0.9630],
        [0.9770, 1.4159, 1.6652,  ..., 0.9515, 1.2479, 1.2459],
        [0.7622, 0.9159, 0.9734,  ..., 0.5249, 0.1216, 0.6906]])
Wall time: 112 ms

查看同样维度矩阵计算GPU与CPU的速度差异

print("GPU 比 CPU 的运算速度块: %.2f 倍" %(112 / 6.45))
输出结果是:
GPU 比 CPU 的运算速度块: 17.36 倍
原文地址:https://www.cnblogs.com/peiziming/p/12719599.html