tikboa's blog


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

天池特征工程经验分享

发表于 2020-03-27 | 分类于 Machine Learning | 阅读次数:

特征工程

目的:将数据转换为更好的表示潜在问题的特征,从而提高机器学习性能

数据理解

目的:探索数据,了解数据,主要再EDA阶段完成

  1. 定性数据:
    • 定类:按名称分类—血型,城市
    • 定序:有序分类—成绩(A B C)
  2. 定量数据:
    • 定距: 可以加减—温度,日期
    • 定比: 可以乘除—价格,重量

数据清洗

目的:提高数据质量,降低算法用错误数据建模的风险

  1. 特征变换:模型无法处理或者不适合处理
    • 定性变量编码:Label Encoder, One-hot Encoder, Distribution Encoder
    • 标准化和归一化:z分数标准化(标准正态分布),min-max归一化
  2. 缺失值处理:增加不确定性,可能会导致不可靠输出
    • 不处理: 少量缺失样本
    • 删除: 大量样本缺失
    • 补全:(同类)均值/中位数/众数补全,高维映射(One-hot),模型预测,最邻近补全,矩阵补全(R-SVD)
  3. 异常值处理:减少脏数据
    • 简单统计:如describe()的统计描述,散点图等;
    • 3sigma法则(正态分布)/箱型图删除/截断;
    • 利用模型进行离群点检测:聚类,k近邻,one class SVM, Isolation Forest
  4. 其它:删除无效列/更改dtypes/删除列中的字符串/将时间戳从字符串转为日期格式等

特征构造

目的:增强数据表达,增加先验知识

  1. 统计量特征:计数,求和,比例,标准差
  2. 时间特征:绝对时间,相对时间,节假日,双休日
  3. 地理信息:分桶
  4. 非线性变换:取log/平方/根号
  5. 数据分桶:等频/等距分桶,best-ks分桶,卡方分桶
  6. 特征组合/特征交叉

特征选择

目的:平衡预测能力和计算复杂度,降低噪声

  1. 过滤式(Filter):先利用特征选择方法对初识特征进行过滤然后再训练学习器,特征选择过程与后续学习器无关

    • Relief/方差选择/相关系数/卡方检验/互信息法

      方差越大,信息量越大,尽可能保留

  2. 包裹式(Wrapper):直接把最终要使用的学习器的性能作为衡量特征子集的评价准则,其目的在于给定学习器选择最有利于其特征的特征子集

    • Las Vegas Wrapper(LVM)
  3. 嵌入式(Embedding): 结合过滤式和包裹式方法,将特征选择与学习器训练过程融为一体,两者在同一优化过程中完成,即学习器训练过程中自动进行了特征选择

    • LR+L1或决策树

类别不平衡

  1. 扩充数据集

  2. 尝试其它评价指标:AUC等

  3. 调整theta值

    逻辑斯蒂回归,调整的是阈值,判断正负样本

  4. 重采样:过采样/欠采样

  5. 合成样本:SMOTE

  6. 选择其它模型:决策树等

  7. 加权少类别的样本错分代价

  8. 创新:

    • 将大类分解成多个小类
    • 将小类是为异常点,并用异常检测建模

代码部分

删除异常值(根据箱线图,将离群值删去)

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
35
36
37
38
39
40
41
42
43
44
45
# 这里我包装了一个异常值处理的代码,可以随便调用。
def outliers_proc(data, col_name, scale=3):
"""
用于清洗异常值,默认用 box_plot(scale=3)进行清洗
:param data: 接收 pandas 数据格式
:param col_name: pandas 列名
:param scale: 尺度
:return:
"""

def box_plot_outliers(data_ser, box_scale):
"""
利用箱线图去除异常值
:param data_ser: 接收 pandas.Series 数据格式
:param box_scale: 箱线图尺度,
:return:
"""
iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))
val_low = data_ser.quantile(0.25) - iqr
val_up = data_ser.quantile(0.75) + iqr
rule_low = (data_ser < val_low)
rule_up = (data_ser > val_up)
return (rule_low, rule_up), (val_low, val_up)

