qrfaction的博客


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

有趣但鸡肋的e2e对抗样本正则项

发表于 2019-05-06 | 分类于 ML&DL

最近频频在论文中看到计算当前样本的对抗样本作为正则项去训练模型
抱着好奇心这个东西究竟有多少收益,在audio tagging的比赛里尝试了一下
结论是成本太高,收益较小,很鸡肋
成本在于一个batch里每个样本都要计算对抗样本 <=> 调试时间和需求显存加倍 。。。
就是bs加了个倍,反正在audio tagging里太浪费了,这么多显存干啥不好。。

对抗样本的介绍下面一张图带过了,入门可参考https://zhuanlan.zhihu.com/p/33316527
这里写图片描述

吐槽归吐槽,下面放出实现方案,以及调试过程中各种形式的收益比较
以下结论来自https://www.kaggle.com/c/freesound-audio-tagging-2019

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
### x_mel_shape  ( time_steps, frequency, channels)

## 特征抽取
output = backbone(x_mel)
output = fc_layer(output)

## 计算loss
logloss = Lambda(lambda x: K.mean(K.binary_crossentropy(x[0], x[1]),axis=-1))([y_in, output])

## 计算梯度
g = Lambda(lambda x: tf.stop_gradient(K.gradients(x[0], x[1])[0]),output_shape=x_mel_shape)([logloss, x_mel])
g1 = Lambda(lambda x: cfg.adv_eps * K.sign(x))(g)
g2 = Lambda(lambda x: cfg.adv_eps * x )(g)
因为g2效果好,所以
g = g2

## 生成对抗样本并获得结果
x_adv = Lambda(lambda x:x[0] + x[1])([x_mel,g])
x_adv_fp = backbone(x_adv) # 主干网络
adv_output = fc_layer(x_adv)

## 计算对抗样本的loss
adv_loss1 = Lambda(lambda x: K.mean(K.binary_crossentropy(x[0], x[1]), axis=-1))([y_in, adv_output])
adv_loss2 = Lambda(lambda x: K.mean(K.binary_crossentropy(x[0], x[1]), axis=-1))([output, adv_output])
因为adv_loss2效果好,所以
adv_loss = adv_loss2

## 和正常样本加权平均
loss = Lambda(lambda x:K.mean(cfg.adv_alpha * x[0] + (1-cfg.adv_alpha) * x[1]))([adv_loss,logloss])

model.add_loss(loss)
model.compile(
optimizer=Nadam(lr=cfg.lr),
)

语音信号处理基础学习和源码理解Melspectrogram

发表于 2019-04-20 | 分类于 音频信号处理

最近为了在实习前集满GM的5金去参加了kaggle的语音比赛
参加语音比赛除了为了集金更是为了补足对语音方向基础的了解
以下源码部分来自kapre

音频数据长啥样?

这里写图片描述
如图所示
这是一个单声道的语音数据
输入维度 (time_steps, channels)
channels表示声道个数

以下讨论都以单声道进行讨论,多声道的话同样的处理方式最后在通道轴拼接即可

什么是频谱图?

频谱图是音频信号的一种传统特征,效果不错
先上关键源码,再进行分析

1
2
3
4
5
6
7
8
9
10
11
x = input   ##  x -> (batch_size,time_steps,1,1)
subsample = (self.n_hop, 1)
output_real = K.conv2d(x, self.dft_real_kernels,
strides=subsample,
padding=self.padding,
data_format='channels_last')
output_imag = K.conv2d(x, self.dft_imag_kernels,
strides=subsample,
padding=self.padding,
data_format='channels_last')
output = output_real ** 2 + output_imag ** 2 ## output -> (batch_size,time_steps,1,freq)

总得来说,他是以卷积的方式扩展出了频率轴
会有人问:为什么是频率轴不是通道轴
因为这里的卷积是傅里叶变换的替代实现,这个轴的物理意义即频率。

操作如下:

  1. 音频数据分帧定帧长(即卷积的窗口大小)
  2. 各帧进行FFT后计算频域复数的模长(即能量)
  3. 然后通过帧移对各帧(卷积步长)对各帧进行FFT
  4. 以上从而将(time_steps,1)->(time_steps,freq)
    由于FFT的频率是按序计算,所以音频数据在频率轴仍然有局部依赖
    即可使用CNN或ConvLSTM1D之类的结构进行建模

上一张图吧

这里写图片描述

Melspectrogram

这个Mel频谱其实我也不太理解物理意义
但看源码十分简单,就是用一个矩阵对频谱图做线性变换
翻阅一些其他人的说法主要是考虑了人耳的声学结构
然后在尺度上做一些变换

