一文读懂特征工程特征工程(featureengineering):利用领域知识和现有数据,创造出新的特征,用于机器学习

俗话说:数据与特征工程决定了模型的上限,改进算法只不过是逼近这个上限而已。

importpandasaspdimportnumpyasnpimportseabornassnsdf_titanic=sns.load_dataset('titanic')数据字段描述如下:

1.1区分结构化数据与非结构化数据

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

1.2区分定量和定性数据

目标是提高数据质量,降低算法错误建模的风险。

现实的业务建模过程中,数据常常存在各种问题,数据存在不完全的、有噪声的、不一致的等各种情况。而这些带有错误信息的数据会对模型造成不利的影响。

数据清洗过程包括数据对齐、缺失值处理、异常值处理、数据转化等数据处理。

2.1数据对齐

2)字段:

3)量纲:

主要包括少量缺失的情况下,考虑不处理或删除缺失数据或者采用均值、中位数、众数、同类均值填充。

当缺失值对模型影响比较大,存在比较多的不缺失数据的情况下,可以采用模型预测或者插值的方式。当缺失值过多时,可以对缺失值进行编码操作。

对每个字段都计算其缺失值比例,然后按照缺失比例和字段重要性,分别制定策略,可用下图表示:

空值汇总分布

df_titanic.isnull().sum()survived0pclass0sex0age177sibsp0parch0fare0embarked2class0who0adult_male0deck688embark_town2alive0alone01)删除元组

将存在遗漏信息属性值的对象(元组,记录)删除,从而得到一个完备的信息表。

优点:

简单易行,在对象有多个属性缺失值、被删除的含缺失值的对象与初始数据集的数据量相比非常小的情况下有效;

不足:

当缺失数据所占比例较大,特别当遗漏数据非随机分布时,这种方法可能导致数据发生偏离,从而引出错误的结论。

代码实现

embark_town字段有2个空值,可以考虑删除缺失处理下

df_titanic[df_titanic["embark_town"].isnull()]df_titanic.dropna(axis=0,how='any',subset=['embark_town'],inplace=True)

2)数据填充

用一定的值去填充空值,从而使信息表完备化。通常基于统计学原理,根据初始数据集中其余对象取值的分布情况来对一个缺失值进行填充。

(a)人工填充(fillingmanually)

根据业务知识来进行人工填充。

(b)特殊值填充(TreatingMissingAttributevaluesasSpecialvalues)

将空值作为一种特殊的属性值来处理,它不同于其他的任何属性值。如所有的空值都用“unknown”填充。一般作为临时填充或中间过程。

df_titanic['embark_town'].fillna('unknown',inplace=True)(c)统计量填充

若缺失率较低(小于95%)且重要性较低,则根据数据分布的情况进行填充。

常用填充统计量:

平均值:对于数据符合均匀分布,用该变量的均值填补缺失值。

中位数:对于数据存在倾斜分布的情况,采用中位数填补缺失值。

众数:离散特征可使用众数进行填充缺失值。

fare:缺失值较多,使用中位数填充。

df_titanic['fare'].fillna(df_titanic['fare'].median(),inplace=True)embarked:只有两个缺失值,使用众数填充

df_titanic['embarked'].isnull().sum()执行结果:2df_titanic['embarked'].fillna(df_titanic['embarked'].mode(),inplace=True)df_titanic['embarked'].value_counts()执行结果:S64imputer类提供了缺失数值处理的基本策略,比如使用缺失数值所在行或列的均值、中位数、众数来替代缺失值。该类也兼容不同的缺失值编码。

填补缺失值:sklearn.preprocessing.Imputer(missing_values=’NaN’,strategy=’mean’,axis=0,verbose=0,copy=True)

主要参数说明:

missing_values:缺失值,可以为整数或NaN(缺失值numpy.nan用字符串‘NaN’表示),默认为NaNstrategy:替换策略,字符串,默认用均值‘mean’替换①若为mean时,用特征列的均值替换②若为median时,用特征列的中位数替换③若为most_frequent时,用特征列的众数替换axis:指定轴数,默认axis=0代表列,axis=1代表行copy:设置为True代表不在原数据集上修改,设置为False时,就地修改,存在如下情况时,即使设置为False时,也不会就地修改①X不是浮点值数组②X是稀疏且missing_values=0③axis=0且X为CRS矩阵④axis=1且X为CSC矩阵statistics_属性:axis设置为0时,每个特征的填充值数组,axis=1时,报没有该属性错误

age:根据sex、pclass和who分组,如果落在相同的组别里,就用这个组别的均值或中位数填充。

(d)模型预测填充

使用待填充字段作为Label,没有缺失的数据作为训练数据,建立分类/回归模型,对待填充的缺失字段进行预测并进行填充。

最近距离邻法(KNN)

回归(Regression)

age:缺失量较大,用sex、pclass、who、fare、parch、sibsp六个特征构建随机森林模型,填充年龄缺失值。

df_titanic_age=df_titanic[['age','pclass','sex','who','fare','parch','sibsp']]df_titanic_age=pd.get_dummies(df_titanic_age)df_titanic_age.head()执行结果为age pclass fare parch sibsp sex_female sex_male who_child who_man who_woman0 22.0 3 7.2500 0 1 0 1 0 1 01 38.0 1 71.2833 0 1 1 0 0 0 12 26.0 3 7.9250 0 0 1 0 0 0 13 35.0 1 53.1000 0 1 1 0 0 0 14 35.0 3 8.0500 0 0 0 1 0 1 0#乘客分成已知年龄和未知年龄两部分known_age=df_titanic_age[df_titanic_age.age.notnull()]unknown_age=df_titanic_age[df_titanic_age.age.isnull()]#y即目标年龄y_for_age=known_age['age']#X即特征属性值X_train_for_age=known_age.drop(['age'],axis=1)X_test_for_age=unknown_age.drop(['age'],axis=1)fromsklearn.ensembleimportRandomForestRegressorrfr=RandomForestRegressor(random_state=0,n_estimators=2000,n_jobs=-1)rfr.fit(X_train_for_age,y_for_age)#用得到的模型进行未知年龄结果预测y_pred_age=rfr.predict(X_test_for_age)#用得到的预测结果填补原缺失数据df_titanic.loc[df_titanic.age.isnull(),'age']=y_pred_agesns.distplot(df_titanic.age)

