特征工程部分内容
-
对于原始数据:
- 首先了解数据明确有多少特征,哪些是连续的,哪些是类别的
- 检查特征是否有缺失,对缺失的特征选择适当的方法进行填充
- 对连续性特征进行标准化, 对类别特征进行one-hot编码
- 将需转换成类别型数据的连续型数据二值化
- 为防止过拟合,选择是否要将数据进行正则化
- 若对数据初探之后效果不佳可以尝试使用多项式方法寻找非线性关系
- 根据实际问题分析是否需要对特征进行相应的函数转换
-
缺失值处理
df_train['Age'].fillna(value=df_train['Age'].mean())
-
数据缩放
#对特征进行缩放 (对数缩放) log_age = df_train['Age'].apply(lambda x:np.log(x)) df_train.loc[:,'log_age'] = log_age #特征最大最小缩放 from sklearn.preprocessing import MinMaxScaler mm_scaler = MinMaxScaler() fare_trans = mm_scaler.fit_transform(df_train[['Fare']]) # MaxAbsScaler 原理与上面的很像,只是数据会被规模化到[-1,1]之间。也就是特征中,所有数据都会除以最大值。这个方法对那些已经中心化均值维0或者稀疏的数据有意义 #特征标准化缩放 #标准化的原因为:若特征的方差过大则会主导目标函数从而使参数估计器无法正确的学习其它特征 #标准化的包含两步: 去均值的中心化(均值变为0); 方差的规模化(方差变为1) 1.第一种实现方法: from sklearn import preprocessing x_scale = preprocessing.scale(x) 2.第二种实现方法: from sklearn.preprocessing import StandardScaler std_scaler = preprocessing.StandardScaler().fit(x) new_x = std_scaler.transform(x) # 该方法可以在训练数据集上做了标准住那换操作后将相同的转换应用到测试集中 #若数据中有许多异常值则使用数据的均值和方差做标准化就不适合,此时可使用robust_scale方法,它能在有异常值的情况下保证稳定性 from sklearn.preprocessing import robust_scale fare_robust_trans = robust_scale(df_train[['Fare','Age']]) #将同一行数据规范化,即将样本在向量空间上的转换,经常被用于分类与聚类中 1. from sklearn.preprocessing import Normalizer normalizer = Normalizer() fare_normal_trans = normalizer.fit_transform(df_train[['Age','Fare']]) fare_normal_trans 2. x_normalized= preprocessing.normalize(x,norm='l2')
-
统计值
# 最大最小值 max_age = df_train['Age'].max() min_age = df_train["Age"].min() # 分位数,极值处理,我们最粗暴的方法就是将前后1%的值抹去 age_quarter_01 = df_train['Age'].quantile(0.01) age_quarter_99 = df_train['Age'].quantile(0.99) # 四则运算 df_train.loc[:,'family_size'] = df_train['SibSp']+df_train['Parch']+1 # 多项式特征生成 from sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures(degree=2) poly_fea = poly.fit_transform(df_train[['SibSp','Parch']])
-
离散化
#等距切分 df_train.loc[:, 'fare_cut'] = pd.cut(df_train['Fare'], 20) # 等频切分 df_train.loc[:,'fare_qcut'] = pd.qcut(df_train['Fare'], 10) #OneHot encoding/独热向量编码 1. embarked_oht = pd.get_dummies(df_train[['Embarked']]) 2. from sklearn import preprocessing enc=preprocessing.OneHotEncoder() enc.fit(x) #fit 来学习编码 enc.transform(x2).toarray() #进行编码
-
tips:
- 基于树的模型不需要归一化,不需要onehot编码
特征选择
-
选择特征的两方面目标
- 特征是否发散 如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么用。
- 特征与目标的相关性 这点比较显见,与目标相关性高的特征,应当优选选择。
-
选择特征的三种方法
-
Filter:按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。
-
移除低方差的特征
-
from sklearn.feature_selection import VarianceThreshold X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]] sel = VarianceThreshold(threshold=(.8 * (1 - .8))) sel.fit_transform(X) 【输出后结果不变,其效果待验证】
-
单变量特征选择
-
对于分类问题可采用
-
卡方检验(检验定性自变量对定性因变量的相关性)
#对样本进行一次chi2测试来选择最佳的两项特征 from sklearn.datasets import load_iris from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 iris = load_iris() X, y = iris.data, iris.target X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
-
f_classif
-
multi_info_classif
-
互信息
-
-
对于回归问题可采用
-
皮尔逊相关系数 (衡量变量之间的线性相关性)
import numpy as np from scipy.stats import pearsonr np.random.seed(0) size = 300 x = np.random.normal(0, 1, size) # pearsonr(x, y)的输入为特征矩阵和目标向量,能够同时计算 相关系数 和p-value. print("Lower noise", pearsonr(x, x + np.random.normal(0, 1, size))) print("Higher noise", pearsonr(x, x + np.random.normal(0, 10, size))) **pearson相关系数是看特征之间的相关性而不是和因变量之间的相关性
-
f_regression
-
multi_info_regression
-
最大信息系数
-
-
-
-
Wrapper:包装法,根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。
-
递归特征消除
-
RFE通过递归减少考察的特征集规模来选择特征。首先,预测模型在原始特征上训练,每个特征指定一个权重。之后,那些拥有最小绝对值权重的特征被踢出特征集。如此往复递归,直至剩余的特征数量达到所需的特征数量。
-
from sklearn.feature_selection import RFE from sklearn.ensemble import RandomForestClassifier from sklearn.datasets import load_iris rf = RandomForestClassifier() iris=load_iris() X,y=iris.data,iris.target rfe = RFE(estimator=rf, n_features_to_select=3) X_rfe = rfe.fit_transform(X,y) X_rfe.shape
-
-
-
Embedded:嵌入法,先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。类似于Filter方法,但是是通过训练来确定特征的优劣。
-
使用SelectFromModel选择特征
-
将特征选择过程融入pipeline
-
基于L1的特征选择
-
-
-
处理不均衡的数据
- 机器学习模型的训练一般要求不同类的样本数量相当,所以需要对不平衡的数据集进行采样,其方法有两类:
-
- 将多数类样本进行随机下采样
- 1.1 交叉验证前进行数据下采样 (random under-sampling)
(交叉验证前即模型训练之前就将原始数据集采样完成,得到的训练集和测试集都受到了采样的影响)
df.Class.value_counts()
undersample_data.Class.value_counts()
之后可以进行相关性分析【相关性分析可以选出对目标变量影响大的特征,从而可以降低特征维度、减小计算代价且能降低过拟合】
sub_sample_corr['Class'].sort_values(ascending=False).head()
sub_sample_corr['Class'].sort_values(ascending=False).tail()
1.2 交叉验证期间进行数据下采样 (nearMiss方法)
(交叉验证期间即在在训练集上下采样并进行训练但验证集和测试集并不受下采样的影响,将训练好的模型用在不进行采样的验证集/测试集上更有说服力)
1.2.1 将原始数据集分割为训练集和测试集
1.2.2将训练集通过5折交叉验证,将训练样本通过NearMiass下采样并对模型训练,将验证集用于模型的评估
- 2. 通过SMOTE算法将少数类样本进行过采样
- SMOTE策略:对每个少数类样本x,通过欧氏距离搜索K个近邻点(少数类样本),由采样倍率从K中选出N个点并在x-N之间插入新值
- SMOTE算法的不足:1)当选取的少数类样本周围都是少数类样本时则合成的新样本可能不会提供太多有用的信息 2)当选取的少数类样本周围都是多数类样本时,这样的样本很可能时噪声点,则合成的样本会与周围多数类样本产生大部分重叠导致分类困难,但SMOTE过采样方法时学术界和工业界广泛使用的策略
- 最后可以通过混淆矩阵分析过采样和欠采样哪种策略比较好
ref:
特征工程(上)【金融风控实战笔记】 - 知乎 (zhihu.com)