zby-patch-1
into main
@@ -0,0 +1,255 @@ | |||
# pytorch学习笔记 | |||
来自datawhale的深入浅出pytorch教程的笔记。主要对第二章和第三章的常用函数和方法进行梳理,方便要用的时候查找和复习,同时巩固对pytorch实现深度学习基本流程的认识。 | |||
教程链接:[深入浅出pytorch](https://datawhalechina.github.io/thorough-pytorch/index.html) | |||
--- | |||
### 第二章:pytorch基础知识 | |||
#### 2.1张量 | |||
1. 生成tensor | |||
|函数 |功能 | | |||
| --- | --- | | |||
|Tensor(sizes)|基础构造函数| | |||
|tensor(data)|类似于np.array| | |||
|ones(sizes)|全1| | |||
|zeros(sizes)|全0| | |||
|eye(sizes)|对角为1,其余为0| | |||
|arange(s,e,step)|从s到e,步长为step| | |||
|linspace(s,e,steps)|从s到e,均匀分成step份| | |||
|rand/randn(sizes)|rand是[0,1)均匀分布;randn是服从N(0,1)的正态分布| | |||
|normal(mean,std)|正态分布(均值为mean,标准差是std)| | |||
|randperm(m)|随机排列| | |||
2. 加法 | |||
- x+y | |||
- x.add_(y) | |||
- torch.add(x,y) | |||
3. 索引:类似numpy,如x[3:5,:] | |||
4. x.view(-1,3):改变形状,填-1表示由其他维度决定,view只改变观察角度不改tensor本身 | |||
5. y=x.clone():复制x,二者内存独立 | |||
6. x.item():x 的数值,不涉及其他性质 | |||
7. 广播机制:两个形状不同的tensor按元素计算(如加法)时会先适当复制元素使这两个 Tensor 形状相同后再按元素运算。 | |||
#### 2.2自动求导 | |||
- requires_grad:布尔值,在创建张量时设置,表示是否计算梯度,若训练需要用到梯度为true,某些情况例如评估时为false。 | |||
- grad_fn:布尔值。将y看作x的函数。这样创建的张量的grad_fn为true,如果是赋值给自身则为false。 | |||
- out.backward():对out反向传播,对于标量out.backward()和 out.backward(torch.tensor(1.)) 等价,对于张量必须在括号内传入一个张量。每次传播梯度都会叠加 | |||
- x.grad:x的梯度,返回的也是一个tensor对象 | |||
- x.data:x的值,对x.data的操作会影响x的值但不影响梯度计算 | |||
- x.grad.data.zero_():令梯度为0,防止梯度的累加 | |||
- with torch.no_grad()::其后面的代码不会跟踪梯度的变化 | |||
一个例子 | |||
```python | |||
import torch | |||
x = torch.ones(2, 2, requires_grad=True) | |||
print(x) | |||
y = x**2 | |||
print(y) | |||
print(y.grad_fn) | |||
z = y * y * 3 | |||
out = z.mean() | |||
print(z, out) | |||
out.backward() | |||
print(x.grad) | |||
``` | |||
最后一项输出为tensor([[3., 3.], [3., 3.]]) | |||
---------- | |||
### 第三章:pytorch主要组成模块 | |||
#### 3.2基本配置 | |||
必须导入的包 | |||
```python | |||
import os | |||
import numpy as np | |||
import torch | |||
import torch.nn as nn | |||
from torch.utils.data import Dataset, DataLoader | |||
import torch.optim as optimizer | |||
``` | |||
一些基础配置 | |||
- batch size | |||
- 初始学习率(初始) | |||
- 训练次数(max_epochs) | |||
- GPU配置 | |||
```python | |||
batch_size = 16 | |||
# 批次的大小 | |||
lr = 1e-4 | |||
# 优化器的学习率 | |||
max_epochs = 100 | |||
``` | |||
GPU的设置有两种常见的方式: | |||
```python | |||
# 方案一:使用os.environ,这种情况如果使用GPU不需要设置 | |||
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1' | |||
# 方案二:使用“device”,后续对要使用GPU的变量用.to(device)即可 | |||
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") | |||
``` | |||
我们可以定义自己的Dataset类来实现灵活的数据读取,定义的类需要继承PyTorch自身的Dataset类。主要包含三个函数: | |||
- __init__: 用于向类中传入外部参数,同时定义样本集 | |||
- __getitem__: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据 | |||
- __len__: 用于返回数据集的样本数 | |||
```python | |||
class MyDataset(Dataset): | |||
def __init__(self, data_dir, info_csv, image_list, transform=None): | |||
""" | |||
Args: | |||
data_dir: path to image directory. | |||
info_csv: path to the csv file containing image indexes | |||
with corresponding labels. | |||
image_list: path to the txt file contains image names to training/validation set | |||
transform: optional transform to be applied on a sample. | |||
""" | |||
label_info = pd.read_csv(info_csv) | |||
image_file = open(image_list).readlines() | |||
self.data_dir = data_dir | |||
self.image_file = image_file | |||
self.label_info = label_info | |||
self.transform = transform | |||
def __getitem__(self, index): | |||
""" | |||
Args: | |||
index: the index of item | |||
Returns: | |||
image and its labels | |||
""" | |||
image_name = self.image_file[index].strip('\n') | |||
raw_label = self.label_info.loc[self.label_info['Image_index'] == image_name] | |||
label = raw_label.iloc[:,0] | |||
image_name = os.path.join(self.data_dir, image_name) | |||
image = Image.open(image_name).convert('RGB') | |||
if self.transform is not None: | |||
image = self.transform(image) | |||
return image, label | |||
def __len__(self): | |||
return len(self.image_file) | |||
``` | |||
#### 3.3数据读入 | |||
构建好Dataset后,就可以使用DataLoader来按批次读入数据了,实现代码如下: | |||
```python | |||
from torch.utils.data import DataLoader | |||
train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=4, shuffle=True, drop_last=True) | |||
val_loader = torch.utils.data.DataLoader(val_data, batch_size=batch_size, num_workers=4, shuffle=False) | |||
``` | |||
其中: | |||
- batch_size:样本是按“批”读入的,batch_size就是每次读入的样本数 | |||
- num_workers:有多少个进程用于读取数据 | |||
- shuffle:是否将读入的数据打乱 | |||
- drop_last:对于样本最后一部分没有达到批次数的样本,使其不再参与训练 | |||
#### 3.4模型构建 | |||
定义MLP类:_init_:用于初始化和定义前向计算的基础函数(如全连接层,relu);forward:调用_init_中的函数形成前向计算函数,无需定义backward,系统会自动计算。类的输入可以是模型的任意一个组件。 | |||
神经网络的层可分为有参数与无参数两种,无参数例如标准化,有参数的有多种,包括: | |||
- 二维卷积层:Conv2D,参数有输入通道数in_channels,输出通道数out_channels,卷积核宽度kernel_size,卷积核长宽不一致的填充数字padding | |||
- 池化层:pool2d,参数有池化层边长pool_size,和池化方式mode | |||
一个神经网络的典型训练过程如下: | |||
1. 定义包含一些可学习参数(或者叫权重)的神经网络 | |||
2. 在输入数据集上迭代 | |||
3. 通过网络处理输入 | |||
4. 计算 loss (输出和正确答案的距离) | |||
5. 将梯度反向传播给网络的参数 | |||
6. 更新网络的权重,一般使用一个简单的规则:weight = weight - learning_rate * gradient(梯度下降) | |||
使用torch.nn包来构建神经网络,nn包则依赖于autograd包来定义模型并对它们求导。一个nn.Module包含各个层和一个forward(input)方法,该方法返回output。 | |||
- torch.Tensor - 一个多维数组,支持诸如backward()等的自动求导操作,同时也保存了张量的梯度。 | |||
- nn.Module - 神经网络模块。是一种方便封装参数的方式,具有将参数移动到GPU、导出、加载等功能。 | |||
- nn.Parameter - 张量的一种,当它作为一个属性分配给一个Module时,它会被自动注册为一个参数。 | |||
- autograd.Function - 实现了自动求导前向和反向传播的定义,每个Tensor至少创建一个Function节点,该节点连接到创建Tensor的函数并对其历史进行编码。 | |||
- net.parameters() -网络的可学习参数 | |||
#### 3.5模型初始化 | |||
使用torch初始化conv和linear | |||
```python | |||
torch.nn.init.kaiming_normal_(conv.weight.data) | |||
torch.nn.init.constant_(linear.weight.data,0.3) | |||
``` | |||
#### 3.6损失函数 | |||
常用损失函数: | |||
1. 二分类交叉熵损失函数 | |||
torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean') | |||
- weight:每个类别的loss设置权值 | |||
- size_average:数据为bool,为True时,返回的loss为平均值;为False时,返回的各样本的loss之和。 | |||
- reduce:数据类型为bool,为True时,loss的返回是标量。 | |||
2. 交叉熵损失函数 | |||
torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean') | |||
ignore_index:忽略某个类的损失函数。 | |||
3. L1损失函数 | |||
torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean') | |||
reduction参数决定了计算模式。有三种计算模式可选:none:逐个元素计算。 sum:所有元素求和,返回标量。 mean:加权平均,返回标量。 如果选择none,那么返回的结果是和输入元素相同尺寸的。默认计算方式是求平均。 | |||
4. MSE损失函数 | |||
torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean') | |||
5. 平滑L1 (Smooth L1)损失函数 | |||
torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='mean', beta=1.0) | |||
6. 二分类logistic损失函数 | |||
torch.nn.SoftMarginLoss(size_average=None, reduce=None, reduction='mean') | |||
#### 3.7 训练与评估 | |||
切换模型的状态: | |||
```python | |||
model.train() # 训练状态 | |||
model.eval() # 验证/测试状态 | |||
``` | |||
一个完整的训练过程: | |||
用for循环读取DataLoader中的全部数据。 | |||
for data, label in train_loader: | |||
之后将数据放到GPU上用于后续计算,此处以.cuda()为例 | |||
data, label = data.cuda(), label.cuda() | |||
开始用当前批次数据做训练时,应当先将优化器的梯度置零: | |||
optimizer.zero_grad() | |||
之后将data送入模型中训练: | |||
output = model(data) | |||
根据预先定义的criterion计算损失函数: | |||
loss = criterion(output, label) | |||
将loss反向传播回网络: | |||
loss.backward() | |||
使用优化器更新模型参数: | |||
optimizer.step() | |||
#### 3.9 pytorch优化器 | |||
共十种,均来自pytorch.optim。先实例化再step一下即可更新参数。 | |||
```python | |||
optimizer = torch.optim.SGD([weight], lr=0.1, momentum=0.9) | |||
optimizer.step() | |||
``` | |||
--- | |||
### 其他 | |||
#### 模型定义与修改 | |||
有三种方式定义模型:Sequential,ModuleList和ModuleDict,他们的方法大致相同。以Sequential为例: | |||
```python | |||
import torch.nn as nn | |||
net = nn.Sequential( | |||
nn.Linear(784, 256), | |||
nn.ReLU(), | |||
nn.Linear(256, 10), | |||
) | |||
print(net) | |||
``` | |||
通过net.fc(某一模型层)=classifier(替换层)可以修改模型的某一层。 | |||
在forward函数里可以给模型增加输入输出 | |||
```python | |||
def forward(self, x, add_variable): | |||
x1000 = self.net(x) | |||
x10 = self.dropout(self.relu(x1000)) | |||
x10 = self.fc1(x10) | |||
x10 = self.output(x10) | |||
return x10, x1000 | |||
``` | |||
#### 模型保存与读取 | |||
```python | |||
# 保存+读取整个模型 | |||
torch.save(model, save_dir) | |||
loaded_model = torch.load(save_dir) | |||
loaded_model.cuda() | |||
``` | |||
#### torchvision | |||
torchvision包含了在计算机视觉中常常用到的数据集,模型和图像处理的方式。常用模块: | |||
- torchvision.datasets 常见数据集 | |||
- torchvision.models 预训练模型 | |||
- torchvision.tramsforms 图像处理方法 | |||
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》