(e)插值法填充

包括随机插值,多重插补法,热平台插补,拉格朗日插值,牛顿插值等。

使用插值法可以计算缺失值的估计值,所谓的插值法就是通过两点(x0,y0),(x1,y1)估计中间点的值,假设y=f(x)是一条直线,通过已知的两点来计算函数f(x),然后只要知道x就能求出y,以此方法来估计缺失值。

.interpolate(method='linear',axis)方法将通过linear插值使用沿着给定axis的值替换NaN值,这个差值也就是前后或者上下的中间值

df_titanic['fare'].interpolate(method='linear',axis=0)同时,也可用行值插入

df_titanic['fare'].interpolate(method='linear',axis=1)代码实现

多重插补方法分为三个步骤:

Step1:为每个空值产生一套可能的插补值,这些值反映了无响应模型的不确定性;

每个值都可以被用来插补数据集中的缺失值,产生若干个完整数据集合;

Step2:每个插补数据集合都用针对完整数据集的统计方法进行统计分析;

Step3:对来自各个插补数据集的结果,根据评分函数进行选择,产生最终的插补值。

(f)哑变量填充

若变量是离散型,且不同值较少,可转换成哑变量,例如性别SEX变量,存在male,fameal,NA三个不同的值,可将该列转换成IS_SEX_MALE、IS_SEX_FEMALE、IS_SEX_NA。若某个变量存在十几个不同的值,可根据每个值的频数,将频数较小的值归为一类’other’,降低维度。此做法可最大化保留变量的信息。

sex_list=['MALE','FEMALE',np.NaN,'FEMALE','FEMALE',np.NaN,'MALE']df=pd.DataFrame({'SEX':sex_list})display(df)df.fillna('NA',inplace=True)df=pd.get_dummies(df['SEX'],prefix='IS_SEX')display(df)#原始数据SEX0MALE1FEMALE2NaN3FEMALE4FEMALE5NaN6MALE#填充后IS_SEX_FEMALEIS_SEX_MALEIS_SEX_NA001011002001310041005001601(g)当特征值缺失超过80%以上,建议删除【或变成是否变量】,容易影响模型效果

df_titanic.drop(["deck"],axis=1)2.3异常处理:

1)异常值识别

sns.catplot(y="fare",x="survived",kind="box",data=df_titanic,palette="Set2");

sns.distplot(df_titanic.age)

(a)基于统计分析

通常用户用某个统计分布对数据点进行建模,再以假定的模型,根据点的分布来确定是否异常。

如通过分析统计数据的散度情况,即数据变异指标,对数据的分布情况有所了解,进而通过数据变异指标来发现数据中的异常点数据。

常用的数据变异指标有极差、四分位数间距、均差、标准差、变异系数等等,如变异指标的值大表示变异大、散布广;值小表示离差小,较密集。

譬如最大最小值可以用来判断这个变量的取值是否超过了合理的范围,如客户的年龄为-20岁或200岁,为异常值。

(b)3σ原则

(c)箱线图分析

箱线图提供了识别异常值的一个标准:如果一个值小于Q1-1.5IQR或大于Q3+1.5IQR的值,则被称为异常值。

Q1为下四分位数,表示全部观察值中有四分之一的数据取值比它小;

Q4为上四分位数,表示全部观察值中有四分之一的数据取值比它大;

IQR为四分位数间距,是上四分位数Q1与下四分位数Q3的差值,包含了全部观察值的一半。

箱型图判断异常值的方法以四分位数和四分位距为基础,四分位数具有鲁棒性:25%的数据可以变得任意远并且不会干扰四分位数,所以异常值不能对这个标准施加影响。因此箱型图识别异常值比较客观,在识别异常值时有一定的优越性。

(d)基于模型检测

首先建立一个数据模型,异常是那些同模型不能完美拟合的对象;如果模型是簇的集合,则异常是不显著属于任何簇的对象;在使用回归模型时,异常是相对远离预测值的对象。

有坚实的统计学理论基础,当存在充分的数据和所用的检验类型的知识时,这些检验可能非常有效。

缺点:

对于多元数据,可用的选择少一些,并且对于高维数据,这些检测可能性很差。

(e)基于距离

基于距离的方法是基于下面这个假设:即若一个数据对象和大多数点距离都很远,那这个对象就是异常。通过定义对象之间的临近性度量,根据距离判断异常对象是否远离其他对象,主要使用的距离度量方法有绝对距离(曼哈顿距离)、欧氏距离和马氏距离等方法。

基于距离的方法比基于统计类方法要简单得多;

因为为一个数据集合定义一个距离的度量要比确定数据集合的分布容易的多。

该方法对参数的选择也是敏感的;

不能处理具有不同密度区域的数据集,因为它使用全局阈值,不能考虑这种密度的变化。

(f)基于密度

考察当前点周围密度,可以发现局部异常点,离群点的局部密度显著低于大部分近邻点,适用于非均匀的数据集。

给出了对象是离群点的定量度量,并且即使数据具有不同的区域也能够很好的处理。

对于低维数据使用特定的数据结构可以达到O(mlogm);

参数选择困难。

虽然算法通过观察不同的k值,取得最大离群点得分来处理该问题,但是,仍然需要选择这些值的上下界。

(g)基于聚类

对象是否被认为是异常点可能依赖于簇的个数(如k很大时的噪声簇)。该问题也没有简单的答案。一种策略是对于不同的簇个数重复该分析。另一种方法是找出大量小簇,其想法是:

较小的簇倾向于更加凝聚;

如果存在大量小簇时一个对象是异常点,则它多半是一个真正的异常点。

不利的一面是一组异常点可能形成小簇而逃避检测。

基于线性和接近线性复杂度(k均值)的聚类技术来发现离群点可能是高度有效的;

簇的定义通常是离群点的补,因此可能同时发现簇和离群点。

缺点:

产生的离群点集和它们的得分可能非常依赖所用的簇的个数和数据中离群点的存在性;

聚类算法产生的簇的质量对该算法产生的离群点的质量影响非常大。

(h)基于邻近度的异常点检测