data_n = data.copy()
data_series = data_n[col_name]
rule, value = box_plot_outliers(data_series, box_scale=scale)
index = np.arange(data_series.shape[0])[rule[0] | rule[1]]
print("Delete number is: {}".format(len(index)))
data_n = data_n.drop(index)
data_n.reset_index(drop=True, inplace=True)
print("Now column number is: {}".format(data_n.shape[0]))
index_low = np.arange(data_series.shape[0])[rule[0]]
outliers = data_series.iloc[index_low]
print("Description of data less than the lower bound is:")
print(pd.Series(outliers).describe())
index_up = np.arange(data_series.shape[0])[rule[1]]
outliers = data_series.iloc[index_up]
print("Description of data larger than the upper bound is:")
print(pd.Series(outliers).describe())

fig, ax = plt.subplots(1, 2, figsize=(10, 7))
sns.boxplot(y=data[col_name], data=data, palette="Set1", ax=ax[0])
sns.boxplot(y=data_n[col_name], data=data_n, palette="Set1", ax=ax[1])
return data_n

GPSQiQ.png

GPS6L6.png

采用spearman相关系数,因为他不要求数据是正态分布

GPS7OP.png

GPp9O0.png

Q&A

GPp8te.png

GP999H.png

经验总结

特征工程是比赛中最至关重要的的一块,特别的传统的比赛,大家的模型可能都差不多,调参带来的效果增幅是非常有限的,但特征工程的好坏往往会决定了最终的排名和成绩。

特征工程的主要目的还是在于将数据转换为能更好地表示潜在问题的特征,从而提高机器学习的性能。比如,异常值处理是为了去除噪声,填补缺失值可以加入先验知识等。

特征构造也属于特征工程的一部分,其目的是为了增强数据的表达。

有些比赛的特征是匿名特征,这导致我们并不清楚特征相互直接的关联性,这时我们就只有单纯基于特征进行处理,比如装箱,groupby,agg 等这样一些操作进行一些特征统计,此外还可以对特征进行进一步的 log,exp 等变换,或者对多个特征进行四则运算(如上面我们算出的使用时长),多项式组合等然后进行筛选。由于特性的匿名性其实限制了很多对于特征的处理,当然有些时候用 NN 去提取一些特征也会达到意想不到的良好效果。

对于知道特征含义(非匿名)的特征工程,特别是在工业类型比赛中,会基于信号处理,频域提取,丰度,偏度等构建更为有实际意义的特征,这就是结合背景的特征构建,在推荐系统中也是这样的,各种类型点击率统计,各时段统计,加用户属性的统计等等,这样一种特征构建往往要深入分析背后的业务逻辑或者说物理原理,从而才能更好的找到 magic。

当然特征工程其实是和模型结合在一起的,这就是为什么要为 LR NN 做分桶和特征归一化的原因,而对于特征的处理效果和特征重要性等往往要通过模型来验证。

总的来说,特征工程是一个入门简单,但想精通非常难的一件事。

未命名

发表于 2020-03-27 | 阅读次数:

特征工程

目的:将数据转换为更好的表示潜在问题的特征,从而提高机器学习性能

数据理解

目的:探索数据,了解数据,主要再EDA阶段完成

  1. 定性数据:
    • 定类:按名称分类—血型,城市
    • 定序:有序分类—成绩(A B C)
  2. 定量数据:
    • 定距: 可以加减—温度,日期
    • 定比: 可以乘除—价格,重量

数据清洗

目的:提高数据质量,降低算法用错误数据建模的风险

  1. 特征变换:模型无法处理或者不适合处理
    • 定性变量编码:Label Encoder, One-hot Encoder, Distribution Encoder
    • 标准化和归一化:z分数标准化(标准正态分布),min-max归一化
  2. 缺失值处理:增加不确定性,可能会导致不可靠输出
    • 不处理: 少量缺失样本
    • 删除: 大量样本缺失
    • 补全:(同类)均值/中位数/众数补全,高维映射(One-hot),模型预测,最邻近补全,矩阵补全(R-SVD)
  3. 异常值处理:减少脏数据
    • 简单统计:如describe()的统计描述,散点图等;
    • 3sigma法则(正态分布)/箱型图删除/截断;
    • 利用模型进行离群点检测:聚类,k近邻,one class SVM, Isolation Forest
  4. 其它:删除无效列/更改dtypes/删除列中的字符串/将时间戳从字符串转为日期格式等

