深度学习实践结构性经验总结

  2019-1-14 


总体流程

  • 定义网络结构
  • 定义数据变换
  • 定义超参数,损失函数,优化方法,自适应学习率等…
  • 读取训练集与测试集(自定义数据集,多种读入方式等..)
    开始训练

    • 训练一个Epoch
      自适应学习率更新
      循环:训练一个batch——从dataloader读取一个mini batch

      • 转换为cuda变量
      • 梯度清0
        FORWARD
      • 将数据输入模型得到结果
      • 根据结果得到预测标签
      • 计算train loss
        BACKWARD
      • 反向计算梯度
      • 优化器更新
        统计本batch
    • 统计本epoch

【注】
①如果是测试,则取消[自适应学习率更新]和[BACKWARD]的步骤即可
训练和测试可以结合起来 train=datalodaer(trainset…),test=dataloader(testset…)
则在开始训练一个epoch的时候,加一个循环 for phase in [train,test]即可,后面的在测试不需要的步骤作判断if phase is train: do就行
②可以设置一个全局的最优准确率,然后记录下来最佳准确率,并储存当时的最优模型权重
③注意设置模型模式model.train(True)设置为训练模式model.eval(True)设置为测试模式

定义网络结构

在定义网络结构的时候,如下形式

# 定义的网络结构类必须继承自nn.Module
class myNet(nn.Module):
    # 注意传入参数self到结构函数
    # init中的参数为初始化网络的参数
    def __init__(self):
        super().__init__
        # 定义网络
        # 单个定义
        self.s1 = nn.Conv2d(......)
        # 或集合定义
        self.s1 = nn.Sequential(
            nn.Conv2d(......),
            nn.ReLU()
        )
        # 全连接层(对于卷积神经网络用于分类)
        self.fc = nn.Linear()
    # 注意传入参数self和x(输入矩阵)!
    # forward中的参数为训练的时候要传入的参数 比如求output = model(x)时
    def forward(self,x):
        x = self.conv1(x)
        x = self.fc(x)
        # 经过特征提取层后,要扁平化才能进入fc层!
        x = x.view(x.size(0), -1) 
        return F.softmax(x)	

注意,一个误区:定义网络是定义网络的结构!输入一般输入一个batch,对该batch的处理为网络的内容

nn包含了所有的层结构定义组件, F包含了所有的函数, nn中的每个组件都需要添加到nn.Module容器中才能使用. def参数中的self即指向nn.Module(指向本类,而本类继承自nn.Module), 通过定义self.diyiceng = nn.Conv2d(xxx) 即将组件添加到了nn.Module容器中

nn.Sequential 组合一系列组件定义

#eg
self.conv2 = nn.Sequential( 
	nn.Conv2d(16, 32, 5, 1, 2), 
	nn.ReLU(),  
	nn.MaxPool2d(2)
)  
#这里就将三个组件组合成一个组件了
#注意里面直接写组件组成即可 不是变量定义

建立深度学习模型一般实践

数据预处理与特征工程

  • 向量化
  • 值归一化
  • 处理缺省值
  • 特征工程
    过拟合
  • 获取更多数据、数据增强等
  • 缩小网络规模
  • 应用权重正则化
  • 应用dropout
    欠拟合
  • 获取更多数据
  • 增加权重

一般流程

  • 问题定义与数据集创建
  • 选择模型评估标准
  • 评估协议(测试集 验证集)
  • 准备数据
  • 模型基线(创建一个非常简单的模型来打破基线分数 如二分类为0.5)
  • 训练大达到过拟合
  • 应用正则化
  • 学习率选择策略

且听风吟