一个对象是异常的,如果它远离大部分点。这种方法比统计学方法更一般、更容易使用,因为确定数据集的有意义的邻近性度量比确定它的统计分布更容易。一个对象的异常点得分由到它的k-最近邻的距离给定。异常点得分对k的取值高度敏感。如果k太小(例如1),则少量的邻近异常异常点可能导致较异常低的异常点得分;如果K太大,则点数少于k的簇中所有的对象可能都成了异常异常点。为了使该方案对于k的选取更具有鲁棒性,可以使用k个最近邻的平均距离。

简单

总结:

在数据处理阶段将离群点作为影响数据质量的异常点考虑,而不是作为通常所说的异常检测目标点,一般采用较为简单直观的方法,结合箱线图和MAD的统计方法判断变量的离群点。

sns.scatterplot(x="fare",y="age",hue="survived",data=df_titanic,palette="Set1")

2)处理方法

对异常值处理,需要具体情况具体分析,异常值处理的方法常用有四种:

目标是增强数据表达,添加先验知识。

如果我们对变量进行处理之后,效果仍不是非常理想,就需要进行特征构建了,也就是衍生新变量。

指根据业务经验或者常识等自行设定划分的区间,然后将原始数据归类到各个区间中。

(b)等距分箱

按照相同宽度将数据分成几等份。

从最小值到最大值之间,均分为N等份,这样,如果A,B为最小最大值,则每个区间的长度为W=(BA)/N,则区间边界值为A+W,A+2W,….A+(N1)W。这里只考虑边界,每个等份里面的实例数量可能不等。

缺点是受到异常值的影响比较大

(c)等频分箱

将数据分成几等份,每等份数据里面的个数是一样的。

区间的边界值要经过选择,使得每个区间包含大致相等的实例数量。比如说N=10,每个区间应该包含大约10%的实例。

2.计算出KS最大的那个值,即为切点,记为D。然后把数据切分成两部分。

3.重复步骤2,进行递归,D左右的数据进一步切割。直到KS的箱体数达到我们的预设阈值即可。

5.分箱过程中,决定分箱后的KS值是某一个切点,而不是多个切点的共同作用。这个切点的位置是原始KS值最大的位置。

注:代码实现请从网上查阅

3)卡方分桶

自底向上的(即基于合并的)数据离散化方法。它依赖于卡方检验:具有最小卡方值的相邻区间合并在一起,直到满足确定的停止准则。

基本思想

对于精确的离散化,相对类频率在一个区间内应当完全一致。因此,如果两个相邻的区间具有非常类似的类分布,则这两个区间可以合并;否则,它们应当保持分开。而低卡方值表明它们具有相似的类分布。

实现步骤

Step1:预先定义一个卡方的阈值;

Step2:初始化;根据要离散的属性对实例进行排序,每个实例属于一个区间;

Step3:合并区间;

计算每一对相邻区间的卡方值;

将卡方值最小的一对区间合并;

Aij:第i区间第j类的实例的数量;Eij:Aij的期望频率(=(Ni*Cj)/N),N是总样本数,Ni是第i组的样本数,Cj是第j类样本在全体中的比例;

阈值的意义

类别和属性独立时,有90%的可能性,计算得到的卡方值会小于4.6。大于阈值4.6的卡方值就说明属性和类不是相互独立的,不能合并。如果阈值选的大,区间合并就会进行很多次,离散后的区间数量少、区间大。

注意

ChiMerge算法推荐使用0.90、0.95、0.99置信度,最大区间数取10到15之间;也可以不考虑卡方阈值,此时可以考虑最小区间数或者最大区间数。指定区间数量的上限和下限,最多几个区间,最少几个区间;对于类别型变量,需要分箱时需要按照某种方式进行排序。

需要使总熵值达到最小,也就是使分箱能够最大限度地区分因变量的各类别。

熵是信息论中数据无序程度的度量标准,提出信息熵的基本目的是找出某种符号系统的信息量和冗余度之间的关系,以便能用最小的成本和消耗来实现最高效率的数据存储、管理和传递。

数据集的熵越低,说明数据之间的差异越小,最小熵划分就是为了使每箱中的数据具有最好的相似性。给定箱的个数,如果考虑所有可能的分箱情况,最小熵方法得到的箱应该是具有最小熵的分箱。

注:有限考虑强特征维度

1)离散+离散:笛卡尔积

2)离散+连续:连续特征分桶后进行笛卡尔积或基于类别特征groupby,类似于聚类特征构造

3)连续+连续:加减乘除,二阶差分等

df_titanic_numerical=df_titanic[['age','sibsp','parch','fare','family_size']]df_titanic_numerical.head()执行结果:age sibsp parch fare family_size0 22.0 1 0 7.2500 21 38.0 1 0 71.2833 22 26.0 0 0 7.9250 13 35.0 1 0 53.1000 24 35.0 0 0 8.0500 1#扩展数值特征fromsklearn.preprocessingimportPolynomialFeaturespoly=PolynomialFeatures(degree=2,include_bias=False,interaction_only=False)df_titanic_numerical_poly=poly.fit_transform(df_titanic_numerical)pd.DataFrame(df_titanic_numerical_poly,columns=poly.get_feature_names()).hea

sns.heatmap(pd.DataFrame(df_titanic_numerical_poly,columns=poly.get_feature_names()).corr())

目标是降低噪声,平滑预测能力和计算复杂度,增强模型预测性能

当数据预处理完成后,我们需要选择有意义的特征输入机器学习的算法和模型进行训练。

通常来说,从两个方面考虑来选择特征:

根据特征选择的形式又可以将特征选择方法分为3种:

1)方差过滤

这是通过特征本身的方差来筛选特征的类。比如一个特征本身的方差很小,就表示样本在这个特征上基本没有差异,可能特征中的大多数值都一样,甚至整个特征的取值都相同,那这个特征对于样本区分没有什么作用。所以无论接下来的特征工程要做什么,都要优先消除方差为0的特征。VarianceThreshold有重要参数threshold,表示方差的阈值,表示舍弃所有方差小于threshold的特征,不填默认为0,即删除所有的记录都相同的特征。

比如说,我们希望留下一半的特征,那可以设定一个让特征总数减半的方差阈值,只要找到特征方差的中位数,再将这个中位数作为参数threshold的值输入就好了:

df_titanic_numerical_fsvar=VarianceThreshold(np.median(df_titanic_numerical.var().values)).fit_transform(df_titanic_numerical)当特征是二分类时,特征的取值就是伯努利随机变,假设p=0.8,即二分类特征中某种分类占到80%以上的时候删除特征