特征构造

目的:增强数据表达,增加先验知识

  1. 统计量特征:计数,求和,比例,标准差
  2. 时间特征:绝对时间,相对时间,节假日,双休日
  3. 地理信息:分桶
  4. 非线性变换:取log/平方/根号
  5. 数据分桶:等频/等距分桶,best-ks分桶,卡方分桶
  6. 特征组合/特征交叉

特征选择

目的:平衡预测能力和计算复杂度,降低噪声

  1. 过滤式(Filter):先利用特征选择方法对初识特征进行过滤然后再训练学习器,特征选择过程与后续学习器无关

    • Relief/方差选择/相关系数/卡方检验/互信息法

      方差越大,信息量越大,尽可能保留

  2. 包裹式(Wrapper):直接把最终要使用的学习器的性能作为衡量特征子集的评价准则,其目的在于给定学习器选择最有利于其特征的特征子集

    • Las Vegas Wrapper(LVM)
  3. 嵌入式(Embedding): 结合过滤式和包裹式方法,将特征选择与学习器训练过程融为一体,两者在同一优化过程中完成,即学习器训练过程中自动进行了特征选择

    • LR+L1或决策树

类别不平衡

  1. 扩充数据集

  2. 尝试其它评价指标:AUC等

  3. 调整theta值

    逻辑斯蒂回归,调整的是阈值,判断正负样本

  4. 重采样:过采样/欠采样

  5. 合成样本:SMOTE

  6. 选择其它模型:决策树等

  7. 加权少类别的样本错分代价

  8. 创新:

    • 将大类分解成多个小类
    • 将小类是为异常点,并用异常检测建模

代码部分

删除异常值(根据箱线图,将离群值删去)

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
35
36
37
38
39
40
41
42
43
44
45
# 这里我包装了一个异常值处理的代码,可以随便调用。
def outliers_proc(data, col_name, scale=3):
"""
用于清洗异常值,默认用 box_plot(scale=3)进行清洗
:param data: 接收 pandas 数据格式
:param col_name: pandas 列名
:param scale: 尺度
:return:
"""

def box_plot_outliers(data_ser, box_scale):
"""
利用箱线图去除异常值
:param data_ser: 接收 pandas.Series 数据格式
:param box_scale: 箱线图尺度,
:return:
"""
iqr = box_scale * (data_ser.quantile(0.75) - data_ser.quantile(0.25))
val_low = data_ser.quantile(0.25) - iqr
val_up = data_ser.quantile(0.75) + iqr
rule_low = (data_ser < val_low)
rule_up = (data_ser > val_up)
return (rule_low, rule_up), (val_low, val_up)

data_n = data.copy()
data_series = data_n[col_name]
rule, value = box_plot_outliers(data_series, box_scale=scale)
index = np.arange(data_series.shape[0])[rule[0] | rule[1]]
print("Delete number is: {}".format(len(index)))
data_n = data_n.drop(index)
data_n.reset_index(drop=True, inplace=True)
print("Now column number is: {}".format(data_n.shape[0]))
index_low = np.arange(data_series.shape[0])[rule[0]]
outliers = data_series.iloc[index_low]
print("Description of data less than the lower bound is:")
print(pd.Series(outliers).describe())
index_up = np.arange(data_series.shape[0])[rule[1]]
outliers = data_series.iloc[index_up]
print("Description of data larger than the upper bound is:")
print(pd.Series(outliers).describe())

fig, ax = plt.subplots(1, 2, figsize=(10, 7))
sns.boxplot(y=data[col_name], data=data, palette="Set1", ax=ax[0])
sns.boxplot(y=data_n[col_name], data=data_n, palette="Set1", ax=ax[1])
return data_n

