sklearn中自定义转换器以及使用流水线对数据进行处理

尽管 Scikit-Learn 提供了许多有用的转换器,你还是需要自己动手写转换器执行任务,比如自定义的清理操作,或属性组合。你需要让自制的转换器与 Scikit-Learn 组件(比如流水线)无缝衔接工作,因为 Scikit-Learn 是依赖鸭子类型的(而不是继承),你所需要做的是创建一个类并执行三个方法: fit() (返回 self ), transform() ,和 fit_transform() 。通过添加 TransformerMixin 作为基类,可以很容易地得到最后一个。另外,如果你添加 BaseEstimator 作为基类(且构造器中避免使用 *args 和 **kargs ),你就能得到两个额外的方法( get_params() 和 set_params() ),二者可以方便地进行超参数自动微调。例如,一个小转换器类添加了上面讨论的属性:(来自hands _On Machine Learning with Scikit_learn&TensorFlow

我们的原始数据格式:

上述数据的第3、4、5、6列数据分别是总共房间数、总共的床数、人口数、总共的家庭数,我们可以通过对这些数据变换得到更加细致的数据。比如可以算出每个家庭拥有的房间数、每个房间平均拥有的床数

首先我们需要使用sklearn中的TransformerMixin和BaseEstimator

 

导入的类:

import pandas as pd
from sklearn.base import BaseEstimator,TransformerMixin


全局变量

  total_rooms,total_bedrooms,population,household=3,4,5,6 #取出我们需要的属性列
 

 

自定义的转换器:

class Attribute_Add(BaseEstimator,TransformerMixin): # 导入两个基类获得fit、transform方法
    def __init__(self,bedrooms_per_room=None):       # bedrooms_per_room=bedrooms_per_room为可选属性,同时我们设置了两个必选属性
        self.bedrooms_per_room=bedrooms_per_room
    def fit(self,x,y=None):
        return self
    def transform(self, x, y=None, ):
          # x=inputdata,y=targetdata
          #下面两个属性为我们必选合成属性
        rooms_per_household = x[:,total_rooms] / x[:,household] # 求取每个房间平均的房间数
        rooms_per_population = x[:,population] / x[:,total_rooms]# 求每个人拥有的平均房间数
        if self.bedrooms_per_room:
          bedrooms_per_room=x[:,total_rooms]/x[:,total_bedrooms]  #bedrooms_per_room为可选的合成属性
          return np.c_[x,rooms_per_househols,rooms_per_population,bedrooms_per_room]
        else:
            return np.c_[x,rooms_per_househols,rooms_per_population]

同理我们定义如下的转换器:get_data()、MyOneHotEncode、

class get_data(BaseEstimator,TransformerMixin):#获取数据表中数值数据或者是文本类型的数据,其中attributes为我们属性值列表
    def __init__(self,attributes):
        self.attributes=attributes;
    def fit(self,x,y=None):
        return self
    def transform(self,x,y=None):
        return x[self.attributes].values
class MyOneHotEncode(BaseEstimator,TransformerMixin):#将文本类型的数据转换成数值类型的数据,然后再转换成独热码
    def __init__(self,data=None):
        self.data=data
    def fit(self,x,y=None):
        return self
    def transform(self,x,y=None):
        encoder = LabelEncoder()
        array1 = encoder.fit_transform(x)
        onehotencode=OneHotEncoder()
        tp=onehotencode.fit_transform(array1.reshape(-1,1))
        #print(tp.toarray())
        return tp.toarray()

 流水线(pipeline)

from sklearn.pipeline import Pipeline  #通俗理解就是前一个转换器的输出作为下一个转换的输入,依次对数据进行处理
from sklearn.pipeline import FeatureUnion #可以理解为多个流水线同时并行对数据操作,各个流水线工作互不影响
"""
sklearn 中的流水线处理数字数据
"""
num_attributes=list(housing_data.drop("ocean_proximity",axis=1))# ocean_proximity为非数值类型的数据,需要去除掉
num_pipeline=Pipeline([
                 ('get_num',get_data(num_attributes)), # 获取数值类型数据
                 ('imputer',Imputer(strategy="median")),#补全数据中的空值(用中位数填充空值)sklearn自带的Imputer      # ( 需要导入,这里没有写出 from sklearm.preprocessing import Imputer)
                 ('add_attributes',Attribute_Add()),    #合成属性
                 ('normalize',StandardScaler()),        #数据标准化

])
"""
sklearn中的流水线处理非数字数据
"""
cat=["ocean_proximity"]  # 非数值属性列
N_num_pipeline=Pipeline([
    ('get_char',get_data(cat)), #获取非数值数据
    ('label_bin',MyOneHotEncode()),转换成独热码
])

使用FeatureUnion来让两个流水线并行工作(from sklearn.pipline import FeatureUnion)

union_pipeline=FeatureUnion(transformer_list=[
    ("pipeline1",num_pipeline),
    ("pipeline2",N_num_pipeline),
])
tq=union_pipeline.fit_transform(housing_data) # 运行 得出的结果是一个简单numpy数组,我们可以将其转换成pd中DataFrame数据
#格式,方便我们查看
list=["rooms_per_househols","rooms_per_population","hot1","hot2","hot3","hot4","hot5"] #为新增的属性列增加名称
num_attributes.extend(list) # 与之前的属性列合并
final_data=pd.DataFrame(tq,columns=num_attributes) #转换成DataFrame
print(final_data) #显示数据

变量空间显示的数据

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值