1
output = K.dot(power_spectrogram, self.freq2mel)

了解到这儿应该够我做这个任务了。。
毕竟就算理解了Mel频谱的滤波器设计方式我也大概率优化不好

最后

MFCC也不详述了,因为MFCC根据往年比赛方案以及相关总结都是说不适合nn
上面讲的特征都是可以e2e实现的,但是一旦设置成可训练效果极差。。。真是NB的手工特征

一篇实体识别和关系抽取的联合训练文章简读

发表于 2019-03-26 | 分类于 NLP

先附上原文链接,一篇18年4月份的文章,仍然是标准的bilstm+crf
Joint entity recognition and relation extraction as a multi-head selection problem

然后大图镇场
这里写图片描述

Joint model

底下三层序列标注的标准方式自然没啥好说的
emmm还是要说一下的
这里写图片描述
底部embedding layer
word level语义与bilstm 获得的char level语义拼接
不过也算常规操作

然后CRF获得序列得分进行优化

不过一个小细节说明一下,在第三层第四层的衔接处
CRF后面是不能接layer的,他后续使用维比特算法解码的序列标签也不能求梯度,如何实现呢?

  1. 框架中设置这里的不求梯度就好了
  2. 不过文章里貌似是训练时把正确label传进去,测试时用crf获得的结果去推断

Relation extraction as multi-head selection

接着是关系抽取部分
直接上公式
这里写图片描述
这里写图片描述
r是relation,z是word/char在lstm encoding后的向量
w是word/char
其实很简单,实体标签embedding信息和词经过lstm后的encoding信息
句子里的字两两计算关系类别得到一个N*N的矩阵,矩阵的每个元素都是某对字/词的关系分类结果
此处使用sigmoid激活,因为可能存在多种关系
这里写图片描述

最后

感觉最后的关系分类还是可以试试别的而非sigmoid
得分矩阵的每一行都是有序列关系在里面的
例如第一行是第一个字和每个词是的关系得分
或许可以像序列标注一样套个概率图模型加强约束?

得分矩阵非每一个都是有效的
有些地方是否需要加个mask让他不要产生梯度影响训练?

瑞金知识图谱比赛总结

发表于 2019-02-28 | 分类于 NLP

这个小破赛到昨天才答辩,吐槽一波(恩,好像没隔壁oppo惨,hh)

前言

涨分的应该都说了,但有些具体涨多少实在忘掉了
答辩队友没准备充分,部分答错加答漏,导致被翻盘少了两万,此处拉出来鞭尸
复赛2nd,答辩3rd

初赛

命名体识别问题,采用序列标注方式
数据特点:数据集脏,句子不易切分,句子长度方差较大,长句严重影响训练调试速度

我们初期着重点一直在如何加速调试
我们初期直接采用了sota:LSTM+CRF(不考虑外部工具及模型)
然而这个模型实在训练太慢了
0) 预处理一种是按规则切分和按行切分,按行略差3个千
1) 改模型LSTM为CuDNNGRU/CuDNNLSTM
  速度*5~10具体多少忘了,分数下降10个点(CuDNNGRU/CuDNNLSTM不支持mask zero)
2) 由于CuDNNGRU/CuDNNLSTM不支持mask zero
  实现伪mask zero(解决循环单元前传,反传无法解决),上涨8个点
3) 解决句子边缘识别太差
  sample = [sentence1,sentence2,sentence3]
  y = [y1,y2,y3]
  输入输出改成窗口为三同时输入三句话的方式,最后结果只取y2
  因为中间句sentence2没有边缘信息不足问题
  这个方式训练速度下降三倍,不用CuDNNGRU一般是跑不动的。。。
  分数上涨2-4个点
4) 添加词性词边界特征将其embedding后与字向量拼接
  上涨1-2个点
5) 将GRU容量压到最小后开始逐层调Spatial Dropout
6) 差分学习率,embedding层学习率小十倍,上涨1个点左右
7) 按行切分和按规则切分集成分数上涨0.2~0.3个点


以上是初赛的解决方案
其实线下再加一层CuDNNGRU还可以涨3-4个百分点
由于之前实验未控制好变量,得到错误结论故一直没采用
CuDNNGRU两层后速度彻底和两层GRU的速度拉开来了超多倍

初赛主要赢在让模型训练速度大幅度加倍的同时只是略降分数
使得我们可以采用很暴力的上分方式

复赛

