
Abstract:18年复活节前的五天,kaggle举办了数据预处理的五个挑战。这里做每天学习到的技术要点的回顾。这篇是第二天的内容,主要是有关数据的比例调整和分布调整。
数据比例调整的需求
我理解的原因有二:1. 数据的各列feature之间,有的时候数量级会差特别多,比如年龄和收入,一个在两位数,一个5位数甚至更多。年龄上相差10岁和年薪上相差10块,对结果的影响大概率会是天差地别的。所以要尽量把各个feature的数据都按比例调整到[-1, 1]之间,方便做比较。2. 在梯度下降中,各列feature数据的范围相同可以加速收敛。
数据分布调整的需求
对于一般事物的观察数据,通常符合高斯分布,也叫正态分布。统计图为钟形曲线,即中值的样本最多,远离中值的样本数剧减。有一些机器学习模型需要所输入的数据为正态分布,我知道的例子是「异常检测」,就是无监督学习来自动辨别数据里的异常现象。其原理就是找高斯分布钟形曲线两端的极端现象,需要把数据正常化(normalisation)。
- 环境设置
所需的库有numpy,pandas,scipy,mlxtend.preprocessing,seaborn(可视化),matplotlib(作图)。
# modules we'll use
import pandas as pd
import numpy as np
# for Box-Cox Transformation
from scipy import stats
# for min_max scaling
from mlxtend.preprocessing import minmax_scaling
# plotting modules
import seaborn as sns
import matplotlib.pyplot as plt
# read in all our data
kickstarters_2017 = pd.read_csv("../input/kickstarter-projects/ks-projects-201801.csv")
- 比例调整
由于Xsc=(X−Xmin)/(Xmax−Xmin),scaling的结果是[0, 1].
# select the usd_goal_real column
usd_goal = kickstarters_2017.usd_goal_real
# scale the goals from 0 to 1
scaled_data = minmax_scaling(usd_goal, columns = [0])
#这里的column0表示对dataframe的第一列做minmax
# plot the original & scaled data together to compare
fig, ax=plt.subplots(1,2)
sns.distplot(kickstarters_2017.usd_goal_real, ax=ax[0])
ax[0].set_title("Original Data")
sns.distplot(scaled_data, ax=ax[1])
ax[1].set_title("Scaled data")
- 分布调节
# get the index of all positive pledges (Box-Cox only takes postive values)
index_of_positive = kickstarters_2017.pledged > 0
# get only positive pledges (using their indexes)
positive_pledged = kickstarters_2017.pledged.loc[index_of_positive]
# normalize the pledges (w/ Box-Cox)
normalised_data = stats.boxcox(positive_pledged)[0]
# 这里我尝试了开10次方和做log,同样有效
manual_exp = positive_pledged ** (1/10)
manual_log = np.log(positive_pledged + 3)
fig, ax = plt.subplots(2,2)
sns.distplot(positive_pledged, ax = ax[0,0])
ax[0,0].set_title("Original")
sns.distplot(normalised_data, ax = ax[0,1])
ax[0,1].set_title("Normalised")
sns.distplot(manual_exp, ax = ax[1,0])
ax[1,0].set_title("Manual exp")
sns.distplot(manual_log, ax = ax[1,1])
ax[1,1].set_title("Manual log")

第二天的内容就是这样。
网友评论