赞
踩
pytorch通过继承nn.Module类,定义子模块的实例化和前向传播,实现深度学习模型的搭建。其构建代码如下:
import torch
import torch.nn as nn
class Model(nn.Module):
def __init__(self, *kargs): # 定义类的初始化函数,...是用户的传入参数
super(Model, self).__init__()#调用父类nn.Module的初始化方法
... # 根据传入的参数来定义子模块
def forward(self, *kargs): # 定义前向计算的输入参数,...一般是张量或者其他的参数
ret = ... # 根据传入的张量和子模块计算返回张量
return ret
import torch
import torch.nn as nn
class LinearModel(nn.Module):
def __init__(self, ndim):
super(LinearModel, self).__init__()
self.ndim = ndim#输入的特征数
self.weight = nn.Parameter(torch.randn(ndim, 1)) # 定义权重
self.bias = nn.Parameter(torch.randn(1)) # 定义偏置
def forward(self, x):
# 定义线性模型 y = Wx + b
return x.mm(self.weight) + self.bias
实例化方法如下:
lm = LinearModel(5) # 定义线性回归模型,特征数为5
x = torch.randn(4, 5) # 定义随机输入,迷你批次大小为4
lm(x) # 得到每个迷你批次的输出
对于model.train()和model.eval()用法和区别进一步可以参考:《Pytorch:model.train()和model.eval()用法和区别》
对于上面定义的线性模型来举例:
lm.named_parameters() # 获取模型参数(带名字)的生成器 #<generator object Module.named_parameters at 0x00000279A1809510> list(lm.named_parameters()) # 转换生成器为列表 [('weight', Parameter containing: tensor([[-1.0407], [ 0.0427], [ 0.4069], [-0.7064], [-1.1938]], requires_grad=True)), ('bias', Parameter containing: tensor([-0.7493], requires_grad=True))] lm.parameters() # 获取模型参数(不带名字)的生成器 list(lm.parameters()) # 转换生成器为列表 [Parameter containing: tensor([[-1.0407], [ 0.0427], [ 0.4069], [-0.7064], [-1.1938]], requires_grad=True), Parameter containing: tensor([-0.7493], requires_grad=True)] lm.cuda()#模型参数转到GPU上 list(lm.parameters()) # 转换生成器为列表
model.train()是保证BN层能够用到每一批数据的均值和方差。对于Dropout,model.train()是在训练中随机去除神经元,用一部分网络连接来训练更新参数。如果被删除的神经元(叉号)是唯一促成正确结果的神经元。一旦我们移除了被删除的神经元,它就迫使其他神经元训练和学习如何在没有被删除神经元的情况下保持准确。这种dropout提高了最终测试的性能,但它对训练期间的性能产生了负面影响,因为网络是不全的
在测试时添加model.eval()。model.eval()是保证BN层能够用全部训练数据的均值和方差,即测试过程中要保证BN层的均值和方差不变(model.eval()时,框架会自动把BN和Dropout固定住,不会取平均,直接使用在训练阶段已经学出的mean和var值)
pytorch损失函数有两种形式:
import torch
import torch.nn as nn
mse = nn.MSELoss() # 初始化平方损失函数模块
#class torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')
t1 = torch.randn(5, requires_grad=True) # 随机生成张量t1
tensor([ 0.6582, 0.0529, -0.9693, -0.9313, -0.7288], requires_grad=True)
t2 = torch.randn(5, requires_grad=True) # 随机生成张量t2
tensor([ 0.8095, -0.3384, -0.9510, 0.1581, -0.1863], requires_grad=True)
mse(t1, t2) # 计算张量t1和t2之间的平方损失函数
tensor(0.3315, grad_fn=<MseLossBackward>)
t1s = torch.sigmoid(t1)
t2 = torch.randint(0, 2, (5, )).float() # 随机生成0,1的整数序列,并转换为浮点数
bce=torch.nn.BCELoss()
(t1s, t2) # 计算二分类的交叉熵
bce_logits = nn.BCEWithLogitsLoss() # 使用交叉熵对数损失函数
bce_logits(t1, t2) # 计算二分类的交叉熵,可以发现和前面的结果一致
N=10 # 定义分类数目
t1 = torch.randn(5, N, requires_grad=True) # 随机产生预测张量
t2 = torch.randint(0, N, (5, )) # 随机产生目标张量
t1s = torch.nn.functional.log_softmax(t1, -1) # 计算预测张量的LogSoftmax
nll = nn.NLLLoss() # 定义NLL损失函数
nll(t1s, t2) # 计算损失函数
ce = nn.CrossEntropyLoss() # 定义交叉熵损失函数
ce(t1, t2) # 计算损失函数,可以发现和NLL损失函数的结果一致
更多学习率优化器和调度器参考《torch.optim官方文档》
以波士顿房价问题举例,构建SGD优化器。第一个参数是模型的参数生成器(lm.parameters()调用),第二个参数是学习率。训练时通过 optim.step()进行优化计算。
from sklearn.datasets import load_boston boston = load_boston() lm = LinearModel(13) criterion = nn.MSELoss() optim = torch.optim.SGD(lm.parameters(), lr=1e-6) # 定义优化器 data = torch.tensor(boston["data"], requires_grad=True, dtype=torch.float32) target = torch.tensor(boston["target"], dtype=torch.float32) for step in range(10000): predict = lm(data) # 输出模型预测结果 loss = criterion(predict, target) # 输出损失函数 if step and step % 1000 == 0 : print("Loss: {:.3f}".format(loss.item())) optim.zero_grad() # 清零梯度 loss.backward() # 反向传播 optim.step()
torch.optim.SGD(params,lr=<required parameter>,momentum=0,
dampening=0,weight_decay=0,nesterov=False)
#momentum:动量因子
#dampening:动量抑制因子
#nesterov:设为True时使用nesterov动量
torch.optim.Adagrad(
params,lr=0.01,lr_decay=0,weight_decay=0,
initial_accumulator_value=0,eps=1e-10)
#lr_decay:学习率衰减速率
#weight_decay:权重衰减
#initial_accumulator_value:梯度初始累加值
对不同参数指定不同的学习率:
optim.SGD([
{'params': model.base.parameters()},
{'params': model.classifier.parameters(), 'lr': 1e-3}
], lr=1e-2, momentum=0.9)
这意味着model.base的参数将使用 的默认学习率1e-2, model.classifier的参数将使用 的学习率1e-3,0.9所有参数将使用动量 。
更多学习率优化器和调度器参考《torch.optim官方文档》
scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
#没经过30的个迭代周期,学习率降为原来的0.1倍。每个epoch之后学习率都会衰减。
or epoch in range(100):
train(...)
validate(...)
scheduler.step()
大多数学习率调度器都可以称为背靠背(也称为链式调度器)。结果是每个调度器都被一个接一个地应用于前一个调度器获得的学习率。
例子:
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler1 = ExponentialLR(optimizer, gamma=0.9)
scheduler2 = MultiStepLR(optimizer, milestones=[30,80], gamma=0.1)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler1.step()
scheduler2.step()
本节也可以参考《编写transformers的自定义pytorch训练循环(Dataset和DataLoader解析和实例代码)》
4.1 DataLoader参数
PyTorch 数据加载实用程序的核心是torch.utils.data.DataLoader 类。它代表一个 Python 可迭代的数据集,支持:
train_loader = DataLoader(dataset=train_data, batch_size=6, shuffle=True ,num_workers=4)
test_loader = DataLoader(dataset=test_data, batch_size=6, shuffle=False,num_workers=4)
下面看看dataloader代码:
class DataLoader(object):
def __init__(self, dataset, batch_size=1, shuffle=False, sampler=None,
batch_sampler=None, num_workers=0, collate_fn=None,
pin_memory=False, drop_last=False, timeout=0,
worker_init_fn=None,*, prefetch_factor=2,persistent_workers=False)
self.dataset = dataset
self.batch_size = batch_size
self.num_workers = num_workers
self.collate_fn = collate_fn
self.pin_memory = pin_memory
self.drop_last = drop_last
self.timeout = timeout
self.worker_init_fn = worker_init_fn
想用随机抽取的模式加载输入,可以设置 sampler 或 batch_sampler。如何定义抽样规则,可以看sampler.py脚本,或者这篇帖子:《一文弄懂Pytorch的DataLoader, DataSet, Sampler之间的关系》
DataLoader 构造函数最重要的参数是dataset,它表示要从中加载数据的数据集对象。PyTorch 支持两种不同类型的数据集:
其构造方法如下:
class Dataset(object):
def __getitem__(self, index):
# index: 数据缩索引(整数,范围为0到数据数目-1)
# ...
# 返回数据张量
def __len__(self):
# 返回数据的数目
# ...
主要重写两个方法:
更具体的可以参考《torch.utils.data.Dataset》
class MyIterableDataset(torch.utils.data.IterableDataset): def __init__(self, start, end): super(MyIterableDataset).__init__() assert end > start, \ "this example code only works with end >= start" self.start = start self.end = end def __iter__(self): worker_info = torch.utils.data.get_worker_info() if worker_info is None: # 单进程数据载入 iter_start = self.start iter_end = self.end else: # 多进程,分割数据 #根据不同工作进程序号worker_id,设置不同进程数据迭代器取值范围。保证不同进程获取不同的迭代器。 per_worker = int(math.ceil((self.end - self.start) \ / float(worker_info.num_workers))) worker_id = worker_info.id iter_start = self.start + worker_id * per_worker iter_end = min(iter_start + per_worker, self.end) return iter(range(iter_start, iter_end))
更多详细信息,请参阅IterableDataset
将根据shufflea的参数自动构建顺序或混洗采样器DataLoader。或者,用户可以使用该sampler参数来指定一个自定义Sampler对象,该对象每次都会生成下一个要获取的索引/键。
一次Sampler生成批量索引列表的自定义可以作为batch_sampler参数传递。也可以通过batch_size和 drop_last参数启用自动批处理。
经由参数 batch_size,drop_last和batch_sampler,DataLoader支持批处理数据
当启用自动批处理时,每次都会使用数据样本列表调用 collate_fn。预计将输入样本整理成一个批次,以便从数据加载器迭代器中产生。
例如,如果每个数据样本由一个 3 通道图像和一个完整的类标签组成,即数据集的每个元素返回一个元组 (image, class_index),则默认 collate_fn 将此类元组的列表整理成单个元组一个批处理图像张量和一个批处理类标签张量。特别是,默认 collate_fn 具有以下属性:
它总是预先添加一个新维度作为批次维度。
它会自动将 NumPy 数组和 Python 数值转换为 PyTorch 张量。
它保留了数据结构,例如,如果每个样本是一个字典,它输出一个具有相同键集但批量张量作为值的字典(如果值不能转换为张量,则为列表)。列表 s、元组 s、namedtuple s 等也是如此。
用户可以使用自定义 collate_fn 来实现自定义批处理,例如,沿着除第一个维度之外的维度进行整理,填充各种长度的序列,或添加对自定义数据类型的支持。
torch.save(obj, f, pickle_module=pickle, pickle_protocol=2)
torch.load(f, map_location=None, pickle_module=pickle, **pickle_load_args)
torch.save参数
torch.load函数
如果模型保存在GPU中,而加载的当前计算机没有GPU,或者GPU设备号不对,可以使用map_location=‘cpu’。
PyTorch默认有两种模型保存方式:
torch.save(model.state_dict(), PATH)
model = TheModelClass(*args, **kwargs)
model.load_state_dict(torch.load(PATH))
model.eval()
以 Python `pickle 模块的方式来保存模型。这种方法的缺点是:
torch.save(model, PATH)
# 模型类必须在此之前被定义
model = torch.load(PATH)
model.eval()
一个模型的检查点代码如下:
torch.save({
'epoch': epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
...
}, PATH)
加载
model = TheModelClass(*args, **kwargs)
optimizer = TheOptimizerClass(*args, **kwargs)
checkpoint = torch.load(PATH)
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
epoch = checkpoint['epoch']
loss = checkpoint['loss']
model.eval()#或model.train()
或者是:
save_info = { # 保存的信息
"iter_num": iter_num, # 迭代步数
"optimizer": optimizer.state_dict(), # 优化器的状态字典
"model": model.state_dict(), # 模型的状态字典
}
# 保存信息
torch.save(save_info, save_path)
# 载入信息
save_info = torch.load(save_path)
optimizer.load_state_dict(save_info["optimizer"])
model.load_state_dict(sae_info["model"])
torch.save({
'modelA_state_dict': modelA.state_dict(),
'modelB_state_dict': modelB.state_dict(),
'optimizerA_state_dict': optimizerA.state_dict(),
'optimizerB_state_dict': optimizerB.state_dict(),
...
}, PATH)
加载
modelA = TheModelAClass(*args, **kwargs)
modelB = TheModelBClass(*args, **kwargs)
optimizerA = TheOptimizerAClass(*args, **kwargs)
optimizerB = TheOptimizerBClass(*args, **kwargs)
checkpoint = torch.load(PATH)
modelA.load_state_dict(checkpoint['modelA_state_dict'])
modelB.load_state_dict(checkpoint['modelB_state_dict'])
optimizerA.load_state_dict(checkpoint['optimizerA_state_dict'])
optimizerB.load_state_dict(checkpoint['optimizerB_state_dict'])
modelA.eval()
modelB.eval()
当保存一个模型由多个 torch.nn.Modules 组成时,例如GAN(对抗生成网络)、sequence-to-sequence (序列到序列模型), 或者是多个模 型融合, 可以采用与保存常规检查点相同的方法。换句话说,保存每个模型的 state_dict 的字典和相对应的优化器。如前所述,可以通 过简单地将它们附加到字典的方式来保存任何其他项目,这样有助于恢复训练。
参考《PyTorch学习笔记(九) ---- 使用 TensorBoard 可视化模型,数据和训练》
TensorBoard安装:
pip install tensorflow-tensorboard
pip install tensorboard
安装完之后import tensorboard时报错ImportError: TensorBoard logging requires TensorBoard version 1.15 or above试了几种方法。最后关掉ipynb文件,新建一个ipynb文件复制代码运行就好了。
TensorBoard是分为前段显示和后端数据记录的,因此其Pipeline也分为两步:
后端数据记录:TensorBoard中把后端服务器抽象成了一个类:SummaryWriter
。声明之后就会开启后端数据记录的服务。
#从tensorboard构造一个摘要写入器SummaryWriter。
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter()
参数解析如下:
class SummaryWriter(log_dir=None, comment='', purge_step=None, max_queue=10, flush_secs=120, filename_suffix='')
log_dir (str)
:指定了数据保存的文件夹的位置,不存在则创建。
comment (string)
:给默认的log_dir添加的后缀,如果我们已经指定了log_dir具体的值,那么这个参数就不会有任何的效果purge_step (int)
:
max_queue (int)
:在记录数据的时候,在内存中开的队列的长度,当队列满了之后就会把数据写入磁盘(文件)中。flush_secs (int)
:表示写入tensorboard文件的时间间隔(s),默认是120秒,即两分钟。filename_suffix (string)
:添加到log_dir中每个文件的后缀,默认为空。更多文件名称设置要参考tensorboard.summary.writer.event_file_writer.EventFileWriter类。添加数据。实例化SummaryWriter类使用实例化方法添加数据,这些方法都以add_开头,例如:add_scalar、add_scalars、add_image……具体来说,所有的方法有:
前端查看数据
tensorboard-logdir./run
:启动tensorboard服务器。默认端口6006。访问http://127.0.0.1:6006可以看到tensorboard网页界面。writer.close()
可关闭服务也可参考yolov5教程,里面有使用tensorboard和clearML。
from sklearn.datasets import load_boston from torch.utils.tensorboard import SummaryWriter import torch import torch.nn as nn #定义线性回归模型 class LinearModel(nn.Module): def __init__(self, ndim): super(LinearModel, self).__init__() self.ndim = ndim self.weight = nn.Parameter(torch.randn(ndim, 1)) # 定义权重 self.bias = nn.Parameter(torch.randn(1)) # 定义偏置 def forward(self, x): # 定义线性模型 y = Wx + b return x.mm(self.weight) + self.bias boston = load_boston() lm = LinearModel(13) criterion = nn.MSELoss() optim = torch.optim.SGD(lm.parameters(), lr=1e-6) data = torch.tensor(boston["data"], requires_grad=True, dtype=torch.float32) target = torch.tensor(boston["target"], dtype=torch.float32) writer = SummaryWriter() # 构造摘要生成器,定义TensorBoard输出类 for step in range(10000): predict = lm(data) loss = criterion(predict, target) writer.add_scalar("Loss/train", loss, step) # 输出损失函数 writer.add_histogram("Param/weight", lm.weight, step) # 输出权重直方图 writer.add_histogram("Param/bias", lm.bias, step) # 输出偏置直方图 if step and step % 1000 == 0 : print("Loss: {:.3f}".format(loss.item())) optim.zero_grad() loss.backward() optim.step()
colab上加载tensorboard:
%load_ext tensorboard
%tensorboard --logdir runs/swin_s
也可在命令行调用:
# 打开cmd命令
tensorboard --logdir=.\Chapter2\runs --bind_all
#TensorBoard 2.2.2 at http://DESKTOP-OHLNREI:6006/ (Press CTRL+C to quit)
SummaryWriter添加数据的API都以add_开头,具体有:
add_scalar(tag, scalar_value, global_step=None, walltime=None)
于在tensorboard中加入loss,其中常用参数有:
- tag:不同图表的标签,如下图所示的Train_loss。
- scalar_value:标签的值,浮点数
- global_step:当前迭代步数,标签的x轴坐标
- walltime:迭代时间函数。如果不传入,方法内部使用time.time()返回一个浮点数代表时间
writer.add_scalar('Train_loss', loss, (epoch*epoch_size + iteration))
add_scalars(main_tag, tag_scalar_dict, global_step=None, walltime=None)
和上一个方法类似,通过传入一个主标签(main_tag),然后传入键值对是标签和标量值的一个字典(tag_scalar_dict),对每个标量值进行显示。
显示张量分量的直方图和对应的分布
add_histogram(tag, values, global_step=None, bins='tensorflow', walltime=None, max_bins=None)
传入pytorch模块及输入,显示模块对应的计算图
if Cuda:
graph_inputs = torch.from_numpy(np.random.rand(1,3,input_shape[0],input_shape[1])).type(torch.FloatTensor).cuda()
else:
graph_inputs = torch.from_numpy(np.random.rand(1,3,input_shape[0],input_shape[1])).type(torch.FloatTensor)
writer.add_graph(model, (graph_inputs,))
显示准确率-召回率曲线(Prediction-Recall Curve)。
add_pr_curve(tag, labels, predictions, global_step=None, num_thresholds=127,
weights=None, walltime=None)
# 1\. gets the probability predictions in a test_size x num_classes Tensor # 2\. gets the preds in a test_size Tensor # takes ~10 seconds to run class_probs = [] # 预测概率 class_preds = [] # 预测类别标签 with torch.no_grad(): for data in testloader: images, labels = data output = net(images) class_probs_batch = [F.softmax(el, dim=0) for el in output] _, class_preds_batch = torch.max(output, 1) class_probs.append(class_probs_batch) class_preds.append(class_preds_batch) test_probs = torch.cat([torch.stack(batch) for batch in class_probs]) test_preds = torch.cat(class_preds) # helper function def add_pr_curve_tensorboard(class_index, test_probs, test_preds, global_step=0): ''' Takes in a "class_index" from 0 to 9 and plots the corresponding precision-recall curve ''' tensorboard_preds = test_preds == class_index tensorboard_probs = test_probs[:, class_index] writer.add_pr_curve(classes[class_index], tensorboard_preds, tensorboard_probs, global_step=global_step) writer.close() # plot all the pr curves for i in range(len(classes)): add_pr_curve_tensorboard(i, test_probs, test_preds)
现在,您将看到一个“ PR Curves”选项卡,其中包含每个类别的精度回召曲线。 继续戳一下; 您会发现在某些类别中,模型的“曲线下面积”接近 100%,而在另一些类别中,该面积更低:
# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()
# create grid of images
img_grid = torchvision.utils.make_grid(images)
# show images
matplotlib_imshow(img_grid, one_channel=True)
# write to tensorboard
writer.add_image('four_fashion_mnist_images', img_grid)
tensorboard --logdir=runs
有的时候,在服务器上训练模型的时候为了避免和别人的TensorBoard的端口撞了,我们需要指定新的端口。或者有的时候我们在docker容器里跑TensorBoard,我们通过一个端口映射到主机上去,这个时候就需要指定TensorBoard使用特定的端口。格式为:tensorboard --logdir=数据文件夹 --port=端口
。例如:
tensorboard --logdir=./Feb05_01-00-48_Alienware/ --port=10000
save_name=swins_mixup # 代表swin_transformer模型的S Type(一共有T、S、L三种模型大小),以及数据增强用了Mixup
board_time = "{0:%Y-%m-%dT%H-%M-%S/}".format(datetime.now())
comment=f'save_nmae={save_name} lr={lr} transforms={transforms}' # 这个写了好像没啥用
writer = SummaryWriter(log_dir='runs/'+save_name+board_time,comment=comment)
运行
%load_ext tensorboard
%tensorboard --logdir runs/
下图那些背景现就是同一个文件夹的不同log文件显示的曲线。所以说要对比,log日志不能在一个文件夹。
TensorBoard 的优势之一是其可视化复杂模型结构的能力。 让我们可视化我们构建的模型。
writer.add_graph(net, images)
writer.close()
现在刷新 TensorBoard 后,您应该会看到一个“ Graphs”标签,如下所示:
继续并双击“ Net”以展开它,查看组成模型的各个操作的详细视图。
TensorBoard 具有非常方便的功能,可在低维空间中可视化高维数据,例如图像数据; 接下来我们将介绍。
# helper function def select_n_random(data, labels, n=100): ''' Selects n random datapoints and their corresponding labels from a dataset ''' assert len(data) == len(labels) perm = torch.randperm(len(data)) return data[perm][:n], labels[perm][:n] # select random images and their target indices images, labels = select_n_random(trainset.data, trainset.targets) # get the class labels for each image class_labels = [classes[lab] for lab in labels] # log embeddings features = images.view(-1, 28 * 28) writer.add_embedding(features, metadata=class_labels, label_img=images.unsqueeze(1)) writer.close()
现在,在 TensorBoard 的“投影仪”选项卡中,您可以看到这 100 张图像-每个图像 784 维-向下投影到三维空间中。 此外,这是交互式的:您可以单击并拖动以旋转三维投影。 最后,有两个技巧可以使可视化效果更容易看到:在左上方选择“颜色:标签”,并启用“夜间模式”,这将使图像更容易看到,因为它们的背景是白色的:
# helper functions def images_to_probs(net, images): ''' Generates predictions and corresponding probabilities from a trained network and a list of images ''' output = net(images) # convert output probabilities to predicted class _, preds_tensor = torch.max(output, 1) preds = np.squeeze(preds_tensor.numpy()) return preds, [F.softmax(el, dim=0)[i].item() for i, el in zip(preds, output)] def plot_classes_preds(net, images, labels): ''' Generates matplotlib Figure using a trained network, along with images and labels from a batch, that shows the network's top prediction along with its probability, alongside the actual label, coloring this information based on whether the prediction was correct or not. Uses the "images_to_probs" function. ''' preds, probs = images_to_probs(net, images) # plot the images in the batch, along with predicted and true labels fig = plt.figure(figsize=(12, 48)) for idx in np.arange(4): ax = fig.add_subplot(1, 4, idx+1, xticks=[], yticks=[]) matplotlib_imshow(images[idx], one_channel=True) ax.set_title("{0}, {1:.1f}%\n(label: {2})".format( classes[preds[idx]], probs[idx] * 100.0, classes[labels[idx]]), color=("green" if preds[idx]==labels[idx].item() else "red")) return fig
在训练过程中,我们将生成一幅图像,显示该批次中包含的四幅图像的模型预测与实际结果。
running_loss = 0.0 for epoch in range(1): # loop over the dataset multiple times for i, data in enumerate(trainloader, 0): # get the inputs; data is a list of [inputs, labels] inputs, labels = data # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 1000 == 999: # every 1000 mini-batches... # ...log the running loss writer.add_scalar('training loss', running_loss / 1000, epoch * len(trainloader) + i) # ...log a Matplotlib Figure showing the model's predictions on a # random mini-batch writer.add_figure('predictions vs. actuals', plot_classes_preds(net, inputs, labels), global_step=epoch * len(trainloader) + i) running_loss = 0.0 print('Finished Training')
我们可以查看整个学习过程中模型在任意批次上所做的预测。 查看“图像”选项卡,然后在“预测与实际”可视化条件下向下滚动以查看此内容; 这向我们表明,例如,仅经过 3000 次训练迭代,该模型就能够区分出视觉上截然不同的类,例如衬衫,运动鞋和外套
右上方三个依次是:
权重分布和直方图应该是随着训练一直变化,直到分布稳定。如果一直没有变化,可能模型结构有问题或者反向传播有问题。
Scalars:这个面板是最常用的面板,主要用于将神经网络训练过程中的acc(训练集准确率)val_acc(验证集准确率),loss(损失值),weight(权重)等等变化情况绘制成折线图。
参考《AUGMIX:A SIMPLE DATA PROCESSING METHOD TO IMPROVE ROBUSTNESS AND UNCERTA》
最新提出的数据增广方法有,如上图:
Mixup实现:
!pip install torchtoolbox
from torchtoolbox.tools import mixup_data, mixup_criterion
alpha = 0.2
for i, (data, labels) in enumerate(train_data):
data = data.to(device, non_blocking=True)
labels = labels.to(device, non_blocking=True)
data, labels_a, labels_b, lam = mixup_data(data, labels, alpha)
optimizer.zero_grad()
outputs = model(data)
loss = mixup_criterion(Loss, outputs, labels_a, labels_b, lam)
loss.backward()
optimizer.update()
from torchvision import transforms
from torchtoolbox.transform import Cutout
train_transform = transforms.Compose([
transforms.RandomResizedCrop(224),
Cutout(),
transforms.RandomHorizontalFlip(),
transforms.ColorJitter(0.4, 0.4, 0.4),
transforms.ToTensor(),
normalize,
])
from torchtoolbox.nn.loss import ArcLoss, CosLoss, L2Softmax
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。