特征工程基本概述与简单实践

简介

数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已

好的数据和特征能够让机器学习事半功倍,甚至大大减轻算法的工作。想象一下极端情况,如果用全世界猫狗的照片来训练一个猫狗分类器,他将做到万无一失,反观如果只有几张猫狗照片来训练,甚至都不是猫狗的照片去训练猫狗分类器,那结果必定无法让人满意。手头的数据一般都是有限,但特征是需要我们去提取的,选出好的有意义的特征能够让数据的质量大大提高,达到以百抵千的效果。

实例

三位数的特征

  1. 数字的分布
  2. 三位是否是等差数列
  3. 三位是否一样
  4. 被某数整除

股票的特征

  1. 6和8特别多 (吉利数字)
  2. 4特别多 (不吉利数字)

电话号的特征

  1. 连续号 (有钱人喜欢用)
  2. 炸弹号

内容

概要

  • 特征使用
    • 数据选择
    • 数据的可用性
  • 特征获取
    • 特征来源
    • 特征存储
  • 特征处理
    • 数据清洗
    • 特征预处理
  • 特征监控
    • 现有特征
    • 探寻新的特征

下面详解特征处理环节

数据清洗

数据抽样

从总数据中抽取符合要求的数据集,是一种数据归约的处理方式

  1. 样本要具有代表性
  2. 样本比例要平衡
    • 要分析的是全体男生女生,而总数据里男生女生不平衡,那么我们需要抽取平衡的样本
  3. 可以的情况下尽量使用全量数据

异常值(空值)处理

将异常值丢弃或者修改,以方便后续的建模过程

  1. 识别异常值、重复值
  2. 丢弃或替代异常值
    1. 用平均值、众数替代
    2. 用边界值替代

特征预处理

标注

给自己最终的目的属性进行标注,这个反应我们目的的属性就是我们的标记、标签、label

例子

要预测某个时间是否下雨,那么我们的数据集中是否下雨就是我们的标注

特征选择

剔除掉与标注不相关或者冗余的特征。主要根据数据本身的特征和任务的需求进行选择,并且需要反复迭代,每次特征选择都要使用模型去验证,最后的目的就是为了选出最好的特征,其实就是一种数据归约的处理方式

三个切入思路

  1. 过滤思想
    • 直接评价某个特征与标注的相关性特征,如果相关性特征没有则去掉
  2. 包裹思想
    • 遍历特征子集
    • RFE算法
  3. 嵌入思想
    • 将特征嵌入到一个简单的模型进行分析
    • 比如通过一个线性回归分析特征,其中w系数很小的特征就可以抛弃
    • 如果模型选择不当容易导致重要属性被丢弃
    • 既然这里已经用模型了,为何不直接用这个建模
      • 实际的数据量很大,在真正建模前,我们采用样本先进行特征选择,精简特征,以达到更好的效果

特征变换

根据特征的特性进行一定方式的转换,使其更好的发挥自己的特点

  1. 对指化

    1. 对数据进行对数化和指数化的过程
    2. 比如把很小的数进行指数化,数据与数据间的差距就变大了
    3. 对数化则相反,比如可以把差距很大的收入数据进行对数化,地震的级别也是进行对数化的
  2. 离散化

    离散化的原因

    1. 克服数据缺陷
    2. 某些算法要求输入离散数据
      • 朴素贝叶斯算法
    3. 非线数据映射
      • 比如曲线存在很明显的拐点,离散化后可能比原版更具备特征

    离散化的方法

    1. 等深分箱(数的个数)
    2. 等宽分箱(数的区间)
    3. 自因变量优化
    #%% 等深分箱
    
    lst = [6, 8, 10, 15, 16, 24, 25, 40, 67]
    pd.qcut(lst, q=3, labels=["low", "medium", "high"])
    #%% 等宽分箱
    
    pd.cut(lst, bins=3, labels=["low", "medium", "high"])
    
  3. 归一化

    1. Min-Max法
    2. 对定距数据归一化,使其具备乘除特性
  4. 标准化

    1. Z-score法
    #%% 归一化
    
    from sklearn.preprocessing import MinMaxScaler, StandardScaler
    MinMaxScaler().fit_transform(np.array([1, 4, 10, 15, 21]).reshape([-1, 1]))
    #%% 标准化
    
    StandardScaler().fit_transform(np.array([1, 0, 0, 0, 0, 0, 0, 0]).reshape([-1, 1]))
    
  5. 数值化

    1. 对一些定类、定序数据进行数值化
    2. 把low\medium\high处理成0\1\2
    3. 把定类数据用one-hot-encode处理
  6. 正规化

    1. 直接用在特征上
    2. 用在每个对象的各个特征的表示上,也就是用在行上
    3. 模型的参数上

