数据特征工程

更多总结查看Github

只要数据好,模型随便搞。所以说来相对于机器学习和建模,准备好数据是极其重要的。那如何准备数据呢,讨论一下。

对于数据特征工程,可以这样划分:

1. 特征使用 <数据选择,可用性>

2. 特征获取 <特征来源,特征存储>

3. 特征处理 <数据清洗,特征预处理>

4. 特征监控 <现有特征,新特性>

今天说说最复杂的一步骤,特征预处理,包括以下几项

  1. 特征选择 
  2. 特征变换
  3. 特征降维
  4. 特征衍生

一. 特征选择

简单来说,就是依靠统计学方法或者模型进行与标注影响大小的排序后,移除排名靠后的特征,实现降维。或者说是剔除与标注不相关或冗余的特征。

常用的三个思想:过滤思想, 包裹思想, 嵌入思想。

import pnadas as pd
import numpy as np
import scipy.stats as ss
from sklearn.svm import SVR  # 线性回归器
from sklearn.tree import DecisionTreeRegressor  # 决策树回归器
from sklearn.feature_selection import SelectKBest, RFE, SelectFromModel
"""
SelectKBest是过滤思想使用的包,
RFE 是包裹思想使用的包,
SelectFromModel是嵌入思想使用的包

"""
# "D"为label,"A","B","C" 是三個特征
>>> df=pd.DataFrame({"A":ss.norm.rvs(size=10), "B":ss.norm.rvs(size=10), "C": ss.norm.rvs(size=10), "D":np.random.randint(0,2,size=10)})

>>> df
>>>
          A         B         C  D
0  0.923187  0.384042 -0.261672  1
1  0.619342 -1.068809  0.279934  0
2  0.284038  1.037739 -0.574052  0
3 -0.445716  0.605456  1.297583  1
4  0.336248  0.563767 -0.482365  0
5  0.481252 -0.033403  0.091762  0
6 -1.377989  0.091305 -0.762167  0
7 -0.892782 -0.892560  1.571945  1
8 -1.210382  0.131639 -1.090856  1
9 -0.192815  0.180512 -1.328096  1

>>> X=df.loc[:, ["A","B","C"]]
>>> Y=df.loc[:, "D"]
>>> skb=SelectKBest(k=2)  # 留下兩個特征
>>> skb.fit_transform(X, Y)  # 拟合 转换
>>> 
array([[ 0.92318731, -0.26167169],
       [ 0.61934239,  0.27993381],
       [ 0.28403782, -0.57405165],
       [-0.44571598,  1.29758274],
       [ 0.3362478 , -0.48236513],
       [ 0.48125228,  0.0917617 ],
       [-1.37798928, -0.76216674],
       [-0.89278198,  1.57194517],
       [-1.21038202, -1.09085592],
       [-0.19281496, -1.32809554]])
# 可以看到经过嵌入思想的方法,把关联性差的"B"特征去掉了。

>>> rfe=RFE(estimator=SVR(kernel="linear"), n_features_to_select=2, step=1)  # 同样留下两个特征
>>> rfe.fit_transform(X, Y)
>>> 
array([[ 0.92318731, -0.26167169],
       [ 0.61934239,  0.27993381],
       [ 0.28403782, -0.57405165],
       [-0.44571598,  1.29758274],
       [ 0.3362478 , -0.48236513],
       [ 0.48125228,  0.0917617 ],
       [-1.37798928, -0.76216674],
       [-0.89278198,  1.57194517],
       [-1.21038202, -1.09085592],
       [-0.19281496, -1.32809554]])
# 这是经过包裹思想的方法,结果和上面一样

>>> sfm=SelectFromModel(estimator=DecisionTreeRegressor(), threshold=0.01) # 指定阈值可以调节
>>> sfm.fit_transform(X, Y)
>>> 
array([[ 0.92318731],
       [ 0.61934239],
       [ 0.28403782],
       [-0.44571598],
       [ 0.3362478 ],
       [ 0.48125228],
       [-1.37798928],
       [-0.89278198],
       [-1.21038202],
       [-0.19281496]])
# 这是嵌入思想过滤之后

二. 特征变换

特征变换常用的方法:对指化、离散化、归一化、数值化、正规化

1. 对指化就是对数据指数化或对数化的转化,用来扩大或缩放单位数据的变化,方便统计。

numpy.log
numpy.exp

2. 离散化是将连续数据转化为离散数据的操作。比如朴素贝叶斯的算法要求离散化的数据。

常用方法有等频,等距,自因变量优化(基本上看数据拐点)

等频等距方法都属于分箱技术(等频即等深, 等距即等宽)

>>> lst=[4, 6, 8, 11, 0, 54, 34, 16, 19]
>>> lst.sort()
# 分箱前一定排序
# 等深分箱
>>> pd.qcut(lst, q=3)
>>>
[(-0.001, 7.333], (-0.001, 7.333], (-0.001, 7.333], (7.333, 17.0], (7.333, 17.0], (7.333, 17.0], (17.0, 54.0], (17.0, 54.0], (17.0, 54.0]]
Categories (3, interval[float64]): [(-0.001, 7.333] < (7.333, 17.0] < (17.0, 54.0]]