GPSQiQ.png

GPS6L6.png

采用spearman相关系数,因为他不要求数据是正态分布

GPS7OP.png

GPp9O0.png

Q&A

GPp8te.png

GP999H.png

经验总结

特征工程是比赛中最至关重要的的一块,特别的传统的比赛,大家的模型可能都差不多,调参带来的效果增幅是非常有限的,但特征工程的好坏往往会决定了最终的排名和成绩。

特征工程的主要目的还是在于将数据转换为能更好地表示潜在问题的特征,从而提高机器学习的性能。比如,异常值处理是为了去除噪声,填补缺失值可以加入先验知识等。

特征构造也属于特征工程的一部分,其目的是为了增强数据的表达。

有些比赛的特征是匿名特征,这导致我们并不清楚特征相互直接的关联性,这时我们就只有单纯基于特征进行处理,比如装箱,groupby,agg 等这样一些操作进行一些特征统计,此外还可以对特征进行进一步的 log,exp 等变换,或者对多个特征进行四则运算(如上面我们算出的使用时长),多项式组合等然后进行筛选。由于特性的匿名性其实限制了很多对于特征的处理,当然有些时候用 NN 去提取一些特征也会达到意想不到的良好效果。

对于知道特征含义(非匿名)的特征工程,特别是在工业类型比赛中,会基于信号处理,频域提取,丰度,偏度等构建更为有实际意义的特征,这就是结合背景的特征构建,在推荐系统中也是这样的,各种类型点击率统计,各时段统计,加用户属性的统计等等,这样一种特征构建往往要深入分析背后的业务逻辑或者说物理原理,从而才能更好的找到 magic。

当然特征工程其实是和模型结合在一起的,这就是为什么要为 LR NN 做分桶和特征归一化的原因,而对于特征的处理效果和特征重要性等往往要通过模型来验证。

总的来说,特征工程是一个入门简单,但想精通非常难的一件事。

cs_224w

发表于 2020-02-18 | 阅读次数:

mmdetection 经验汇总

发表于 2020-02-18 | 分类于 Deep Learning | 阅读次数:

修改源码

方法1:

从福哥编译镜像处学到的方法是,首先将mmdet正常编译,然后将编译后的mmdet移到主要工程目录下。运行程序时,为了调用工程目录下的mmdet,sh中需要加入下述命令:

1
export PYTHONPATH=.

由于python就近调用机制,所以可以直接调用工程目录下的mmdet

方法2:

根据王老板的方法,在mmdet外部构建一个修改包,将所有注册器都加载进去,

3FtfaT.png

加载所有注册器为:

1
2
3
4
5
6
7
8
9
from mmdet.models.registry import BACKBONES,NECKS,ROI_EXTRACTORS,SHARED_HEADS,HEADS,LOSSES,DETECTORS
from mmdet.datasets.registry import DATASETS, PIPELINES

from mmdet.datasets.custom import CustomDataset
from mmdet.models.builder import build_loss
__all__ = ['BACKBONES','NECKS','ROI_EXTRACTORS',
'SHARED_HEADS','HEADS','LOSSES','DETECTORS',
'DATASETS', 'PIPELINES',
'CustomDataset', 'build_loss']

当我向对PIPELINES的loading增加函数方法时,可以:

1
2
3
4
5
6
7
8
9
10
11
12
import os.path as osp
import warnings

import mmcv
import numpy as np
import pycocotools.mask as maskUtils
from bottle_module.init_registry import PIPELINES

@PIPELINES.register_module
class LoadTmpRawImageFromFile(object):
...
...

加载修改包:

1
2
3
4
import sys
sys.path.insert(0, '../')
sys.path.insert(0, '../bottle_module')
import bottle_module

加载的都是当前工作目录下的mmdet和修改包

总体而言,感觉方法二更人性化,若要修改源码直接继承在修改包就行,不像方法一每次必须到源码处对应修改

参数

