• 使用sklearn进行数据挖掘-房价预测(4)—数据预处理


    使用sklearn进行数据挖掘系列文章:

    在使用机器算法之前,我们先把数据做下预处理,先把特征和标签拆分出来

    housing = strat_train_set.drop("median_house_value",axis=1) #原始数据集并未发生改变
    housing_labels=strat_train_set["median_house_value"].copy()
    

    数据清洗###

    大多数机器学习算法是不能在有缺失值的数据集上面运行的,而本数据集特征total_bedrooms是存在数据缺失现象的,所以就需要想办法处理,有以下几个思路:

    • 1.将存在缺失数据的样本去除掉
    • 2.将存在缺失数据的特征去除掉
    • 3.将缺失值用统一的值替换,如:均值、中值等

    上面对应的操作:

    housing.dropna(subset=["total_bedrooms"]) # 1.删除样本
    housing.drop("total_bedrooms", axis=1) # 2.删除特征,注意参数的用法和1不一样
    median = housing["total_bedrooms"].median()
    housing["total_bedrooms"].fillna(median) # 3. 中值填充
    

    如果采用的是方法3那么就需要将替换的值保存起来,在后续的工作中需要将它应用到测试集,以及可能添加的新数据。上面这个操作是使用pandas,sklearn提供了Imputer,同样能够很好解决缺失值问题,下面其用法

    from sklearn.preprocessing import Imputer
    imputer = Imputer(strategy="median")
    housing_num = housing.drop("ocean_proximity", axis=1) #去除非数值类特征
    imputer.fit(housing_num)
    

    imputer提供了以下几种填充策略

    • If "mean", then replace missing values using the mean along the axis.
    • If "median", then replace missing values using the median along the axis.
    • If "most_frequent", then replace missing using the most frequent value along the axis.

    通过statistics_ 查看填充的数值

    >>imputer.statistics_
    array([-118.51      ,   34.26      ,   29.        , ...,    5.23228423,
              0.20303137,    2.8176527 ])
    

    再看一看pandas计算出来的中值

    >>housing_num.median().values
    array([-118.51      ,   34.26      ,   29.        , ...,    5.23228423,
              0.20303137,    2.8176527 ])
    

    接下来就需要将计算得到的数值应用到数据集中

    X = imputer.transform(housing_num) 
    >>type(X)
    numpy.ndarray
    

    最终得到的是结果是array类型,如果想转为pandas类型

    housing_tr = pd.DataFrame(X, columns=housing_num.columns)
    

    上面我们把ocean_proximity这一特征去掉,所以这些操作是处理数值类型的特征,那么非数值类型的该如何处理呢?

    处理标签类特征###

    决策树、贝叶斯等分类器能够处理标签类特征,但很多算法是不能处理这类特征,需要转换为数值类型,sklearn提供了LabelEncoder特征转换方法

    from sklearn.preprocessing import LabelEncoder
    encoder = LabelEncoder()
    housing_cat = housing["ocean_proximity"]
    housing_cat_encoded = encoder.fit_transform(housing_cat)
    >>housing_cat_encoded 
     array([0, 0, 4, ..., 1, 0, 3], dtype=int64)
    

    上面是输出编码的结果,那么对应的0、1...是指的什么呢?

    >>encoder.clases_
    array(['<1H OCEAN', 'INLAND', 'ISLAND', 'NEAR BAY', 'NEAR OCEAN'], dtype=object)
    

    通过类别号可以表示类别,还有一种方法能够表示类别---one hot,该特征取的值位置为1,其余为0;当然sklearn也提供了实现方法OneHotEncoder

    from sklearn.preprocessing import OneHotEncoder
    encoder = OneHotEncoder()
    housing_cat_1hot = encoder.fit_transform(housing_cat_encoded.reshape(-1,1))#返回的为稀疏矩阵
    >>housing_cat_1hot.toarray()
    array([[ 1.,  0.,  0.,  0.,  0.],
           [ 1.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  1.],
           ..., 
           [ 0.,  1.,  0.,  0.,  0.],
           [ 1.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  1.,  0.]])
    

    note:housing_cat_encoded返回的为1D 数组,fit_transform需要传入的为一个2D数组,需要先转为列向量。
    可以将上面encoderone hot过程合并为一个

    from sklearn.preprocessing import LabelBinarizer
    encoder = LabelBinarizer()
    housing_cat_1hot=encoder.fit_transform(housing_cat)
    >>housing_cat_1hot #numpy array
    array([[1, 0, 0, 0, 0],
           [1, 0, 0, 0, 0],
           [0, 0, 0, 0, 1],
           ..., 
           [0, 1, 0, 0, 0],
           [1, 0, 0, 0, 0],
           [0, 0, 0, 1, 0]])
    

    自定义处理方法###

    尽管sklearn提供了强大的数据处理功能,有些时候我们需要根据自己的需求自定义一些数据预处理方法,并且让我们这些操作有着sklearnAPI相似的用法,我们所需要做的就是继承BaseEstimator类,并覆写三个方法fittransformfit_transform,第三个方法是前两个的整合,如果不想覆写fit_transform,可以继承TransformerMixin(从类名称就可以看出其作用)这个类

    from sklearn.base import BaseEstimator, TransformerMixin
    rooms_ix, bedrooms_ix, population_ix, household_ix = 3, 4, 5, 6
    class CombinedAttributesAdder(BaseEstimator, TransformerMixin):
        def __init__(self, add_bedrooms_per_room = True): # no *args or **kargs
            self.add_bedrooms_per_room = add_bedrooms_per_room
        def fit(self, X, y=None):
            return self # nothing else to do
        def transform(self, X, y=None):
            rooms_per_household = X[:, rooms_ix] / X[:, household_ix]
            population_per_household = X[:, population_ix] / X[:, household_ix]
            if self.add_bedrooms_per_room:
                bedrooms_per_room = X[:, bedrooms_ix] / X[:, rooms_ix]
                return np.c_[X, rooms_per_household, population_per_household,bedrooms_per_room]
            else:
                return np.c_[X, rooms_per_household, population_per_household]
    
    

    使用方法

    attr_adder = CombinedAttributesAdder(add_bedrooms_per_room=False)
    housing_extra_attribs = attr_adder.transform(housing.values) 
    

    上面定义的类的功能是为原数据集添加新的特征,X[:,3]表示的是第4列所有数据,np.c_表示的是拼接数组。
    另外sklearn是不能直接处理DataFrames的,那么我们需要自定义一个处理的方法将之转化为numpy类型

    class DataFrameSelector(BaseEstimator,TransformerMixin):
        def __init__(self,attribute_names): #可以为列表
            self.attribute_names = attribute_names
        def fit(self,X,y=None):
            return self
        def transform(self,X):
            return X[self.attribute_names].values #返回的为numpy array
    

    特征缩放###

    机器学习算法在缩放尺度不一样的数据效果比较差,比就如房价数据集total_bedrooms的取值范围为1~6445,而median_income的范围是0.5~15,所以需要对特征进行缩放。
    note:通常情况下Target特征不需缩放
    有两种缩放数据的方法

    • min-max方式,对应的方法为
    MinMaxScaler(self, feature_range=(0, 1), copy=True)
    
    • standardization 标准化数据,对应的方法为
    StandardScaler(self, copy=True, with_mean=True, with_std=True)
    

    特征处理流程###

    目前在数据预处理阶段,我们需要对缺失值进行处理、特征组合和特征缩放。每一步的执行都有着先后顺序,sklearn提供了Pipeline帮助顺序完成转换。

    num_attribs = list(housing_num)#返回的为列名[col1,col2,....]
    cat_attribs = ["ocean_proximity"]
    
    num_pipeline = Pipeline([ #数值类型
            ('selector', DataFrameSelector(num_attribs)),
            ('imputer', Imputer(strategy="median")),
            ('attribs_adder', CombinedAttributesAdder()),
            ('std_scaler', StandardScaler()),
        ])
    
    cat_pipeline = Pipeline([ #标签类型
            ('selector', DataFrameSelector(cat_attribs)),
            ('cat_encoder', CategoricalEncoder(encoding="onehot-dense")),
        ])
    

    上面定义的为分别处理数值类型和标签类型的转换流程,housing_numDataFrame类型,list(DataFrame)的结果会是什么?返回的为列名字,不管你们信不信,反正我是信了。pandas真是太强大了。上面着两个流程还可以再整合一起

    from sklearn.pipeline import FeatureUnion
    full_pipeline = FeatureUnion(transformer_list=[
            ("num_pipeline", num_pipeline),
            ("cat_pipeline", cat_pipeline),
        ])
    housing_prepared = full_pipeline.fit_transform(housing)#最终的结果
    

    今天就到这里把,工作了一天好困、眼疼,先发出去,明天再看看有没有什么错误。

  • 相关阅读:
    T-SQL取时间的不同方法
    JavaScript获取地址栏中的参数值并存入一个对象
    jquery.ocupload上传文件到指定目录
    Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(三)
    Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(二)
    Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(一)
    Python2.x和3.x主要差异总结
    python学习视频整理
    Django-Rest-Framework 教程: 快速入门
    Django RESTful API 设计指南
  • 原文地址:https://www.cnblogs.com/wxshi/p/7764518.html
Copyright © 2020-2023  润新知