DL中的数值稳定性、模型效果影响因素和kaggle竞赛流程举例

1. 梯度消失和梯度爆炸

这是DL中有关数值稳定性的经典问题, 当神经网络的层数较多时容易出现. 例如, 在激活函数为恒等变换时 (\phi(x)=x), 给定输入\boldsymbol{X},多层感知机的第层的输出\boldsymbol{H}^{(l)} = \boldsymbol{X} \boldsymbol{W}^{(1)} \boldsymbol{W}^{(2)} \ldots \boldsymbol{W}^{(l)}, 若所有层的权重都是标量如0.2和5, 则在第30层处的输出为0.2^{30}\to0 (消失) 和5^30\to\infty (爆炸). 梯度的计算同理.

2. 初始化模型参数

2.1 其必要性

(输出单元设为1) 整个网络具有对称性, 如果不进行参数随机初始化, 即每个隐藏单元参数的初始值都是一样, 那么无论在正向/反向传播时, 同层所有单元运算结果和梯度都会是一样的, 因此本质上仅有1个隐藏单元在发挥作用


网络具有对称性

2.2 初始化方法

之前的例子中使用的都是PyTorch自带的torch.nn.init.normal()正态分布随机初始化, 另外nn.Module模块针对具体的layer类型采取了较为合理的初始化方法, 一般无需我们考虑.

还有一种常用的初始化方法Xavier随机初始化. 假设某全连接层的输入个数为a, 输出个数为b,Xavier随机初始化将使该层中权重参数的每个元素都随机采样于均匀分布:
U(-\sqrt{\frac{6}{a+b}},\sqrt{\frac{6}{a+b}})
它的设计主要考虑到, 模型参数初始化后, 每层输出的方差不该受该层输入个数影响, 且每层梯度的方差也不该受该层输出个数影响.

  1. 训练集-测试集数据差异的环境因素
    主要是: 协变量偏移, 标签偏移, 概念偏移
环境因素 特点 举例
协变量偏移 P(X)改变, P(y|X)不变 特征整体偏移: 例如同地不同医院的肺炎病例特征, 因为检测设备 (例如分别为核酸检测和CT影像) 不一样, 所提取特征的分布也不一样, 但是基于各自的特征预测出来的病例分布是一样的
标签偏移 P(y)改变, P(X|y)不变 出现新的标签或标签分布变化: 例如一家医院在流感高发季节和肺炎疫情时期来医院就诊的各种病患的比例是不一样的, 或者直接地, nCoV-2019出现以前和之后的疾病种类不一样 (多了一种标签), 但是每种疾病有自己特有的特征分布
概念偏移 P(y|X)变化 对某一概念的定义出现了变化: 例如美国对软饮料称呼的定义在不同地区的变化, 分别指代苏打水/可乐/汽水. 需要引入其他协变量来避免这个问题, 另一个可取之处是P(y∣x)通常只是逐渐变化.
美国软饮料名称的概念转变

4. Kaggle房价预测实战

kaggle比赛的一般流程:

  1. 获取数据集
  2. 数据预处理
  3. 模型设计
  4. 模型验证和模型调整(调参)
  5. 模型预测以及提交
  • 前两步主要使用pandas, 对数据先进行一轮描述统计, 以熟悉数据特点
  • 数据标准化可以使用sklearn.preprocessing模块, 有不同的标准化方法可供使用
  • 标准化时, 把离散特征转变为离散数值 (0/1) 作为指示特征, 即onehot
  • 比赛一般会规定评价指标, 以此作为优化目标函数 (房价预测比赛的目标函数是对数均方根误差, 如下)

一些有用的代码

  • \sqrt{\frac{1}{n}\sum_{i=1}^n\left(\log(y_i)-\log(\hat y_i)\right)^2}
def log_rmse(net, features, labels):
    with torch.no_grad():
        # 将小于1的值设成1,使得取对数时数值更稳定
        clipped_preds = torch.max(net(features), torch.tensor(1.0))
        rmse = torch.sqrt(2 * loss(clipped_preds.log(), labels.log()).mean())
    return rmse.item()
  • K折交叉验证
def get_k_fold_data(k, i, X, y):
    # 返回第i折交叉验证时所需要的训练和验证数据
    assert k > 1
    fold_size = X.shape[0] // k
    X_train, y_train = None, None
    for j in range(k):
        idx = slice(j * fold_size, (j + 1) * fold_size)
        X_part, y_part = X[idx, :], y[idx]
        if j == i:
            X_valid, y_valid = X_part, y_part
        elif X_train is None:
            X_train, y_train = X_part, y_part
        else:
            X_train = torch.cat((X_train, X_part), dim=0)
            y_train = torch.cat((y_train, y_part), dim=0)
    return X_train, y_train, X_valid, y_valid

def k_fold(k, X_train, y_train, num_epochs,
           learning_rate, weight_decay, batch_size):
    # 返回K次训练和验证的平均误差
    train_l_sum, valid_l_sum = 0, 0
    for i in range(k):
        data = get_k_fold_data(k, i, X_train, y_train)
        net = get_net(X_train.shape[1])
        train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,
                                   weight_decay, batch_size)
        train_l_sum += train_ls[-1]
        valid_l_sum += valid_ls[-1]
        if i == 0:
            d2l.semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'rmse',
                         range(1, num_epochs + 1), valid_ls,
                         ['train', 'valid'])
        print('fold %d, train rmse %f, valid rmse %f' % (i, train_ls[-1], valid_ls[-1]))
    return train_l_sum / k, valid_l_sum / k
  • 按比赛要求所需, 提交结果代码
def train_and_pred(train_features, test_features, train_labels, test_data,
                   num_epochs, lr, weight_decay, batch_size):
    net = get_net(train_features.shape[1])
    train_ls, _ = train(net, train_features, train_labels, None, None,
                        num_epochs, lr, weight_decay, batch_size)
    d2l.semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'rmse')
    print('train rmse %f' % train_ls[-1])
    preds = net(test_features).detach().numpy()
    test_data['SalePrice'] = pd.Series(preds.reshape(1, -1)[0])
    submission = pd.concat([test_data['Id'], test_data['SalePrice']], axis=1)
    submission.to_csv('./submission.csv', index=False)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容