Feature generation. 对于这个技术点, 其实没有什么诀窍, 就是一个, 深刻理解咱们的数据的意义再加上一点点创造力. 大家是不是很懵逼, 哈哈, 这就完啦???? 哈哈当然不是啦, 但是这一块缺失没有一个统一的模式, 具有一定的随机性. 但是通过总结, 咱们可以总结一下常用的模式, 方便大家在应用的时候参考. 2.1 Interaction. 这个其实就是相当于交叉的意思, 咱们可以将几个 features 直接的拼接在一起, 形成一个 "有意思" 的新的 feature, 记住一定要有意义的, 否则你不但白搞了, 甚至原来好好的数据都被你搞砸了, 不要为了装逼而装逼, 咱要装逼于无形之中. 那么这个有什么意义呢? 首先它能将多个 columns 装换成一个 column, 方便咱们的数据处理; 其次在有些特定的数据中, 这种 interaction 更加能反映出数据的本质. 具体怎么操作了, 咱们通过一个简单的代码来展示, 注意我只截取了我代码的一部分, 默认数据都已经加载完毕, 所以不要纠结我的代码的变量和数据哈, 大家主要看过程和思路
- interactions = data_raw["category"]+"_"+data_raw["country"]
- baseline_data = baseline_data.assign(category_country = label_encoder.fit_transform(interactions))
上面的第一句代码就是咱们 interaction 的部分, 第二句是讲 interaction 过后的数据 label encoding 并且加入到咱们的数据集里面, 简单明了. 上面是将原始数据中的 category 和 country 连接在一起从而形成一个新的 feature 2.2 numerical transforming. 这是什么意思呢, 对于有些 numerical data 的 columns, 他们的数据分布是很不均匀的, 或者说他们的数值太大或者太小, 有的时候不适合咱们的数据的训练, 可能会出现 vanishing gradient 或者 gradient explode 的情况. 具体啥叫 vanishing gradient 和 gradient exploding, 咱们在后面的内容在慢慢解释. 暂时只需要知道这是个很麻烦的事情就好了, 会导致咱们训练的模型不那么牛逼就行了. 那么咱们通过什么方法解决呢? 这里主要通过一些常见的数学的方式来解决, 例如用 log 或者 sqrt 等等方式. 咱们可以通过下面的代码来简单的展示一下
- np.sqrt(baseline_data['goal'])
- np.log(baseline_data['goal'])
从上面咱们可以看出, 这里咱们主要还是通过 numpy 里面提供的 API 进行处理的, 非常简单, 简单跟 1 一样, 好了这里就说到这了. 对了, 忘记一个事儿, 就是 numerical transforming 在 tree-based 模型中没有什么卵用的, 因为 tree-based 的所有模型都是 scale invariant 的, 就是 tree-based 模型都是不 care 数据的大小分布的. 2.3 rolling. 这个就比较高级一点啦 (相比前两种方式), 首先咱们先要明白 rolling 的概念, 其实 rolling 就是相当于在咱们的数据(series) 上面卡上一个 fixed-size 的小 Windows, 然后对于这个 Windows 覆盖的数据进行一些简单的计算, 例如: counting,mean,sum 等等. 如果大家还是觉得不懂, 我把它的官方链接贴在这里, 大家自己去看看, 里面还有很多实例: . 那么我先写一个简单的小例子给大家参考一下哈
- launched = pd.Series(data_raw.index,data_raw.launched,name="count_7_days").sort_index()
- count_7_days = launched.rolling('7d').count()
- count_7_days.index = launched.values
- count_7_days = count_7_days.reindex(data_raw.index)
我先简单解释一下上面代码的意思哈, 第一句是让时间作为这个 series 的 index, 第二句 rolling 是计算最近 7 天的的数量, 第三第四句是讲数据还原到之前的 index 的顺序, 房间重新 join 到原来的数据集中. 那么 rolling 这种方式一般在什么情况下用呢? 一般在你的数据有 datetime 的时候, 或者前面数据会影响到后面的结果的时候, 大家可以考虑一下下, 但是这个是不一定的, 还是需要大家有一定的 creativity 的. 例如上面的例子就是统计最近 7 天一共上传的 App 的数量, 来判断某一个 App 是否被下载的应用场景. 一般情况下, 最近上传的 App 数量太多, 被下载的概率就越低, 所以他们还是有一定关联关系的. 所以我 generate 一个新的 feature 还是有一定道理的. 2.4 Time delta. 从这个命名中咱们可以知道, 这个跟 time 肯定有关系, 这个大家猜的很对. time delta 也是有一定随机性的, 有时需要有时也不需要, 也是要根据实际的数据的特性来决定的, 甚至是根据工程师自己来决定的, 跟上面的 rolling 有点相似. 为了方便解释这其中的细节, 我也是直接来一个例子然后慢慢解释
- def time_since_last_project_same_category(series):
- return series.diff().dt.total_seconds()/3600
- df = data_raw[['category','launched']].sort_values('launched')
- group_category = df.groupby('category')
- timedeltas = group_category.transform(time_since_last_project_same_category)
- timedeltas = timedeltas.fillna(timedeltas.mean()).reindex(baseline_data.index)
上面前两行是一个计算相邻 datatime 之间的相差多少个小时, 第三行创建一个按照排序好的 launched time 为 index 的 dataframe, 第四行是按照 category 的条件来 group 前面创建的 df, 第五行是计算 group 里面相邻数据之间的 time delta, 并且返回一个 series, 第六行是填充这些空数据, 并且按照原始数据的方式 index 重新排序方便加入到原始数据. 流程就这样结束了. 上面的场景是计算同一个 category 相邻 App 上传的时间差, 这个其实也是会影响到咱们的 App 是否被下载的因素. 所以这个也是咱们的一个 creativity, 实际情况中千变万化, 一定要根据实际情况来定, 不能为了装逼而装逼, 一定要根据实际的业务需要, 否则适得其反. 好了, 其实关于 feature generation 还有很多种方式, 例如有些事计算两个 columns 之间的差值, 取模等等, 这里没有统一的标准, 唯一的捷径和 key 就是咱们一定得理解咱们每一个 columns 和 dataset 的实际业务的意思, 否则再牛逼的 generation 也拯救不了你. 下面咱们进入到这一章的最后一节 feature selection 吧.
来源: https://www.cnblogs.com/tangxiaobo199181/p/12210734.html