X_bvar=VarianceThreshold(.8*(1-.8)).fit_transform(df_titanic_numerical)X_bvar.shape执行结果:(891,5)2)卡方过滤

卡方检验类feature_selection.chi2计算每个非负特征和标签之间的卡方统计量,并依照卡方统计量由高到低为特征排名

df_titanic_categorical=df_titanic[['sex','class','embarked','who','age_bin','adult_male','alone','fare_bin']]df_titanic_numerical=df_titanic[['age','sibsp','parch','fare','family_size','pclass']]df_titanic_categorical_one_hot=pd.get_dummies(df_titanic_categorical,columns=['sex','class','embarked','who','age_bin','adult_male','alone','fare_bin'],drop_first=True)df_titanic_combined=pd.concat([df_titanic_numerical,df_titanic_categorical_one_hot],axis=1)y=df_titanic['survived']X=df_titanic_combined.iloc[:,1:]fromsklearn.feature_selectionimportchi2fromsklearn.feature_selectionimportSelectKBestchi_value,p_value=chi2(X,y)#根据p值,得出k值k=chi_value.shape[0]-(p_value>0.05).sum()#要保留的特征的数量14#根据卡方值,选择前几特征,筛选后特征X_chi=SelectKBest(chi2,k=14).fit_transform(X,y)X_chi.shape(893)F检验

F检验,又称ANOVA,方差齐性检验,是用来捕捉每个特征与标签之间的线性关系的过滤方法。它即可以做回归也可以做分类,因此包含feature_selection.f_classif(F检验分类)和feature_selection.f_regression(F检验回归)两个类。其中F检验分类用于标签是离散型变量的数据,而F检验回归用于标签是连续型变量的数据。

F检验的本质是寻找两组数据之间的线性关系,其原假设是”数据不存在显著的线性关系“。

fromsklearn.feature_selectionimportf_classiff_value,p_value=f_classif(X,y)#根据p值,得出k值k=f_value.shape[0]-(p_value>0.05).sum()#筛选后特征X_classif=SelectKBest(f_classif,k=14).fit_transform(X,y)4)互信息法

互信息法是用来捕捉每个特征与标签之间的任意关系(包括线性和非线性关系)的过滤方法。和F检验相似,它既可以做回归也可以做分类,并且包含两个类:

feature_selection.mutual_info_classif(互信息分类)feature_selection.mutual_info_regression(互信息回归)

递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练。使用feature_selection库的RFE类来选择特征的代码如下:

fromsklearn.feature_selectionimportRFEfromsklearn.linear_modelimportLogisticRegression#递归特征消除法,返回特征选择后的数据#参数estimator为基模型#参数n_features_to_select为选择的特征个数X_ref=RFE(estimator=LogisticRegression(),n_features_to_select=10).fit_transform(X,y)2)重要性评估

fromsklearn.ensembleimportExtraTreesClassifier#featureextractionmodel=ExtraTreesClassifier()model.fit(X,y)print(model.feature_importances_)feature=list(zip(X.columns,model.feature_importances_))feature=pd.DataFrame(feature,columns=['feature','importances'])feature.sort_values(by='importances',ascending=False).head(20)feature importances2 fare 0.22765915 adult_male_True 0.13000010 who_man 0.1089395 sex_male 0.07806511 who_woman 0.0590907 class_Third 0.0557554 pclass 0.0487333 family_size 0.0383470 sibsp 0.0354899 embarked_S 0.0295121 parch 0.02377820 fare_bin_(39.688,512.329] 0.02298514 age_bin_young 0.02140412 age_bin_midlife 0.0193796 class_Second 0.01930117 fare_bin_(7.854,10.5] 0.01644819 fare_bin_(21.679,39.688] 0.01600618 fare_bin_(10.5,21.679] 0.01487116 alone_True 0.01309313 age_bin_old 0.01123)排列重要性评估

**优点:**快速计算;易于使用和理解;特征重要性度量的属性;追求特征稳定性

**原理:**在训练机器学习模型之后计算置换重要性。这种方法在向模型提出假设,如果在保留目标和所有其他列的同时随机打乱一列验证集特征数据,对预测机器学习模型的准确性的影响程度。对于一个具有高度重要性的特征,random-reshuffle会对机器学习模型预测的准确性造成更大的损害。

**结果解读:**每一行的第一个数字表示模型性能(例子中用的是准确率)衰减了多少,±后面的数字表示多次打乱的标准差。

importnumpyasnpimportpandasaspdfromsklearn.model_selectionimporttrain_test_splitfromsklearn.ensembleimportRandomForestClassifierimporteli5fromeli5.sklearnimportPermutationImportancemy_model=RandomForestClassifier(random_state=0).fit(train_X,train_y)perm=PermutationImportance(my_model,random_state=1).fit(val_X,val_y)eli5.show_weights(perm,feature_names=val_X.columns.tolist())

1)基于惩罚项的特征选择法

使用带惩罚项的基模型,除了筛选出特征外,同时也进行了降维。

使用feature_selection库的SelectFromModel类结合带L1惩罚项的逻辑回归模型,来选择特征的代码如下:

fromsklearn.feature_selectionimportSelectFromModelfromsklearn.linear_modelimportLogisticRegression#带L1和L2惩罚项的逻辑回归作为基模型的特征选择,这个设置带L1惩罚项的逻辑回归作为基模型的特征选择lr=LogisticRegression(solver='liblinear',penalty="l1",C=0.1)X_sfm=SelectFromModel(lr).fit_transform(X,y)X_sfm.shape(891,7使用feature_selection库的SelectFromModel类结合SVM模型,来选择特征的代码如下:

fromsklearn.feature_selectionimportSelectFromModelfromsklearn.svmimportLinearSVClsvc=LinearSVC(C=0.01,penalty='l1',dual=False).fit(X,y)model=SelectFromModel(lsvc,prefit=True)X_sfm_svm=model.transform(X)X_sfm_svm.shape(891,72)基于树模型

树模型中GBDT也可用来作为基模型进行特征选择,使用feature_selection库的SelectFromModel类结合GBDT模型,来选择特征的代码如下:

fromsklearn.feature_selectionimportSelectFromModelfromsklearn.ensembleimportGradientBoostingClassifier#GBDT作为基模型的特征选择gbdt=GradientBoostingClassifier()X_sfm_gbdt=SelectFromModel(gbdt).fit_transform(X,y)X_sfm_gbdt.shape(891,5)总结一下,有几点做特征选择的方法经验:

(1)如果特征是分类变量,那么可以从SelectKBest开始,用卡方或者基于树的选择器来选择变量;

(3)如果是二分类问题,可以考虑使用SelectFromModel和SVC;

(4)在进行特征选择前,还是需要做一下EDA。

转换为Z-score,使数值特征列的算数平均为0,方差(以及标准差)为1。不免疫outlier。

注:如果数值特征列中存在数值极大或极小的outlier(通过EDA发现),应该使用更稳健(robust)的统计数据:用中位数而不是算术平均数,用分位数(quantile)而不是方差。这种标准化方法有一个重要的参数:(分位数下限,分位数上限),最好通过EDA的数据可视化确定。免疫outlier。

fromsklearn.preprocessingimportStandardScale#标准化模型训练Stan_scaler=StandardScaler()Stan_scaler.fit(x)x_zscore=Stan_scaler.transform(x)x_test_zscore=Stan_scaler.transform(x_test)joblib.dump(Stan_scaler,'zscore.m')#写入文件2)归一化(Normalization)把每一行数据归一化,使之有unitnorm,norm的种类可以选l1、l2或max。不免疫outlier。

,其中\iota表示norm函数。

将一列的数值,除以这一列的最大绝对值。

MinMaxScaler:线性映射到[0,1],不免疫outlier。

MaxAbsScaler:线性映射到[-1,1],不免疫outlier。

fromsklearnimportpreprocessingmin_max_scaler=preprocessing.MinMaxScaler()min_max_scaler.fit_transform(x)x_minmax=min_max_scaler.transform(x)x_test_minmax=min_max_scaler.transform(x_test)joblib.dump(min_max_scaler,'min_max_scaler.m')#写入文件注:如果数值特征列中存在数值极大或极小的outlier(通过EDA发现),应该使用更稳健(robust)的统计数据:用中位数而不是算术平均数,用分位数(quantile)而不是方差。这种标准化方法有一个重要的参数:(分位数下限,分位数上限),最好通过EDA的数据可视化确定。免疫outlier。

归一化与标准化区别

(a)目的不同,归一化是为了消除纲量压缩到[0,1]区间;标准化只是调整特征整体的分布。(b)归一化与最大,最小值有关;标准化与均值,标准差有关。(c)归一化输出在[0,1]之间;标准化无限制。

归一化与标准化应用场景

(a)在分类、聚类算法中,需要使用距离来度量相似性的时候(如SVM、KNN)或者使用PCA技术进行降维的时候,标准化(Z-scorestandardization)表现更好。(b)在不涉及距离度量、协方差计算、数据不符合正太分布的时候,可以使用第一种方法或其他归一化方法。比如图像处理中,将RGB图像转换为灰度图像后将其值限定在[0255]的范围。(c)基于树的方法不需要进行特征的归一化。例如随机森林,bagging与boosting等方法。如果是基于参数的模型或者基于距离的模型,因为需要对参数或者距离进行计算,都需要进行归一化。

利用统计或数学变换来减轻数据分布倾斜的影响。使原本密集的区间的值尽可能的分散,原本分散的区间的值尽量的聚合。

这些变换函数都属于幂变换函数簇,通常用来创建单调的数据变换。它们的主要作用在于它能帮助稳定方差,始终保持分布接近于正态分布并使得数据与分布的平均值无关。

log变换通常用来创建单调的数据变换。它的主要作用在于帮助稳定方差,始终保持分布接近于正态分布并使得数据与分布的平均值无关。因为log变换倾向于拉伸那些落在较低的幅度范围内自变量值的范围,倾向于压缩或减少更高幅度范围内的自变量值的范围。从而使得倾斜分布尽可能的接近正态分布。所以针对一些数值连续特征的方差不稳定,特征值重尾分布我们需要采用log化来调整整个数据分布的方差,属于方差稳定型数据转换。

log变换属于幂变换函数簇。该函数用数学表达式表示为

自然对数使用b=e,e=2.71828,通常叫作欧拉常数。你可以使用通常在十进制系统中使用的b=10作为底数。

sns.distplot(df_titanic.fare,kde=False)

df_titanic['fare_log']=np.log((1+df_titanic['fare']))sns.distplot(df_titanic.fare_log,kde=False)

box-cox变换是另一个流行的幂变换函数簇中的一个函数。该函数有一个前提条件,即数值型值必须先变换为正数(与log变换所要求的一样)。万一出现数值是负的,使用一个常数对数值进行偏移是有帮助的。

box-cox变换函数:

生成的变换后的输出y是输入x和变换参数的函数;当λ=0时,该变换就是自然对数log变换,前面我们已经提到过了。λ的最佳取值通常由最大似然或最大对数似然确定。

LabelEncoder是对不连续的数字或者文本进行编号,编码值介于0和n_classes-1之间的标签。

例如:比如有[dog,cat,dog,mouse,cat],我们把其转换为[1,2,1,3,2]。这里就产生了一个奇怪的现象:dog和mouse的平均值是cat。

优点:相对于OneHot编码,LabelEncoder编码占用内存空间小,并且支持文本特征编码。

缺点:它隐含了一个假设:不同的类别之间,存在一种顺序关系。在具体的代码实现里,LabelEncoder会对定性特征列中的所有独特数据进行一次排序,从而得出从原始输入到整数的映射。所以目前还没有发现标签编码的广泛使用,一般在树模型中可以使用。

fromsklearn.preprocessingimportLabelEncoderle=LabelEncoder()le.fit(["超一线","一线","二线","三线"])print('特征:{}'.format(list(le.classes_)))#输出特征:['一线','三线','二线','超一线']print('转换标签值:{}'.format(le.transform(["超一线","一线","二线"])))#输出转换标签值:array([302]...)print('特征标签值反转:{}'.format(list(le.inverse_transform([2,2,1]))))#输出特征标签值反转:['二线','二线','三线2)独热编码(onehotencoder)OneHotEncoder用于将表示分类的数据扩维。最简单的理解用N位状态寄存器编码N个状态,每个状态都有独立的寄存器位,且这些寄存器位中只有一位有效,只能有一个状态。

为什么要使用独热编码?

