该文档是诸位同事机器学习代码学习的经验整合,主要流程为:
- 导入工具包及数据
- Features 及其缺失值处理
- 建模
具体内容如下:
1.import 工具包。
将各类工具包导入进工程。
-
新模块说明:matplotlib
%matplotlib inline
IPython 内置了一套非常强大的指令系统,又被称作魔法命令,使得在IPython环境中的操作更加得心应手。matplotlib 支持输出多种格式的图形图像,并且可以使用多种 GUI 界面库交互式地显示图表。使用%matplotlib命令可以将 matplotlib 的图表直接嵌入到 Notebook之中,或者使用指定的界面库显示图表,它有一个参数指定 matplotlib 图表的显示方式。inline表示将图表嵌入到Notebook中。
新模块:seaborn
比 Matplotlib 上手简单,Seaborn本质上使用Matplotlib作为核心库(就像Pandas对NumPy一样)。seaborn有以下几个优点:
默认情况下就能创建赏心悦目的图表。
创建具有统计意义的图。
能理解 pandas 的 DataFrame 类型
- 新模块说明:SciPy
scipy 包包含许多专注于科学计算中的常见问题的工具箱。它的子模块对应于不同的应用,比如插值、积分、优化、图像处理、统计和特殊功能等。
scipy 可以与其他标准科学计算包相对比,比如 GSL (C和C++的GNU科学计算包), 或者Matlab的工具箱。scipy是Python中科学程序的核心程序包;这意味着有效的操作numpy数组,因此,numpy和scipy可以一起工作。
- 新模块说明:sklearn
在这个案例中用到了 preprocessing 中的 StandardScaler
标准化预处理数据包括:
preprocessing.scale(X, axis=0, with_mean=True, with_std=True, copy=True):
将数据转化为标准正态分布(均值为0,方差为1)
preprocessing.minmax_scale(X, feature_range=(0, 1), axis=0, copy=True):
将数据在缩放在固定区间,默认缩放到区间 [0, 1]
preprocessing.maxabs_scale(X, axis=0, copy=True):
数据的缩放比例为绝对值最大值,并保留正负号,即在区间 [-1.0, 1.0] 内。唯一可用于稀疏数据 scipy.sparse 的标准化
preprocessing.robust_scale(X, axis=0, with_centering=True, with_scaling=True, copy=True):
通过 Interquartile Range (IQR) 标准化数据,即四分之一和四分之三分位点之间
它们对应的标准化预处理类:
class preprocessing.StandardScaler(copy=True, with_mean=True, with_std=True):
标准正态分布化的类
属性:scale_:ndarray,缩放比例mean_:ndarray,均值var_:ndarray,方差n_samples_seen_:int,已处理的样本个数,调用partial_fit()时会累加,调用fit()会重设
class preprocessing.MinMaxScaler(feature_range=(0, 1), copy=True):
将数据在缩放在固定区间的类,默认缩放到区间 [0, 1]
属性:min_:ndarray,缩放后的最小值偏移量scale_:ndarray,缩放比例data_min_:ndarray,数据最小值data_max_:ndarray,数据最大值data_range_:ndarray,数据最大最小范围的长度
class preprocessing.MaxAbsScaler(copy=True):
数据的缩放比例为绝对值最大值,并保留正负号,即在区间 [-1.0, 1.0] 内。可以用于稀疏数据 scipy.sparse
属性:scale_:ndarray,缩放比例max_abs_:ndarray,绝对值最大值n_samples_seen_:int,已处理的样本个数
class preprocessing.RobustScaler(with_centering=True, with_scaling=True, copy=True):
通过 Interquartile Range (IQR) 标准化数据,即四分之一和四分之三分位点之间
属性:center_:ndarray,中心点scale_:ndarray,缩放比例
class preprocessing.KernelCenterer:
生成 kernel 矩阵,用于将 svm kernel 的数据标准化(参考资料不全)
以上几个标准化类的方法:
fit(X[, y]):根据数据 X 的值,计算标准化缩放的比例
transform(X[, y, copy]):用之前设置的比例标准化 X
fit_transform(X[, y]):根据 X 设置标准化缩放比例并标准化
partial_fit(X[, y]):累加性的计算缩放比例
inverse_transform(X[, copy]):将标准化后的数据转换成原数据比例
get_params([deep]):获取参数
set_params(**params):设置参数
2.读入数据。
train = pd.read_csv("../input/train.csv")
设置数据格式:
如下为为设置显示的浮点数位数,保留三位小数。
pd.set_option('display.float_format', lambda x: '%.3f' % x)
建议可以将 .csv 文件用 excel 打开,后续可作数据上的人为调整,观察不同的调整对代码结果的影响。
3.检查是否有重复数据,并去除 ID 列。
检查是否有重复数据:
idsUnique = len(set(train.Id))
idsTotal = train.shape[0]
idsDupli = idsTotal - idsUnique
print("There are " + str(idsDupli) + " duplicate IDs for " + str(idsTotal) + " total entries")
其中, train.shape 返回的是(1460,80),即行列的数目; train.shape[0] 返回的是行的数目。
在本数据集中没有重复数据,然而如果在其他数据集中要做重复数据的处理,建议使用 DataFrame.drop_duplicates(subset=None, keep='first', inplace=False) Return DataFrame with duplicate rows removed, optionally only considering certain columns.
其中, 如上几个参数解释如下:
subset : column label or sequence of labels, optional.Only consider certain columns for identifying duplicates, by default use all of the columns。选择要作用于的列。
keep : {‘first’, ‘last’, False}, default ‘first’.first : Drop duplicates except for the first occurrence. last : Drop duplicates except for the last occurrence. False : Drop all duplicates.
inplace : boolean, default False. Whether to drop duplicates in place or to return a copy. 如果选的是 True 则在原来 dataframe 上直接修改,否则就返回一个删减后的 copy。
去除 ID 列数据:
train.drop("Id", axis = 1, inplace = True)
其中几个参数的意思分别是:
“ID” 为列名。
axis = 1 表明是列;如果是 0 ,则表明是行。
inplace = True:凡是会对原数组作出修改并返回一个新数组的,往往都有一个 inplace可选参数。如果手动设定为True(默认为False),那么原数组直接就被替换。
数据处理
1.观察数据并去除异常值。
-
观察数据
可以先直接观察一下目标问题的数据,包括个数、平均值、标准差、最小值、最大值、分位数等;还可以利用直方图,画出数据分布情况;通过观察直方图,可以看出数据并不是完全符合正态分布曲线,有偏度和峰度;通过观察散点图或盒图,可以注意到有异常值。#describe statistics summary df_train['SalePrice'].describe # histogram sns.distplot(df_train['SalePrice']) # skewness and kurtosis print("Skewness: %f" % df_train['SalePrice'].skew) # scatter plot plt.scatter(train.GrLivArea, train.SalePrice, c = "blue", marker = "s") plt.title("Looking for outliers") plt.xlabel("GrLivArea") plt.ylabel("SalePrice") plt.show()
-
去除异常值
train = train[train.GrLivArea < 4000] # 去除右侧的异常点
判断异常值并根据情况进行处理,注意:
偏离太多的异常值可以删除;
偏离但是仍然符合分布的异常值可以保留;
处理异常值要考虑清楚 trade-off,是否值得花力气处理;
2.对 target feature 进行 log transform
对 target feature 也就是此处的 sale price 进行 log transform,将有偏度的分布转换为正态分布,有利于后续分析。
matplotlib.rcParams['figure.figsize'] = (12.0, 6.0)
prices = pd.DataFrame({"price":train["SalePrice"], "log(price + 1)":np.log1p(train["SalePrice"])})
prices.hist()#直方图
左:log(feature+1) 转换后,右:转换前
要注意的是建议采用 log(1+x)的形式:
- take log 的作用:
Small values that are close together are spread further out.
Large values that are spread out are brought closer together.
- take log(1+x) 的作用:
朴素贝叶斯中,防止变量之前从未出现的时候,出现的概率为 0 ,出现数学计算的错误。
3.数据 features 及其缺失值处理
3.1 categorical 数据填充:选最低等级或最常出现的值
处理不可使用中位数或平均数或 most common value 进行填充的 feature 的缺失值。
替换数据的依据:
根据 label 判断该 feature 下缺失值最有可能是什么,就填入什么。
train.loc[:, "Alley"] = train.loc[:, "Alley"].fillna("None")
其中 train.loc[:, "Alley"] means select every row of column "alley"., .fillna(XX) means fill na cell with XX.
具体来说,要深入去看原始数据集:
- 如果 values 中有等级划分(优劣差等各等级;2、1、0 或 Y/N),一般选择最低等级的一类作为填充值。
- 如果 values 中为类型划分,则选择该 features 下最经常出现的值作为填充值。
3.2 categorical 和 numerical 的 features 互换
原始数据中,有一些 categorical features 理应是 numerical,反之亦然,为了更好的预测结果,我们要将部分 categorical 和 numerical 的 features 做处理。这一步在其他示例中没有出现,但建议保留。
** 3.2.1 将 numerical features 转为 categories**
Some numerical features 事实上是类型值, 要把它们转化成类别。比如月份的数字本身无任何数值意义,所以转换为英文缩写。
train = train.replace({"MSSubClass" : {20 : "SC20", 30 : "SC30", 40 : "SC40", 45 : "SC45", 50 : "SC50", 60 : "SC60", 70 : "SC70", 75 : "SC75", 80 : "SC80", 85 : "SC85", 90 : "SC90", 120 : "SC120", 150 : "SC150", 160 : "SC160", 180 : "SC180", 190 : "SC190"},
"MoSold" : {1 : "Jan", 2 : "Feb", 3 : "Mar", 4 : "Apr", 5 : "May", 6 : "Jun", 7 : "Jul", 8 : "Aug", 9 : "Sep", 10 : "Oct", 11 : "Nov", 12 : "Dec"}})
3.2.2 将 category features 转为 ordered numbers
将一些 categorical features 转换为 ordered numbers,
- 有明确分级的 feature,这些数值的顺序本身是有信息的,比如,"BsmtQual" : {"No" : 0, "Po" : 1, "Fa" : 2, "TA": 3, "Gd" : 4, "Ex" : 5};
- 分类关系中分级关系可以比较明确区分出来,如 Alley ,大多数人都偏好铺好的平整路面,而不是碎石路;LotShape,大多数人都偏好规整的 LotShape。反例则是比如 neighborhood 虽然可以反应出分级,毕竟大多数人喜欢的社区还是相似的,但是很难区分。
train = train.replace({"Alley" : {"Grvl" : 1, "Pave" : 2},
"BsmtCond" : {"No" : 0, "Po" : 1, "Fa" : 2, "TA" : 3, "Gd" : 4, "Ex" : 5},
……)
3.3 Create new features
这一步在有些示例中并没有,但建议保留。
Then we will create new features, in 3 ways :
- Simplifications of existing features
- Combinations of existing features
- Polynomials on the top 10 existing features
3.3.1 简化 features 1 Simplifications of existing features*
第一种简化 features 的方法,即简化已有的 features 数据层级,比如如下将原来 9 级的数据(1–9)可以划分为 3 级(1–3)。
train["SimplOverallQual"] = train.OverallQual.replace(
{1 : 1, 2 : 1, 3 : 1, # bad
4 : 2, 5 : 2, 6 : 2, # average
7 : 3, 8 : 3, 9 : 3, 10 : 3 # good
})
3.3.2 简化 features 2 Combinations of existing features*
第二种简化 features 的方法,即将若干种紧密相关的 features 合并在一起。
具体语法(示例):
train["OverallGrade"] = train["OverallQual"] * train["OverallCond"]
可能用到的讲解视频 Multivariate Linear Regression - Features and Polynomial Regressions - Housing Prices Predicting , given by Andrew NG, Stanford University。要注意的是,采用这种方法要格外注意 scaling。
3.3.3 简化 features 3 Polynomials on the top 10 existing features*
寻找重要 features
Find most important features relative to target. 按照其他 features 和 SalePrice 的相关度 correlation 降序排列。
corr = train.corr()
corr.sort_values(["SalePrice"], ascending = False, inplace = True)
Features and Polynomial Regressions
关于这一步,个人的理解是:先将重要的 features 挑选出来,然后为了更好地拟合某个模型,将这些重要的模型做了一个 Polynomial Regressions 的处理。
代码示例:
train["OverallQual-s2"] = train["OverallQual"] ** 2
train["OverallQual-s3"] = train["OverallQual"] ** 3
train["OverallQual-Sq"] = np.sqrt(train["OverallQual"])
关于何时使用 polynomial,有如下三个 situations:
- 理论需求。即作者假设这里会由曲线构成。
- 人为观察变量。在做回归分析之前,要先做单变量或二变量观察。可以通过画简单的散点图来检验是否有曲线关系。
- 对残差的观察。如果你试图将线性模型应用在曲线关系的数据上,那么散点图中间会在中间区域有整块的正值残差,然后在横坐标(X 轴即
predictor)一末端有整块的负值残差;或者反之。这就说明了线性模型是不适用的。但我个人觉得,第三种方式只是不适用线性模型的若干种情况之一,非充要条件。
同样的,用到的讲解视频 Multivariate Linear Regression - Features and Polynomial Regressions - Housing Prices Predicting , given by Andrew NG, Stanford University。要注意的是,采用这种方法要格外注意 scaling。
有趣的是,执行了上述代码之后,重新将影响 SalePrice 的 features 排序后,新生成的 features 进入了 influential features top 10,可见 polynomial 是有意义的。
3.4 numerical 数据缺失值填充
对 numerical features 中缺失的数据进行填充。
-
区分出 numerical 和 categorical features 。
categorical_features = train.select_dtypes(include = ["object"]).columns numerical_features = train.select_dtypes(exclude = ["object"]).columns numerical_features = numerical_features.drop("SalePrice")
其中 object 是指 categorical features 的数据类型。
填充缺失的数据。
对于 numerical features 中的缺失值,使用中位数或平均值作为填充值(>15% 数据量缺失的 features 可考虑不必填充)。
#filling NA's with the median of the column:
train_num = train_num.fillna(train_num.median())
或者
#filling NA's with the mean of the column:
all_data = all_data.fillna(all_data.mean())
4.对 numerical features 进行 log transfrom
对 skewed numerical features 取 Log 变换可以弱化异常值的影响。
skewness = train_num.apply(lambda x: skew(x))
skewness = skewness[abs(skewness) > 0.5]
skewed_features = skewness.index
train_num[skewed_features] = np.log1p(train_num[skewed_features])
Inspired by Alexandru Papiu's script. As a general rule of thumb, a skewness with an absolute value > 0.5 is considered at least moderately skewed. 要注意的是,此处取的偏度值为 0.5,在其他示例中,也可能采用不同的偏度值如 0.75。
5.对 categorical features 进行 get dummies 操作
Create dummy features for categorical values. Create dummy features for categorical values via one-hot encoding.
train_cat = [pd.get_dummies(train_cat)](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.get_dummies.html)
在回归分析中,dummy 变量(也被称为 indicator variable, design variable, Boolean indicator, categorical variable, binary variable, or qualitative variable)取值为 0 或 1,意味着是否会有可能影响输出的 categorical effect。Dummy 变量常用于分类互斥分类(比如吸烟者/非吸烟者)。
get_dummies 作用于 categorical features,举例来说明 get_dummies 的作用:
- 在执行 get_dummies 操作之前,每一列都是一个feature,这一列内取值都是原始数据或处理后的原始数据,对于 feature MSSubClass 的取值可分为 SC20/SC60/ SC70...SC120...等,其中第 23 行的数据记录为 SC120。
- 在执行 get_dummies 操作之后,每一列的列名依次变为每一个原来 feature 的取值,比如原来的 MSSubClass 列会拓展为 SC20/SC60/ SC70...SC120...等。以 SC120 举例,原来第 23 行记录为 SC120, 那么对应修改后新增的 SC120 列中第 23 行值为 1;原来若干行记录不是 SC120 的,对应变换后值为 0.
建模
lasso
1.1 parmaters:alpha
1.2 建模 和 predict
1.3 plot 检验结果xgboost
2.1 parmaters:
2.2 建模 和 predict
2.3 plot 检验结果