数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功的关键。

那特征工程是什么?

特征工程是利用数据领域的相关知识来创建能够使机器学习算法达到最佳性能的特征的过程。

特征工程又包含了 Data PreProcessing(数据预处理)、Feature Extraction(特征提取)、Feature Selection(特征选择)和 Feature construction(特征构造)等子问题,本章内容主要讨论特征构造的方法。

文章目录

  • 0x01 特征构造介绍
  • 0x02 时间特征构造
    • 1.连续值时间特征
    • 2.离散值时间特征
      • 1)时间特征拆解
        • 程序实现
      • 2)时间特征判断
        • 程序实现
    • 3.结合时间维度的聚合特征
      • 1)首日聚合特征
      • 2)最近时间聚合特征
      • 3)区间内的聚合特征
  • 0x03 时间序列特征构造
    • 1.时间序列聚合特征
      • 1)平均值
      • 2)最小值
      • 3)最大值
      • 4)扩散值
      • 5)离散系数值
      • 6)分布性
    • 2.时间序列历史特征
      • 1)前一(或n)个窗口的取值
      • 2)周期性时间序列前一(或n)周期的前一(或n)个窗口的取值
    • 3.时间序列复合特征
      • 1)趋势特征
      • 2)窗口差异值特征
      • 3)自相关性特征
  • 0x0FF 总结
    • 1.时间特征主要有两大类:
      • 1)从时间变量提取出来的特征
      • 2)对时间变量进行条件过滤,然后再对其他变量进行聚合操作所产生的特征
      • 2\. 时间序列数据可以从带有时间的流水数据统计得到,实际应用中可以分别从带有时间的流水数据以及时间序列数据中构造特征,这些特征可以同时作为模型输入特征。
      • 参考文献

0x01 特征构造介绍

时间特构造以及时间序列特征构造的具体方法:

0x02 时间特征构造

对于时间型数据来说,即可以把它转换成连续值,也可以转换成离散值。

1.连续值时间特征

  • 持续时间(单页浏览时长);

  • 间隔时间;

  • 上次购买/点击离现在的时长;

  • 产品上线到现在经过的时长;

2.离散值时间特征

1)时间特征拆解

  • 年;

  • 月;

  • 日;

  • 时;

  • 分;

  • 数;

  • 一天中的第几分钟;

  • 星期几;

  • 一年中的第几天;

  • 一年中的第几个周;

  • 一天中哪个时间段:凌晨、早晨、上午、中午、下午、傍晚、晚上、深夜;

  • 一年中的哪个季度;

程序实现
import pandas as pd
# 构造时间数据
date_time_str_list = ['2019-01-01 01:22:26', '2019-02-02 04:34:52', '2019-03-03 06:16:40','2019-04-04 08:11:38', '2019-05-05 10:52:39', '2019-06-06 12:06:25','2019-07-07 14:05:25', '2019-08-08 16:51:33', '2019-09-09 18:28:28','2019-10-10 20:55:12', '2019-11-11 22:55:12', '2019-12-12 00:55:12',
]
df = pd.DataFrame({'时间': date_time_str_list})
# 把字符串格式的时间转换成Timestamp格式
df['时间'] = df['时间'].apply(lambda x: pd.Timestamp(x))# 年份
df['年']=df['时间'].apply(lambda x: x.year)# 月份
df['月']=df['时间'].apply(lambda x: x.month)# 日
df['日']=df['时间'].apply(lambda x: x.day)# 小时
df['时']=df['时间'].apply(lambda x: x.hour)# 分钟
df['分']=df['时间'].apply(lambda x: x.minute)# 秒数
df['秒']=df['时间'].apply(lambda x: x.second)# 一天中的第几分钟
df['一天中的第几分钟']=df['时间'].apply(lambda x: x.minute + x.hour*60)# 星期几;
df['星期几']=df['时间'].apply(lambda x: x.dayofweek)# 一年中的第几天
df['一年中的第几天']=df['时间'].apply(lambda x: x.dayofyear)# 一年中的第几周
df['一年中的第几周']=df['时间'].apply(lambda x: x.week)# 一天中哪个时间段:凌晨、早晨、上午、中午、下午、傍晚、晚上、深夜;
period_dict ={23: '深夜', 0: '深夜', 1: '深夜',2: '凌晨', 3: '凌晨', 4: '凌晨',5: '早晨', 6: '早晨', 7: '早晨',8: '上午', 9: '上午', 10: '上午', 11: '上午',12: '中午', 13: '中午',14: '下午', 15: '下午', 16: '下午', 17: '下午',18: '傍晚',19: '晚上', 20: '晚上', 21: '晚上', 22: '晚上',
}
df['时间段']=df['时'].map(period_dict)# 一年中的哪个季度
season_dict = {1: '春季', 2: '春季', 3: '春季',4: '夏季', 5: '夏季', 6: '夏季',7: '秋季', 8: '秋季', 9: '秋季',10: '冬季', 11: '冬季', 12: '冬季',
}
df['季节']=df['月'].map(season_dict)