>>> pd.qcut(lst, q=3, labels=["low", "medium", "high"])  # 可以指定label
>>> 
[low, low, low, medium, medium, medium, high, high, high]
Categories (3, object): [low < medium < high]


# 等宽分箱
>>> pd.cut(lst, bins=3)
>>> 
[(-0.054, 18.0], (-0.054, 18.0], (-0.054, 18.0], (-0.054, 18.0], (-0.054, 18.0], (-0.054, 18.0], (18.0, 36.0], (18.0, 36.0], (36.0, 54.0]]
Categories (3, interval[float64]): [(-0.054, 18.0] < (18.0, 36.0] < (36.0, 54.0]]

>>> pd.cut(lst, bins=3, labels=["low", "medium", "high"])
>>>
[low, low, low, low, low, low, medium, medium, high]
Categories (3, object): [low < medium < high]

3. 归一化便是把数据范围缩放到 0—1之间,数据间对比更加方便。

from sklearn.preprocessing import MinMaxScaler, StandardScaler

>>> MinMaxScaler().fit_transform(np.array([1, 4, 10, 15, 21]).reshape(-1, 1))
>>>
array([[0.  ],
       [0.15],
       [0.45],
       [0.7 ],
       [1.  ]])

# 归一化把数组转化成了0-1之间的数


>>> StandardScaler().fit_transform(np.array([1,1,1,1,0,0,0,0]).reshape(-1, 1))
>>>
array([[ 1.],
       [ 1.],
       [ 1.],
       [ 1.],
       [-1.],
       [-1.],
       [-1.],
       [-1.]])

# 这是另一种标准化准换,x` = (x-xi)/std(), 就是每个数变为此数与平均数的差除以方差得到的结果

4.数值化就是将非数值数据转化为数值数据。

对于某些数据,比如 "UP", "DOWN"可以转化为0,1

而对于像 "红","黄","蓝","绿"这类数据简单转化为0,1,2,3 好像不太合适了。

from sklearn.preprocessing import LabelEncoder, OneHotEncoder

>>> LabelEncoder().fit_transform(np.array(["Down","Down","Up","Up"]).reshape(-1, 1))
>>> array([0, 0, 1, 1], dtype=int64)

# 另一种转换就麻烦点了
>>> lb_tran_f=LabelEncoder().fit_transform(np.array(["red", "yellow", "blue", "green"]))
>>> lb_tran_f
>>> 
array([2, 3, 0, 1], dtype=int64)  # 如果这种结果我们不想要继续下面的操作
>>> oht_encoder = OneHotEncoder().fit(lb_tran_f.reshape(-1,1))
>>> oht_encoder.transform(lb_encoder.transform(np.array(["red", "yellow","blue", "green"])).reshape(-1,1))
>>> oht_encoder.transform(lb_encoder.transform(np.array(["red", "yellow","blue", "green"])).reshape(-1,1)).toarray()
>>> 
array([[0., 0., 1., 0.],
       [0., 0., 0., 1.],
       [1., 0., 0., 0.],
       [0., 1., 0., 0.]])

# 四种颜色就转化为了向量矩阵

5. 正规化分为L1和L2两种,具体公式不多解释。

from sklearn.preprocessing import Normalizer

>>> Normalizer(norm="l1").fit_transform(np.array([[1,1,3,-1,2]]))
>>>
array([[ 0.125,  0.125,  0.375, -0.125,  0.25 ]])

>>> Normalizer(norm="l2").fit_transform(np.array([[1,1,3,-1,2]]))
>>>
array([[ 0.25,  0.25,  0.75, -0.25,  0.5 ]])

# 需要注意的是正规化是针对行,如果是列就会产生错误,例如:
>>> Normalizer(norm="l1").fit_transform(np.array([1,1,3,-1,2]).reshape(-1,1))
>>>
array([[ 1.],
       [ 1.],
       [ 1.],
       [-1.],
       [ 1.]])

三. 特征降维

降维包括主成分分析(PCA) 和 奇异值分解(SVD), 两种降维都和标注无关

而LDA降维是和标注有关的,具体理论还真一句话解释不明白,看代码吧

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# LDA降维
# Y为标注,X为特征
>>> X=np.array([[-1,-1], [-2, -1], [-3,-2], [1,1], [2,1], [3,2]])
>>> Y=np.array([1,1,1,2,2,2])
>>> LinearDiscriminantAnalysis(n_components=1).fit_transform(X, Y)  # n_components=1降到1维
>>>
array([[-1.73205081],
       [-1.73205081],
       [-3.46410162],
       [ 1.73205081],
       [ 1.73205081],
       [ 3.46410162]])

>>> clf = LinearDiscriminantAnalysis(n_components=1).fit(X, Y)
>>> clf.predict([[0.8, 1]])
>>>
array([2])
# 预测分类结果为 2

# fisher_classifier分类器

四. 特征衍生

这就很好理解了,多角度衍生出新的特征。方法有: 数据加减乘除、求导和高阶求导、人工归纳。

 

总结:数据的路还很长....

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值