最近面试有被问到自己项目中关于周期性特征的编码问题。网上搜索了一下,中文的资料居然没什么。。。用英文搜好多(果然中文内容还是不够多),搬运一下kaggle的编码教程,并记录一下周期性编码的方式
机器学习中特征的重要性不言而喻,如何将现实世界中描述数据的特征用准确的方式编码并传达给机器进行运算至关重要
对于周期性的变量,如日期,月,日,时,分,单纯用数值表示或者简单按数值可取数量编码是欠妥的,如23时和凌晨1h,二者相差只有2h,但是如果只是将时按简单的数字做特征,23与1,二者相差22h,将严重误导模型学习的结果。所以有必要对诸如小时,分钟这样的周期性特征做合适的编码工作。最典型的编码方式是将一维数值变量扩展为二维的(正弦值,余弦值)来编码。步骤如下:
1.某特征X,计算其最大取值max_value,如小时的最大取值是23时,max_value = 23
2.计算正弦值余弦值:
正弦:
余弦:
3.将扩充后的特征Xsin,Xcos加入到特征集合中,去除其对应的原特征X(不用单独的“时”数值特征,用“时”的sin,cos值代替)
具体说一下
计算sin,cos的方式,就是普通的数值转弧度制,计算正弦余弦值。
而单单把一维变量转化为同样是一维的sin/cos的话,由于sin/cos的周期性,会带来同一取值对应多个不同时刻的问题,如下图
第一张sin,第二张cos,数据X:0,1,2,3,...,23,Y:对应的sin(x),cos(x)
单独的一维sin/cos并不能限制取值的唯一性,而sin,cos组合便可以达到这个目的
代码
import pandas as pd
import numpy as np
#创建数据
data = pd.DataFrame({'hour':list(range(24))})
data.plot()
#生成sin/cos特征
data['hour_sin'] = np.sin(2 * np.pi * data['hour']/23.0)
data['hour_cos'] = np.cos(2 * np.pi * data['hour']/23.0)
#sin/cos绘图
data['hour_sin'].plot()
data['hour_cos'].plot()
#(sin,cos)组合绘图
data.plot.scatter('hour_sin', 'hour_cos').set_aspect('equal')