本章从商业数据分析和挖掘的角度详细地介绍了特征工程及其使用的响应方法:数据预处理、特征构造、特征抽取以及特征选择。系统性地说明了用于构建分析用的结构化数据的过程。
特征工程分为数据预处理(Data Preprocessing)、特征构造(Feature Construction)、特征抽取(Feature Extraction)和特征选择(Feature Selection)等几个步骤,每个步骤间没有明显的顺序之分,往往需要根据需求反复执行,甚至也没有严格区分的概念边界,例如特征构造可能会与数据预处理使用同样的数据变换技术等等。
其中"display.max_columns"设置了在notebook中显示的最大列数,当显示的数据超过10列时中间的部分数据会使用省略号表示,这仅仅是为了展示方便而已,如果该值被设置为"none",则会显示所有列,超出页面宽度时会出现相应滚动条。
(1)修正
补充正确信息:例如重新导入原始的正确数据。
对照其他信息源:例如使用CRM系统中正确的用户年龄替换手工填报的错误年龄。
视为空值:将数据清空,等待下一步处理。
(2)删除
删除记录。
删除特征。
如果通过删除来处理错误值,那么要保证该处理不会对后续工作造成重要影响,删除的记录过多会影响数据的分布,删除的特征也不能是那些重要的字段。
以下是一个通过业务规则发现错误值的例子。
新的数据集“data”将不包含流量消费大于5000MB的用户。
对于分类变量,可以采用一定的技术手段去识别错误值,因为错误值通常极少出现,因此可以通过对比分类变量各分类水平之间的数量差异去识别。比如对用户状态“state”进行汇总,代码如下。
通过汇总,发现用户状态为“2”和“4”的记录非常少,则这两类数据很有可能是错误的。为了更直观地展现数量差异,可以使用饼图来描述数据:
异常值有时意味着错误,有时不是。无论是否代表错误,异常值都应当被处理。通常可以根据对业务的理解来设置异常值的边界,也可以使用一定的技术手段辅助识别异常值。常用的识别方法包括以下两种。
(1)平均值法:对于正态分布来说,三倍标准差之外的样本仅占所有样本的1%,因此,设置平均值±3×标准差之外的数据为离群值,极端值被定义为平均值±5×标准差之外数据。
(2)四分位数法:设置1.5倍四分位距以外的数据为异常值,即IQR = Q3–Q1,IQR为四分位距,Q3和Q1分别为第三和第一四分位点,定义正常数据在Q1–1.5 ´ IQR ~ Q3 + 1.5 ´ IQR 之间。
例如:绘制月消费额箱线图。
使用盖帽法进行异常值处理的示例如下。
这类数据也可以通过对数转换使其更接近于正态分布,同时消除异常值,由于对数函数的定义域为(0,+∞),而消费额这样的数据往往包括0,因此可以对数据进行加1操作,再进行对数转换,这样的转换可以保证原来为0的数据转换后依然为0,新数据都是非负的,示例代码如下。
可以看到使用scikit-learn中的函数转换可以一次性对多个字段进行处理。
为了更加准确的判断缺失值的数量,可以使用isnull函数,如果数值为空返回True,否则为False,再进行求和(True被作为1,False被作为0),就可以统计每个字段缺失值的数量。同样可以使用notnull函数进行类似分析,其返回结果与isnull相反。示例如下:
缺失值的处理可以非常灵活,比如对“营销次数”的填补可以使用众数填补,也可以填为0(如果缺失是因为在营销数据库中没有该记录造成的则填0)。此外,营销活动通常是对满足一定条件的用户开展的,因此也可以通过建模“预测”该用户“被营销”的次数。
以下是对之前的data数据集按照缺失值数量进行记录删除的一个例子。
这种方法可以指定用于表示缺失的值,strategy参数则指定了填补策略,比如示例中使用的众数,其它策略包括均值、中位数等,具体可参考帮助或文档。
对于示例数据集当中的"IMEI"字段是手机串码(原本为15位),一部移动设备对应一个,是全球唯一的,这样的字段与ID字段一样无法进入模型。通过观察,发现有大量的记录IMEI为空值(现已填补为0),因此可以将有IMEI的设置为1,没有的设置为0。在scikit-learn的preprocessing中,使用Binarizer可以将字段二值化,示例如下:
需要注意的是传入的阈值列表是包含了上下界的,切割的区间为左开右闭,即切割后的两个区间为(-∞,0]和(0,+∞)。如果要切割成多个区域,只需把所有阈值以列表形式传入"bins"参数即可。
为了演示离散化,我们将示例数据集中的“入网时间”转化为“在网时长”:
至此,我们“在网时长”属于连续型特征,我们可以对其进行离散化。
1. 等宽离散
使用Pandas进行等宽离散的例子如下:
该函数使用分位数确定某一列特征的划分区间,再使用pandas.cut将数据按照划分区间进行离散,这里的pandas.cut函数因为指定了区间,将不再按照默认的等宽方式离散了。
使用自定义的函数可以方便地对数据进行等分离散:
从图中,离散化后的离网率规律一目了然。
3. 人工离散
仅需要人工指定区间划分的阈值就可以很容易地使用pandas.cut进行人工离散化,如下例:
图18-1
一般有m个分类水平的变量经过哑编码之后,会生成m个哑变量,各个哑变量之间两两互斥,应用中一般仅保留其中m-1个进入模型,留下1个作为对照组,对照组可以通过其他m-1个哑变量完全还原出来。在使用哑变量建模时,一般需要保证由这m-1个哑变量都能进入模型,或者都不进入模型。
在pandas中可以使用get_dummies函数来对分类变量进行哑编码,新生成的哑变量与原变量的分类水平数相等,对照组可自行选择,get_dummies使用方法如下所示:
另外,scikit-learn的preprocessing当中,可以使用OneHotEncoder对数据进行哑编码,同样会生成与原变量水平数相等的哑变量,代码如下:
同样的样本点,如果流量采用MB为单位,则AB为一个簇,CD为一个簇;如果使用GB为单位,则AC一个簇,BD一个簇。可见因为单位不同对模型的结果会产生颠覆性的影响。
为了消除字段间因为单位差异而导致模型不稳定的情况,需要将变量的单位消除,使得它们都是在一个“标准”的尺度上进行比较分析。因此需要采用标准化的技术,常用的方法包括极值标准化与学生标准化:
极差标准化
学生标准化
使用preprocessing.StandardScaler可以对多个字段一次性进行学生标准化,而且fit之后的转换器std_scaler可以重复使用。比如,使用训练集数据fit的转换器可以对测试集进行相同的转换(使用训练集的均值和标准差进行学生标准化)。
将标准化后的数据添加到数据集当中:
极值标准化的方法也类似:
scikit-learn当中可以使用preprocessing.Normalizer对每一行进行规范化,仅仅是为了演示代码,我们将通信账单数据集的后三列提取出来,使用规范化方法进行转换如下:
可以发现转换后每个行向量都是单位长度,只是具有不同的角度。需要再次强调的是,本例仅为演示代码,因为对行执行规范化后,每列的分布形态会发生改变,因此不适用于本数据集。
欢迎大家关注我的博客:https://home.cnblogs.com/u/sm123456
欢迎大家加入千人交流学习,资源共享群:125240963
希望与广大网友互动??
点此进行留言吧!