2)时间特征判断

  • 是否闰年;

  • 是否月初;

  • 是否月末;

  • 是否季节初;

  • 是否季节末;

  • 是否年初;

  • 是否年尾;

  • 是否周末;

  • 是否公共假期;

  • 是否营业时间;

  • 两个时间间隔之间是否包含节假日/特殊日期;

程序实现
import pandas as pd
# 构造时间数据
date_time_str_list = ['2010-01-01 01:22:26', '2011-02-03 04:34:52', '2012-03-05 06:16:40','2013-04-07 08:11:38', '2014-05-09 10:52:39', '2015-06-11 12:06:25','2016-07-13 14:05:25', '2017-08-15 16:51:33', '2018-09-17 18:28:28','2019-10-07 20:55:12', '2020-11-23 22:55:12', '2021-12-25 00:55:12','2022-12-27 02:55:12', '2023-12-29 03:55:12', '2024-12-31 05:55:12',
]
df = pd.DataFrame({'时间': date_time_str_list})
# 把字符串格式的时间转换成Timestamp格式
df['时间'] = df['时间'].apply(lambda x: pd.Timestamp(x))# 是否闰年
df['是否闰年'] = df['时间'].apply(lambda x: x.is_leap_year)# 是否月初
df['是否月初'] = df['时间'].apply(lambda x: x.is_month_start)# 是否月末
df['是否月末'] = df['时间'].apply(lambda x: x.is_month_end)# 是否季节初
df['是否季节初'] = df['时间'].apply(lambda x: x.is_quarter_start)# 是否季节末
df['是否季节末'] = df['时间'].apply(lambda x: x.is_quarter_end)# 是否年初
df['是否年初'] = df['时间'].apply(lambda x: x.is_year_start)# 是否年尾
df['是否年尾'] = df['时间'].apply(lambda x: x.is_year_end)# 是否周末
df['是否周末'] = df['时间'].apply(lambda x: True if x.dayofweek in [5, 6] else False)# 是否公共假期
public_vacation_list = ['20190101', '20190102', '20190204', '20190205', '20190206','20190207', '20190208', '20190209', '20190210', '20190405','20190406', '20190407', '20190501', '20190502', '20190503','20190504', '20190607', '20190608', '20190609', '20190913','20190914', '20190915', '20191001', '20191002', '20191003','20191004', '20191005', '20191006', '20191007',
] # 此处未罗列所有公共假期
df['日期'] = df['时间'].apply(lambda x: x.strftime('%Y%m%d'))
df['是否公共假期'] = df['日期'].apply(lambda x: True if x in public_vacation_list else False)# 是否营业时间
df['是否营业时间'] = False
df['小时']=df['时间'].apply(lambda x: x.hour)
df.loc[((df['小时'] >= 8) & (df['小时'] < 22)), '是否营业时间'] = Truedf.drop(['日期', '小时'], axis=1, inplace=True)

3.结合时间维度的聚合特征

具体就是指结合时间维度来进行聚合特征构造,聚合特征构造的具体方法可以参考《聚合特征构造以及转换特征构造》中的《聚合特征构造》章节。

1)首日聚合特征

例如:注册首日投资总金额、注册首日页面访问时长、注册首日总点击次数等;

2)最近时间聚合特征

例如:最近N天APP登录天数、最近一个月的购买金额、最近购物至今天数等;

3)区间内的聚合特征

例如:2018年至2019年的总购买金额、每天下午的平均客流量、在某公司工作期间加班的天数等;

0x03 时间序列特征构造

时间序列不仅包含一维时间变量,还有一维其他变量,如股票价格、天气温度、降雨量、订单量等。时间序列分析的主要目的是基于历史数据来预测未来信息。对于时间序列,我们关心的是长期的变动趋势、周期性的变动(如季节性变动)以及不规则的变动。