实体对关系分类问题
数据特点:
1) 已知实体对可能关系类别,但未知是否成立
2) 数据集标签存在一定噪声(存在关系的实体对相隔太远)

核心思路
0) 实体对两两组合,并将覆盖他们的句子切出进行分类,其中过滤长度大于200的句子
1) 覆盖实体对的句子在两端各取一定长度的短句丰富上下文信息

if end - begin <= 100:
padding = 50 # window是在两边补多少词
elif end - begin <= 140:
padding = 30
else:
padding = 0

2) 特征工程
  1.实体对距离特征:这个特征原本没有用,因为句子的补0数量可以让模型捕捉到长度信息
  但是1)中的方法使得这个信息丢失,让模型不易捕捉
  2.词性特征+position embedding(每个字到实体1,2的距离),与字向量拼接
  3.实体segment特征,实体1标0.1,实体2为-0.1,其他为0,与字向量相加
    选0.1主要考虑到默认初始化的方差大小,故选择一个较小的值
    这个特征一方面是标示出实体对 yu的差异与其他字的差异
    另一方面是为了后面利用他获得实体1,2的特征向量
  4.邻近实体对存在关系的概率特征(这个好像没什么人发现)
    example:
      中国2型糖尿病防治指南(2010)在LSM和二甲双胍基础上HBA1C,≥7.O%:
      新诊断有明显体重减轻或其他严重高血糖状的患者
    我们观察到 (2型糖尿病,LSM) 是否存在关系,还与 (2型糖尿病,二甲双胍) ,(2型糖尿病,HBA1C)有关

    其实这个特征真不是看数据得到的。。
    主要是开始分fold发现不按文档分而按句子分会严重leak验证集,线上线下对不上
    既然leak了验证集,如果能利用好还是能劣势转优势的
    查找leak的原因后,观察发现文章中某些实体对强相关。
    然后用初版模型对实体对打分,将邻近实体对的分数作为特征上了不到一个百
    (前面特征用太多了,快上限了)
3) 模型
  两层GRU + SpatialDropout + attention pooling + dropout + fc + 差分学习率
4) attention (1~2个点)
  使用之前的segment标示出的实体位置,在输入的text中取出对应字向量
  并将其平均处理,再通过权重共享的全连接层将文本和字映射到同一个空间
  使用e2-(e1+text)作为相似度计算的方式(参考知识图谱的embedding算法)
  e2-(e1+text)越小权重越高
  然后用获得的attention pooling进行加权平均
5) prior mask实现独立分类器
  我们的输出非11个单元,也非1个单元的二分类
  而是输出了10个单元的二分类(即sigmoid激活,不是softmax)
  由于我们之前知道了实体对可能的类别
  故可以生成类似如下的向量
  prior mask = [0,0,0,0,0,1,0,0,0,0]
  而模型输出output = [0.1,0.9,0.5,0.4,0.3,0.2,0.1,0.5,0.6,0.7]
  output = output * prior mask = [0,0,0,0,0,0.2,0,0,0,0]
  然后用bce计算loss回传梯度
  这个方式结合了11分类与2分类的好处
  11分类会有类间干扰,2分类会导致所有类别用同一个分类器权重
6) 知识蒸馏二次训练3个千
7) 替换GRU为LSTM训练集成,3个千

最后
比赛比较懒,数据清洗方面一直懒得下功夫
模型也都是用之前的经验,懒得调试
loss也懒得动
其他队正好和我们队互补,可以参考一下他们的

Alibaba Cloud German AI Challenge 比赛总结

发表于 2019-02-14 | 分类于 CV

赛季1:主要是hadxu和haowei在干活儿
赛季2:主要是我和haowei在干活儿

源码链接:https://github.com/lhwcv/cloud_german_rank10

赛题分析

题目数据来自卫星数据有18通道
各通道数据区间相差较大
比较麻烦的是验证集与测试集同分布,而训练集非同分布
而且训练集,验证集和测试集疑似存在很多伪重图片,造成线下cv和线上难以对上

个人一直很烦这种问题,大部分找不到很好的解决方案,只能采取一些维稳策略
毕竟只有良好的验证集才能帮助正确评估模型快速迭代优化方案
各位看客有比较好的解决方案望告知

解决方案