降低显存

1
2
fp16 = dict(loss_scale=512.) #混合精度训练
with_cp = True, #插入到backbone中, 速度降低

跨卡BN

1
norm_cfg = dict(type='SyncBN', requires_grad=True) #backbone+FPN+head中插入

增点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#代替smoothL1Loss
loss_bbox=dict(type='BalancedL1Loss', alpha=0.5, gamma=1.5, beta=1.0, loss_weight=1.0)

#rcnn head采用4conv+1fc
dict(
type='ConvFCBBoxHead',
num_shared_convs=4,
num_shared_fcs=1,
in_channels=256,
conv_out_channels=256,
fc_out_channels=1024,
roi_feat_size=7,
num_classes=11,
target_means=[0., 0., 0., 0.],
target_stds=[0.05, 0.05, 0.1, 0.1],
reg_class_agnostic=True,
loss_cls=dict(
type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0))

#设置正负样本比例上限,原始设置为-1,不做约束
neg_pos_ub=3/5,

Bounding Box Regression with Uncertainty for Accurate Object Detection

发表于 2019-10-06 | 分类于 Deep Learning | 阅读次数:

概要

在目标检测数据集中,ground-truth bounding box在一些情况下经常会有一些内在的歧义。这些歧义通常来源于以下几个方面:a) 不准确的标记;b) 由于物体拥挤产生歧义;c) 物体本身的边界就存在歧义。本文提出了一个新的bbox regression loss。该loss将bounding box transformation与localization variance 联合学习。传统的bbox regression没有考虑ground truth bounding boxes的歧义性。此外,当分类分支的分数较高时,bbox regression 也被默认为是准确的。

方法

网络架构

bbox 参数化

不同于R-CNN系列算法对$(x,y,w,h)$进行回归,该文提出对$(x_1,y_1,x_2,y_2)$进行回归,参数化的定义如下所示:

接下来,该文假设坐标之间相互独立,为了简化期间,使用单变量的高斯分布:

其中$\Theta$是学习的参数,$x_e$是估计的bbox坐标,标准差$\sigma$度量估计的不确定性,当$\sigma\rightarrow0$时,意味着网络对于估计的bbox坐标相当确信。
真实框的bbox也能表达成一个高斯分布,当$\sigma\rightarrow0$时,该高斯分布转化为Dirac delta函数:

其中$x_g$是真实框的bbox坐标。

KL损失的bbox回归

从上述的描述可以得知,最终的目标是最小化$P_\Theta(x)$和$P_D(x)$的KL散度:

因此当使用KL散度作为bbox regresssion时表示$L_{reg}$为:

由于$\frac{\log{2\pi}}{2}$和$H(P_D(x))$和估计的参数$\Theta$无关,故:

当$L_{reg}$对$\sigma$求导时,$\sigma$在分母位置,训练初期易出现梯度爆炸,所以为了解决这一问题,使用$a=\log{\sigma^2}$来代替$\sigma$的预测:

类似于smooth L1 loss中对$|x_g-x_e|>1$的处理,KL loss采用同样的处理方式:

方差投票

最终的检测结果是一系列包含方差的bbox,为了获得更好的结果可以利用这些方差对近邻的bbox加权式的投票:

对接近最大分数bbox和最小方差的bbox赋予高权重,新的坐标计算如下所示:

实验

消融实验

图的基础知识

发表于 2019-09-15 | 分类于 Deep Learning | 阅读次数:

图的基本定义

设$G=(V,E)$是一个无向图,其中顶点集$V={v_1,…,v_n}$,对于一个无向图而言,$w_{ij}=w_{ji}$。一个顶点的$v_i\in{V}$的按照如下定义:

定义一个指示向量,$\mathbb{1}_A={f_1,…,f_n}’$,当向量$v_i\in A$时,$f_i=1$,否则$f_i=0$,对于两个不相交的集合,定义:

对于一个顶点集合$A\subset V$的大小有如下两种定义:
$A$中所包含顶点的数量

图的拉普拉斯矩阵以及它的的特性

