#深入浅出PyTorch_【01】pytorch基础
2023.01.23
主要内容就是张量
2.1 张量
张量是基于向量和矩阵的推广
0
维张量 :代表数字1
维张量 :代表向量2
维张量 :代表矩阵3
维张量 :代表时间序列数据 股价 文本数据 单张彩色图片(RGB)
这里有一些存储在各种类型张量的公用数据集类型:
- 3维 = 时间序列
- 4维 = 图像
- 5维 = 视频
在PyTorch中, torch.Tensor 是存储和变换数据的主要工具
2.1.2 创建tensor
- 随机初始化矩阵 我们可以通过
torch.rand()
的方法,构造一个随机初始化的矩阵
import torch
x = torch.rand(4,3)
print(x)
tensor([[0.8588, 0.8956, 0.9268],
[0.4135, 0.3667, 0.2543],
[0.9537, 0.4734, 0.6466],
[0.2807, 0.9355, 0.3539]])
import torch
x= torch.ones(3,4)
x,x.type
(tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]),
<function Tensor.type>)
- 创建tensor,用
dtype
指定类型。注意类型要匹配
import torch
x= torch.ones(3,4,dtype=torch.long)
x,x.type
(tensor([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]),
<function Tensor.type>)
torch.zero_()
和torch.zeros_like()
将现有矩阵转换为全0矩阵;
x = torch.zero_(x)
x
tensor([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
- 直接构造
import torch
x = torch.tensor([5.5, 3])
print(x)
tensor([5.5000, 3.0000])
x = x.new_ones(4, 3, dtype=torch.double)
# 创建一个新的全1矩阵tensor,返回的tensor默认具有相同的torch.dtype和torch.device
# 也可以像之前的写法 x = torch.ones(4, 3, dtype=torch.double)
print(x)
x = torch.randn_like(x, dtype=torch.float)
# 重置数据类型
print(x)
# 结果会有一样的size
# 获取它的维度信息
print(x.size())
print(x.shape)
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([[-0.5745, 1.5043, 0.2415],
[-0.2920, -0.5703, -1.8614],
[-0.8955, -1.0411, 0.7916],
[-0.4730, -1.2235, -0.5225]])
torch.Size([4, 3])
torch.Size([4, 3])
- rand/randn(sizes):rand是[0,1)均匀分布;randn是服从N(0,1)的正态分布
- normal(mean,std):正态分布(均值为mean,标准差是std)
- eye(sizes):对角为1,其余为0
- arange(s,e,step):从s到e,步长为step
2.1.3 张量的操作
1. 加法
import torch
# 方式1
y = torch.rand(4, 3)
print(x + y)
# 方式2
print(torch.add(x, y))
# 方式3 in-place,原值修改,对y进行了修改
y.add_(x)
print(y)
tensor([[-0.5626, 1.7055, 0.6383],
[ 0.5036, 0.1955, -1.2501],
[-0.4412, -0.6775, 1.3401],
[ 0.2041, -0.6125, -0.5171]])
tensor([[-0.5626, 1.7055, 0.6383],
[ 0.5036, 0.1955, -1.2501],
[-0.4412, -0.6775, 1.3401],
[ 0.2041, -0.6125, -0.5171]])
tensor([[-0.5626, 1.7055, 0.6383],
[ 0.5036, 0.1955, -1.2501],
[-0.4412, -0.6775, 1.3401],
[ 0.2041, -0.6125, -0.5171]])
2. 索引操作
需要注意的是:索引出来的结果与原数据共享内存,修改一个,另一个会跟着修改。如果不想修改,可以考虑使用copy()等方法
import torch
x = torch.rand(4,3)
# 取第二列
print(x[:, 1])
tensor([0.6927, 0.1586, 0.3831, 0.6569])
y = x[0,:]
y += 1
print(y)
print(x[0, :]) # 源tensor也被改了了
tensor([1.3175, 1.6927, 1.5891])
tensor([1.3175, 1.6927, 1.5891])
3 维度变换
张量的维度变换常见的方法有torch.view()和torch.reshape()
torch.view()
返回的新tensor与源tensor共享内存(其实是同一个tensor),更改其中的一个,另外一个也会跟着改变。(顾名思义,view()仅仅是改变了对这个张量的观察角度)
import torch
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) # -1是指这一维的维数由其他维度决定
print(x.size(), y.size(), z.size())
print(x)
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
tensor([[-0.6597, 1.5669, 0.4268, 0.4641],
[ 1.0047, -0.7919, -1.6572, 1.1146],
[-0.2664, 1.1993, -0.5021, -0.0344],
[-0.3572, 0.1908, -1.0161, -1.4660]])
# 更改其中的一个,另外一个也会跟着改变
x += 1
print("x:",x)
print("z:",z)
x: tensor([[-0.6597, 1.5669, 0.4268, 0.4641],
[ 1.0047, -0.7919, -1.6572, 1.1146],
[-0.2664, 1.1993, -0.5021, -0.0344],
[-0.3572, 0.1908, -1.0161, -1.4660]])
z: tensor([[-0.6597, 1.5669, 0.4268, 0.4641, 1.0047, -0.7919, -1.6572, 1.1146],
[-0.2664, 1.1993, -0.5021, -0.0344, -0.3572, 0.1908, -1.0161, -1.4660]])
为了使创建的张量和原始张量不共享内存,我们需要使用第二种方法torch.reshape(), 同样可以改变张量的形状,但是此函数并不能保证返回的是其拷贝值,所以官方不推荐使用。推荐的方法是我们先用 clone()
创造一个张量副本然后再使用 torch.view()进行函数维度变换 。
# 用
x= torch.rand(3,4)
print(x)
y=torch.clone(x)
y=torch.reshape(y,(-1,6))
print(y)
x+=1
print(x)
print(y)
tensor([[0.5614, 0.8459, 0.9528, 0.2821],
[0.8855, 0.8525, 0.4966, 0.4935],
[0.1116, 0.5185, 0.9479, 0.2859]])
tensor([[0.5614, 0.8459, 0.9528, 0.2821, 0.8855, 0.8525],
[0.4966, 0.4935, 0.1116, 0.5185, 0.9479, 0.2859]])
tensor([[1.5614, 1.8459, 1.9528, 1.2821],
[1.8855, 1.8525, 1.4966, 1.4935],
[1.1116, 1.5185, 1.9479, 1.2859]])
tensor([[0.5614, 0.8459, 0.9528, 0.2821, 0.8855, 0.8525],
[0.4966, 0.4935, 0.1116, 0.5185, 0.9479, 0.2859]])
注:使用 clone() 还有一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源 Tensor 。 3. 取值操作 如果我们有一个元素 tensor ,我们可以使用 .item() 来获得这个 value,而不获得其他性质:
import torch
x = torch.randn(1)
print(type(x))
print(type(x.item()))
<class 'torch.Tensor'>
<class 'float'>
2.2 自动求导
https://blog.youkuaiyun.com/wistonty11/article/details/127252798
2.3 并行计算
CUDA是我们使用GPU的提供商——NVIDIA提供的GPU并行计算框架
在编写程序中,当我们使用了.cuda()
时,其功能是让我们的模型或者数据从CPU迁移到GPU(0)当中,通过GPU开始计算。
当我们的服务器上有多个GPU,我们应该指明我们使用的GPU是哪一块,如果我们不设置的话,tensor.cuda()方法会默认将tensor保存到第一块GPU上,等价于tensor.cuda(0),这将会导致爆出out of memory的错误。我们可以通过以下两种方式继续设置。
#设置在文件最开始部分
import os
os.environ["CUDA_VISIBLE_DEVICE"] = "2" # 设置默认的显卡
CUDA_VISBLE_DEVICE=0,1 python train.py # 使用0,1两块GPU