数据预处理
一、特征的离散化
1.1、使用NumPy中的digitize()函数离散化
"""
使用NumPy中的digitize()函数离散化
"""
#创建10个标准正态分布的随机数用于实验
import numpy as np
np.random.seed(1)
x = np.random.randn(10)
print(x)
#创建由5个边界构成的6个区间
bins = np.linspace(min(x),max(x),5)
print("区间边界值为:",bins,sep="")
#使用digitize()函数计算每个数据所属区间代码
bin_num = np.digitize(x,bins=bins)
print("每个数据所属区间代码:",bin_num)
#运行结果
[ 1.62434536 -0.61175641 -0.52817175 -1.07296862 0.86540763 -2.3015387
1.74481176 -0.7612069 0.3190391 -0.24937038]
区间边界值为:[-2.3015387 -1.28995108 -0.27836347 0.73322415 1.74481176]
每个数据所属区间代码: [4 2 2 2 4 1 5 2 3 3]
1.2、使用Pandas中的cut()函数离散化
"""
使用Pandas中的cut()函数离散化
"""
import pandas as pd
import numpy as np
#设置随机数种子
np.random.seed(1)
#获取30个0~100内的随机数
scores = np.random.randint(0,100,size=30)
#设置间隔值
bins = [0,60,70,80,90,np.inf]
cut = pd.cut(scores,bins=bins,right=False)
print(cut)
#设置标签
cut_label = pd.cut(scores,bins=bins,right=False,labels=["不及格","及格","中等","良好","优秀"])
print(cut_label)
#创建DataFrame对象
df_scores = pd.DataFrame(scores,columns=["cl"])
print(df_scores[:3])
#将分类作为一列加入DataFrame对象中,类似于字典
df_scores["成绩分类"] = pd.cut(df_scores["cl"],bins=bins,right=False,labels=["不及格","及格","中等","良好","优秀"])
print(df_scores[:3])
#获取分类的样本数
print(df_scores["成绩分类"].value_counts())
#运行结果
[[0.0, 60.0), [0.0, 60.0), [70.0, 80.0), [0.0, 60.0), [70.0, 80.0), ..., [80.0, 90.0), [90.0, inf), [90.0, inf), [80.0, 90.0), [0.0, 60.0)]
Length: 30
Categories (5, interval[float64, left]): [[0.0, 60.0) < [60.0, 70.0) < [70.0, 80.0) < [80.0, 90.0) <
[90.0, inf)]
['不及格', '不及格', '中等', '不及格', '中等', ..., '良好', '优秀', '优秀', '良好', '不及格']
Length: 30
Categories (5, object): ['不及格' < '及格' < '中等' < '良好' < '优秀']
cl
0 37
1 12
2 72
cl 成绩分类
0 37 不及格
1 12 不及格
2 72 中等
成绩分类
不及格 17
中等 5
良好 4
及格 2
优秀 2
Name: count, dtype: int64
二、识别与处理异常值
异常值是指样本中的一些极端特征值。sklearn中内置有椭圆模型拟合、隔离森林、局部异常系数等异常检测工具。
使用四分位差来识别异常值:
np.percentile(a, q, axis=None, out=None, overwrite_input=False, interpolation='linear', keepdims=False)
参数说明:
- a:输入数组
- q:要计算的百分位数,在0~100之间
- axis:沿着它计算百分位数的轴
- keepdims:bool是否保持维度不变
"""
识别与处理异常值
"""
import numpy as np
np.random.seed(1)
#获取随机数组
x = np.random.randn(10)
#将第0个值替换为异常值
x[0] = -1000
#将最后一个值替换成异常值
x[-1] = 1000
q3,q1 = np.percentile(x,[75,25])
#四分位差
iqr = q3-q1
n = 2
#下限
range_lower = q1-n*iqr
#上限
range_upper = q3+n*iqr
#异常值
dif = np.where((x<range_lower)|(x>range_upper))
print(dif)
#运行结果
(array([0, 9], dtype=int64),)
当我们知道了异常值时,我们就需要对异常值进行处理,根据不同的业务需求,我们会有不同的处理方式。
- 忽略异常值所在的样本
- 大于上限的值用上限值来代替,小于下限的值用下限值来代替
三、特征值的Min-Max缩放
由于计算机单位不同等原因,特征值之间的数值大小差距可能较大,这种差距可能导致模型对特定特征有特别的偏好,从而影响模型的精度。在数学上,每列的特征可以采用每个数值减去该列最小值然后除以该列的最大值与最小值的差值,从而将该列特征中每个值缩放到0和1之间。
sklearn中的MinMaxScaler类可以用来缩放数组的数据。
四、特征值的标准化
标准化是将特征值缩放为均值为0、标准差为1、基本符合正态分布的数据。
sklearn中的StandardScaler类实现数据标准化。
五、特征值的稳健缩放
如果数据中包含很多异常值,这些异常值会影响均值、方差和标准差,使用均值和标准差的标准化缩放不是一个好的选择。
sklearn中的RobustScaler通过中位数和四分位间距来缩放,可以减少异常值带来的影响
六、无序分类数据的热编码
机器学习算法一般只接受数值型数据,非数值型的数据需要转换成数值型数据。对于一些类别类型的数据,可以直接为每一个类型赋一个数值,但数值是存在大小顺序关系的,而一些类别可能没有大小顺序关系。如果直接为每个类别赋予不同的数值,将影响机器学习的效果。
一个有效的方案就是为无序分类中的每个类别创建一个特征,如果出现该类别,相应的新特征赋值为1;如果没有出现该类别,相应的新特征赋值为0.这种方法在机器学习邻域称为one-hot编码。
对于多标签多分类的情况,可以使用sklearn.preprocessing中的MultiLabelBinarizer类实现热编码
七、有序分类数据编码
有些类别存在顺序关系或大小关系,如学号,成绩对应的标签优秀,及格等。
import pandas as pd
df = pd.DataFrame({"学号":[2,3,1,4],"成绩":["良好","及格","优秀","不及格"]})
print(df)
mapper = {"优秀":5,"良好":4,"中等":3,"及格":2,"不及格":1}
s = df["成绩"].replace(mapper)
print(s)
df["成绩编码"] = s
print(df)
df = df.drop(columns=["成绩"])
print(df)
#运行结果
学号 成绩
0 2 良好
1 3 及格
2 1 优秀
3 4 不及格
0 4
1 2
2 5
3 1
Name: 成绩, dtype: int64
学号 成绩 成绩编码
0 2 良好 4
1 3 及格 2
2 1 优秀 5
3 4 不及格 1
学号 成绩编码
0 2 4
1 3 2
2 1 5
3 4 1
八、每个样本特征值的正则化
正则化是将每个样本各个特征值缩放到单位范数。也就是对每个样本计算器p-范数,然后将样本中每个特征值除以该范数。