独热编码是因为大部分算法是基于向量空间中的度量来进行计算的,为了使非偏序关系的变量取值不具有偏序性,并且到圆点是等距的。使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。将离散型特征使用one-hot编码,会让特征之间的距离计算更加合理。

为什么特征向量要映射到欧式空间?

将离散特征通过one-hot编码映射到欧式空间,是因为在回归、分类、聚类等机器学习算法中,特征之间距离或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算。

举个例子-假如有三种颜色特征:红、黄、蓝。

所以这时标签编码是不够的,需要进一步转换。因为有三种颜色状态,所以就有3个比特。即红色:100,黄色:010,蓝色:001。如此一来每两个向量之间的距离都是根号2,在向量空间距离都相等,所以这样不会出现偏序性,基本不会影响基于向量空间度量算法的效果。

优点:独热编码解决了分类器不好处理属性数据的问题,在一定程度上也起到了扩充特征的作用。它的值只有0和1,不同的类型存储在垂直的空间。

缺点:只能对数值型变量二值化,无法直接对字符串型的类别变量编码。当类别的数量很多时,特征空间会变得非常大。在这种情况下,一般可以用PCA来减少维度。而且onehotencoding+PCA这种组合在实际中也非常有用。

sex_list=['MALE','FEMALE',np.NaN,'FEMALE','FEMALE',np.NaN,'MALE']df=pd.DataFrame({'SEX':sex_list})display(df)df.fillna('NA',inplace=True)df=pd.get_dummies(df['SEX'],prefix='IS_SEX')display(df)#原始数据SEX0MALE1FEMALE2NaN3FEMALE4FEMALE5NaN6MALE#填充后IS_SEX_FEMALEIS_SEX_MALEIS_SEX_NA001011002001310041005001pd.get_dummies(df_titanic,columns=['sex','class','pclass','embarked','who','family_size','age_bin'],drop_first=True)

注:当特征是字符串类型时,需要先用LabelEncoder()转换成连续的数值型变量,再用OneHotEncoder()二值化sklearn.preprocessing中的OneHotEncoder将shape=(None,1)的列向量中每个分量表示的下标(index)编码成onehot行向量。importnumpyasnpfromsklearn.preprocessingimportOneHotEncoder行向量转列向量:#非负整数表示的标签列表labels=[0,1,0,2]#行向量转列向量labels=np.array(labels).reshape(len(labels),-1)onehot编码:enc=OneHotEncoder()enc.fit(labels)targets=enc.transform(labels).toarray()#如果不加toarray()的话,输出的是稀疏的存储格式,即索引加值的形式,也可以通过参数指定sparse=False来达到同样的效果编码结果:array([[1.,0.,0.],[0.,1.,0.],[1.,0.,0.],[0.,0.,1.]])3)标签二值化(LabelBinarizer)功能与OneHotEncoder一样,但是OneHotEncoder只能对数值型变量二值化,无法直接对字符串型的类别变量编码,而LabelBinarizer可以直接对字符型变量二值化。

fromsklearnimportdatasetsiris_data=datasets.load_iris()X=iris_data.datay=iris_data.targetdefdraw_result(X,y):"""X:降维后的数据iris:原数据"""plt.figure()#提取Iris-setosasetosa=X[y==0]#绘制点:参数1x向量,y向量plt.scatter(setosa[:,0],setosa[:,1],color="red",label="Iris-setosa")#Iris-versicolorversicolor=X[y==1]plt.scatter(versicolor[:,0],versicolor[:,1],color="orange",label="Iris-versicolor")#Iris-virginicavirginica=X[y==2]plt.scatter(virginica[:,0],virginica[:,1],color="blue",label="Iris-virginica")plt.legend()plt.show()draw_result(X,y

作用:降维、压缩

步骤:

(a)手动实现PCA

classPCA:def__init__(self,dimension,train_x):#降维后的维度self.dimension=dimension#原始数据集self.train_x=train_x@propertydefresult(self):'返回降维后的矩阵'#1.数据中心化data_centering=self.train_x-np.mean(self.train_x,axis=0)#2.计算协方差矩阵cov_matrix=np.cov(data_centering,rowvar=False)#3.特征值分解eigen_val,eigen_vec=np.linalg.eig(cov_matrix)#4.生成降维后的数据p=eigen_vec[:,0:self.dimension]#取特征向量矩阵的前k维returnnp.dot(data_centering,p)调用方法:pca=PCA(2,X)iris_2d=pca.resultdraw_result(iris_2d,y

(b)sklearn的PCA

importnumpyasnpfromsklearn.decompositionimportPCApca=PCA(n_components=2)newX=pca.fit_transform(X)draw_result(newX,y)

作用:特征分解、降维

(a)手动实现SVD

classSVD:def__init__(self,dimension,train_x):self.dimension=dimensionself.train_x=train_x@propertydefresult(self):'返回降维后的矩阵'data_centering=self.train_x-np.mean(self.train_x,axis=0)#SVDU,Sigma,VT=np.linalg.svd(data_centering)returnnp.dot(data_centering,np.transpose(VT)[:,:self.dimension])调用方法:svd=SVD(2,X)iris_svd=svd.resultdraw_result(iris_svd,y)

(b)sklearn的SVD

TruncatedSVD,截断奇异值分解(当数据量非常大,svd跑不出来时使用此方法)。

fromsklearn.decompositionimportTruncatedSVDiris_2d=TruncatedSVD(2).fit_transform(X)draw_result(iris_2d,y)

是有监督的降维,通过最小化类内离散度与最大化类间离散度来获得最优特征子集。

LD1通过线性判定,可以很好的将呈正态分布的两个类分开。LD2的线性判定保持了数据集的较大方差,但LD2无法提供关于类别的信息,因此LD2不是一个好的线性判定。

fromsklearn.discriminant_analysisimportLinearDiscriminantAnalysisasLDAlda=LDA(n_components=2)iris_2d=lda.fit_transform(X,y)draw_result(iris_2d,y)

LDA与PCA相似:

PCA试图寻找到方差最大的正交的主成分分量轴LDA发现可以最优化分类的特征子空间LDA和PCA都是可用于降低数据集维度的线性转换技巧PCA是无监督算法LDA是监督算法LDA是一种更优越的用于分类的特征提取技术

