专栏首页SAMshareMLK | 特征工程系统化干货笔记+代码了解一下(上)

MLK | 特征工程系统化干货笔记+代码了解一下(上)

? 目录

  • ? 特征理解
  • ? 特征增强
  • ? 特征构建(待更新)
  • ✅ 特征选择(待更新)
  • ? 特征转换(待更新)
  • ? 特征学习(待更新)

大家可以先看下思维导图:

? 01 特征理解

在拿到数据的时候,我们第一步需要做的是理解它,一般我们可以从下面几个角度入手:

(注:本节用到了两个数据集,分别是Salary_Ranges_by_Job_Classification 和 GlobalLandTemperaturesByCity)

1. 区分结构化数据与非结构化数据

如一些以表格形式进行存储的数据,都是结构化数据;而非结构化数据就是一堆数据,类似于文本、报文、日志之类的。

2. 区分定量和定性数据

定量数据:指的是一些数值,用于衡量某件东西的数量; 定性数据:指的是一些类别,用于描述某件东西的性质。

其实区分了定量和定性数据,还可以继续细分下去,分为定类(nominal)、定序(ordinal)、定距(interval)、定比数据(ratio),下面我们分别对这4类数据进行举例说明,加深大家对它们的印象。

1)定类(nominal)

也就是分类,比如:血型(A/B/O/AB型)、性别(男/女)、货币(人民币/美元/日元),而且值得注意的是这些分类之间没有大小可比性。一般画图的话就只能看下分布占比,可以用条形图、饼图来表示。

2)定序(ordinal)

定序相比于定类,也就是多了一个“可排序”的属性,也就是说虽然它们是类别变量,但是它们的变量值之间是存在“大小”之分的。比如:期末绩点(A、B、C、D、E、F)、问卷答案(非常满意、满意、一般、不满意)。可视化方面,和定类一样,不过就是多了一个 箱体图 可以用(因为定序变量可以有中位数)。

3)定距(interval)

定距的话,就是变量值之间可以做加减法计算,也就是可以引入均值、方差之类的名词了,而且能够画的图也多了,包括先前的那些,还包括了直方图。

4)定比(ratio)

定比相比于定距更加严格,不仅仅有定距的所有属性,同时,有一个 绝对零点 的概念,可以做加减乘除运算,比如说某个商品的价格是另一个的2倍。值得注意的是,温度一般不归入定比,而是定距,没有说20度是10度的两倍这种说法。

最后把上面的内容总结一下:

3. 关键代码汇集

以下的代码只是核心片段,完整代码可在公众号(SAMshare)后台输入关键字 特征工程 获取。

1)常见简易画图

# 绘制条形图
salary_ranges['Grade'].value_counts().sort_values(ascending=False).head(10).plot(kind='bar')

# 绘制饼图
salary_ranges['Grade'].value_counts().sort_values(ascending=False).head(5).plot(kind='pie')

# 绘制箱体图
salary_ranges['Union Code'].value_counts().sort_values(ascending=False).head(5).plot(kind='box')

# 绘制直方图
climate['AverageTemperature'].hist()

# 为每个世纪(Century)绘制平均温度的直方图
climate_sub_china['AverageTemperature'].hist(by=climate_sub_china['Century'],
                                            sharex=True,
                                            sharey=True,
                                            figsize=(10, 10),
                                            bins=20)

# 绘制散点图
x = climate_sub_china['year']
y = climate_sub_china['AverageTemperature']

fig, ax = plt.subplots(figsize=(10,5))
ax.scatter(x, y)
plt.show()

2)检查缺失情况

# 移除缺失值
climate.dropna(axis=0, inplace=True)

# 检查缺失个数
climate.isnull().sum()

3)变量类别转换

# 日期转换, 将dt 转换为日期,取年份, 注意map的用法
climate['dt'] = pd.to_datetime(climate['dt'])
climate['year'] = climate['dt'].map(lambda value: value.year)

# 只看中国
climate_sub_china = climate.loc[climate['Country'] == 'China']
climate_sub_china['Century'] = climate_sub_china['year'].map(lambda x:int(x/100 +1))
climate_sub_china.head()

? 02 特征增强

