由于数据源包含不同类型的变量,不同的变量往往处理方法不同
无量纲化使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化和区间缩放法。标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。区间缩放法利用了边界值信息,将特征的取值区间缩放到某个特定的范围,例如[0,1]等。
标准化变换后各维特征的均值为0,方差为1,也叫做Z—Score 规范化,计算方式如下式,为特征值减去均值,除以标准差。

- import numpy as np
- from sklearn import preprocessing
-
- x= np.array([[1.,-1.,2.],
- [2.,0.,0.],
- [0.,1.,-1.]])
- x_scaled = preprocessing.scale(x)
- x_scaled

- import numpy as np
- from sklearn import preprocessing
-
- x= np.array([[1.,-1.,2.],
- [2.,0.,0.],
- [0.,1.,-1.]])
- x_max_min_scaled = preprocessing.MinMaxScaler().fit_transform(x)
- x_max_min_scaled
norm支持L1、 L2 、max
- import numpy as np
- from sklearn import preprocessing
-
- x= np.array([[1.,-1.,2.],
- [2.,0.,0.],
- [0.,1.,-1.]])
- x_normalize = preprocessing.normalize(x,norm='l2')
- x_normalize
对特征进行非线性变换增加模型复杂度,常用的变化有 基于多项式,基于指数函数,基于对数函数的变换,
一般对数变换后分布更平稳。对数变换能够很好地解决随自变量增加,因变量方差变大的问题。将非线性数据通过对数变换,转换为线性数据,以便使用线性模型进行学习,如SVM,对于线性不可分的数据,先将数据进行核函数映射,再将低维的数据映射到高位空间,使数据在投影后的高维空间中线性可分。
- 无监督的离散化方法通常为对特征进行装箱,分为等宽度离散化方法和等频度离散化方法。等宽度离散方法,就是根据箱的个数得出固定的宽度,使得分到每个箱中的数据的宽度是相等的。等频分箱法是使得分到每个箱中的数据的个数是相同的。在等宽或等频划分后,可用箱中的中位数或者平均值替换箱中的每个值,实现特征的离散化。这两种方法需要指定区间的个数,同时等宽度离散化方法对异常点较为敏感,倾向于把特征不均匀地分到各个箱中,这样会破坏特征的决策能力。等频度的离散化方法虽然会避免上述问题却可能会将具有相同标签的相同特征值分入不同的箱中,同样会造成决策能力下降。
- 基于聚类分析的离散化方法也是一种无监督的离散化方法。此种方法包含两个步骤,首先是将某特征的值用聚类算法(如K—means算法)通过考虑特征值的分布以及数据点的邻近性划分成簇,然后将聚类得到的簇进行再处理,处理方法可分为自顶向下的分裂策略和自底向上的合并策略。分裂策略是将每一个初始簇进一步分裂为若干子簇,合并策略则是通过反复地对邻近簇进行合并。聚类分析的离散化方法通常也需要用户指定簇的个数,从而决定离散产生的区间数。
- 对于实际数据的离散化,具体可以根据业务的规律进行相应的调整,利用自然区间进行相应的离散。
- 有监督的离散化方法相较无监督的离散化方法拥有更多的表现形式及处理方式,
- 比较常用的方法为基于熵的离散化方法和基于卡方的离散化方法。
- 由于建立决策树时用熵来分裂连续特征的方法在实际中运行得很好,故将这种思想扩展到更通常的特征离散化中,通过反复地分裂区间直到满足停止的条件。由此产生了基于熵的离散化方法。熵是最常用的离散化度量之一。基于熵的离散化方法使用类分布信息计算和确定分裂点,是一种有监督的、自顶向下的分裂技术。ID3和C4.5是两种常用的使用熵的度量准则来建立决策树的算法,基于这两种方法进行离散化特征几乎与建立决策树的方法一致。
- 在上述方法上又产生了MDLP方法(最小描述距离长度法则),MDLP的思想是假设断点是类的分界,依此得到许多小的区间,每个区间中的实例的类标签都是一样的,然后再应用 MDLP 准则衡量类的分界点中哪些是符合要求可以作为端点,哪些不是端点需要将相邻区间进行合并。由此选出必要的断点,对整个数据集进行离散化处理。
利用R的discretization包以R自带的数据集iris为例进行MDLP方法
- //MDLP特征离散化
- library(discretization)
- data(iris)
- mdlp(iris)$Disc.data
基于卡方的离散化方法:
不同于基于熵的离散化方法,基于卡方的离散化方法是采用自底向上的策略,首先将数据取值范围内的所有数据值列为一个单独的区间,再递归找出最佳邻近可合并的区间,然后合并它们,进而形成较大的区间。在判定最佳邻近可合并的区间时,会用到卡方统计量来检测两个对象间的相关度。最常用的基于卡方的离散化方法是ChiMerge方法。
- 首先将数值特征的每个不同值看作一个区间,对每对相邻区间计算卡方统计量,将其与由给定的置信水平确定的阈值进行比较,高于阈值则把相邻区间进行合并,因为高的卡方统计量表示这两个相邻区间具有相似的类分布,而具有相似类分布的区间应当进行合并成为一个区间。合并的过程递归地进行,直至计算得到的卡方统计量不再大于阈值,也就是说,找不到相邻的区间可以进行合并,则离散化过程终止,得到最终的离散化结果。
在实际的推荐系统中,很多特征为类别属性型特征,通常会利用One—Hot编码将这些特征进行编码。如果一个特征有m个可能值,那么通过One—Hot 编码后就变成了m个二元特征,并且这些特征互斥。One—Hot 编码可以将离散特征的取值扩展到欧式空间,离散特征的某个取值就是对应欧式空间的某个点,可以方便在学习算法中进行相似度等计算,并且可以稀疏表示,减少存储,同时可以一定程度上起到扩充特征的作用。
- import numpy as np
- from sklearn import preprocessing
-
- one_hot_enc = preprocessing.OneHotEncoder()
- one_hot_enc.fit([[1,1,2],[0,1,0],[0,2,1],[1,0,3]])
- after_one_hot = one_hot_enc.transform([[0,1,3]]).toarray()
- print(after_one_hot)
- # [[1. 0. 0. 1. 0. 0. 0. 0. 1.]]
特征哈希法的目标是把原始的高维特征向量压缩成较低维特征向量,且尽量不损失原始特征的表达能力,是一种快速且很节省空间的特征向量化方法。在推荐系统中会存在很多例如ID类型特征(当然也可以利用embedding方法,但哈希方法更节约资源),利用特征哈希,可以避免生成极度稀疏的数据,但是可能会引发碰撞,
碰撞可能会降低 结果的准确性,也可能会提升结果的准确性,一般利用另外一个函数解决碰撞。其一般描述为,设计一个函数v=h(x),能够将d 维度向量x=(x(1),x(2),··.转化成 m维度的新向量v,这里的m可以大于也可以小于d。通常使用方法为利用哈希函数将x(1)映射到v(h(1)) ),将 x(d) 映射到 v(h(d))。Hash 函数能够将任意输入转换到一个固定范围的整数输出。下面利用文本对此进行说明,可以看到程序将句子转化为一个固定维度的向量,同样ID类型的特征也可以利用同样的方法进行处理,将每一个单词对应为一个ID。
- def hashing_vectorizer(s,N):
- x = [0 for i in range(N)]
- for f in s.split():
- h = hash(f)
- x[h % N] += 1
- return x
- print( hashing_vectorizer('make a hash feature',3))
- # [2, 2, 0]
在推荐系统中通常会包含很多时间相关的特征,如何有效地挖掘时间相关特征也会很大程度上影响推荐的效果。通常方案是按照业务逻辑以及业务目的进行相关特征的处理,Christ,M等提出了一种层次化处理时间特征的方案,如图5.7所示。其中包含了时间窗口统计特征:最大、最小、均值、分位数,并利用标签相关性对特征进行选择。下面简单介绍利用Python的tsfresh 工具对 Robot Execution Failures 数据集进行特征提取
- from tsfresh.examples.robot_execution_failures import download_robot_execution_failures,\
- load_robot_execution_failures
-
- download_robot_execution_failures()
- timeseries, y = load_robot_execution_failures()
-
- from tsfresh import extract_features
- extracted_features = extract_features(timeseries, column_id="id",
- column_sort="time")
-
- from tsfresh import select_features
- from tsfresh.utilities.dataframe_functions import impute
- impute(extracted_features)
- features_filtered = select_features(extracted_features,y)