讲的很细,因为没啥东西,算是个抛砖引玉
个人感觉基础分类任务创新也是蛮难得,基本上看到都是loss啥变变

  1. 可见光通道所在的卫星数据进行亮度对比度数据增广
  2. 所有数据进行flip+rotate
  3. 数据z-score规范化使各通道范数相近(据队友实验数据好像归一化会严重掉分,不过我没这习惯hh)
  4. 卫星数据reflect放大,一直测试到160*160,因为春节大家都比较懒只测到这么大了,一直有涨
  5. 学习率三次衰减,再衰减线下虽还未过拟合,线上分数已经开始掉了
  6. label smooth -> label = (1-alpha)label+alpha(1-label)/16
  7. batch level ohem
  8. Nadam+pytorch
  9. deep backbone + light head
  10. 使用初版模型获得训练数据的fc特征,再聚类聚5类分fold(约几个千)
  11. 半监督伪标签,四份测试集取较高分数段滤掉部分低质量样本加入训练集训练
  12. TTA × 8
  13. 112,128,144,160大小图像差异集成,xcep + IncepResnetv2 + seresnext50 + resnet50集成

最后

恩,方案简简单单普普通通
模型也还行,春节期间比较忙,最后临时抱佛脚性质跑了四个模型
等着前排答辩完开个方案

Gradient Harmonizing Mechanism简读

发表于 2019-01-31 | 分类于 ML&DL

文章链接 https://arxiv.org/pdf/1811.05181.pdf

核心思想

通过数据集的梯度分布去调节训练时权重
旨在降低label噪声影响和对hard example更好的学习

这里写图片描述
这里写图片描述

Gradient Density

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
意思就是密度越大的样本权重越低
密度大且loss大的样本认为是outlier

Unit Region Approximation

将梯度分区间段统计计算梯度密度
很简单的一个近似估计来降低算法时间复杂度

Exponential Moving Average

梯度密度是根据一个mini-batch的样本统计所得
通常情况下batch不能很好反应整个数据集的分布情况
梯度密度变化十分不稳定
通过滑动平均让这个变化变得更加smooth

graph conv

发表于 2019-01-13 | 分类于 GNN

主要是将知乎上这个回答按自己的逻辑整理了一下
https://www.zhihu.com/question/54504471/answer/332657604

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

kaggle Human Protein Atlas 比赛总结

发表于 2019-01-12 | 分类于 CV

前言

这个是要被队友借去改改发知乎上的
给别人写的不能像自己的凑合,所以这次写的总结会比以往的都正式很多。。
此次比赛和队友一起拿下了金牌,最终名次11/2172
原本是想着积分榜第一的巨佬bestfitting公开方案后写个方案汇总的
但怕是等不到了。。。
这个比赛是对于believe your cv的死教条的一个很好的反面示例
那些不会依据客观事实变通只知道守着死教条的人都死得很惨!!!

比赛介绍

任务介绍

本次比赛的问题是场景识别
定位的是蛋白质所处位置的识别,例如在细胞液,细胞核里之类的
依输出分所属多标签分类

难点及数据介绍

首先一张示例图如下
这里写图片描述

1) 一个样本由四个”通道图”组成(分成四张存储,每个”通道图”单通道),2048*2048大小,官方提供了插值缩小为512大小的数据
2) 外部数据70k(每个”通道图”都是rgb格式)
3) 图片伪重多,然后四个”通道图”,id相同但实例不同的情况也很多,如下
这里写图片描述

1),2)对比我们发现了外部数据总共有4 3个通道,而官方数据只有4 1个
这便带来了第一个难点,如何处理外部数据
2),3)最麻烦的是伪重问题,伪重造成验证集leak,不能制作一个好的验证集

外部数据处理后加入训练集,要制作一个好的验证集就得跨过两道坎

  1. 外部数据无论咋处理总是和测试集分布有些不一样的
  2. 训练集里伪重过多,如何保证验证集不leak

这个问题貌似只有bestfitting解决了,但是他还没公开方案。。。
1)2)3)共同造成的线下val的不可靠,这时候线上比线下可靠,但仍需注意不要过拟合线上

our solution

model config1

  1. 数据增广(亮度对比度调整,crop_resize,flip,other)
    我们总共用了12倍的TTA
    亮度对比度主要用于让模型对外部数据和官方数据差异的鲁棒性更好
    crop_resize对于显微镜下实例大小方差巨大的情况,带来了较好的线下收益
    受限于调试成本,为了不避免数据增广带来的分布偏移问题,于是只选择性的尝试了上述几种,不过也一蒙及中。
  2. Models
    res18 (batchsize=64)
    res34 (batchsize=32)
    bninception (batchsize=32)
    inceptionv3 (batchsize=32)
    xception (batchsize=24, P40-24G)
    se-resnext50(batchsize=24, P40-24G)
    其中模型对batchsize大小十份敏感,正确来说是模型对参与batchnorm计算的样本数十分敏感,需用sync-bn或者P40(24G)显存实现
  3. lr schedule
    Nadam优化器
    阶段性学习率衰减
    差分学习率(其中初层用于转换通道的卷积和最后的model head同学习率,中间的backbone学习率小一倍)

