* 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 倍