这一步其实就是数据清洗了,虽然上一步中也有涉及到部分清洗工作(比如清除空值、日期转换之类的),但却是分散的,这节重点讲讲数据清洗的一些技巧和实践代码,供大家在实际项目中去使用。

Step1: 进行EDA(Exploratory Data Analysis),思路如下:

(1)首先看看目标占比情况(针对二分类问题,也就是0和1的占比情况),直接 value_counts()就可以解决,看看样本是否失衡。

(2)接着看看有没有空值,直接统计 isnull().sum() 的个数,不过需要注意的是,可能统计出来没有缺失,并不是因为真的没有缺失,而且缺失被人用某个特殊值填充了,一般会用 -9、blank、unknown、0之类的,需要注意⚠️识别,后面需要对缺失进行合理填充。

(2.1)怎么识别缺失值呢?一般可以通过 data.describe() 获取基本的描述性统计,根据均值、标准差、极大极小值等指标,结合变量含义来判断。

(3)再接着看不同类别之间的特征值分布情况,可通过画直方图(数值型变量)和计算变量值占比分布(类别变量)来观察。

(4)观察不同变量之间的相关性情况,可以通过绘制 相关矩阵的热力图 来观察大体情况。

Step2: 处理数据缺失问题

缺失处理的办法有好多种,但最为常用的作者讲到有两种:填充和删除。

而在处理缺失前,我们在上面的小节中识别出来了部分被人工填充的缺失,

需要还原一下:

# 处理被错误填充的缺失值0,还原为 空(单独处理)
pima['serum_insulin'] = pima['serum_insulin'].map(lambda x:x if x !=0 else None)
# 检查变量缺失情况
pima['serum_insulin'].isnull().sum()


# 批量操作 还原缺失值
columns = ['serum_insulin','bmi','plasma_glucose_concentration','diastolic_blood_pressure','triceps_thickness']

for col in columns:
    pima[col].replace([0], [None], inplace=True)

# 检查变量缺失情况
pima.isnull().sum()

1) 删除含有缺失值的行

这里的话比较简单,就是使用 dropna() 来处理即可,同时我们还可以检查下我们到底删除了多少数据量:round(data.shape[0]-data_dropped.shape[0])/float(data.shape[0]) 就可以统计出来了。当然,删除之后,我们还需要看看数据的分布,对比目标占比、特征分布与先前的是否存在明显差异,如果是的话,建议不要使用这种办法。

2) 缺失值合理填充

缺失填充,这里介绍的有均值填充、-9填充、中位数填充。这里会比较简单,我们可以通常都是通过 sklearn的 Pipeline以及 Imputer来实现,下面是一个简单的完整

Demo:

# 使用sklearn的 Pipeline以及 Imputer来实现缺失值填充
from sklearn.pipeline import Pipeline
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import Imputer

# 调参候选
knn_params = {'classify__n_neighbors':[1,2,3,4,5,6]}

# 实例化KNN模型
knn = KNeighborsClassifier()

# 管道设计
mean_impute = Pipeline([('imputer', Imputer(strategy='mean')),
                        ('classify',knn)
                       ])

x = pima.drop('onset_disbetes', axis=1) # 丢弃y
y = pima['onset_disbetes']

# 网格搜索
grid = GridSearchCV(mean_impute, knn_params)
grid.fit(x, y)

# 打印模型效果
print(grid.best_score_, grid.best_params_)
# 0.73177

Step3: 标准化和归一化

经过上面的处理,模型的精度可以达到0.73177,但我们可以继续优化吗?那是肯定的。

我们可以先看看所有特征的分布(特征少的时候可以这么看):

pima_imputed_mean.hist(figsize=(15,15))

从上图中我们可以看出一个问题,那就是每个特征之间的量纲都是不一样的,这对于knn这种基于距离的模型来说是“致命”的bug,因此我们需要进行标准化和归一化处理。

我们重点关注3种方法:

1)Z分数标准化

最为常用的标准化技术,利用了统计学中的z分数思想,也就是将数据转换为均值为0,标准差为1的分布,其在python中的调用方法:

# z分数标准化(单一特征)
from sklearn.preprocessing import StandardScaler
# 实例化方法
scaler = StandardScaler()
glucose_z_score_standarScaler = scaler.fit_transform(pima[['plasma_glucose_concentration']].fillna(-9))
# 可以看看转换之后的均值和标准差是否为0和1
glucose_z_score_standarScaler.mean(), glucose_z_score_standarScaler.std()


