机器学习—特征工程

特征工程概述

特征工程组织图

一、特征工程概述

特征工程 = 数据准备(for 数据挖掘)
数据清洗、转换
1.1 特征工程主要内容
1.2 特征工程重要性
好数据>多数据>好算法
    数据和特征决定了模型预测的上限,而算法只是逼这个上限而已
应用机器学习基本上就是特征工程

二、特征构造的常用方法

文本数据特征提取(类似茎叶图)
图像数据特征提取
用户行为特征提取
2.1 不同类型数据的特征提取方法
用户特征 RFM 行为特征提取:
在客户关系管理(CRM),有三个刻画用户的神奇指标
最近一次消费间隔时长(Recency)
消费频率(Frequency)
消费金额(Monetary)
代码演示:
import matplotlib.pyplot as plt
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'

trade = pd.read_csv(./data/transaction.txt)    #导入交易数据类型
trad.info()
trad.head()

trade['Date'] = pd.to_datetime(trade['Date'])  #把date数据转换成日期类型
trade.info()
trade.head()

RFM = trade.groupby('CardID').egg(             #汇总生成 RFM 特征
    {'Date':'max','CardID':'count','Amount':'sum'})
RFM.head()

三、特征转换

3.1 连续型变量

▶3.1.1 连续变量无量纲化
无量纲化: 使不同规格尺度的数据转化统一规格尺度(将数据单位统一)
无量纲化方法:标准化, 区间所方法
标准化: 将连续性变量转变为 均值0 标准差1 的变量

x = x x ¯ σ

其中 x ¯ 是均值, σ 是标准差

代码:                                 #对 Amount字段--均值为0,方差为1标准化
from sklearn import preprocessing
std = preprocessing.StandardScaler()  #StandardScaler
Amount = RFM['Amount'].values.reshape(-1,1)
std.fit(Amount)
RFM['Amount_std'] = std.transform(Amount)
RFM.head(5)
区间缩放法:把原始的连续型变量转换为范围在[a,b]或者 [0,1] 之间的变量

x = x m i n ( x ) m a x ( x ) m i n ( x )

代码:                                       #对 Amount字段--[0,1]区间归一化 
from sklearn import preprocessing
MinMaxscaler = preprocessing.MinMaxscaler()  #MinMaxscaler
Amount = RFM['Amount'].values.reshape(-1,1)
MinMaxscaler.fit(Amount)                     #拟合(训练)
RFM['Amount_range'] = MinMaxscaler.transform(Amount)
RFM.head(5)
▶3.1.2 连续变量数据变换
数据变换:通过函数变换改变原始数据的分布
目   的: 数据从无关系 -> 有关系
         呈偏态分布-->变换后差异拉开
         让数据符合模型理论所需要的假设,然后对其分析,例如:变换后数据呈正态分布

数据变化方法:

logX Ine 等 对数函数变换 x = l n ( x )
box-cox 变换 :自动寻找最佳正态分布变换函数的方法
这里写图片描述

代码1#对 Amount字段--log 变换
import numpy as np
RFM['Amount_log'] = np.log(RFM['Amount'])
RFM,head(5)

代码2#对 Amount字段--sqrt (平方根) 变换
import numpy as np
RFM['Amount_sqrt'] = np.sqrt(RFM['Amount'])
RFM,head(5)
▶3.1.3 连续变量离散化
目的:方便探索数据相关性
      减少异常数据对模型的干扰
      为模型引入非线性,提升模型预测能力
      离散后,可进行特征交叉组合,又M+N 变成 M*N
数据离散化方法:
    非监督离散方法:
        自定义规则,
        等宽方法,
        等频/等深方法
