模型选择
回归任务:关键点检测GoogLeNet
分类任务
场景任务
根据具体情况选择模型,根据精度及预测时间等方面 API
模型训练
1.基于高层API训练模型
优化器,损失函数,精度计算方式
2.使用PaddleX训练模型
3.模型训练通用配置基本原则
每个输入数据的维度要保持一致,且一定要和模型输入保持一致。 配置学习率衰减策略时,训练的上限轮数一定要计算正确。 BatchSize不宜过大,太大容易内存溢出,且一般为2次幂
超参优化
超参优化的基本概念:见课件
调整超参数的四大方法
使用提前停止来确定训练的迭代次数:防止过拟合
让学习率从高逐渐降低:学习率太大无法收敛,学习率太小收敛太慢(动态学习率或找到合适学习率)
宽泛策略:化简模型,如十分类转换成二分类
小批量数据(mini-batch)大小不必最优
效果展示
可视化输入与输出
巧用VisualDL:可视化工具,也可用来进行参数调整
权重可视化
预测 预测过程可以分为两步:
1.通过网络输出计算出预测框位置和所属类别的得分。 2.使用非极大值抑制来消除重叠较大的预测框。
模型效果及可视化 1.创建数据读取器以读取单张图片的数据
2.定义绘制预测框的画图函数
3.读取指定的图片,输入网络并计算出预测框和得分,然后使用多分类非极大值抑制消除冗余的框。将最终结果可视化。
优化 防止梯度消失和梯度爆炸 更换激活函数 ResNet block batch normalization 梯度截断 设置阈值 预训练+微调
防止过拟合 数据增强 提前停止 权重正则化 L1 L2… dropout
参数调优 学习率 训练轮数 优化函数 在线难例挖掘
后处理 模型融合 测试结果融合 根据实际任务改进
同时在图像大作业中
work目录下少了一个文件mobilenet.py
内容如下
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import paddle
from paddle import ParamAttr
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import Conv2D, BatchNorm, Linear, Dropout
from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D
import math
__all__ = [
"MobileNetV2_x0_25", "MobileNetV2_x0_5", "MobileNetV2_x0_75",
"MobileNetV2", "MobileNetV2_x1_5", "MobileNetV2_x2_0"
]
class ConvBNLayer(nn.Layer):
def __init__(self,
num_channels,
filter_size,
num_filters,
stride,
padding,
channels=None,
num_groups=1,
name=None,
use_cudnn=True):
super(ConvBNLayer, self).__init__()
self._conv = Conv2D(
in_channels=num_channels,
out_channels=num_filters,
kernel_size=filter_size,
stride=stride,
padding=padding,
groups=num_groups,
weight_attr=ParamAttr(name=name + "_weights"),
bias_attr=False)
self._batch_norm = BatchNorm(
num_filters,
param_attr=ParamAttr(name=name + "_bn_scale"),
bias_attr=ParamAttr(name=name + "_bn_offset"),
moving_mean_name=name + "_bn_mean",
moving_variance_name=name + "_bn_variance")
def forward(self, inputs, if_act=True):
y = self._conv(inputs)
y = self._batch_norm(y)
if if_act:
y = F.relu6(y)
return y
class InvertedResidualUnit(nn.Layer):
def __init__(self, num_channels, num_in_filter, num_filters, stride,
filter_size, padding, expansion_factor, name):
super(InvertedResidualUnit, self).__init__()
num_expfilter = int(round(num_in_filter * expansion_factor))
self._expand_conv = ConvBNLayer(
num_channels=num_channels,
num_filters=num_expfilter,
filter_size=1,
stride=1,
padding=0,
num_groups=1,
name=name + "_expand")
self._bottleneck_conv = ConvBNLayer(
num_channels=num_expfilter,
num_filters=num_expfilter,
filter_size=filter_size,
stride=stride,
padding=padding,
num_groups=num_expfilter,
use_cudnn=False,
name=name + "_dwise")
self._linear_conv = ConvBNLayer(
num_channels=num_expfilter,
num_filters=num_filters,
filter_size=1,
stride=1,
padding=0,
num_groups=1,
name=name + "_linear")
def forward(self, inputs, ifshortcut):
y = self._expand_conv(inputs, if_act=True)
y = self._bottleneck_conv(y, if_act=True)
y = self._linear_conv(y, if_act=False)
if ifshortcut:
y = paddle.add(inputs, y)
return y
class InvresiBlocks(nn.Layer):
def __init__(self, in_c, t, c, n, s, name):
super(InvresiBlocks, self).__init__()
self._first_block = InvertedResidualUnit(
num_channels=in_c,
num_in_filter=in_c,
num_filters=c,
stride=s,
filter_size=3,
padding=1,
expansion_factor=t,
name=name + "_1")
self._block_list = []
for i in range(1, n):
block = self.add_sublayer(
name + "_" + str(i + 1),
sublayer=InvertedResidualUnit(
num_channels=c,
num_in_filter=c,
num_filters=c,
stride=1,
filter_size=3,
padding=1,
expansion_factor=t,
name=name + "_" + str(i + 1)))
self._block_list.append(block)
def forward(self, inputs):
y = self._first_block(inputs, ifshortcut=False)
for block in self._block_list:
y = block(y, ifshortcut=True)
return y
class MobileNet(nn.Layer):
def __init__(self, class_dim=1000, scale=1.0):
super(MobileNet, self).__init__()
self.scale = scale
self.class_dim = class_dim
bottleneck_params_list = [
(1, 16, 1, 1),
(6, 24, 2, 2),
(6, 32, 3, 2),
(6, 64, 4, 2),
(6, 96, 3, 1),
(6, 160, 3, 2),
(6, 320, 1, 1),
]
self.conv1 = ConvBNLayer(
num_channels=3,
num_filters=int(32 * scale),
filter_size=3,
stride=2,
padding=1,
name="conv1_1")
self.block_list = []
i = 1
in_c = int(32 * scale)
for layer_setting in bottleneck_params_list:
t, c, n, s = layer_setting
i += 1
block = self.add_sublayer(
"conv" + str(i),
sublayer=InvresiBlocks(
in_c=in_c,
t=t,
c=int(c * scale),
n=n,
s=s,
name="conv" + str(i)))
self.block_list.append(block)
in_c = int(c * scale)
self.out_c = int(1280 * scale) if scale > 1.0 else 1280
self.conv9 = ConvBNLayer(
num_channels=in_c,
num_filters=self.out_c,
filter_size=1,
stride=1,
padding=0,
name="conv9")
self.pool2d_avg = AdaptiveAvgPool2D(1)
self.out = Linear(
self.out_c,
class_dim,
weight_attr=ParamAttr(name="fc10_weights"),
bias_attr=ParamAttr(name="fc10_offset"))
def forward(self, inputs):
y = self.conv1(inputs, if_act=True)
for block in self.block_list:
y = block(y)
y = self.conv9(y, if_act=True)
y = self.pool2d_avg(y)
y = paddle.flatten(y, start_axis=1, stop_axis=-1)
y = self.out(y)
return y
def MobileNetV2_x0_25(**args):
model = MobileNet(scale=0.25, **args)
return model
def MobileNetV2_x0_5(**args):
model = MobileNet(scale=0.5, **args)
return model
def MobileNetV2_x0_75(**args):
model = MobileNet(scale=0.75, **args)
return model
def MobileNetV2(**args):
model = MobileNet(scale=1.0, **args)
return model
def MobileNetV2_x1_5(**args):
model = MobileNet(scale=1.5, **args)
return model
def MobileNetV2_x2_0(**args):
model = MobileNet(scale=2.0, **args)
return model