未归一化的图拉普拉斯矩阵

未归一化的拉普拉斯矩阵定义如下:

特性1. 对于每个向量$f\in R_n$,可以得到:

证明:通过$d_i$的定义,可以得到:

特性2. $L$是对称,半正定矩阵:
$L$的对称性来源于$W,D$,半正定矩阵来自于特征1,对于任何向量都满足$f’Lf\ge 0$.

特性3. L最小的特征值是0,对应的特征向量是$\mathbb{1}$
由$f’Lf=f’\lambda f\ge 0$,且$f’f\ge 0$,可得$\lambda\ge 0$

特性4. L有n个非负实特征值,$\lambda_n\ge…\lambda_2\ge\lambda_1\ge 0$
很明显

特征5. 假设G是一个非负权重无向图,那么$L$特征值0的多重性$k$等同于在该图中所包含的连通图的个数,对应的0特征值的特征向量等于这些连通图的指示向量
证明: 首先假设$k=1$,$f$是该特征值的特征向量,那么可以得知,由于$w_{ij}$都是非负值,所以当两个顶点相连时,则${(f_i-f_j)}^2$必须为0,即$f_i = f_j$。因此,在图中所有顶点只要互相连接,那么$f$对于这些顶点而言,就必须是常量。因此若一个无向图中存在一个连通图,那么$f$在该连通图上为常量,最终可以得到一个常数向量$\mathbb{1}$作为特征值0的特征向量,它同时也是该联通图的指示向量。

假如顶点按照他们所属的联通图排列,不难想象他们的邻接矩阵$W$是一个块对角的形式,同样的$L$矩阵也是。

其中的每个块$L_i$都是一个拉普拉斯矩阵,对应的是第$i$个连通图。由于它是块对角矩阵,所以$L$的频谱是$L_i$谱的并集,$L$的特征向量就是$L_i$的特征向量,其它块的位置对应为$0$。因此,$L$有许多特征为0的特征值,并且0特征值对应的特征向量为相应的连通图的指示向量。

归一化的图拉普拉斯矩阵

通常文献中有两种形式的图归一化矩阵,两种矩阵互相关联,定义如下所示:

其中第一个$L_{sym}$是对称矩阵,而第二个$L_{rw}$是随机游走矩阵,相对于未归一化的拉普拉斯矩阵而言,归一化的拉普拉斯矩阵具有如下类似的性质。
特性1. 对于每个向量$f\in R_n$,可以得到:

证明类似于未归一化的拉普拉斯矩阵,此处不再赘述。

谱聚类算法

unnormalized spectral clustering

normalized spectral clustering

实验

unnorm knn graph

unnorm knn graph

程序

# -*- coding: utf-8 -*-
# @Time    : 2019/10/2 19:38
# @Author  : zhao pengfei
# @Email   : zsonghuan@gmail.com
# @File    : spectral_clustering.py

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib
matplotlib.use("TkAgg")

def plot_value_vector(value, vector):
    plt.figure(figsize=(24, 4))
    plt.subplot(1, 6, 1)
    plt.scatter(range(1, 11), value[:10])
    plt.subplot(1, 6, 2)
    plt.plot(vector[:, 0])
    plt.subplot(1, 6, 3)
    plt.plot(vector[:, 1])
    plt.subplot(1, 6, 4)
    plt.plot(vector[:, 2])
    plt.subplot(1, 6, 5)
    plt.plot(vector[:, 3])
    plt.subplot(1, 6, 6)
    plt.plot(vector[:, 4])
    plt.show()


#generate gaussian dataset
y1 = np.random.normal(2, 0.2, 50)
y2 = np.random.normal(4, 0.2, 50)
y3 = np.random.normal(6, 0.2, 50)
y4 = np.random.normal(8, 0.2, 50)
y = np.hstack((y1, y2, y3, y4))[:,None]
# plt.hist(y, bins=300)
# plt.title("Histogram of the sample")
# plt.show()


data = np.repeat(y, 200, axis=1)
data_t = data.T