按固定时间长度把时间序列划分成多个时间窗,然后构造每个时间窗的特征。

1.时间序列聚合特征

按固定时间长度把时间序列划分成多个时间窗,然后使用聚合操作构造每个时间窗的特征。

1)平均值

例子:历史销售量平均值、最近N天销售量平均值。

2)最小值

例子:历史销售量最小值、最近N天销售量最小值。

3)最大值

例子:历史销售量最大值、最近N天销售量最大值。

4)扩散值

分布的扩散性,如标准差、平均绝对偏差或四分位差,可以反映测量的整体变化趋势。

5)离散系数值

离散系数是策略数据离散程度的相对统计量,主要用于比较不同样本数据的离散程度。

6)分布性

时间序列测量的边缘分布的高阶特效估计(如偏态系数或峰态系数),或者更进一步对命名分布进行统计测试(如标准或统一性),在某些情况下比较有预测力。

程序实现:洗发水销售数据

import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)# 平均值
mean_v = df['value'].mean()
print('mean: {}'.format(mean_v))# 最小值
min_v = df['value'].min()
print('min: {}'.format(min_v))# 最大值
max_v = df['value'].max()
print('max: {}'.format(max_v))# 扩散值:标准差
std_v = df['value'].std()
print('std: {}'.format(std_v))# 扩散值:平均绝对偏差
mad_v = df['value'].mad()
print('mad: {}'.format(mad_v))# 扩散值:四分位差
q1 = df['value'].quantile(q=0.25)
q3 = df['value'].quantile(q=0.75)
irq = q3 - q1
print('q1={}, q3={}, irq={}'.format(q1, q3, irq))# 离散系数
variation_v = std_v/mean_v
print('variation: {}'.format(variation_v))# 分布性:偏态系数
skew_v = df['value'].skew()
print('skew: {}'.format(skew_v))
# 分布性:峰态系数
kurt_v = df['value'].kurt()
print('kurt: {}'.format(kurt_v))# 输出:
mean: 312.59999999999997
min: 119.3
max: 682.0
std: 148.93716412347473
mad: 119.66666666666667
q1=192.45000000000002, q3=411.1, irq=218.65
variation: 0.47644646232717447
skew: 0.8945388528534595
kurt: 0.11622821118738624

注:

  • 上面是单个时间序列的实现代码,多个时间序列的数据集构造特征时需要先进行分组再计算。如IJCAI-17口碑商家客流量预测比赛中,数据集中包含多个商家的历史销售数据,构造特征时需要先按商家分组,然后再构建特征。

  • 上述代码都是使用所有历史数据来构造特征,实际项目中如果待预测目标为t时刻的值,则使用t时刻之前的值来构造特征,不同的t值都可以分别构造训练样本对应的特征。
    如:使用t时刻的y值作为label,则使用t-1时刻之前的y值来构造特征;使用t-1时刻的y值作为label时,则使用t-2时刻之前的y值来构造特征。如此类推,我们可以得到多个训练样本,每个样本有多个特征。

2.时间序列历史特征

1)前一(或n)个窗口的取值

例子:昨天、前天和3天前的销售量。

2)周期性时间序列前一(或n)周期的前一(或n)个窗口的取值

例子:写字楼楼下的快餐店的销售量一般具有周期性,周期长度为7天,7天前和14天前的销售量。

程序实现:洗发水销售数据

import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)df['-1day'] = df['value'].shift(1)
df['-2day'] = df['value'].shift(2)
df['-3day'] = df['value'].shift(3)df['-1period'] = df['value'].shift(1*12)
df['-2period'] = df['value'].shift(2*12)display(df.head(60))

3.时间序列复合特征

1)趋势特征

趋势特征可以刻画时间序列的变化趋势。

例子:每个用户每天对某个Item行为次数的时间序列中,User一天对Item的行为次数/User三天对Item的行为次数的均值,表示短期User对Item的热度趋势,大于1表示活跃逐渐在提高;三天User对Item的行为次数的均值/七天User对Item的行为次数的均值表示中期User对Item的活跃度的变化情况;七天User对Item的行为次数的均值/ 两周User对Item的行为次数的均值表示“长期”(相对)User对Item的活跃度的变化情况。

程序实现:

