• python学习09之分类变量


      本次学习,我们将了解什么是分类变量以及处理这类数据的三种方法。

      1、介绍

        分类变量只接受有限数量的值。

        考虑一项调查,询问你多久吃一次早餐,并提供四个选项:“从不”、“很少”、“大多数日子”或“每天”。

        在本例中,数据是分类的,因为响应属于一组固定的类别。如果人们对他们所拥有的汽车品牌进行调查,他们的回答可以分为“本田”、“丰田”和“福特”。

        在本例中,数据也是分类的。如果我们试图在没有预先处理这些变量的情况下将这些变量插入Python中的大多数机器学习模型中,那么我们将会得到一个错误。

      2、三种方法的使用

        1)、删除分类变量

           处理分类变量最简单的方法是从数据集中删除它们。这种方法只有在列中不包含有用信息的情况下才能很好地工作。

        2)、标签的编码

           标签编码将每个惟一值分配给不同的整数。

           这种方法假设类别的顺序为:“Never”(0)<“rare”(1)<“Most days”(2)<“Every day”(3)。

           在本例中,这个假设是有意义的,因为对类别有一个无可争议的排名。

           并不是所有的分类变量在值中都有一个明确的顺序,但是我们将那些有顺序的变量称为有序变量。

           对于基于树的模型(如决策树和随机森林),可以期望标签编码能够很好地处理有序变量。

        3)、独热编码

           独热编码创建新列,指示原始数据中每个可能值的存在(或不存在)。

             为了理解这一点,我们将通过一个例子:

              在原始数据集中,“颜色”是一个类别变量,有三个类别:“红色”、“黄色”和“绿色”。

              对应的独热编码包含每个可能值的一列,以及原始数据集中每行的一行。当原值为“红色”时,我们在“红色”列中加1;如果原值为“黄色”,我们在“黄色”列中加1,依此类推。

                 与标签编码不同,一个热编码不假定类别的顺序。

              因此,如果分类数据中没有明确的顺序(例如,“红色”既不大于也不小于“黄色”),您可以期望这种方法特别有效。

              我们把没有内在排序的分类变量称为名义变量。             

              如果类别变量具有大量值(即,通常不会将其用于超过15个不同值的变量),则一个热编码通常无法很好地执行。 

      3、举例说明

         和上一次的学习一样,我们将使用墨尔本住房的数据集

    import pandas as pd
    from sklearn.model_selection import train_test_split
    #读取数据
    data = pd.read_csv('E:/data_handle/melb_data.csv')
    #从预测器中分离目标
    y =data.Price
    X = data.drop(['Price'],axis=1)
    #将数据划分为训练和验证子集
    X_train_full, X_valid_full, y_train, y_valid = train_test_split(X, y, train_size=0.8,test_size=0.2,random_state=0)
    #删除有缺少值得列
    cols_with_missing = [col for col in X_train_full.columns
                         if X_train_full[col].isnull().any()]
    X_train_full.drop(cols_with_missing, axis=1, inplace=True)
    X_valid_full.drop(cols_with_missing, axis=1, inplace=True)
    #“基数”是指列中唯一的数目
    #选择技术相对较低的分类列(方便但随意)
    low_cardinality_cols = [cname for cname in X_train_full.columns
                            if X_train_full[cname].dtype == 'object']
    #选择数字列
    numerical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].dtype in ['int64', 'float64']]
    #仅仅保留所选列
    my_cols = low_cardinality_cols + numerical_cols
    X_train = X_train_full[my_cols].copy()
    X_valid = X_valid_full[my_cols].copy()
    #打印前五行数据
    print(X_train.head())

        接下来,我们获得训练数据中所有分类变量的列表。

           我们通过检查每个列的数据类型(或dtype)来做到这一点。
          对象dtype表示列中有文本(理论上它还可以有其他内容,但这对我们的目的并不重要)。  
          对于这个数据集,带有文本的列表示分类变量。
    #获取分类变量列表
    s = (X_train.dtypes == 'object')
    object_cols = list(s[s].index)
    
    print("Categorical variables:")
    print(object_cols)

      4、定义功能来度量每种方法的质量

         我们定义了一个函数score_dataset()来比较处理分类变量的三种不同方法。该函数报告随机森林模型的平均绝对误差(MAE)。一般来说,我们希望MAE尽可能低!
    def score_dataset(X_train, X_valid, y_train, y_valid):
        model = RandomForestRegressor(n_estimators=100, random_state=0)
        model.fit(X_train,y_train)
        preds = model.predict(X_valid)
        return mean_absolute_error(y_valid,preds)

      5、三种方法的MAE得分

        1)、第一种方法

    #方法一求取MAE的值
    drop_X_train = X_train.select_dtypes(exclude=['object'])
    drop_X_valid = X_valid.select_dtypes(exclude=['object'])
    print("MAE from Approach 1 (Drop categorical variables):")
    print(score_dataset(drop_X_train, drop_X_valid, y_train, y_valid))

        2)、第二种方法

    #复制以避免更改原始数据
    label_X_train = X_train.copy()
    label_X_valid = X_valid.copy()
    #将标签编码器应用于每一列与分类数据
    label_encoder = LabelEncoder()
    for col in object_cols:
        label_X_train[col] = label_encoder.fit_transform(X_train[col])
        label_X_valid[col] = label_encoder.transform(X_valid[col])
    print("MAE from Approach 2 (Label Encoding):")
    print(score_dataset(label_X_train, label_X_valid, y_train, y_valid))

          在上面的代码单元格中,对于每一列,我们将每个惟一的值随机分配给一个不同的整数。

          这是一种比提供自定义标签更简单的常见方法;然而,如果我们为所有有序变量提供更好的信息标签,我们可以期望额外的性能提升。    

            但是第二种方法我出现了bug,暂时还未解决,解决ing

        3)、第三种方法

          独热编码:

            我们使用来自scikit-learn的OneHotEncoder类来获得一次热编码。

            有许多参数可用于自定义其行为。

            当验证数据包含训练数据中没有表示的类时,我们设置handle_unknown='ignore'以避免错误,而设置sparse=False确保以numpy数组(而不是稀疏矩阵)的形式返回编码的列。

            要使用编码器,我们只提供我们希望进行单热编码的分类列。

            例如,为了编码训练数据,我们提供X_train[object_cols]。(下面代码单元格中的object_cols是包含分类数据的列名列表,因此X_train[object_cols]包含训练集中的所有分类数据。)

    #方法三求取MAE的值
    
    #对每个列应用独热编码器,其中包含分类数据
    OH_encoder = OneHotEncoder(handle_unknown='ignore', sparse=False)
    OH_cols_train = pd.DataFrame(OH_encoder.fit_transform(X_train[object_cols]))
    OH_cols_valid = pd.DataFrame(OH_encoder.transform(X_valid[object_cols]))
    
    #独热编码删除索引;并放回原处
    OH_cols_train.index = X_train.index
    OH_cols_valid.index = X_valid.index
    
    #删除分类列(将替换为独热编码)
    num_X_train = X_train.drop(object_cols, axis=1)
    num_X_valid = X_valid.drop(object_cols, axis=1)
    
    #向数值特性添加独热编码列
    OH_X_train = pd.concat([num_X_train, OH_cols_train], axis=1)
    OH_X_valid = pd.concat([num_X_valid, OH_cols_valid], axis=1)
    
    print("MAE from Approach 3 (One-Hot Encoding):")
    print(score_dataset(OH_X_train, OH_X_valid, y_train, y_valid))

      5、总结

        哪种方法最好?

          在本例中,删除分类列(方法1)的性能最差,因为它有最高的MAE得分。

          至于另外两种方法,由于返回的MAE分数非常接近,因此其中一种方法对另一种方法似乎没有任何有意义的好处。

          通常,独热编码(方法3)的性能最好,而删除分类列(方法1)的性能最差,但具体情况有所不同。

    本次学习到此结束!!!!!

  • 相关阅读:
    shell脚本学习001
    Discuz 代码分析 001 forum.php
    Oauth2.0 入门
    第一篇文章
    position的四个属性值: relative ,absolute ,fixed,static
    JQuery中stop([clearQueue],[goToEnd])介绍
    <meta>
    sublime 2中Package control安装和使用
    ios 状态码
    <video>和<audio>标签,对视频和音频的支持
  • 原文地址:https://www.cnblogs.com/fb1704011013/p/11196714.html
Copyright © 2020-2023  润新知