提示:深度学习框架
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
深度学习的总的框架包括以下一些内容:就是对于我们所要的数据进行相关的预处理。包括数据格式的统一以及必要的数据转换,同时进行训练数据集和测试数据集的划分,选择我们所需要的模型,设定相应的损失函数以及优化函数和对应的超参数进行相应的设置,最后使用模型去拟合训练集数据,在验证集和测试集上计算模型表现。
提示:以下是本篇文章正文内容,下面案例可供参考
一、基本配置
首先要导入必要的packbag 、 模块等
os、numpy、torch.utils.data.dataset、torch.utils.data.dataloader、torch.optimizer
batch size 每次训练读入数据的的量
lr 学习率
num_workers 多个线程供你读入数据
epochs 总共训练的批次
GPU 的配置
方案一:使用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")
二、数据读入
1.dataset
_ _init _ _:用于向类中传入外部参数,同时定义样本集
_ _ getitem __:用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据
_ _ len _ _:用于返回数据集的样本数
train_data = datasets.ImageFolder(train_path, transform=data_transform)
val_data = datasets.ImageFolder(val_path, transform=data_transform)
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)
2.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)
shuffle:是否将读入的数据打乱
drop_last:对于样本最后一部分没有达到批次数的样本,使其不再参与训练
三、模型构建
1.神经网络构建
继承moudle 类 构造多层感知机
init函数
forward函数
import torch
from torch import nn
class MLP(nn.Module):
# 声明带有模型参数的层,这里声明了两个全连接层
def __init__(self, **kwargs):
# 调用MLP父类Block的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数
super(MLP, self).__init__(**kwargs)
self.hidden = nn.Linear(784, 256)
self.act = nn.ReLU()
self.output = nn.Linear(256,10)
# 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出
def forward(self, x):
o = self.act(self.hidden(x))
return self.output(o)
模板一样的
import torch
from torch import nn
class MyLayer(nn.Module):
def __init__(self, **kwargs):
super(MyLayer, self).__init__(**kwargs)
def forward(self, x):
return x - x.mean()
四、损失函数
它是数据输入到模型当中,产生的结果与真实标签的评价指标,我们的模型可以按照损失函数的目标来做出改进。
1.二分类交叉熵损失函数
代码如下(示例):
torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')
功能:计算二分类任务时的交叉熵(Cross Entropy)函数。在二分类中,label是{0,1}。对于进入交叉熵函数的input为概率分布的形式。一般来说,input为sigmoid激活层的输出,或者softmax的输出。
weight:每个类别的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')
功能: 计算输出y和真实标签target之间的差值的绝对值。
我们需要知道的是,reduction参数决定了计算模式。有三种计算模式可选:none:逐个元素计算。 sum:所有元素求和,返回标量。 mean:加权平均,返回标量。 如果选择none,那么返回的结果是和输入元素相同尺寸的。默认计算方式是求平均。
4.MSE损失函数
代码如下(示例):
torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')
功能: 计算输出y和真实标签target之差的平方。
和L1Loss一样,MSELoss损失函数中,reduction参数决定了计算模式。有三种计算模式可选:none:逐个元素计算。 sum:所有元素求和,返回标量。默认计算方式是求平均。
5.平滑L1 (Smooth L1)损失函数
代码如下(示例):
torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='mean', beta=1.0)
功能: L1的平滑输出,其功能是减轻离群点带来的影响
。
。
。
。
6.多标签边界损失函数
代码如下(示例):
torch.nn.MultiLabelMarginLoss(size_average=None, reduce=None, reduction='mean')
功能: 对于多标签分类问题计算损失函数。
五、优化器
本质上就是一个函数去寻找最优解,只不过这个最优解是一个矩阵
1.第一种是直接暴力穷举一遍参数,这种方法实施可能性基本为0,堪比愚公移山plus的难度。
2.为了使求解参数过程更快,人们提出了第二种办法,即BP+优化器逼近求解。
Pytorch很人性化的给我们提供了一个优化器的库torch.optim,在这里面提供了十种优化器。
torch.optim.ASGD
torch.optim.Adadelta
torch.optim.Adagrad
torch.optim.Adam
torch.optim.AdamW
torch.optim.Adamax
torch.optim.LBFGS
torch.optim.RMSprop
torch.optim.Rprop
torch.optim.SGD
torch.optim.SparseAdam
1.每个优化器都是一个类,我们一定要进行实例化才能使用,比如下方实现:
class Net(nn.Moddule):
···
net = Net()
optim = torch.optim.SGD(net.parameters(),lr=lr)
optim.step()
2.optimizer在一个神经网络的epoch中需要实现下面两个步骤:
梯度置零
梯度更新
optimizer = torch.optim.SGD(net.parameters(), lr=1e-5)
for epoch in range(EPOCH):
...
optimizer.zero_grad() #梯度置零
loss = ... #计算loss
loss.backward() #BP反向传播
optimizer.step() #梯度更新
六、训练与评估
model.train() # 训练状态
model.eval() # 验证/测试状态
读取数据
for data, label in train_loader:
数据加载到GPU
data, label = data.cuda(), label.cuda()
梯度清零
optimizer.zero_grad()
数据输入模型
output = model(data)
损失计算
loss = criterion(output, label)
损失回传
loss.backward()
优化器更新参数
optimizer.step()
验证/测试的流程基本与训练过程一致,不同点在于:
需要预先设置torch.no_grad,以及将model调至eval模式
不需要将优化器的梯度置零
不需要将loss反向回传到网络
不需要更新optimizer