非监督离散方法:
 #对 Amount字段--自定义区间 离散化
        cut_points = [0,200,500,800,1000]
        RFM['Amount_bin'] = pd.cut(RFM['Amount'],bin = cut_points)
        RFM,head(5)
 #对 Amount字段--等宽 离散化
        RFM['Amount_width_bin'] = pd.cut(RFM.Amount,20) #分成20等分
        RFM,head(5)
        grouped = RFM.groupby('Amount_width_bin')
        grouped['CardID'].count()
 #对 Amount字段--等深 离散化
        RFM['Amount_depth_bin'] = pd.qcut(RFM.Amount,5) #分成5人的等分约20%
        RFM,head(5)
        grouped = RFM.groupby('Amount_depth_bin')
        grouped['CardID'].count()
有监督离散方法:决策树
离散化后的目标分类纯度最高(对目标有很好的区分能力)
一种特殊的离散化方法:
    二值化:           把连续型变量分割为0/1(是/否) 例如:是否大于18岁(是/否)
    Rounding(取整): 本质上时一种类似‘等距方法’的离散

3.2 类别变量编码

类别变量编码:
类别型变量----编码成---> 数值型变量
目的:
机器学习算法 无法处理类别型变量,必须转换为数值型变量
一定程度起到了扩充特征的作用(构造了新的特征)

one-hot 编码 (独热编码)
count-Encoding 频数编码 (可以去量纲化,秩序,归一化)
Target encoding 二分类 用目标变量中的某一类的比例来编码

代码:
import pandas as pd                    #导入的数据源于 特征构造
trade = pd.read_csv('./data/transaction.txt')
trade['Date'] = pd.to_datetime(trade['Date'])
RFM = trade.groupby('CardID').egg({'Date':'max','CardID':'count','Amount':'sum'})
RFM.head()

Onehot 编码(独热编码)                  #使用pandas
onehot = pd.get_dummies(RFM['CardID']),drop_first = False,prefix = 'Freq'

onehot.head()
    from sklearn import preprocessing  #使用sklearn 导入OneHotEncoder
    onehot = preprocessing.OneHotEncoder() #OneHotEncoder
    Freq = RFM['CardID'].values.reshape(-1,1)
onehot.fit(Freq)
    Freq_onehot = onehot.transform(Freq).toarray()
    Freq_onehot
    df = pd.DataFrame(Freq_onehot)    #将array 转为pandas 的dataframe
    df.head()

3.3 日期型变量转换

时间型
日期型

代码:
import pandas as pd
data = pd.DataFrame({'data_time':pd.date_range('1/1/2017 00:00:00',period = 12,freq = 'H'),'data':pd.date_range('2017-1-1',period = 12,freq = 'M')
})

■ data:提取日期型和时间型的特征变量
data['year']= data['data_time'].dt.year
data['month'] = data['data_time'].dt.month
data['day'] = data['data_time'].dt.day
data['hour'] = data['data_time'].dt.hour
data['minute'] = data['data_time'].dt.minute
data['second'] = data['data_time'].dt.second
data['quarter'] = data['data_time'].dt.quarter
data['week'] = data['data_time'].dt.week
data['yearmonth'] = data['data_time'].dt.strftime('%Y-%m')
data['halfyear'] = data['data_time'].mapa(lambda d:'H' if d.month <= 6 else 'H2')data:转换为相对时间特征
import datetime
data['deltaDayToToday'] = (datetime.date.today()-data['date'].dt.date).dt.days  #距离今天的间隔(天数)
data['deltaMonthToToday'] = datetime.date.today().month - data['date'].dt.month #距离今天的间隔(月数)
data['daysOfyear'] = data['date'].map(lambda d:366 if d.is_leap_year els 365)   #一年过去的进度
data['rateOfyear'] = data['date'].dt.dayofyear/data['daysOfyear']
data.head()

3.4 缺失值处理

处理方法:
    删除缺失值记录
    缺失值替换:  用0替换
                平均数替换
                众数替换
                预测模型替换

构造NaN encoding编码 :构造一个新的字段来标识是否有缺失(1/0) 任何时候都可使用

