参考资料:
在机器学习任务中,数据集的质量优劣对数据分析的结果影响非常大,所谓Garbage in, garbage out,数据决定模型的上限,因此数据质量成为数据分析流程不可或缺的一个环节。即使是像Kaggle那样主办方已经把数据集准备好的场景,也需要评估train set和test set的分布是否一致,存不存在偏斜等。如果两者不一致,可能会导致离线cv分数非常高,可是在leaderborad却下跌了很多,以至于大量花在模型调参上的功夫其实都白费了。
sklearn.preprocessing
提供了许多很有用的函数帮助我们将原始特征向量转化为更适合训练的数据。
大部分情况下,在构造 Feature 之前,我们需要对比赛提供的数据集进行一些处理。通常的处理有:
数据清洗可以从以下几个角度完成:
.drop_duplicates(subset=,keep=)
subset
:指出需要删除重复数据的列。
keep
:保留重复的哪一个数据,last
,first
,False
,false表示删除所有重复数据。
每个变量都应该根据业务实际情况来处理
# 删除变量
df_train = df_train.drop((missing_data[missing_data['Total'] > 1]).index,1)
# 删除样本
df_train = df_train.drop(df_train.loc[df_train['Electrical'].isnull()].index)
.dropna()
train_df=train_df[~train_df['order_detail_status'].isin([101])]# 删除101订单状态订单
.fillna()
填充缺失值,如all_data = all_data.fillna(all_data.mean())
,以下是常用的填充值根据业务实际情况填充。
统计量:众数、中位数、均值
插值法填充:包括随机插值,多重差补法,热平台插补,拉格朗日插值,牛顿插值等
模型填充:使用回归、贝叶斯、随机森林、决策树等模型对缺失数据进行预测。
定值填充
其他:
np.random.randint(age_avg - age_std, age_avg + age_std, size=age_null_count)
int( 中位数/0.5 + 0.5 ) * 0.5
还可以分组填充
保留缺失值,用'None'
填充
偏正态分布,使用均值代替,可以保持数据的均值;偏长尾分布,使用中值代替,避免受 outlier 的影响
# 标准化
saleprice_scaled = StandardScaler().fit_transform(df_train['SalePrice'][:,np.newaxis])
# 删除
talExposureLog = totalExposureLog.loc[(totalExposureLog.pctr<=1000)]
df_train = df_train.drop(df_train[df_train['Id'] == 1299].index)
在比赛当中,如果数据包含文本,往往需要进行大量的数据清洗工作。如去除HTML 标签,分词,拼写纠正, 同义词替换,去除停词,抽词干,数字和单位格式统一等
在有Outlier的情况下,稳健的(robust)scaler 或 transformers会表现得更好。那么我们该如何选择标准化方法呢?
也叫做z-score标准化。z−score标准化对个别极端元素不敏感,且把所有元素分布在0的周围,一般情况下元素越多,0周围区间会分布大部分的元素,每当有新的元素进来,都要重新计算方差与均值。
x ′ = x − x ˉ σ x x'=\frac{x-\bar x}{\sigma_x} x′=σxx−xˉ
方法简单,而且保证规范化后所有元素都是正的,每当有新的元素进来,只有在该元素大于最大值或者小于最小值时才要重新计算全部元素。但是若存在一个极大(小)的元素,会导致其他元素变的非常小(大)。
def scale_minmax(col):
return (col-col.min())/(col.max()-col.min())
QuantileTransformer
and quantile_transform
PowerTransformer
.StandardScaler(copy=True, with_mean=True, with_std=True)
:该标准器本质上是保留了原数据的均值和标准差,并可以同样标准化作用于测试数据。.scale(X, axis=0, with_mean=True, with_std=True, copy=True)
.MinMaxScaler(feature_range=(0, 1), copy=True)
把数据转化到某个区间.MaxAbsScaler(copy=True)
,用法同MinMaxScaler,范围变成[-1,1].minmax_scale(X, feature_range=(0, 1), axis=0, copy=True)
.maxabs_scale(X, axis=0, copy=True)
.fit(X_train)
.transform(X_test)
.fit_transform(X_train)
.normalize(X, norm=’l2’, axis=1, copy=True, return_norm=False)
.Normalizer(norm=’l2’, copy=True)
.RobustScaler(with_centering=True, with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
:使数据在面对异常值时robust。#standardizing data
saleprice_scaled = StandardScaler().fit_transform(df_train['SalePrice'][:,np.newaxis]);
low_range = saleprice_scaled[saleprice_scaled[:,0].argsort()][:10]
high_range= saleprice_scaled[saleprice_scaled[:,0].argsort()][-10:]
print('outer range (low) of the distribution:')
print(low_range)
print('\nouter range (high) of the distribution:')
print(high_range)
outer range (low) of the distribution:
[[-1.83820775]
[-1.83303414]
[-1.80044422]
[-1.78282123]
[-1.77400974]
[-1.62295562]
[-1.6166617 ]
[-1.58519209]
[-1.58519209]
[-1.57269236]]
outer range (high) of the distribution:
[[3.82758058]
[4.0395221 ]
[4.49473628]
[4.70872962]
[4.728631 ]
[5.06034585]
[5.42191907]
[5.58987866]
[7.10041987]
[7.22629831]]
训练集与验证集的分布不一致会带来许多问题。
df_train['SalePrice'].describe()
:描述信息
df_train['SalePrice'].value_counts
:频数
# 直方图和分布函数曲线
sns.distplot(df_train['SalePrice'], fit=norm)
# 显示偏度和峰度
print("Skewness: %f" % df_train['SalePrice'].skew())
print("Kurtosis: %f" % df_train['SalePrice'].kurt())
# 或调用scipy.stat库中的函数
from scipy.stats import kurt, skew
skew(df_train)
kurt(df_train)
# 概率图?
res = stats.probplot(df_train['SalePrice'], plot=plt)
# log处理
df_train['SalePrice'] = np.log(df_train['SalePrice'])
# 若该变量存在大量值为0的样本,可分类处理或者使用log1p,处理完之后若要还原要使用expm1
df_train.loc[df_train['TotalBsmtSF']>0,'TotalBsmtSF'] = np.log(df_train['TotalBsmtSF'])
train["SalePrice"] = np.log1p(train["SalePrice"])
# log1p转换偏度过高的变量
numeric_feats = all_data.dtypes[all_data.dtypes != "object"].index
skewed_feats = train[numeric_feats].apply(lambda x: skew(x.dropna())) #compute skewness
skewed_feats = skewed_feats[skewed_feats > 0.75]
skewed_feats = skewed_feats.index
all_data[skewed_feats] = np.log1p(all_data[skewed_feats])
# 一般情况下,可以对连续变量进行Box-Cox变换。
# 通过变换可以使得模型更好的优化,通常也会带来效果上的提升。
skewness = skewness[abs(skewness) > 0.75]
print("There are {} skewed numerical features to Box Cox transform".format(skewness.shape[0]))
from scipy.special import boxcox1p
skewed_features = skewness.index
lam = 0.15
for feat in skewed_features:
#all_data[feat] += 1
all_data[feat] = boxcox1p(all_data[feat], lam)
#all_data[skewed_features] = np.log1p(all_data[skewed_features])
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
,dataset['Title'].map(title_mapping)
.OneHotEncoder(n_values=None, categorical_features=None, categories=None, drop=None, sparse=True, dtype=, handle_unknown=’error’)
:热编码,若有n个类,则生成n个特征,其中一个是1其余是0.
sparse
:默认为True表示用稀疏矩阵表示,一般使用.toarray()
转换到False,即数组。
.OrdinalEncoder(categories=’auto’, dtype=)
:序数编码,0到 n c a t e g o r i e s − 1 n_{categories}-1 ncategories−1.LabelEncoder()
:和OrdinalEncoder
类似。# 示例代码
LabelEncoder().fit_transform(data[feature].astype(np.str)
pandas.DataFrame.replace
后再进行编码。pandas.DataFrame.astype
pandas.cut
,然后通过pandas.Series.value_counts
观察切分点,再将对应bins或者说区间的连续值通过pandas.DataFrame.replace
或pandas.DataFrame.loc
到离散点0,1,2,…后再进行编码。一般切分点的选择可以用IV指标来评估,若把改变量离散成n个块,则 I V = ∑ i = 1 n ( a i − b i ) ∗ l n ( a i b i ) IV=\sum_{i=1}^n(a_i-b_i)*ln(\frac{a_i}{b_i}) IV=∑i=1n(ai−bi)∗ln(biai),其中 a i a_i ai为该块中正样本占总正样本的比例, b i b_i bi为该块中负样本占总负样本的比例。
IV | 划分效果 |
---|---|
<0.03 | 无预测能力 |
0.03~0.09 | 低 |
0.1~0.29 | 中 |
0.3~0.49 | 高 |
>=0.5 | 极高 |
preprocessing.KBinsDiscretizer
preprocessing.Binarizer
多表数据整合