#深入浅出PyTorch_【01】pytorch基础
2023.01.23
主要内容就是张量 自动求导
pytorch
pytorch为深度学习框架,与Tensorflow为最火的两个框架。开始我们的学习
2.1 张量
张量的英文是Tensor
,它是PyTorch里面基础的运算单位,与Numpy的ndarray相同都表示的是一个多维的矩阵,是基于向量和矩阵的推广。
0
维张量 :代表数字1
维张量 :代表向量2
维张量 :代表矩阵3
维张量 :代表时间序列数据 股价 文本数据 单张彩色图片(RGB)
这里有一些存储在各种类型张量的公用数据集类型:
- 3维 = 时间序列
- 4维 = 图像
- 5维 = 视频
在PyTorch中, torch.Tensor 是存储和变换数据的主要工具
2.1.1 创建tensor
整体来说,用法和Numpy
类似
- 【随机初始化矩阵】
torch.rand(*Size)
:返回区间[0,1)
均匀分布中抽取的随机数;torch.randn(*Size)
:返回从标准正态分布中(均值0,方差1)中抽取的随机数;torch.empty(*Size)
:返回没有初始化的Tensor,数是随机的;
import torch
x = torch.rand(4,3)
print(x)
tensor([[0.1959, 0.3711, 0.0449],[0.4131, 0.5672, 0.9595],[0.0715, 0.8527, 0.9035],[0.7361, 0.0864, 0.5155]])
torch.empty(2,3)
tensor([[7.5556e+28, 5.2839e-11, 7.6194e+31],[2.5318e-12, 2.3044e-12, 1.8590e+34]])
- 【直接创建】
x = torch.tensor([5.5, 3])
print(x)
tensor([5.5000, 3.0000])
torch.ones()
:创建都是1的torch.zero()
:创建都是0的torch.eye()
:对角线为1,其他为0arange(s,e,step)
:从s到e,步长为step
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>)
*注意上面两实例1
后面的.
# 这个对角线不一定非要正矩阵
x= torch.eye(3,4)
x
tensor([[1., 0., 0., 0.],[0., 1., 0., 0.],[0., 0., 1., 0.]])
- 【
torch.arange
创建】
https://blog.csdn.net/wistonty11/article/details/128752554
x_arange = torch.arange(0,24,2).reshape(3,4)
x_arange
tensor([[ 0, 2, 4, 6],[ 8, 10, 12, 14],[16, 18, 20, 22]])
- 【基于已经存在的 tensor,创建一个 tensor】
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
tensor([[1., 1., 1.],[1., 1., 1.],[1., 1., 1.],[1., 1., 1.]], dtype=torch.float64)
tensor([[-0.5762, 1.0635, -0.0626],[-1.1970, 1.1228, 0.5248],[-1.8541, 0.8132, 2.0941],[ 0.9579, -0.8021, 1.1239]])
torch.zero_()
和torch.zeros_like()
:将现有矩阵转换为全0矩阵;
print(x_arange)
x = torch.zero_(x_arange)
x
tensor([[ 0, 2, 4, 6],[ 8, 10, 12, 14],[16, 18, 20, 22]])tensor([[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 0, 0]])
2.2 张量的操作
.type;.shape,.item;
2.2.1 基本操作
.type
:查看类型- `.shape:查看形状
print("x_arange:",x_arange)
print("x_arange.type:",x_arange.type)
print("x_arange.shape:",x_arange.shape)
x_arange: tensor([[ 0, 2, 4, 6],[ 8, 10, 12, 14],[16, 18, 20, 22]])
x_arange.type: <built-in method type of Tensor object at 0x00000241741D5E00>
x_arange.shape: torch.Size([3, 4])
.item
:只有一个元素张量里面的元素值
只有一个元素,不论维度如何,都可以用item()
方法,得到数值
x1 = torch.tensor([4])
x2 = torch.tensor([[4]])
print(x1.item(),x2.item())
4 4
2.2.2 加法
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.2.3 索引操作
需要注意的是:索引出来的结果与原数据共享内存,修改一个,另一个会跟着修改。如果不想修改,可以考虑使用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])
2.2.4 维度变换
张量的维度变换常见的方法有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]])
-
【
reshape()
和clone()
】:改变形状 -
torch.reshape()
:原始张量 可能共享内存, 改变张量的形状,所以官方不推荐使用。
-
- 推荐的方法是我们先用
clone()
:和原始张量 不共享内存,再使用 torch.view()进行函数维度变换 。
- 推荐的方法是我们先用
x= torch.rand(3,4)
print(x)y_clone=torch.clone(x)
y_reshape=torch.reshape(x,(-1,6))
print(y_reshape)x+=1
print("x_new:",x)
print("y_clone:",y_clone)
print("y_reshape:",y_reshape)
tensor([[0.8411, 0.5763, 0.1609, 0.3009],[0.1353, 0.3344, 0.6934, 0.0483],[0.6640, 0.5972, 0.0647, 0.5472]])
tensor([[0.8411, 0.5763, 0.1609, 0.3009, 0.1353, 0.3344],[0.6934, 0.0483, 0.6640, 0.5972, 0.0647, 0.5472]])
x_new: tensor([[1.8411, 1.5763, 1.1609, 1.3009],[1.1353, 1.3344, 1.6934, 1.0483],[1.6640, 1.5972, 1.0647, 1.5472]])
y_clone: tensor([[0.8411, 0.5763, 0.1609, 0.3009],[0.1353, 0.3344, 0.6934, 0.0483],[0.6640, 0.5972, 0.0647, 0.5472]])
y_reshape: tensor([[1.8411, 1.5763, 1.1609, 1.3009, 1.1353, 1.3344],[1.6934, 1.0483, 1.6640, 1.5972, 1.0647, 1.5472]])
注:使用 clone() 还有一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源 Tensor 。
2.2 自动求导
https://blog.csdn.net/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
使用CUDA加速训练:
在PyTorch框架下,CUDA的使用变得非常简单,我们只需要显式的将数据和模型通过.cuda()方法转移到GPU上就可加速我们的训练,在此处我们仅讨论单卡的情况下,后续我们会介绍多卡训练的使用方法。
model = Net()
model.cuda() # 模型显示转移到CUDA上for image,label in dataloader:# 图像和标签显示转移到CUDA上image = image.cuda() label = label.cuda()