代码:
    import pandas as pd
    titanic = pd.read_csv('./data/titanic.csv')
    titanic.info()

    age_mean = round(titanic['Age'].mean())        #对缺失值进行填充
    titanic['Age'].fillna(age_mean,inplace = True) #填充平均年龄
    titanic.info()

    titanic = pd.read_csv('./data/titanic.csv') #构造缺失值的标志变量(0/1)
    titanic.info()
    titanic['Age_ismissing'] = 0
    titanic.loc[titanic['Age'].isnull(),'Age_ismissing'] = 1
    titanic['Age_ismissing'].value_counts()

3.5 特征组合

目的:构造更多更好的特征,提升模型精度(例如:地球仪的经纬密度)
方法:
多个连续变量: 加减乘除运算
多个类别型变量: 所有值交叉组合

代码:
import pandas as pd 
titanic = pd.read_csv('./data/titanic.csv')
titanic.head()

组合特征
titanic['Sex_pclass_combo'] = titanic['Sex']+'_pclass_'+titanic['Pclass'].astype(str)
titanic.Sex_pclass_combo.value_counts()

onehot编码
Sex_pclass_combo = pd.get_dummies['Sex_pclass_combo'],drop_first = False,prefix = 'onehot'
Sex_pclass_combo.head()

四、数据降维

概念:在尽量减少信息量的前提下,采用某种映射方法(函数)把原来的高维数据(变量多)—映射—>低维数据(变量少)
避免维数灾难 :增加样本量
常用的降维方法:
    线性方法                          非线性方法
有监督方法 --> LDA(线性判别分析)      无
无监督方法 --> PCA(主成分分析)        局部线性嵌入(LLE)拉普拉斯特征映射

4.1主成分分析(PCA)原理(无监督)

理解 PCA 的关键,一是坐标变换,二是新坐标(也就是投影)

4.1.1 通过线性投影
这里写图片描述
4.1.2 主成分分析(PCA)操作流程
A 原始数据—减均值
这里写图片描述
B 求特征变量的协方差矩阵
这里写图片描述
C 求协方差的 特征值 和 特征向量
D 将特征值大->小排序,选择最大的k(1)个,然后对k(1)个特征向量分别作为 列向量组成特征向量矩阵(最大的特征根对应的特征向量)
E 将样本点投影到选取的向量上,得到最终降维后的新维度(1个)

代码:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'
from sklearn import datesets

iris= datasets.load_iris() #导入iris数据
X = iris.data
y = iris.target
X[:10]
y[:10]

#PCA 降维

from sklearn.decomposition import PCA
 # sklearn.decomposition.PCA(n_components=None,copy = True whiten = False)
 # n_components:主成分个数
 # copy:是否在运行算法时,将原始数据复制一份,缺省时默认 Ture
 # whiten:白化,使得每个特征具有相同的方差,缺省时默认 False

PCA = PCA(n_components = 3)   #定义一个PCA模型
pca.fit(X)                    #fit
X_new = pca.transform(X)      #transform
X_new[:5]
X_new = pca.fit_transform(X) #fit_transform --可以替代fit 和 transform(X)
X_new[:5]

 #主成分 解释方差占比
print pca.explained_variance_ratio_
print pca.explained_variance_ 
 #PCA 降维后可视化
pca = PCA(n_components = 2)
pca.fit(X)
X_new = pca.transform(X)
import matplotlib.pyplot as plt
%matplotlib inline
plt.scatter(X_new[:,0],X_new[:,1],mark = 'o',c = y)
plt.show()

4.2线性判别分析(LDA)原理(有监督)

LDA 是一种 监督学习 的线性降维技术,与PCA最大的区别,它需要一个目标类别变量
LDA 思想:投影后类内方差最小,类间方差最大。--能最好的把目标变量的类别区分开
LDA降维后得到的新维度可以继续作用目标变量分类预测的特征