fromsklearn.manifoldimportTSNEtsne=TSNE(n_components=2)iris_2d=tsne.fit_transform(X)draw_result(iris_2d,y)

切忌:一开始就把所有的特征一股脑地扔进模型,容易被一些没用的特征误导。

1)EDA

plot,plot,plot,重要的事情说三遍

2)特征预处理

连续特征离散化(决策树类型的模型没意义):一种挺有趣的变种,就是限制浮点数特征的精度,异常数据有很强的鲁棒性,模型也会更稳定。

clipping:可以用pandasdataframe的.clip(low,upper)方法,把特征值的取值限制在一定范围内

3)数据清洗

要合情合理,不可盲目填充缺失值、删除异常值,要建立在统计科学基础上。

4)特征变换

除非万不得已,不要用PCA或者LDA降维,建议直接减原始特征。

任何针对单独特征列的单调变换(如对数):不适用于决策树类算法。

对于决策树而言,X、X^3、X^5之间没有差异,|X|、X^2、X^4之间没有差异,除非发生了舍入误差。

用N1和N2表示数值特征,用C1和C2表示类别特征,利用pandas的groupby操作,可以创造出以下几种有意义的新特征:(其中,C2还可以是离散化了的N1)

median(N1)_by(C1)\\中位数mean(N1)_by(C1)\\算术平均数mode(N1)_by(C1)\\众数min(N1)_by(C1)\\最小值max(N1)_by(C1)\\最大值std(N1)_by(C1)\\标准差var(N1)_by(C1)\\方差freq(C2)_by(C1)\\频数仅仅将已有的类别和数值特征进行以上的有效组合,就能够大量增加优秀的可用特征。

将这种方法和线性组合等基础特征工程方法结合(仅用于决策树),可以得到更多有意义的特征,如:

N1-median(N1)_by(C1)N1-mean(N1)_by(C1)基于geneticprogramming的symbolicregression【python环境下首推基因编程库为gplearn】。

基因编程的两大用法:

spearman多用于决策树(免疫单特征单调变换),pearson多用于线性回归等其他算法。

回归(regression):原理同上,只不过直接用于回归而已。

在决策树系列的算法中(单棵决策树、gbdt、随机森林),每一个样本都会被映射到决策树的一片叶子上。因此,我们可以把样本经过每一棵决策树映射后的index(自然数)或one-hot-vector(哑编码得到的稀疏矢量)作为一项新的特征,加入到模型中。

具体实现:apply()以及decision_path()方法,在scikit-learn和xgboost里都可以用。

5)模型

对特征数值幅度不敏感,可以不进行无量纲化和统计变换处理;由于数模型依赖于样本距离来进行学习,可以不进行类别特征编码(但字符型特征不能直接作为输入,所以需要至少要进行标签编码)。LightGBM和XGBoost都能将NaN作为数据的一部分进行学习,所以不需要处理缺失值。其他情况下,我们需要使用。

对于数值型特征需要进行无量纲化处理;对于一些长尾分布的数据特征,可以做统计变换,使得模型能更好优化;对于线性模型,特征分箱可以提升模型表达能力;

光喻:【持续更新】机器学习特征工程实用技巧大全zhuanlan.zhihu.com