import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)df['last 3 day mean'] = (df['value'].shift(1) + df['value'].shift(2) + df['value'].shift(3))/3
df['最近3天趋势'] = df['value'].shift(1)/df['last 3 day mean']
display(df.head(60))

2)窗口差异值特征

一个窗口到下一个窗口的差异。例子:商店销售量时间序列中,昨天的销售量与前天销售量的差值。

程序实现:

import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)df['最近两月销量差异值'] = df['value'].shift(1) - df['value'].shift(2)
display(df.head(60))

3)自相关性特征

原时间序列与自身左移一个时间空格(没有重叠的部分被移除)的时间序列相关联。

程序实现:

import statsmodels.tsa.api as smt
import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)print('滞后数为1的自相关系数:{}'.format(df['value'].autocorr(1)))
print('滞后数为2的自相关系数:{}'.format(df['value'].autocorr(2)))
# 输出:
滞后数为1的自相关系数:0.7194822398024308
滞后数为2的自相关系数:0.8507433352850972

除了上面描述的特征外,时间序列还有历史波动率、瞬间波动率、隐含波动率、偏度、峰度、瞬时相关性等特征。

0x0FF 总结

1.时间特征主要有两大类:

1)从时间变量提取出来的特征

  • 如果每条数据为一条训练样本,时间变量提取出来的特征可以直接作为训练样本的特征使用。

例子:用户注册时间变量。对于每个用户来说只有一条记录,提取出来的特征可以直接作为训练样本的特征使用,不需要进行二次加工。

  • 如果每条数据不是一条训练样本,时间变量提取出来的特征需要进行二次加工(聚合操作)才能作为训练样本的特征使用。

例子:用户交易流水数据中的交易时间。由于每个用户的交易流水数量不一样,从而导致交易时间提取出来的特征的数据不一致,所以这些特征不能直接作为训练样本的特征来使用。我们需要进一步进行聚合操作才能使用,如先从交易时间提取出交易小时数,然后再统计每个用户在每个小时(1-24小时)的交易次数来作为最终输出的特征。

2)对时间变量进行条件过滤,然后再对其他变量进行聚合操作所产生的特征

主要是针对类似交易流水这样的数据,从用户角度进行建模时,每个用户都有不定数量的数据,因此需要对数据进行聚合操作来为每个用户构造训练特征。而包含时间的数据,可以先使用时间进行条件过滤,过滤后再构造聚合特征。

2. 时间序列数据可以从带有时间的流水数据统计得到,实际应用中可以分别从带有时间的流水数据以及时间序列数据中构造特征,这些特征可以同时作为模型输入特征。

例如:美团的商家销售量预测中,每个商家的交易流水经过加工后可以得到每个商家每天的销售量,这个就是时间序列数据。

参考文献

[1] https://machinelearning-notes.readthedocs.io/zh_CN/latest/feature/%E7%89%B9%E5%BE%81%E5%B7%A5%E7%A8%8B%E2%80%94%E2%80%94%E6%97%B6%E9%97%B4.html
[2] https://www.cnblogs.com/nxf-rabbit75/p/11141944.html#_nav_12
[3] https://gplearn.readthedocs.io/en/stable/examples.html#symbolic-classifier
[4] 利用 gplearn 进行特征工程. https://bigquant.com/community/t/topic/120709
[5] Practical Lessons from Predicting Clicks on Ads at Facebook. https://pdfs.semanticscholar.org/daf9/ed5dc6c6bad5367d7fd8561527da30e9b8dd.pdf
[6] Feature Tools:可自动构造机器学习特征的Python库. https://www.jiqizhixin.com/articles/2018-06-21-2
[7] 各种聚类算法的系统介绍和比较. https://blog.csdn.net/abc200941410128/article/details/78541273

