文章目录
skLearn中的数据预处理和特征工程
数据挖掘的五大流程 |
---|
1. 获取数据 |
2. 数据预处理 数据预处理是从数据中检测、纠正或删除损坏,不准确或不适用于模型的记录的过程。可能面对的问题有: 数据类型不同 ,比如有的是文字,有的是数字,有的含时间序列,有的连续,有的间断。也可能,数据的质量不行 ,有噪声,有异常,有缺失,数据出错,量纲不一,有重复,数据是偏态,数据量太大或太小。数据预处理的目的: 让数据适应模型,匹配模型的需求
|
3. 特征工程 特征工程是将原始数据转换为更能代表预测模型的潜在问题的特征的过程。可以通过挑选最相关的特征,提取特征以及创造特征来实现。其中创造特征又经常以降维算法的方式实现。可能面对的问题有: 特征之间有相关性 ,特征和标签无关 ,特征太多或太小 ,或者干脆就无法表现出应有的数据现象 或无法展示数据的真实面貌 。特征工程的目的: 1) 降低计算成本 2) 提升模型上限 |
4. 建模 ---- 测试模型并预测出结果 |
5. 上线 ---- 验证模型效果 |
sklearn中包含众多数据预处理和特征工程相关的模块,虽然刚接触sklearn时,大家都会为其中包含的各种算法的广度深度所震惊,但其实sklearn六大板块中有两块都是关于数据预处理和特征工程的,两个板块互相交互,建模之前的全部工程打下基础。
- 模块
preprocessing
:几乎包含数据预处理的所有内容 - 模块
Impute
:填补缺失值专用 - 模块
feature_selection
:包含特征选择的各种方法的实践 - 模块
decomposition
:包含降维算法
♑ 数据预处理 Preprocessing & Impute
① 数据无量纲化
在机器学习算法实践中,我们往往有着将不同规格的数据转换到同一规格,或不同分布的数据转换到某个特定分布的需求,这种需求统称为将数据“无量纲化”。譬如梯度和矩阵为核心的算法中,譬如逻辑回归,支持向量机,神经网络,无量纲化可以加快求解速度;而在距离类模型,譬如K近邻,K-Means聚类中,无量纲化可以帮我们提升模型精度,避免某一个取值范围特别大的特征对距离计算造成影响。(一个特例是决策树和树的集成算法们,对决策树我们不需要无量纲化,决策树可以把任意数据都处理得很好。)
数据的无量纲化可以是线性的,也可以是非线性的。线性的无量纲化包括中心化(Zero-centered或者Meansubtraction)处理和缩放处理(Scale)
。
-
中心化的本质是
让所有记录减去一个固定值,即让数据样本数据平移到某个位置
。 -
缩放的本质是
通过除以一个固定值,将数据固定在某个范围之中,取对数也算是一种缩放处理
。
• preprocessing.MinMaxScaler
当数据(x)按照最小值中心化后,再按极差(最大值 - 最小值)缩放,数据移动了最小值个单位,并且会被收敛到[0,1]
之间,而这个过程,就叫做数据归一化(Normalization,又称Min-Max Scaling)
。注意,Normalization是归一化,不是正则化,真正的正则化是regularization,不是数据预处理的一种手段。归一化之后的数据服从正态分布,公式如下:
在sklearn当中,我们使用preprocessing.MinMaxScaler来实现这个功能。MinMaxScaler有一个重要参数,feature_range
:控制我们希望把数据压缩到的范围,默认是[0,1]。
# 导包
from sklearn.preprocessing import MinMaxScaler
# 构建数据集
data = [[-1,2],[-0.5,6],[0,10],[1,18]]
# 实现归一化
scaler = MinMaxScaler() # 实例化
scaler = scaler.fit(data) # fit,在这里本质是生成min(x)和max(x)
result = scaler.transform(data) # 通过接口导出结果
print("归一化的结果是:\n",result) # 通过结果可以看出两列数据的分布大致一致
归一化的结果是:
[[0. 0. ]
[0.25 0.25]
[0.5 0.5 ]
[1. 1. ]]
- 注意:
fit()
+transform()
连个接口可以使用一个fit_transform()
接口来实现。
# fit()+transform() => fit_transform()
result_ = scaler.fit_transform(data)
print("归一化的结果是:\n",result_)
归一化的结果是:
[[0. 0. ]
[0.25 0.25]
[0.5 0.5 ]
[1. 1. ]]
inverse_transform()
接口可以用来讲归一化结果逆转。
# 将归一化的结果进行逆转 --- inverse_transform(归一化结果)
scaler.inverse_transform(result)
array([[-1. , 2. ],
[-0.5, 6. ],
[ 0. , 10. ],
[ 1. , 18. ]])
feature_range
属性可以用来对归一化的范围进行设置,任意取范围。
# 实现数据归一化至其他范围的值
data = [[-1,2],[-0.5,6],[0,10],[1,18]]
scaler = MinMaxScaler(feature_range=[5,10]) # 实例化并将数据归结到5-10
result = scaler.fit_transform(data)
print("重新设置范围后的结果:\n",result)
重新设置范围后的结果:
[[ 5. 5. ]
[ 6.25 6.25]
[ 7.5 7.5 ]
[10. 10. ]]
- 使用原理实现归一化、归一化逆转(numpy):
import pandas as pd
# 归一化处理
data = pd.DataFrame(data)
data_nor = (data - data.min())/(data.max()-data.min())
data_nor
归一化结果:
0 1
0 0.00 0.00
1 0.25 0.25
2 0.50 0.50
3 1.00 1.00
# 归一化逆转
x_returned = data_nor*(data.max()-data.min()) + data.min()
x_returned
归一化逆转结果:
0 1
0 -1.0 2.0
1 -0.5 6.0
2 0.0 10.0
3 1.0 18.0
注意:
当data中的特征数量非常多的时候,fit
会报错并表示 — 数据量太大了计算机无法计算
此时使用partial_fit()
作为训练接口scaler = scaler.partial_fit(data)
• preprocessing.StandardScaler
当数据(x)按均值(μ)中心化后,再按标准差(σ)缩放,数据就会服从为均值为0,方差为1的正态分布(即标准正态分布),而这个过程,就叫做数据标准化(Standardization,又称Z-score normalization)
,公式如下:
# 1.导包
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
# 2.构建数据集
data = [[-1,2],[-0.5,6],[0,10],[1,18]]
scaler = StandardScaler() # 实例化
scaler = scaler.fit(data) # 本质是生成均值和方差
print("均值是:\n",scaler.mean_)
print("方差是:\n",scaler.var_)
均值是:
[-0.125 9. ]
方差是:
[ 0.546875 35. ]
# 3.获取标准化结果
result = scaler.transform(data)
print("查看标准化后的数据集:\n",result)
print("查看标准化后的数据的方差:\n",result.var())
print("查看标准化后的数据的均值:\n",result.mean())
查看标准化后的数据集:
[[-1.18321596 -1.18321596]
[-0.50709255 -0.50709255]
[ 0.16903085 0.16903085]
[ 1.52127766 1.52127766]]
查看标准化后的数据的方差:
1.0
查看标准化后的数据的均值:
0.0
# 4.实现数据集逆转
data_returned = scaler.inverse_transform(result)
data_returned
逆转的结果:
array([[-1. , 2. ],
[-0.5, 6. ],
[ 0. , 10. ],
[ 1. , 18. ]])
对于StandardScaler
和MinMaxScaler
来说,空值NaN
会被当做是缺失值,在fit()
的时候忽略,在transform()
的时候保持缺失值NaN
的状态显示。并且,尽管去量纲化过程不是具体的算法,但在fit()接口
中,依然只允许导入至少二维数组,一维数组导入会报错。通常来说,我们输入的X
会是我们的特征矩阵,现实案例中特征矩阵不太可能是一维所以不会存在这个问题。
-
StandardScaler和MinMaxScaler选哪个?
- 多数机器学习算法中,会选择StandardScaler来进行特征缩放,因为MinMaxScaler对异常值非常敏感。在PCA,聚类,逻辑回归,支持向量机,神经网络这些算法中,StandardScaler往往是最好的选择。MinMaxScaler在不涉及距离度量、梯度、协方差计算以及数据需要被压缩到特定区间时使用广泛,比如数字图像处理中量化像素强度时,都会使用MinMaxScaler将数据压缩于[0,1]区间之中。建议先试试看StandardScaler,效果不好换MinMaxScaler。
-
除了StandardScaler和MinMaxScaler之外,sklearn中也提供了各种其他缩放处理(中心化只需要一个pandas广播一下减去某个数就好了,因此sklearn不提供任何中心化功能)。比如,在希望压缩数据,却不影响数据的稀疏性时(不影响矩阵中取值为0的个数时),我们会使用MaxAbsScaler;在异常值多,噪声非常大时,我们可能会选用分位数来无量纲化,此时使用RobustScaler。更多详情请参考以下列表:
② 缺失值处理
对于实际收集数据的人却不是如此,因此数据挖掘之中,常常会有重要的字段缺失值很多,但又不能舍弃字段的情况。因此,数据预处理中非常重要的一项就是处理缺失值。在这里,我们使用从泰坦尼克号提取出来的数据,这个数据有三个特征,一个数值型,两个字符型,标签也是字符型。
• impute.SimpleImputer
class sklearn.impute.SimpleImputer (missing_values=nan, strategy=’mean’, fill_value=None,
verbose=0,copy=True)
在随机森林的案例时,我们用这个类和随机森林回归填补了缺失值,对比了不同的缺失值填补方式对数据的影响。这个类是专门用来填补缺失值的。它包括四个重要参数:
参数 | 含义&输入 |
---|---|
missing_values | 告诉SimpleImputer,数据中的缺失值长什么样,默认空值np.nan
|
strategy | 我们填补缺失值的策略,默认均值。 输入 “mean” 使用均值填补(仅对数值型特征可用)输入 “median" 用中值填补(仅对数值型特征可用)输入 "most_frequent” 用众数填补(对数值型和字符型特征都可用)输入 “constant" 表示请参考参数“fill_value "中的值(对数值型和字符型特征都可用) |
fill_value | 当参数startegy 为”constant" 的时候可用,可输入字符串或数字表示要填充的值,常用0 |
copy | 默认为True ,将创建特征矩阵的副本,反之则会将缺失值填补到原本的特征矩阵中去。 |
- 下面我们利用泰坦尼克号预测生还人数数据集的一部分进行操作。
# 导包
import numpy as np
import pandas as pd
from sklearn.impute import SimpleImputer
# 读取数据集
data = pd.read_csv(r"G:\Projects\Jupyter notebook\机器学习skLearn\data\Narrativedata.csv"
,index_col=0)
data.head(20)
-
获取的部分数据集如下,可以看到在此数据集中包含有部分空值(
NaN
)。
- 使用
xxx.info()
可以查看数据集的基本完整情况。Int64Index
表示整个数据集的记录数,下面的表单是列名
、不为空的记录数
、数据类型
。我们可以发现,整体数据集有891
条记录,其中的Age
、Embarked
各有缺失存在。
data.info() # 查看整体数据集信息 --- 检测缺失值
<class 'pandas.core.frame.DataFrame'>
Int64Index: 891 entries, 0 to 890
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Age 714 non-null float64
1 Sex 891 non-null object
2 Embarked 889 non-null object
3 Survived 891 non-null object
dtypes: float64(1), object(3)
memory usage: 34.8+ KB
- 拿
Age列
为例:首先skLearn
中不支持一维数据的形式存在,所以首先我们要将数据集(Age列
)进行升维处理。
# 提取数据集,并进行升维处理
age = data.loc[:,'Age'].values.reshape(-1,1)
age
array([[22. ],
[38. ],
[26. ],
[35. ],
[35. ],
[ nan],
[54. ],
.........
[28. ],
[25. ],
[39. ],
[27. ],
[19. ],
[ nan],
[26. ],
[32. ]])
使用三种策略进行填补:均值
、中位数
、0值
# 实例化
imp_mean = SimpleImputer() # 默认采用均值填补
imp_median = SimpleImputer(strategy='median') # 用中位数填补
imp_0 = SimpleImputer(strategy='constant',fill_value=0) # 用0值填补
# 训练、获取结果
imp_mean = imp_mean.fit_transform(age)
imp_median = imp_median.fit_transform(age)
imp_0 = imp_0.fit_transform(age)
print("均值填补的结果:\n",imp_mean[:10])
print("中位数填补的结果:\n",imp_median[:10])
print("o值填补的结果:\n",imp_0[:10])
均值填补的结果:
[[22. ]
[38. ]
[26. ]
[35. ]
[35. ]
[29.69911765] # 均值填补
[54. ]
[ 2. ]
[27. ]
[14. ]]
中位数填补的结果:
[[22.]
[38.]
[26.]
[35.]
[35.]
[28.] # 中位数填补
[54.]
[ 2.]
[27.]
[14.]]
o值填补的结果:
[[22.]
[38.]
[26.]
[35.]
[35.]
[ 0.] # 0值填补
[54.]
[ 2.]
[27.]
[14.]]
- 通过三种不同的策略填补,其中的均值和中位数填补结果相差不大,但是为了保持数据的统一性,我们最终采用中位数填补。如下代码所示,最终使用的是
中位数
进行Age列
的空值填补。
# 使用中位数填补Age
Age = data.loc[:,'Age'].values.reshape(-1,1)
imp_mode = SimpleImputer(strategy="median")
data.loc[:,'Age'] = imp_mode.fit_transform(Age)
data.info()
中位数填补结果:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 891 entries, 0 to 890
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Age 891 non-null float64 # 记录不为空值数补全
1 Sex 891 non-null object
2 Embarked 889 non-null object
3 Survived 891 non-null object
dtypes: float64(1), object(3)
memory usage: 34.8+ KB
- 同样的按照上面的步骤,我们对
Embarked列
进行众数
的填补。 - 其实这里的
Embsrked列
缺失程度比较小,我们也可以采取 删除空值记录的方式。
# 使用众数填补Embarked
Embarked = data.loc[:,'Embarked'].values.reshape(-1,1)
imp_mode = SimpleImputer(strategy="most_frequent")
data.loc[:,'Embarked'] = imp_mode.fit_transform(Embarked)
data.info()
众数填补结果:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 891 entries, 0 to 890
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Age 891 non-null float64
1 Sex 891 non-null object
2 Embarked 891 non-null object
3 Survived 891 non-null object
dtypes: float64(1), object(3)
memory usage: 34.8+ KB
③ 处理分类型特征
在机器学习中,大多数算法,譬如逻辑回归,支持向量机SVM,k近邻算法等都只能够处理数值型数据,不能处理文字;在sklearn当中,除了专用来处理文字的算法,其他算法在fit()的时候全部要求输入数组或矩阵,也不能够导入文字型数据(其实手写决策树和普斯贝叶斯可以处理文字,但是sklearn中规定必须导入数值型)。然而在现实中,许多标签和特征在数据收集完毕的时候,都不是以数字来表现的。比如说,学历的取值可以是[“小学”,“初中”,“高中”,“大学”],付费方式可能包含[“支付宝”,“现金”,“微信”]等等。在这种情况下,为了让数据适应算法和库,我们必须将数据进行编码
,即是说,将文字型数据转换为数值型
。
数据类型以及常用统计量:
数据类型 | 数据名称 | 数学含义 | 描述 | 举例 | 可用操作 |
---|---|---|---|---|---|
离散, 定性 |
名义 | =,!= |
名义变量就是不同的名字,是用来告诉我们: 这两个数据是否相同的 |
邮编,性别,眼睛的 颜色,职工号 |
众数, 信息熵 情形分析表或 列联表, 相关性分析, 卡方检验 |
离散, 定性 |
有序 | < ,> |
有序变量为数据的相对大小提供信息,告诉 我们数据的顺序,但数据之间大小的间隔不 是具有固定意义的,因此有序变量不能加减 |
材料的硬度,学历 | 中位数, 分位数, 非参数相关分析(等级相关), 测量系统分析, 符号检验 |
连续, 定量 |
有距 | +,- |
有距变量之间的间隔是有固定意义的,可以 加减,比如,一单位量纲 |
日期,以摄氏度或 华氏度为量纲的温度 |
均值,标准差, 皮尔逊相关系数, t和F检验 |
连续, 定量 |
比率 | *,/ |
比变量之间的间隔和比例本身都是有意义的, 既可以加减又可以乘除 |
以开尔文为量纲 的温度,货币数量,计数, 年龄,质量,长度,电流 |
百分数, 变化量, 几何平均, 调和平均 |
编码
• preprocessing.LabelEncoder
标签
专用,能够将分类标签
转换为分类数值
。
# 导包
import numpy as np
import pandas as pd
from sklearn.impute import SimpleImputer
# 读取数据集
data = pd.read_csv(r"G:\Projects\Jupyter notebook\机器学习skLearn\data\Narrativedata.csv"
,index_col=0)
from sklearn.preprocessing import LabelEncoder
y = data.iloc[:,-1] # 提取标签列
y:
0 No
1 Yes
2 Yes
3 Yes
4 No
...
886 No
887 Yes
888 No
889 Unknown
890 No
Name: Survived, Length: 891, dtype: object
le = LabelEncoder() # 实例化
le = le.fit(y) # 导入数据
label = le.transform(y) # 调取结果
label:
array([0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 1, 2, 0, 0, 0, 1, 0, 2, 0, 2, 1, 2,
2, 2, 0, 1, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 1,
................................................................
2, 0, 0, 0, 2, 0, 1, 1, 1, 0, 0, 2, 0, 1, 0, 0, 2, 2, 0, 0, 0, 2,
2, 0, 0, 1, 0, 0, 0, 2, 0, 1, 0])
# 查看标签中的类别
le.classes_
array(['No', 'Unknown', 'Yes'], dtype=object)
# 逆转标签
le.inverse_transform(label) # 还原标签为字符型
实际应用:
from sklearn.preprocessing import LabelEncoder
data.iloc[:,-1] = LabelEncoder().fit_transform(data.iloc[:,-1])
• preprocessing.OrdinalEncoder
特征
专用,能够将分类特征
转换为分类数值
from sklearn.preprocessing import OrdinalEncoder
data_ = data.copy()
categories = OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories
categories
直接运行的时候报错了:ValueError: Input contains NaN
,因为我重新读取了数据,没有先进行缺失值处理,同时也间接说明了对于特征的转化之前必须进行数据预处理。
from sklearn.preprocessing import OrdinalEncoder
# 拷贝数据
data_ = data.copy()
# 数据预处理
from sklearn.impute import SimpleImputer
Age = data_.loc[:,'Age'].values.reshape(-1,1)
Embarked = data_.loc[:,'Embarked'].values.reshape(-1,1)
data_.loc[:,'Age'] = SimpleImputer(strategy='median').fit_transform(Age) # 中位数填补年龄
data_.loc[:,'Embarked'] = SimpleImputer(strategy='most_frequent').fit_transform(Embarked) #众数填补舱门
categories = OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_
print("特征转化的类别有:\n",categories)
# 一步转化
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])
print("转化后的数据前5行是:\n",data_.head())
特征转化的类别有:
[array(['female', 'male'], dtype=object), array(['C', 'Q', 'S'], dtype=object)]
转化后的数据前5行是:
Age Sex Embarked Survived
0 22.0 1.0 2.0 0
1 38.0 0.0 0.0 2
2 26.0 0.0 2.0 2
3 35.0 0.0 2.0 2
4 35.0 1.0 2.0 0
可以看到,经过preprocessing.OrdinalEncoder
的处理后,分类特征也转化成了数值类型数据。
哑变量
preprocessing.OneHotEncoder
preprocessing.OneHotEncoder
是指独热编码,创建哑变量。
我们刚才已经用OrdinalEncoder把分类变量Sex和Embarked都转换成数字对应的类别了。在舱门Embarked这一列中,我们使用[0,1,2]代表了三个不同的舱门,然而这种转换是正确的吗?
我们来思考三种不同性质的分类数据:
- 1)
舱门(S,C,Q)
三种取值S,C,Q是相互独立的,彼此之间完全没有联系
,表达的是S≠C≠Q
的概念。这是名义变量。 - 2)
学历(小学,初中,高中)
三种取值不是完全独立的,我们可以明显看出,在性质上可以有高中>初中>小学这样的联系,学历有高低,但是学历取值之间却不是可以计算的,我们不能说小学 + 某个取值 = 初中
。这是有序变量。 - 3)
体重(>45kg,>90kg,>135kg)
各个取值之间有联系,且是可以互相计算的,比如120kg - 45kg = 90kg
,分类之间可以通过数学计算,对类别互相转换。这是有距变量。
然而在对特征进行编码的时候,这三种分类数据都会被我们转换为[0,1,2]
,这三个数字在算法看来,是连续且可以计算的,这三个数字相互不等,有大小,并且有着可以相加相乘的联系。所以算法会把舱门,学历这样的分类特征,都误会成是体重这样的分类特征。这是说,我们把分类转换成数字的时候,忽略了数字中自带的数学性质,所以给算法传达了一些不准确的信息,而这会影响我们的建模。
类别OrdinalEncoder
可以用来处理有序变量
, 但对于名义变量,我们只有使用哑变量的方式来处理,才能够尽量向算法传达最准确的信息:
这样的变化,让算法能够彻底领悟,原来三个取值是没有可计算性质的,是“有你就没有我
”的不等概念。在我们的数据中,性别
和舱门
都是这样的名义变量
。因此我们需要使用独热编码,将两个特征都转换为哑变量。
# 数据预处理
from sklearn.impute import SimpleImputer
Age = data.loc[:,'Age'].values.reshape(-1,1)
Embarked = data.loc[:,'Embarked'].values.reshape(-1,1)
data.loc[:,'Age'] = SimpleImputer(strategy='median').fit_transform(Age)
data.loc[:,'Embarked'] = SimpleImputer(strategy='most_frequent').fit_transform(Embarked)
# 使用独热编码转化数据
from sklearn.preprocessing import OneHotEncoder
x = data.iloc[:,1:-1]
ohe = OneHotEncoder(categories='auto').fit(x)
result = ohe.transform(x).toarray()
result
array([[0., 1., 0., 0., 1.],
[1., 0., 1., 0., 0.],
[1., 0., 0., 0., 1.],
...,
[1., 0., 0., 0., 1.],
[0., 1., 1., 0., 0.],
[0., 1., 0., 1., 0.]])
-
可以看到结果中包含有5列,对比上面的哑变量处理图就很容易理解。在性别中只有两类,所以会分为两列,而舱门中有三类,所以会分为三列,总共是5列。不信我们可以将其还原:
- 同时也可以利用
get_feature_names()
获取对应列的类别名称:传入数据
[特征列索引
]_特征类别
# 获取稀疏矩阵特征类别名称
ohe.get_feature_names()
array(['x0_female', 'x0_male', 'x1_C', 'x1_Q', 'x1_S'], dtype=object)
# 合并数据
newdata = pd.concat([data,pd.DataFrame(result)],axis=1)
newdata.drop(['Sex','Embarked'],axis=1,inplace=True)
newdata.columns = ["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]
newdata.head()
④ 处理连续型特征
二值化
• sklearn.preprocessing.Binarizer
根据阈值
将数据二值化
(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈值的值映射为0
。默认阈值为0时,特征中所有的正值都映射到1。二值化是对文本计数数据的常见操作,分析人员可以决定仅考虑某种现象的存在与否。它还可以用作考虑布尔随机变量的估计器的预处理步骤(例如,使用贝叶斯设置中的伯努利分布建模)
# 将年龄二值化处理
from sklearn.preprocessing import Binarizer
data_age = data.copy()
x = data_age.iloc[:,0].values.reshape(-1,1)
transformer = Binarizer(threshold=30).fit_transform(x) # threshold 用来设定二值化的分界点
transformer
array([[0.],
[1.],
[0.],
[1.],
[1.],
[0.],
[1.],
[0.],
[0.],
....
[0.],
[0.],
[0.],
[1.]])
分段(分箱)
• preprocessing.KBinsDiscretizer
这是将连续型变量
划分为分类变量
的类,能够将连续型变量
排序后按顺序
分箱后编码。总共包含三个重要参数:
参数 | 含义&输入 |
---|---|
n_bins | 每个特征中分箱的个数,默认5,一次会被运用到所有导入的特征 |
encode | 编码的方式,默认“onehot ”" onehot ":做哑变量,之后返回一个稀疏矩阵,每一列是一个特征中的一个类别,含有该类别的样本表示为1,不含的表示为0“ ordinal ”:每个特征的每个箱都被编码为一个整数,返回每一列是一个特征,每个特征下含有不同整数编码的箱的矩阵" onehot-dense ":做哑变量,之后返回一个密集数组。 |
strategy | 用来定义箱宽的方式,默认"quantile "" uniform ":表示等宽分箱,即每个特征中的每个箱的最大值之间的差为(特征.max() - 特征.min())/(n_bins)" quantile ":表示等位分箱,即每个特征中的每个箱内的样本数量都相同" kmeans ":表示按聚类分箱,每个箱中的值到最近的一维k均值聚类的簇心得距离都相同 |
# 分箱 --- 将连续型数据划分为类别
from sklearn.preprocessing import KBinsDiscretizer
x = data.iloc[:,0].values.reshape(-1,1)
# 分三箱,采用ordinal编码方式,每箱为一个编码,并且使用等宽分箱
kbd = KBinsDiscretizer(n_bins=3,encode='ordinal',strategy='uniform').fit_transform(x)
# 检测分箱结果
set(kbd.ravel())
{0.0, 1.0, 2.0}
# 分三箱,采用onehot独热编码方式,并且使用等宽分箱
est = KBinsDiscretizer(n_bins=3, encode='onehot', strategy='uniform')
#查看转换后分的箱:变成了哑变量
est.fit_transform(x).toarray()
array([[1., 0., 0.],
[0., 1., 0.],
[1., 0., 0.],
...,
[0., 1., 0.],
[1., 0., 0.],
[0., 1., 0.]])