# z分数标准化(全部特征)
from sklearn.preprocessing import StandardScaler
# 实例化方法
scaler = StandardScaler()
pima_imputed_mean_scaled = pd.DataFrame(scaler.fit_transform(pima_imputed_mean), columns=pima_columns)
# 看下标准化之后的分布
pima_imputed_mean_scaled.hist(figsize=(15,15), sharex=True)


# 在Pipeline中使用
model = Pipeline([
    ('imputer', Imputer()),
    ('standardize', StandarScaler())
])

2)min-max标准化

min-max标准化和z-score类似,其公式为:(X - Xmin)/(Xmax - Xmin)

在python中的调用方法:

# min-max标准化
from sklearn.preprocessing import MinMaxScaler
# 实例化方法
min_max = MinMaxScaler()
# 使用min-max标准化
pima_min_maxed = pd.DataFrame(min_max.fit_transform(pima.fillna(-9)), columns=pima_columns)

3)行归一化

行归一化针对的是每一行数据,不同于上面的两种方法(针对列),对行进行处理是为了保证每行的向量长度一样(也就是单位范围,unit norm),有L1、L2范数。

在python中的调用方法:

# 行归一化
from sklearn.preprocessing import Normalizer
# 实例化方法
normalize = Normalizer()
# 使用行归一化
pima_normalized = pd.DataFrame(normalize.fit_transform(pima.fillna(-9)), columns=pima_columns)
# 查看矩阵的平均范数(1)
np.sqrt((pima_normalized**2).sum(axis=1)).mean()

本文分享自微信公众号 - SAMshare(gh_8528ce7b7e80),作者:Samshare

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 特征锦囊:怎么把被错误填充的缺失值还原?

    上个小锦囊讲到我们可以对缺失值进行丢弃处理,但是这种操作往往会丢失了很多信息的,很多时候我们都需要先看看缺失的原因,如果有些缺失是正常存在的,我们就不需要进行丢...

    Sam Gor
  • 特征锦囊:常用的统计图在Python里怎么画?

    这里的话我们介绍几种很简单但也很实用的统计图绘制方法,分别有条形图、饼图、箱体图、直方图以及散点图,关于这几种图形的含义这边就不多做解释了。

    Sam Gor
  • BDK | 数据如何进行同步才好呢?

    从上次文章我们知道了最上游的数据采集流程,知道日志数据是如何产生并且传输到我们服务器进行存储的。到了我们的服务器中,会存储在不同的数据库中,数据库是分布在不同系...

    Sam Gor
  • 在Linux上安装Memcached服务

    1.分别把memcached和libevent下载回来,放到 /home/downloads 目录下:

    ken.io
  • 速读原著-TCP/IP(ICMP时间戳请求与应答)

    I C M P时间戳请求允许系统向另一个系统查询当前的时间。返回的建议值是自午夜开始计算的毫秒数,协调的统一时间( Coordinated Universal ...

    cwl_java
  • python3 购物车小程序

    #定义商品列表 List_of_commodities = [ ('Iphone',6888), ('Mac Pro',12888), ('Bike',3000...

    用户2398817
  • 科学瞎想系列之一〇六 NVH那些事(11)

    【部分来自网络如有侵权敬请邮箱联系。欢迎原文转发到朋友圈,未经许可的媒体平台谢绝图片转载,如需转载或合作请邮件联系。

    标准答案
  • (02)Struts2_概述

    qubianzhong
  • 从0开始策划ISO 27001制度文件

    对于ISO 27001,安全从业者都不陌生,它是信息安全体系的重要标准,也是多数企业信息安全建设的依据,甚至是很多大公司服务商选型的准入要求。在构建ISO 27...

    FB客服
  • 1068 万绿丛中一点红 (20 分)

    对于计算机而言,颜色不过是像素点对应的一个 24 位的数值。现给定一幅分辨率为 M×N 的画,要求你找出万绿丛中的一点红,即有独一无二颜色的那个像素点,并且该点...

    可爱见见

扫码关注云+社区

领取腾讯云代金券