机器学习中的特征工程详解

转载请注明出处:http://blog.csdn.net/linxdcn/article/details/80866745


最近看完一本写特征工程的书,概念清晰,内容全面,所以总结如下读书笔记,书名:Feature Engineering Made Easy,可免费试用在线阅读。


1 特征认识(Feature understanding)

  • 结构化数据:可分解为观测记录和属性的数据,如表格数据,行为观测,列为属性
  • 非结构化数据:数据形式随意,不遵循特定规则,如一堆数据(log文件),博客信息,或者只有一个特征的数据
  • 定量数据:有明确数值的数据
  • 定性数据:类别数据
1.1 探索性数据分析(Exploratory data analysis)&描述性分析(Descriptive analysis)

常用的函数有(调用pandas包):head()info()describe()isnull()corr()

1.2 四种数据级别
  • 名义级别(The nominal level):全部为定性数据,不能进行加减乘除数学运算,但可以做计数(count)统计,如血型数据,可采用饼图、直方图可视化
  • 序列级别(The ordinal level):与名义级别基本一致,但数据可自然排序,为类别(category)数据,数学上数据可比较(compare),如大学成绩A、B、C、D,可采用Box-plot可视化
  • 间隔级别(The interval level):除了名义级别和序列级别的特性,间隔级别数据还可进行加减运算,如温度
  • 比例级别(The ratio level):除了上述级别的特性,比例级别可进行乘除运算(拥有0物理含义),如重量,钱,100块是50块的2倍




2 特征改进(Feature improvement)

2.1 缺失值处理
  • 删除缺失值记录:调用pandas包的dropna()
  • (定量数据)填充均值或中值:(pandas包)data.fillna(value),(sklearn包)Imputer().fit_transform(data)
  • (定性数据)填充众数:(pandas包)data.fillna(data.value_counts().index[0])

注意:缺失值的填补应该在划分训练集和测试集之后,即用训练集的某一特征均值代入测试集的缺失值。

2.2 标准化和正态化(Standardization and Normalization)
  • Z-score standardization:\( z=(x-\mu )/\sigma \),sklearn包调用StandardScaler().fit_transform(data)
  • Min-max scaling:\( m=(x-min)/(max-min) \),sklearn包调用MinMaxScaler().fit_transform(data)
  • Row normalization:使每一行数据的L2范数(L2 Norm)\( \left| x \right|=\sqrt{(x_{1}^{2}+x_{2}^{2}+\cdots +x_{n}^{2})} \)一致,sklearn包调用Normalizer().fit_transform(data)

3 特征构建(Feature Construction)

在做数据变换时,sklearn实现了一种名为Pipelines的流水线处理模式,使得在尝试模型参数进行交叉检验时,多个处理步骤可集成一体,在具体可参考官网sklearn.pipeline.Pipeline的说明。以定性数据的缺失值处理为例:

from sklearn.base import TransformerMixin

class CustomCategoryImputer(TransformerMixin):
    def __init__(self, cols=None):
        self.cols = cols

    def transform(self, df):
        X = df.copy()
        for col in self.cols:
            X[col].fillna(X[col].value_counts().index[0], inplace=True)
        return X

    def fit(self, *_):
        return self

cci = CustomCategoryImputer(cols=['col1', 'col2'])
imputer = Pipeline([('category', cci), ('xxx', xxx)]) 
imputer.fit_transform(X)
3.1 类别数据编码(Encoding categorical variables)
  • 名义级别编码:将类别数据转换为哑变量(Dummy Variable),如(性别:男or女)=>(男:0 or 1;女:0 or 1)(注意这个例子中其实(女:0 or 1)为多余的),类似于One-hot编码,在pandas中可调用get_dummies()
  • 序列级别编码:可采用标签编码(Label Encoder),将序列按0~(n-1)编码
  • 数值特征组合:有时也可将数值特征按多项式组合,生成新的特征,可调用sklearn包的PolynomialFeatures()



3.2 文字特征编码

文字特征的处理常采用bag-of-words的方法,基本思想是采用单词出现的频率来表示一段文字,一般都如下三个步骤:

  • 标记(Tokenizing):将一段文字(英文)按标点符号和空格进行分割,获取标记单词
  • 计数(Counting):统计标记出现的频率
  • 标准化(Normalizing):消除文字长度对标记重要性的影响

具体可调用sklearn包的CountVectorizer()CountVectorizer()


4 特征选择

4.1 模型性能评估指标