THE END
1.数据分析及应用试题库及答案.pdf数据分析及应用试题库及答案 、单选题(共50题,每题1分,共50分) l、用顺序查找法对具有n个结点的线性表查找一个结点的时间复杂度为 () A、AO(log2n2) B、BO(nlog2n) C、CO(n) D、DO(log2n) 正确答案:C 2、a=np.array([10,100])b=np.array([1,2])print https://max.book118.com/html/2024/0922/8064045143006127.shtm
2.第四学期智能数据分析期末复习题1、在线性降维方法中,PCA 主成分分析和现行判别分析对于全局线性结构的数据具有很好的降维效果。 2、主成分分析是一种线性降维方法。 3、与在线分析处理不同,传统的数据库在线事务处理是事件驱动、面向应用的。 4、企业的数据处理大致分为两类,一类是事务型操作型处理,另一类是历史数据分析型处理。 https://blog.csdn.net/Abraxs/article/details/144297526
3.第三单元数据处理与应用测试题1、以下关于数据处理的叙述,错误的是() A.数据处理过程中,数据源会影响数据质量的真实性B.数据处理的基本目的是从大量的、杂乱无章的、难以理解的数据中抽取并推导出对于某些特定的人们来说是有价值、有意义的数据C.数据处理是对数据的获取、存储、加工、表达和传输D.大数据可以不需要处理直接使用 https://www.wjx.cn/xz/164844968.aspx
4.下列数据不属于非结构化数据的是大学职业搜题刷题APP 下载APP首页 课程 题库模板 题库创建教程 创建题库 登录 创建自己的小题库 搜索 【单选题】下列数据不属于非结构化数据的是 A. 网络日志 B. 音频 C. 关系数据库的二维表 D. 微信 题目标签:属于结构数据如何将EXCEL生成题库手机刷题 https://www.shuashuati.com/ti/74fe05e1b7a643a895268cb6dae237a3.html
5.阿里云大数据ACA和ACP题库B:是一个用来处理结构化数据的Spark组件 C:基于内存多语言执行的核心引擎 D:Spark机器学习库 解析:Spark的MLlib提供了较丰富的机器学习库,包括分类、回归、协同过滤、聚合,同时提供了模型选择、自动调参和交叉验证等工具来提高生产力。MLlib主要支持非深度学习的算法模块https://help.aliyun.com/document_detail/4419https://developer.aliyun.com/article/1393816
6.非结构化数据提取技术在统计工作中的应用摘要结构化数据和非结构化数据是大数据的两种类型,目前非结构化数据信息已达信息总量的85%以上,且每年以55%~65%的速度增长,统计工作受到大数据的冲击,日常总会遇到一些非结构化数据提取的难题,导致工作量加大,效率低下。本文对非结构化数据及其提取技术、大数据处理语言——Python语言进行学习研究,解决实际中遇https://tjj.changzhi.gov.cn/sjfx/202207/t20220704_2588893.html
7.数据统计分析学习范文如何实现非结构化数据与结构化数据的结合?首先,完善非结构化数据的整合,然后我们可以用结构化数据做数量说明,非结构化数据加强描述;或是提高数据处理技术,实现结构化数据与非结构化数据的互相转化,选择能更好说明问题的数据形式作为后续分析基础。这都是值得再深入思考研究的新问题,而且这不仅仅是大数据和统计研究的事https://www.gwyoo.com/haowen/174794.html
8.2022年4月自考00051管理系统中计算机应用真题试卷自考B.快速应用开发法 C.结构化方法 D.面向对象方法 18.下列选项中,不是在系统分析阶段使用的描述工具是 A.数据流程图 B.组织结构图 C.业务流程图 D. 模块结构图 19.业务流程图需要描述的信息不包括 A.业务活动 B.业务分布 C.信息关联关系 D.信息处理环节 https://www.educity.cn/zikao/356611.html
9.IBMCloudObjectStorage在银行业非结构化数据存储嘲下的对象随着银行业IT技术的快速发展和业务的不断升级变革,业务应用系统产生的非结构化数据(包括文件、图片、音视频文件等)的规模也越来越大,银行业非结构化数据呈指数式爆发式增长。目前使用非结构化数据的主要系统包括内容管理平台、后督影像系统、身份验证、柜员办业务扫描件等需要用到影像图片,以及呼叫中心系统、电话客服的https://redhat.talkwithtrend.com/Article/242823
10.科学网—[转载]武新:大数据架构及行业大数据应用那时候的数据增长缓慢、系统都比较孤立,用传统数据库基本可以满足各类应用开发。互联网的出现和快速发展,尤其是移动互联网的发展,加上数码设备的大规模使用(CCD、CMOS技术的大规模产业化),今天数据的主要来源已经不是人机会话了,而是通过设备、服务器、应用自动产生的。传统行业的数据同时也多起来了,这些数据以非结构https://blog.sciencenet.cn/blog-887780-1358813.html
11.2022年中国知识图谱行业研究报告澎湃号·湃客澎湃新闻一、互联网信息碎片化与非结构化的处理需求 互联网的海量信息带有碎片化与非架构化特征。新兴互联网应用的蓬勃发展,让完整信息被分类分解为信息片段,信息被大量简化,从而导致信息本身不全面、内在逻辑不完整。同时,文本、图片、各类报表和音频、视频、HTML等非结构化数据广泛存在于互联网中。互联网企业需要在现有的存量业https://www.thepaper.cn/newsDetail_forward_19458208
12.非结构数据怎么分析帆软数字化转型知识库非结构数据指的是不符合特定数据模型的数据类型,这些数据通常包括文本、图像、音频、视频等。与结构化数据不同,非结构数据没有预定义的数据模型,因此在存储、处理和分析时会面临更多的挑战。例如,文本数据需要进行分词和语义理解,图像数据需要进行特征提取和分类,视频数据需要进行帧处理和对象识别。 https://www.fanruan.com/blog/article/644632/
13.2022年度陕西省重点研发计划项目申报指南目录4.9 大规模非结构化网格并行剖分技术研究 4.10 大流量高温燃油调节方法及调节器设计关键技术 5.新一代通信技术 5.1 空地一体化网络立体致密多维覆盖技术 5.2 面向天地一体化大规模星座的网络化测控关键技术 5.3 新型天线形态下基于大规模 MIMO 的机载数据高速传输技术 http://www.kt180.com/html/sxs/9889.html
14.结构化半结构化和非结构化数据腾讯云开发者社区结构化数据,简单来说就是数据库。结合到典型场景中更容易理解,比如企业ERP、财务系统;医疗HIS数据库;教育一卡通;政府行政审批;其他核心数据库等。这些应用需要哪些存储方案呢?基本包括高速存储应用需求、数据备份需求、数据共享需求以及数据容灾需求。 非结构化数据,包括视频、音频、图片、图像、文档、文本等形式。具体到https://cloud.tencent.com/developer/article/1351609
15.mysql数据库技术与应用试题库试题及答案《数据库技术与应用》试题库1 一、填空题 1、数据库是存储和管理数据的仓库,但数据库并不能直接存储数据,而是将数据存储到中的 2、如果MySQL服务名为MySQL8则在Windows的命令窗口中,启动MySQL服务的指令是—o 3、在删除关联表中数据时,可以先删除从表中的相关记录或将从表外键字段值设置为,再删除主表中的相关https://www.yxfsz.com/view/1686946242167410690
16.大数据时代带来的影响(精选5篇)大数据是在种类繁多、数量庞大的多样数据中进行的快速信息获取,它不是定量描述数据量大小的名词,一般产生于邮件、视频、微博、帖子以及页面点击,是结构化数据、半结构化数据与非结构化数据的总和。大数据概念首先出自于天文学学科和基因学学科,最后广泛应用开来,将计算机时代不断增长的信息,应用到各行各业,发挥信息的自https://www.1mishu.com/haowen/289788.html
17.软考【解析】本题考查CPU中相关寄存器的基础知识。 指令寄存器(IR)用来保存当前正在执行的指令。当执行一条指令时,先把它从内存取到数据寄存器(DR)中,然后再传送至IR。为了执行任何给定的指令,必须对操作码进行测试,以便识别所要求的操作。指令https://mp.weixin.qq.com/s?__biz=MzI3ODAyNTEzMA==&mid=2456070202&idx=7&sn=a36bcbdc8598ae8f7deb2201e73ca924&chksm=fccd4effcbbac7e95d6d2e86a95c465ed6801e743eb98cd51830355ab27c84db06f6c6b34508&scene=27
18.mpp数据库架构mpp数据库与传统数据库MPP (Massively Parallel Processing),即大规模并行处理,在数据库非共享集群(传统的单节点不属于集群,双机热备或Oracle RAC等,均是基于共享存储的)中,每个节点都有独立的磁盘存储系统和内存系统,业务数据根据数据库模型和应用特点划分到各个节点上,每台数据节点通过专用网络或者商业通用网络互相连接,彼此协同计算,作为整https://blog.51cto.com/u_16213683/7296250
19.2017年9月计算机二级Msoffice高级应用考试题库一、选择题(每小题1分,共20分) 1.程序流程图中带有箭头的线段表示的是( )。 A.图元关系 B.数据流 C.控制流 D.调用关系 2.结构化程序设计的基本原则不包括( )。 A.多态性 B.自顶向下 C.模块化 D.逐步求精 3.软件设计中模块划分应遵循的准则是( )。 https://www.yjbys.com/edu/jisuanjidengji/312682.html