model config2

这个方案来自后来加入的队友shisu
只简述一下差异的部分

  1. lr schedule
    SGD 优化器
    cosine lr
  2. model
    res18/34 (96batchsize + softf1_loss + float16 + 过采样)
    巨型图片1024*1024上训练出来的(我们只有他成功下载了这部分数据,帮不了他了)

postprocess

基本是利用了伪重的性质
将测试集中的相似图片的预测进行共享,其中预测选择图片质量较高的那张,约0.002的收益

ensemble

外部数据灰度化和外部数据取高范数的通道两种方案得到了两份数据
两份数据上训练出来的模型进行差异化集成
model config1 和 config2进行集成

写到最后

附上其他高质量的分享,个人感觉都不是很新颖
8th place solution
7th place solution
4th place solution
3th place solution
12th place solution
看完这些,会看到有部分LSEP loss,GapNet,autoAugment等花哨的东西
但私以为仍不是重点
其中各种大小的图进行ensemble才是重点,特别是1024*1024 。。。
正确的数据增强和不要太低的线上

其中一个比较具有通用性的trick,可供大家参考
https://www.kaggle.com/c/human-protein-atlas-image-classification/discussion/76665
图片分成多个patch,将baseline模型对这些块输出分数
拿那些响应最高的patch重新训练一次模型
相当于一个hard attention

18总结与未来展望

发表于 2019-01-01 | 分类于 生活

2018整体感觉自己进步还是蛮大的
但是细究起来自己有一堆计划没有完成
下半年的时间利用率很低,2019需要加以调整

2018年

达成成就

  1. 攒下四五个拿得出手的比赛成绩了
  2. gpu编程了解并完成node2vec加速,虽然感觉现在看起来很烂
  3. github差不多满绿
  4. nlp/cv纵向横向知识面拓宽,RL完成一本书的基础阅读量
  5. 抽象思考tabular data切入点并实践
  6. 博客50+
  7. 多次参与国内赛,基本认识了一下圈内人,拓展了一下交际圈
  8. 学生时代达成财富自由

遗憾

kaggle大部分都只搞了一周两周,半步金牌,浪费了时间
下半年太过松懈,时间利用率远没上半年高
没能早点意识去收集比赛称号

对2019年的期望

  1. 达成grandmaster和天池数据科学家称号(如果能有数据大师超级棒啊)
  2. 一线互联网公司实习
  3. 高性能计算方向能深入下去(冒博啥时候写完书诶)
  4. 博客量100+
  5. github继续差不多满绿

pointer,copy,coverage机制简述

发表于 2018-12-28 | 分类于 NLP

Pointer Networks

https://arxiv.org/pdf/1506.03134.pdf

这里写图片描述
这里写图片描述
如上,其实就是直接把注意力权重的结果输出为最后结果了
即在原序列中抽样
旨在解决凸包和旅行商等类似问题

Copying Mechanism

https://arxiv.org/pdf/1603.06393.pdf

理解这个我们首先看个使用场景即如下

这里写图片描述

本文旨在解决oov和低频词版本
让模型学会适当从历史信息中copy文本

这里写图片描述
模型即上图
首先看模型的输入输出
这里写图片描述
这里写图片描述
这里写图片描述
其中ct是当前状态对输入序列的注意力加权后的输出向量
M是输入序列的隐藏态h1 to ht
其中st = f(yt-1,st-1,c)是decoder的隐藏态
这里多加了一个输入,即从M中获得
如下
这里写图片描述
将yt-1在输入中多次出现的词考虑进来

整体来讲模型给那些 不曾在字典中出现过但又在输入中出现过的词 一个输出口
让模型在没能很好学习rare word和oov的语义的情况下能具备一些复制能力

Coverage Mechanism

Get To The Point: Summarization with Pointer-Generator Networks
https://arxiv.org/pdf/1704.04368.pdf
总得来讲
首先维护了在历史状态下decoder时输出的attention权重
这里写图片描述
将其作为特征输入,用于计算当前attention
这里写图片描述
然后对于那些重复出现过高权重的词,给予适当惩罚
这里写图片描述
目的应该是希望模型不要老出现重复词

12…6

qrfaction

59 日志
8 分类
28 标签
RSS
© 2019 qrfaction
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
访问人数 人