更加优雅的因子挖掘技术之自动化特征工程

图片

一、为什么要自动化特征工程

对机器学习有一些了解的小伙伴一定听过 “Garbage in Garbage out”,也就是说模型的表现很大程度上依赖于喂给算法的数据质量。

图片

通常,我们直接将获得的原始数据喂给算法(比如,随机森林、Lasso、SVM)跑出来的效果往往是不好的,所以需要花费大量时间对原始数据进行某种数学变换、组合,然后选择有效因子、剔除无关因子,这个过程就是特征工程和特征选择。下面我们来看看国外网站做的统计,图中绿色部分就包含了特征工程的工作内容,占用了数据科学家的大部分时间,也是数据科学家最不喜欢的工作环节,但又是非常非常重要的环节

图片

图片

在机器学习算法环节,有很多可以调用的库,比如sklearn,可以只用几行代码就能让不懂算法的人轻松的建模。但是在特征工程环节(也是最重要的环节),只能手撸。对数据科学家还好,但是对小白来讲,这样的工作门槛实在太高。没有方法论不说,还会消耗大量的时间。另外,很多人会用深度学习算法,因为深度学习可以学习特征,从而实现特征选择。抛开对硬件的要求高不说,深度学习是个黑箱,解释力度很差,同时对非科班出身的小伙伴不够友好,除非对算法非常精通,否则即使学出效果好的模型,也很难坚持用该模型实盘。·本期就从自动化的角度,对特征工程和特征选择的常用技巧进行介绍,并介绍实现自动化的一套方法,本期非常一重要,且干货很多,建议反复阅读。

二、北斗七星大法——特征工程方法论

特征工程就是对原始特征进行某种转换,以更好的解释输出变量。讲人话就是:

  • 特征就是自变量x,输出变量就是因变量y,我们要求一个函数(也就是算法)。

  • 特征工程就是将x转换成1/x、x平方、log(x)等形式,看看能否得到一个更好的函数来解释y

我总结了7个特征工程的基础方法,取名为“北斗七星大法”,由简到繁的介绍常用处理方法。

1.异常值处理

推荐的方法是对数据进行可视化,画散点图肉眼观察,但是这种方法“费眼”且耗时。

也可以用统计学方法,比如剔除超过3倍标准差的数值、超过一定分位数的数值等方法,这里就不赘述了,网上一搜一大堆。

2.填补缺失值

根据缺失值的比例,采用不同的措施:

  • 缺失值比例超过95%:剔除该特征

  • 缺失值比例50%-95%,先观察缺失值和非缺失值与标签(也就是因变量有)的相关性,看看缺失值是否真的缺失,然后:

  • 数值变量:用某个特定的”异常值“填补,如0、9999;或剔除

  • 分类变量:用other的符号代表缺失值

  • 缺失值比例低于50%:

  • 数值变量:中位数填补

  • 分类变量:用other的符号代表缺失值

3.创造新特征

提高模型预测能力的重要方法是创造新的特征,如对数变换、差分、指数变换、取倒数、不同特征之间做运算等等。下面我来介绍几种常用的方法。

3.1 对数变换

最常用的方法,就是对原始数据取对数,作用是将原始数据的分布转换成近似正态分布:

  • log(x):适用于数据为正的数据。

  • log(1+x):适用于数据大于等于0的情况

  • log(x - min(x) + 1):适用大部分情况。

3.2 差分

适合处理时间序列变量,一阶差分为xn - xn-1,k阶差分为xn - xn-k。差分的目的是将非平稳序列转换成平稳序列,而平稳序列具备均值回归的特性,更容易预测。

但差分的代价是损失信息,阶数越大,损失的就越多。《Advance in Financial Machine Learning》书中给出了平衡平稳性和信息损失的方法,即分数差分,也就是说阶数可以为分数。

关于分数差分的推导过程可以读原书,我就想安静的当个调包侠,各位小伙伴可以直接用 fracdiff 生成分数差分后的特征。

3.3 其他数学变换

  • 1/x

  • ex

  • x2、x3、……、xn

  • x1 * x2

  • cos(x)、sin(x)、tan(x)、tanh(x)

  • sum(x)、mean(x)

  • ……

再多的数学变换就不一一列举了,这里是抛砖引玉,小伙伴自行头脑风暴吧。

注意:不管用那种变换,都要结合金融知识理解背后的逻辑。

4.独热编码

概念就不说的,非常常用的技术,直接上示意图更好理解。

图片

5.特征拆分

适用分类变量,对分类变量进行拆分,提取不同的信息。比如,人名变量拆分成姓和名,日期变量分别拆成年、月、日、星期几等。

或者针对特定字符串进行拆解,如将“Toy Story (1995)”拆成 "Toy Story" 和 "1995"。

6.去纲量

去纲量常用方法包括标准化、归一化,其中归一化对异常值更加敏感,归一化之前要去极值。

7.分箱

图片

分箱可以将连续变量离散化,离散变量简单化,能够有效抵抗过拟合,增加模型鲁棒性。举个例子:

当格力和美的的市盈率分别为10和1000的时候,我们知道格力相对美的被严重低估了,但是当二者市盈率分别为30和35时,区别就不大了,投资哪家公司需要通过其他因素才能判断。因此,将市盈率在30-40之间的取值分成一组,可以降低模型对市盈率因子的敏感度。

另外,需要注意的是,分的箱越多,牺牲的信息也就越多。我个人建议是先用其他办法跑一下模型,如果过拟合再用分箱。

三、挑刺我最牛——特征选择方法论

该有的特征都有了,哪些特征预测能力强,如何选择就是本节的内容了。

