美文网首页
机器学习代码经验整合

机器学习代码经验整合

作者: 刘月玮 | 来源:发表于2017-06-07 15:50 被阅读144次

    该文档是诸位同事机器学习代码学习的经验整合,主要流程为:

    1. 导入工具包及数据
    2. Features 及其缺失值处理
    3. 建模

    具体内容如下:

    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()
      
    scatter.png
    • 去除异常值

      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()#直方图
    
    image.png

    左: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.
    natural log.png
    • 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,

    1. 有明确分级的 feature,这些数值的顺序本身是有信息的,比如,"BsmtQual" : {"No" : 0, "Po" : 1, "Fa" : 2, "TA": 3, "Gd" : 4, "Ex" : 5};
    2. 分类关系中分级关系可以比较明确区分出来,如 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 :

    1. Simplifications of existing features
    2. Combinations of existing features
    3. 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。

    Features Choice.png

    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 是有意义的。

    Features and Polynomial Regressions.png

    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)
    
    OneHotEncoder.png

    在回归分析中,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.

    建模

    1. lasso
      1.1 parmaters:alpha
      1.2 建模 和 predict
      1.3 plot 检验结果

    2. xgboost
      2.1 parmaters:
      2.2 建模 和 predict
      2.3 plot 检验结果

    相关文章

      网友评论

          本文标题:机器学习代码经验整合

          本文链接:https://www.haomeiwen.com/subject/dxfafxtx.html