特征降维

  1. PCA、奇异值分解等线性降维
  2. LDA降维

特征衍生

利用现有的特征进行某些组合生成新的具有含义的特征。直接采集到的特征不一定能提取出全部信息,需要通过特征衍生来发现新的含义

方法

  1. 加减乘除
  2. 求导
  3. 人工归纳
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.preprocessing import Normalizer
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.decomposition import PCA
import seaborn as sns
sns.set_context(font_scale=2)



def hr_preprocessing(sl=False, le=False, npr=False, amh=False, tsc=False, wa=False, pl5=False, dp=False, slr=False, lower_d=True, ld_n=1):
    '''

    :param sl: satisfaction_level false:MinMax true:Standard
    :param le: last_evaluation_level
    :param npr: number_project
    :param amh: average_monthly_hours
    :param tsc: time_spend_company
    :param wa: Work_accident
    :param pl5: promotion_last_5years
    :param dp: department false: Label true: OneHot
    :param slr: salary false: Label true: OneHot
    :param lower_d: 是否降维
    :param ld_n: 保留的维度
    :return:
    '''
    df = pd.read_csv("newHR.csv")
    # 清洗数据
    df = df.dropna(subset=["satisfaction_level", "last_evaluation"])
    df = df[df['satisfaction_level'] <= 1][df["salary"] != "nme"]
    # 得到标注
    label = df['left']
    df = df.drop("left", axis=1)
    # 特征选择
    # 特征处理
    scaler_lst = [sl, le, npr, amh, tsc, wa, pl5]
    column_lst = ['satisfaction_level', 'last_evaluation', 'number_project',\
                  'average_monthly_hours', 'time_spend_company', 'Work_accident',\
                  'promotion_last_5years']
    for i in range(len(scaler_lst)):
        if not scaler_lst[i]:
            df[column_lst[i]] = MinMaxScaler().fit_transform(df[column_lst[i]].values.reshape(-1, 1)).reshape(-1, 1)
        else:
            df[column_lst[i]] = StandardScaler().fit_transform(df[column_lst[i]].values.reshape(-1, 1)).reshape(-1, 1)
    scaler_lst = [slr, dp]
    column_lst = ['salary', 'department']
    for i in range(len(scaler_lst)):
        if not scaler_lst[i]:
            if column_lst[i] == 'salary':
                df[column_lst[i]] = [map_salary(s) for s in df['salary'].values]
            else:
                df[column_lst[i]] = LabelEncoder().fit_transform(df[column_lst[i]])
            df[column_lst[i]] = MinMaxScaler().fit_transform(df[column_lst[i]].values.reshape(-1, 1)).reshape(-1, 1)
        else:
            df = pd.get_dummies(df, columns=[column_lst[i]])
    if lower_d:
        return PCA(n_components=ld_n).fit_transform(df.values), label
    return df, label

d = dict([("low", 0), ("medium", 1), ("high", 2)])
def map_salary(s):
    return d.get(s, 0)


def main():
    print(hr_preprocessing(lower_d=False, ld_n=3))

if __name__ == '__main__':
    main()

你可能感兴趣的:(数据挖掘,特征工程,数据挖掘,数据分析)