数据预处理
定义:从数据中检测,纠正或者损坏不准确,不适用模型的记录的过程
目的:让数据适应模型,匹配模型的需求
面对的问题:
数据类型不同:有的是文字,有的是数字,有的连续,有的间断
数据质量不行:有噪声,有异常,有缺失,有重复,量纲不一,数据量过大或者过小
1、数据的无量纲化
功能:
- 将不同规格的数据转换为同一规格,将不同分布的数据转换为特定分布的需求
- 以梯度和矩阵为核心的算法(LR,SVM、神经网络):可加快速度
- 距离模型(k-近邻,k-means):提升模型精度,避免某一个取值范围特别大的特征对距 离计算造成影响
无量纲化处理包括线性和非线性的,线性的有中心化和缩放处理
中心化:多有记录减去一个固定值,即样本数据平移到某一个位置
缩放:将所有记录除以(或者取对数)一个固定值,将数据固定在某个范围中
处理手段:
归一化–Normalization:
先中心化(数据x-减去最小值)后缩放(除以最大值-最小值),处理后的数据服从正态分布,将不同规格的数据转换为同一规格
通过sklearn中的preprocessing.MinMaxScaler实现
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
from pandas import DataFrame
data=[[-1,-2],[-0.5,6],[0,10],[1,18]]
scaler=MinMaxScaler()
result=scaler.fit_transform(data)
result
array([[0. , 0. ],
[0.25, 0.4 ],
[0.5 , 0.6 ],
[1. , 1. ]])
注意:1、scaler.inverse_transform(result) --->可将归一化结果逆转
2、当数据量过大时使用scaler.partial_fit(data)
scaler=MinMaxScaler(feature_range=[5,10])--->使用feature_range将数据结果归到[5:10]的范围
result=scaler.fit_transform(data1)
result
array([[ 5. , 5. ],
[ 6.25, 7. ],
[ 7.5 , 8. ],
[10. , 10. ]])
标准化–Standardization
数据x按均值(u)中心化,再按标准差塞个马缩放,将不同分布的数据转换为特定分布的需求,数据服从标准正太分布(均值为零,方差为一)
代码处理:
from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()
scaler.fit_transform(data2)
array([[-1.18321596, -1.38675049],
[-0.50709255, -0.2773501 ],
[ 0.16903085, 0.2773501 ],
[ 1.52127766, 1.38675049]])
注意:
在标准化和归一化过程中:
- 空值NAN当作是缺失值,fit时候忽略,transform保持NAN状态
- fit接口只容许导入至少二维的数组,一维会报错,通常我们输入的x是特征矩阵,现实案例中的特征矩阵不太可能是一维,所以不太可能存在这个问题
2、缺失值 sklearn.preprocessing中的Imputer模块
具体处理详情
代码如下
import pandas as pd
from pandas import Series,DataFrame
data=pd.read_csv(r'C:\Users\kyrie\Desktop\data\Narrativedata.csv',index_col=0)
data.head()
data.info()
age=data['Age'].values.reshape(-1,1)##取出值并转换为二维数组
age
from sklearn.preprocessing import Imputer
imp_mean=Imputer()
imp_median=Imputer(strategy="median")
imp_0=Imputer(strategy="most_frequent")
imp_mean=imp_mean.fit_transform(age)
imp_median=imp_median.fit_transform(age)
imp_0=imp_0.fit_transform(age)
data['Age']=imp_mean
使用pandas和numpy进行填充
data1['Age']=data1['Age'].fillna(data1['Age'].median())#.fillna在DataFrame里直接进行填补
data1.dropna(axis=0,inplace=True)#.drop(axis=0)删除有缺失值的行.drop(axis=1)删除有缺失值的列
#inplace为True,表示在原数据集修改,默认为Flase,表示复制一个对象,不在原数据集修改
3、处理分类特征:编码与哑变量
原因:
在机器学习中大多数算法,比如LR、SVM、Knn只能处理数值型数据,不能处理文字,在sklearn当中,有专用处理文字的算法,但是其他算法在fit的时候要求输入数组或矩阵,不能够导入文字型数据,而且现实中的许多标签和数据在收集完毕的时候,都不是以数字来表现的,为了让数据适应算法和库,我们必须将数据进行编码,将文字型数据转换为数值型
preprocessing.LabelEncoding:标签专用,将分类转化为分类数值
from sklearn.preprocessing import LabelEncoder
from pandas import DataFrame,Series
import pandas as pd
data=DataFrame(data=[[-1,2],[-0.5,6],[0,10],[1,18]])
print(data)
y=data.iloc[:,-1]#要输入的是标签,所以容许一维数组
print(y)
le=LabelEncoder()
le.fit(y)#导入数据,调取结果
label=le.transform(y)
# print(le.fit_transform(y))
print("调取结果是:",label)
print(le.classes_)#查看标签中有多少类型
data.iloc[:,-1]=label
print(data)
/Users/dushuo/PycharmProjects/untitled5/venv/bin/python /Users/dushuo/PycharmProjects/sklearn/sklearn_test2.py
0 1
0 -1.0 2
1 -0.5 6
2 0.0 10
3 1.0 18
0 2
1 6
2 10
3 18
Name: 1, dtype: int64
调取结果是: [0 1 2 3]
[ 2 6 10 18]
0 1
0 -1.0 0
1 -0.5 1
2 0.0 2
3 1.0 3
Process finished with exit code 0
如果不需要数学展示
from sklearn.preprocessing import LabelEncoder
data.iloc[:,-1]=LabelEncoder().fit_tranform(data.iloc[:,-1])
preprocessing.OrdinalEncoder:特征专用,能够将分类特征转换为分类数值–数据必须是多维
from sklearn.preprocessing import OrdinalEncoder #接口categories_对应LabelEncoder的接口classes_,一模一样的功能
data_ = data.copy()
data_.head()
OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_
data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])
data_.head()```
**独热编码创建哑变量preprocessing.OneHotEncoder**
特征做哑变量
df=pd.read_csv('20181121222789n2hi02wz/Narrativedata.csv')
print(df.head())
from sklearn.preprocessing import OneHotEncoder
print(df.info())
print(df.columns)
#填充缺失值
from sklearn.impute import SimpleImputer
Age=df.loc[:,'Age'].values.reshape(-1,1)
df.loc[:,'Age']=SimpleImputer(strategy="median").fit_transform(Age)
Embarked=df.loc[:,'Embarked'].values.reshape(-1,1)
df.loc[:,'Embarked']=SimpleImputer(strategy="most_frequent").fit_transform(Embarked)
#独热编码
X=df.iloc[:,1:-1]
# OneHotEncoder(categories='auto').fit_transform(X).toarray()
enc=OneHotEncoder(categories="auto").fit(X)
result=enc.transform(X).toarray()
# print(result)
#编码还原pd.DataFrame(enc.inverse_transform(result))
result1=pd.DataFrame(enc.inverse_transform(result))
enc.get_feature_names()
print(pd.DataFrame(result).head())
print(df.head())
newdata=pd.concat([df,pd.DataFrame(result)],axis=1)
print(newdata.head())
/Users/dushuo/PycharmProjects/untitled5/venv/bin/python /Users/dushuo/PycharmProjects/sklearn/sklearn_test2.py
Unnamed: 0 Age Sex Embarked Survived
0 0 22.0 male S No
1 1 38.0 female C Yes
2 2 26.0 female S Yes
3 3 35.0 female S Yes
4 4 35.0 male S No
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 5 columns):
Unnamed: 0 891 non-null int64
Age 714 non-null float64
Sex 891 non-null object
Embarked 889 non-null object
Survived 891 non-null object
dtypes: float64(1), int64(1), object(3)
memory usage: 34.9+ KB
None
Index(['Unnamed: 0', 'Age', 'Sex', 'Embarked', 'Survived'], dtype='object')
0 1 2 3 4 5 6 ... 86 87 88 89 90 91 92
0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 1.0 0.0 0.0 1.0
1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 1.0 0.0 1.0 0.0 0.0
2 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 1.0 0.0 0.0 0.0 1.0
3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 1.0 0.0 0.0 0.0 1.0
4 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 1.0 0.0 0.0 1.0
[5 rows x 93 columns]
Unnamed: 0 Age Sex Embarked Survived
0 0 22.0 male S No
1 1 38.0 female C Yes
2 2 26.0 female S Yes
3 3 35.0 female S Yes
4 4 35.0 male S No
Unnamed: 0 Age Sex Embarked Survived ... 88 89 90 91 92
0 0 22.0 male S No ... 0.0 1.0 0.0 0.0 1.0
1 1 38.0 female C Yes ... 1.0 0.0 1.0 0.0 0.0
2 2 26.0 female S Yes ... 1.0 0.0 0.0 0.0 1.0
3 3 35.0 female S Yes ... 1.0 0.0 0.0 0.0 1.0
4 4 35.0 male S No ... 0.0 1.0 0.0 0.0 1.0
[5 rows x 98 columns]
Process finished with exit code 0
4、 处理连续特征:二值化与分段sklearn.preprocessing.Binarizer
原因:根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈 值的值映射为0。默认阈值为0时,特征中所有的正值都映射到1。二值化是对文本计数数据的常见操作,分析人员 可以决定仅考虑某种现象的存在与否。它还可以用作考虑布尔随机变量的估计器的预处理步骤(例如,使用贝叶斯 设置中的伯努利分布建模)。
data_2=df.copy()
from sklearn.preprocessing import Binarizer
Age=data_2.iloc[:,0].values.reshape(-1,1)
Bin=Binarizer(threshold=40).fit_transform(Age)
print(Bin.shape)
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 = df.iloc[:,0].values.reshape(-1,1)
est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
est.fit_transform(X)
#查看转换后分的箱:变成了一列中的三箱 set(est.fit_transform(X).ravel()) ravel降维
est = KBinsDiscretizer(n_bins=3, encode='onehot', strategy='uniform') #查看转换后分的箱:变成了哑变量
result=est.fit_transform(X).toarray()
print(result)```
Unnamed: 0 Age Sex Embarked Survived
0 0 22.0 male S No
1 1 38.0 female C Yes
2 2 26.0 female S Yes
3 3 35.0 female S Yes
4 4 35.0 male S No
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 5 columns):
Unnamed: 0 891 non-null int64
Age 714 non-null float64
Sex 891 non-null object
Embarked 889 non-null object
Survived 891 non-null object
dtypes: float64(1), int64(1), object(3)
memory usage: 34.9+ KB
None
Index(['Unnamed: 0', 'Age', 'Sex', 'Embarked', 'Survived'], dtype='object')
(891, 1)
[[1. 0. 0.]
[1. 0. 0.]
[1. 0. 0.]
...
[0. 0. 1.]
[0. 0. 1.]
[0. 0. 1.]]
Process finished with exit code 0
5、类不平衡问题与SMOTE过采样算法
各个类别的样本量分布不均的问题——某些类别的样本数量极多,而有些类别的样本数量极少,也就是所谓的类不平衡(class-imbalance)问题。
解决方案
-
过采样(SMOTE:算法的思想是合成新的少数类样本,合成的策略是对每个少数类样本a,从它的最近邻中随机选一个样本b,然后在a、b之间的连线上随机选一点作为新合成的少数类样本)
对训练集里面样本数量较少的类别(少数类)进行过采样,合成新的样本来缓解类不平衡。from imblearn.over_sampling import SMOTE
-
欠采样
对训练集里面样本数量较多的类别(多数类)进行欠采样,抛弃一些样本来缓解类不平衡。