这或许是全网最全时间序列特征工程构造的文章了相关推荐

  1. 这或许是全网最全 Python dataframe 数据合并方法汇总

    有位朋友面试阿里的数据岗位,面试官问关于Python的5种数据合并的函数,结果他蒙蔽了'... 那么,究竟是哪五个呢?今天,我们就来带大家了解一下,喜欢记得收藏.关注.点赞. 注意:完整代码.资料.技 ...

  2. 【数据竞赛】可能是全网特征工程实操最通透的...

    之前在我写的特征工程方法论里面提了一嘴,用automl搜索+人工启启发式可以高效稳定地完成特征工程,并取得不错的效果. 原文:可能是全网写特征工程最通透的... 不过这篇文章最大的问题是太过于侧重于是 ...

  3. 如何进行时间序列的特征工程?

    作者 | 时序人  责编 | 张文 头图 | CSDN 下载自视觉中国 来源 | 时序人(ID:TSer2020) 前几次的分享,我们了解了时间序列分析的基础方法以及预测方法.在使用这些方法之前,一般 ...

  4. 特征工程与特征选择架构性好文

    作者:马东什么 来源:https://zhuanlan.zhihu.com/ p/96420594 整理:深度传送门 偶然看到的一篇好文,有一些部分讲的不错,分享一下. 特征工程和选择是以最好的方式转 ...

  5. 【算法竞赛学习】心跳信号分类预测-特征工程

    Task3 特征工程 此部分为零基础入门数据挖掘-心跳信号分类预测的 Task3 特征工程部分,带你来了解时间序列特征工程以及分析方法,欢迎大家后续多多交流. 赛题:零基础入门数据挖掘-心跳信号分类预 ...

  6. 正式开启推荐系统特征工程的1年连载出书计划

    作者 | gongyouliu 编辑 | auroral-L 大家好,我是强哥.一个热爱暴走.读书.写作的人! 我们知道推荐系统是机器学习的一个分支学科,并且是一个非常偏业务的.具备商业价值的方向.从 ...

  7. 【直播】王茂霖:二手车交易价格预测-千变万化特征工程(河北高校数据挖掘邀请赛)

    二手车交易价格预测-千变万化特征工程 目前 河北高校数据挖掘邀请赛 正在如火如荼的进行中.为了大家更好的参赛,王茂霖分享了 从0梳理1场数据挖掘赛事!,完整梳理了从环境准备.数据读取.数据分析.特征工 ...

  8. [特征工程系列一] 论特征的重要性

    满打满算,还有十天左右就要过年了,这些天大家或多或少都有点浮躁.反过来想,趁大家都懈怠的时候,正是学习的最佳时机.趁着这几天,也给自己加点码,去认真的再看一下特征工程.我给自己列了下面的这一份学习清单 ...

  9. 天猫用户重复购买预测——特征工程

    天猫用户重复购买预测--特征工程 1.特征工程 1.1 概念 1.2 特征归一化 1.3 类别型特征转换 1.4 高维组合特征的处理 1.5 组合特征 1.6 文本表示模型 2. 赛题特征工程思路 3 ...

最新文章

  1. PHPStorm+XDebug进行调试
  2. Vue PDF文件预览vue-pdf
  3. 如何在MyEclipse中添加 用户自定义类库 以及将自定义的类库加入工程的加载目录...
  4. python玩转大数据视频[非原创视频]
  5. python自动化入门_python自动化-python入门
  6. python 模糊匹配_很冷门,但非常实用的 Python 库
  7. rabbitmq docker
  8. oracle改成归档模式_将Oracle数据库改为归档模式并启用Rman备份
  9. sw修改器初始化服务器错误,solidworks打开出现Loadlibrary failed with error 1114:动态链接库(DLL)初始化例程失败如何解决?...
  10. 使用casewhen来判断执行不同的sql
  11. ie8不支持transform: translateY,ie9支持不友好
  12. ros launch中的节点工作空间路径
  13. 苹果开发者新账号上新app审核被拒绝:Other-Other被拒绝,心路历程记录!
  14. 1-MATLAB APP Design-图像的输入与输出
  15. Java并发编程实践之并发理论基础(一)
  16. Python入门基础(下)之魔方方法
  17. Disk Expert 3.6.1 可视化磁盘清理工具
  18. Python之路【第二十二篇】:Django之Model操作
  19. 提取wux-weapp的微信小程序筛选框:FilterBar
  20. 第一章 简介(待续)

热门文章

  1. 学习FPGA之一:初识FPGA
  2. 学习什么技术 4年后最赚钱
  3. mac出现文件夹问号_Macbook文件夹怎么设置隐藏或显示?开机带问号的文件夹怎么办?...
  4. 静态综合实验(企业内网访问外网工程)
  5. MAT的使用(一)使用方法介绍
  6. JavaSE 第七章集合 Collection
  7. oracle no privileges on tablespace 'USERS
  8. 关于POJO 即DO/DTO/BO/VO/AO说明
  9. 使用uber数据集和kelpergl做路网动态可视化
  10. 达人评测 赛扬J4105和赛扬N5095选哪个好