特征选择的依据是模型性能的好坏,下面首先介绍分类模型的评估指标:

  • 精确率(precision):TP / (TP+FP)
  • 召回率(recall):TP / (TP+FN)
  • 准确率(accuracy,ACC):(TP + TN) / (TP + TN + FP + FN)
  • F1 Score:精准率和召回率的调和均值,2 / F1 = 1 / P + 1 / R



  • True Positive Rate: TPR = TP / (TP+FN) → 将正例分对的概率
  • Fales Positive Rate: FPR = FP / (FP+TN) → 将负例错分为正例的概率
  • ROC曲线:在ROC空间中,每个点的横坐标是FPR,纵坐标是TPR,ROC曲线越靠近左上角,模型越好。ROC曲线有个很好的特性:当测试集中的正负样本的分布变化的时候,ROC曲线能够保持不变,解决类不平衡(class imbalance)的问题
  • AUC:ROC曲线下的面积,AUC越接近1模型越好



对于回归问题的评估指标,常用的有:

  • \( R^2 \)
  • 平均绝对误差MAE(Mean Absolute Error):L1范数损失
  • 平均平方误差MSE(Mean Squared Error):L2范数损失

除此以外,一些其他因素也值得考虑,如:

  • 数据训练时间
  • 数据预测时间
  • 所需的计算机内存等
4.2 特征选择方法

(1)基于概率统计理论的特征选择

  • 根据特征与预测目标的相关性系数挑选
from sklearn.base import TransformerMixin, BaseEstimator
class CustomCorrelationChooser(TransformerMixin, BaseEstimator):
    def __init__(self, response, cols_to_keep=[], threshold=None):
        self.response = response
        self.threshold = threshold
        self.cols_to_keep = cols_to_keep

    def transform(self, X):
        return X[self.cols_to_keep]

    def fit(self, X, *_):
        df = pd.concat([X, self.response], axis=1)
        self.cols_to_keep = df.columns[df.corr()[df.columns[-1]].abs() > self.threshold]
        self.cols_to_keep = [c for c in self.cols_to_keep if c in X.columns]
        return self
  • 采用不同假设检验方法挑选特征,如ANOVA、Chi2检验等
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif
k_best = SelectKBest(f_classif, k=5)
k_best.fit_transform(X, y)
p_values = pd.DataFrame({'column': X.columns, 'p_value': k_best.pvalues_}).sort_values('p_value')
p_values[p_values['p_value'] < .05]

(2)基于机器学习模型的特征选择

一般的,基于概率统计理论的特征选择,在特征数量特别多的时候效果不是很好。

  • 根据决策树一类模型的特征选择
from sklearn.feature_selection import SelectFromModel
select_from_model = SelectFromModel(DecisionTreeClassifier(), threshold=.05)
selected_X = select_from_model.fit_transform(X, y)
  • 根据线性模型的特征选择,如线性回归、逻辑回归、支持向量机等,引入正则项能防止过拟合,提高模型泛化能力
    • L1正则(lasso正则)
    • L2正则(ridge正则)
from sklearn.feature_selection import SelectFromModel
logistic_selector = SelectFromModel(LogisticRegression(penalty=l1), threshold=.05)
selected_X = logistic_selector.fit_transform(X, y)
4.3 特征选择经验
  • 如果大部分特征为类别特征,可采用Chi2检验或者决策树之类的模型进行选择
  • 如果大部分特征为数值特征,可采用线性模型进行选择
  • 如果为二分类问题,采用SelectFromModel()函数和支持向量机模型
  • 有些情况下,也可进行探索性数据分析,手工选择特征,或根据专业知识选择特征

5 特征变换(Feature Transformation)

  • 主成分分析(principal components analysis):sklearn包的PCA
  • 线性判别分析(linear discriminant analysis):sklearn包的LinearDiscriminantAnalysis

PCA是从特征的协方差角度,希望主成分方向携带尽量多的信息量;而LDA则是在已知样本的类标注, 希望投影到新的基后使得不同的类别之间的数据点的距离更大,同一类别的数据点更紧凑。


6 特征学习(Feature Learning)

特征变换和特征学习均数据特征提起范畴,特征变换的PCA和LDA方法只能处理线性变换,且新的特征数量受限于输入特征数量;而特征学习则采用深度学习的方法,可以提取更复杂的特征。

  • 受限玻尔兹曼机(Restricted Boltzmann Machine,RBM):包含两层的神经网络,可见层(visible layer)和隐藏层(hidden layer),可见层神经元数量等于输入的特征数,隐藏层神经元数量等于希望提取的特征数量,sklearn包的BernoulliRBM
6.1 文字特征学习
  • Word2Vec
  • GloVe

转载请注明出处:http://blog.csdn.net/linxdcn/article/details/80866745

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页