首先我们来明确一下,为什么要特征选择:

  • 剔除无关变量,提升模型预测能力;

  • 用更好的特征和简单的模型(如线性回归),使模型更好理解;

  • 不牺牲或小幅牺牲模型表现的前提下,降低模型训练时间。

下面介绍几种“挑刺大法”,帮助我们选择更好的特征:

1. 剔除方差小的特征

想一想,如果一列特征X的方差为0代表着什么?是不是意味着,不同样本的特征X的取值是完全相同的,那么特征X对标签是没有预测能力的。见下图,无论y如何变化,x都会不变的。

图片

因此,方差越接近0,说明特征的解释效力越低,应当剔除。

2. 两两高度相关的特征

由于指标计算、特征创造等原因, 无论原始特征还是新创造的特征之间都会存在一定的相关性、甚至高度相关,我们需要在高度相关的特征之间做选择。

先计算各特征之间的相关性,找出两两高度相关(相关性超过0.8)的特征对;再计算这两个特征与标签的相关性,保留与标签相关性高的特征。

图片

3. 聚类分析

类似于相关性分析,也可以选择聚类分析,适合特征之间存在严重多重共线性的情况。

可以用以下代码,对特征聚类:

图片

得到的结果如下图所示,将x1和x4分成一类,x2和x3为一类。

图片

4. 与标签的相关性

如果特征还是太多,那么也可以剔除与标签相关性低的特征。

另外要说明的是,相关性只能描述两个变量之间的线性关系,而互信息法则可以描述两个变量之间的线性或非线性关系,但是计算比较耗时。

5. Forward/Backward/Stepwise Selection

接下来,介绍三个系统性特征选择大法。三种方法适合码力强的小伙伴,即使码力不足,我认为其中的逻辑也是值得借鉴的。

Forward Selection:

  • 按照某种评价标准(如单因子线性回归,R2最高;或特征与标签相关性最高),选出最好的特征,加入到模型;

  • 按照相同标准,选出剩余特征中最好的特征,加入到模型;

  • 重复上面的步骤,直到模型无法提升或提升幅度很小。

Backward Elimination(与Forward Selection相反):

  • 开始将全部特征纳入到模型;

  • 剔除对标签解释最差的那个特征(如剔除x1后,模型提升最高);

  • 重复上面的步骤,直到模型无法提升或提升幅度很小。

Stepwise Selection(Forward和Backward的结合):

  • 步骤同Forward Selection;

  • 当发现特征效果不佳时,可以从模型中剔除。

6. LASSO

如果说上面的方法比较复杂,还需要自己写代码的话,接下来这个方法就友好多了。

线性回归有两个著名的正则化,即L1和L2正则化,前者的回归叫Lasso,后者叫岭回归。我们这里使用的就是Lasso,它的神奇之处就是在于“L1”正则化。

图片

正则化的目的是对模型施加惩罚,以避免过拟合。L1正则化的惩罚更重,倾向于将不重要的特征的系数压缩至0,而L2 只是将系数压缩到0附近。基于L1的这个特性,Lasso就天然就有特征选择的功能。

另外,还有好多特征选择的方法,包括PCA、树模型基础的特征选择。其PCA的可解释性较差,我很少用。

四、特征工程自动化

基础部分终于结束了,前面讲了那么多,都是在为这部分做铺垫,有了对特征工程的基础认识,能更游刃有余的做个调包侠。这里我要推荐的库为 AutoFeat,有3个主要的类:AutoFeatRegressor、AutoFeatClassifier和 FeatureSelector。

为什么选择AutoFeat

我平时挖掘因子时,我喜欢用线性回归模型,因为其逻辑简单、容易理解,这点在实盘的时候尤为重要。试想下,当策略回撤30%、50%的时候,面对一个自己无法完全理解的模型,你有多大的可能会继续执行该策略。

因此,我倾向于用非线性特征构建线性模型,手动大量生成非线性特征比较耗时,autofeat能帮我省去很多时间,让我有时间聚焦在像策略研究这种附加值更高的工作内容上。

下面我就以AutoFeatRegressor为例,介绍autofeat的用法。

# boston读取数据集
data = load_boston()
X = pd.DataFrame(data['data'], columns=data['feature_names'])
y = pd.DataFrame(data['target'])

# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=12)

# 实例化对象
afreg = AutoFeatRegressor(verbose=1, feateng_steps=2)
# 训练
X_train_tr = afreg.fit_transform(X_train, y_train)
X_test_tr = afreg.transform(X_test)
# 打印训练结果
print("autofeat new features:", len(afreg.new_feat_cols_))
print("autofeat MSE on training data:", mean_squared_error(y_train, afreg.predict(X_train_tr)))
print("autofeat MSE on test data:", mean_squared_error(y_test, afreg.predict(X_test_tr)))
print("autofeat R^2 on training data:", r2_score(y_train, afreg.predict(X_train_tr)))
print("autofeat R^2 on test data:", r2_score(y_test, afreg.predict(X_test_tr)))

输出结果:

图片

从输出结果可以大致看出AutoFeatRegressor的工作流程:

  • 首先,实施特征工程,通过2步(feateng_steps参数控制)生成新特征,并剔除相关性高的特征;

  • 然后,实施特征选择,通过相关性过滤、Lasso等方法,选出最终17个特征,其中16个为新特征;

  • 之后打印了新特征的组合以及系数。

虽然autofeat还是不够完善,但是自动化特征工程这个方向已经明确了,未来还会有越来越多的库可以实现自动化特征工程,自动化做投资决策的一天相信不远了。结合autofeat和sklearn,个人就能写出自主学习的AI机器人。

参考文献:

  • Vishal Patel | A Practical Guide to Dimensionality Reduction

  • autofeat官方文档

你可能感兴趣的:(更加优雅的因子挖掘技术之自动化特征工程)