#full graph unnorm
W = np.exp(-1 * (np.abs(data - data_t) ** 2) / 2)
#self circle removed
W = W - np.eye(W.shape[0])
D = np.zeros_like(W)
for i in range(W.shape[0]):
    D[i, i] = np.sum(W[i, :])
L = D - W

eigenvalue,featurevector=np.linalg.eig(L)
sort_eigenvalue_index = np.argsort(eigenvalue)

sorted_value = eigenvalue[sort_eigenvalue_index]
sorted_vector = featurevector[:, sort_eigenvalue_index]

plot_value_vector(sorted_value, sorted_vector)

#knn graph unnorm
W = np.exp(-1 * (np.abs(data - data_t) ** 2) / 2)
#self circle removed
W = W - np.eye(W.shape[0])

for i in range(W.shape[0]):
    row = W[i, :]
    sort_index = np.argsort(row)
    knn_value = W[i, sort_index[-10:]]
    knn_index = sort_index[-10:]

    new_value = np.zeros_like(row)
    new_value[knn_index] = knn_value

    W[i, :] = new_value

D = np.zeros_like(W)
for i in range(W.shape[0]):
    D[i, i] = np.sum(W[i, :])
L = D - W

eigenvalue,featurevector=np.linalg.eig(L)
sort_eigenvalue_index = np.argsort(eigenvalue)

sorted_value = eigenvalue[sort_eigenvalue_index]
sorted_vector = featurevector[:, sort_eigenvalue_index]

plot_value_vector(sorted_value, sorted_vector)

GA-RPN论文阅读

发表于 2019-09-03 | 分类于 Deep Learning | 阅读次数:

概要

Anchor的设计是现今大多数目标检测框架的基础,高性能的目标检测框架通常依赖于密集的Anchors的设计,这些Anchors基于预定义的尺度与长宽比。 本文提出了GA-RPN利用图像的语义信息指导Anchor的生成,联合两条支路,一路预测物体的中心点位置,另外一路预测对应位置的尺度和长宽比。此外为了保持特征的一致性,采用了一个Feature adaption module。

方法

Anchor的设计遵循着两个原则:

  • alignment

    to use convolutional features as anchor representations, anchor centers need to be well aligned with feature map pixels.

  • consistency

    the receptive field and semantic scope are consistent in different regions of a feature map, so the scale and shape of anchors across different locations should be consistent.

论文主要围绕着这个公式展开:

该公式主要抓住了两个重要的直觉,(1) 物体可能只存在一张图像的某些区域;(2) 物体的形状,尺度,比例和它的位置有关。

该网络主要分为三个部分,Anchor Location Prediction, Anchor Shape Prediction, Anchor-Guided Feature Adaption, 以下将对这三个部分分别介绍。

Anchor Location Prediction

对于特征图$F_I$而言,该分支主要预测对应的位置上物体存在的概率$p(i,j|F_I)$其中$i,j$表示在特征图上的位置,对应的在原始图片的位置为为$((i+\frac{1}{2})s,(j+\frac{1}{2})s)$,其中s是特征图上的步进长度。该分支$N_L$使用一个$1\times1$的卷积层,然后通过sigmoid函数将卷积后的结果转为概率。基于上述产生的概率图,然后设定一个阈值$\epsilon_L$滤除大约$90%$的regions。由于大部分区域并不包含物体,因此使用masked convolution替代后续的卷积层。

Anchor Shape Prediction

确定物体的可能位置后,下一步就是预测物体的形状。基于特征图$F_I$该分支预测对应位置上$(w,h)$,然而直接预测这两个值,难度较大,因此通过预测$dw$和$dh$,然后通过如下公式映射到对应的$w$和$h$:

其中$s$是特征图上的步进长度,$\sigma$是缩放因子(该超参数设置为8),该分支$N_S$同样由一个$1\times1$的卷积层组成,然后产生一个两通道的图,包含$dw$和$dh$。
此外改论文中指出通过这样的设计,它可以更好的捕捉更高或更宽的物体。

Anchor-Guided Feature Adaptation