PCA 与 LDA对比
PCA 投影后的目的:整体方差最大(不关心目标变量各类别的区隔,强调整体方差最大化 即显示所有数据)
LDA ----------:类内方差最小,类间方差最大(目标变量各类别区隔明显,强调局部)
PCA 与 LDA总结
    如果研究问题有目标变量(类别型)
        优先使用LDA 降维
        可以先使用PCA做小幅度的降维,消去噪声,然后再使用LDA降维
    如果研究的问题没有目标变量
        优先使用PCA降维
代码:iris数据集
        iris = datasets.load_iris()    #导入iris数据
        X = iris.data
        y = iris.target
        X[:10]
        y[:10]

LDA 降维
    from sklearn.lda import LDA
    lda = LDA(n_components=2)          #定义一个LDA模型
    X_new = lda.fit_transform(X,y)     #fit_transform --可以替代fit 和 transform(X)
    X_new[:5]
    lda.predict(X) #predict(X)
    lda.score(X,y) #score

对比 PCA 与LDA:

from sklearn.decomposition import PCA  #PCA降维后作图
pca = PCA(n_components = 2)
pca.fit(X)
X_new = pca.transform(X)
import matplotlib.pyplot as plt
%matplotlib inline
plt.scatter(X_new[:,0],X_new[:,1],mark = 'o',c = y)
plt.show()
from sklearn.decomposition import LDA

LDA降维后作图
lda = PCA(n_components = 2)
lda.fit(X,y)
X_new = lda.transform(X)

import matplotlib.pyplot as plt
%matplotlib inline
plt.scatter(X_new[:,0],X_new[:,1],mark = 'o',c = y)
plt.show()

五、特征选择–与降维的差异

相同点:效果一样,都是试图减少数据集中的特征数目
不同点:方法不同
        降维:    通过对原特征进行映射后得到新的少量特征,带到降维目的
        特征选择:从原特征中选择出 对模型重要的特征子集,达到降维的目的

特征选择:
        提高预测准确性
        构造更快,消耗更低的预测模型
        能够对模型有更好的理解和解释

特征选择方法
    Filter(过滤)
    Wrapper(封装)
    Embedded(嵌入)

评估变量重要性指标:信息值(权重)

I n f o r m a t i o n V a l u e ( I V ) = i = 1 n ( D i s t r G o o d i D i s t r B a d i ) l n ( D i s t r G o o d i D i s t r B a d i )

若 Distr Good > Distr Bad 权重结果为正,反之为负

变量重要性的可视化:趋势分析(绘制趋势图)

代码:                   (以titanic号数据演练)
    import numpy as np
    import pandas as pd
    def information_value(target,feature):

 # 计算变量的信息值
 # :param target: ndarray,真实值 1=正例,0=负例
 # :param feature: ndarray 离散变量
 # :return

iv_table = pd.DataFrame({'feature':feature,'y':target})
tot_good = np.sum(target)
tot_bad = len(target)-tot_good
iv_table = iv_table.groupby('feature').agg({
'y':{
        'bad_count': lambda x :len(x) - np.sun(x),
        'good_count': np.sum,
    }
})['y']
iv_table['bad_percent'] = iv_table['bad_count']/tot_bad
iv_table['good_percent'] = iv_table['good_count']/tot_good

iv_table['woe'] = np.log(iv_table['bad_count']/iv_table['bad_count'])
iv_table['iv'] = (iv_table['good_percent'] - iv_table['bad_percent']) * iv_table['woe']
iv_value = np.sum(iv_table['iv'])
return iv_value,iv_table[['bad_count','bad_percent','good_percent','good_count','woe','iv']]

titanic = pd.read_csv('./data/transaction.txt')
titanic.head()

feature = titanic.Pclass
target = titanic.Survived

iv_value,iv_table = information_value(target,feature)

print(iv_table)
print('information_value',iv_value)

 #information_value >0.4 就很好了

猜你喜欢

转载自blog.csdn.net/wsp_1138886114/article/details/80459259