传统的RPN网络中,由于每个位置的Anchor有相同的尺度和长宽比,因此特征图可以学习到一致性的表达,然而在GA-RPN中,Anchor的形状因位置而异。若是依然根据之前的方法,则违背了一致性原则。为此,引出了anchor-guided feature adaptation模块,该模块的公式化表达如下所示:

其中$f_i$是在$i$-th位置的特征,$(w_i,h_i)$是对应的anchor的形状。该分支首先通过一个$1\times1$的卷积从anchor shape预测分支输出一个offset field,接着运用可变卷积联合原始的特征图和offset field获得$f’_I$。后续的基于该adapted features进行分类与回归。

原始的可变卷积中,offset field是通过feature map来预测的,而该分支中的offset field是通过anchor shape来预测的,这也是为何称之为anchor-guided feature adaptation模块。

training

joint objective

anchor location targets
定义三个anchor location区域,CR(center region),IR(ignore region),OR(outside region)

CR是中心区域的周围区域,IR是中心区域外围的一部分区域,OR是除了CR和IR外面的所有区域。其中存在两个超参数,一个是CR的范围$\sigma_1$一个是IR的范围$\sigma_2$

由于CR占比较小,所以训练loss采用Focal loss.

anchor shape targets
anchor形状的优化一般分为两步,首先将Anchor与对应的ground-truth bbox进行匹配,然后迭代的计算最优的$\hat{w}$和$\hat{h}$使其IoU最大化。之前的RPN网络分配一个候选的anchor给ground-truth bbox。但是对于GA-RPN则不适用,因为$w$和$h$并没有预定义。然后提出的解决措施是,基于$(x,y)$位置,采样9对不同尺度和长宽比的anchor。对于loss函数的优化采用的是bounded iou loss。

实验

超参数设置:$\sigma_1=0.2$,$\sigma_2=0.5$,$\lambda_1=1$,$\lambda_2=0.1$
与Fast_RCNN, Faster_RCNN, RetinaNet对比实验

消融实验

决策树

发表于 2019-08-24 | 分类于 Machine Learning | 阅读次数:

CART(Classification and Regression Tree)

CART的本质是对特征空间进行二元划分(即CART生成的决策树是一棵二叉树),它能够对类别变量和连续变量进行分裂,分割思路是先对某一维数据进行排序,然后对已经排好的特征进行切分,然后计算衡量指标(分类树用Gini指数,回归树用最小平方值),最后通过指标计算确定最后的划分点。

Gini指数

  • 对于给定样本集D的Gini指数:分类问题中,假设有K个类,样本点属于第K类的概率为$p_k$,则概率分布的基尼指数为:$Gini(D)=\sum_{k=1}^K{p_k}{(1-p_k)}$

    1.从Gini指数的数学形式中,可以得知,当$p_1=p_2=…=p_K$的时候Gini指数最大。
    2.当某些$p_i$较大,即第$i$类的概率较大,样本类别不平衡,判别性较高。

  • 在给定特征A的条件下,样本集合D的基尼指数为:$Gini(D,A)=p_1Gini(D_1)+p_2Gini(D_2)$,其中$p_i=\frac{D_i}{D_1+D_2}$,$i\in 1,2$
  • 与信息熵的关系,信息熵定义为$Ent(D)=-\sum_{k=1}^K{p_k}{\log p_k}$,令$f(p_k)=-\log p_k \approx -\ln p_k$,对该式在$p=1$处做一阶泰勒展开,得到:带入信息熵的公式,可以得到和基尼系数一致的公式,也即是说基尼指数是信息熵中,$-\log p$在$p=1$处一阶泰勒展开后的结果!所以两者都可以用来度量数据集的纯度

Gini指数例子


对于离散变量
数据集关于第一个特征维度的Gini指数的计算就是:

对于连续变量
因为连续变量的部分已经通过某一个值进行了划分,所以计算的时候和离散变量的计算类似

tik boa

tik boa

Keep Going

8 日志
2 分类
7 标签
© 2020 tik boa
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4