scikit-learn的ColumnTransformer和OneHotEncoder

栏目: 数据库 · 发布时间: 6年前

内容简介:本文介绍scikit-learn 0.20版本中新增的假设现在有这样一个场景:有一个数据集,每个样本包含n个数值型(numeric)特征,m个标称型(categorical)特征,我们在使用这个数据集训练模型之前,需要对n个数值型特征做归一化,对m个标称型特征做one-hot编码?这个要如何实现?其实这个不难,但挺麻烦的。一般的方式是把数值型的特征数据列和标称型数据分别拿出来,然后分别做预处理,处理完之后再拼在一起训练模型。这样一方面是麻烦,另一方面比较难保证原来特征的顺序(虽然顺序一般没什么影响)。sc

本文介绍scikit-learn 0.20版本中新增的 sklearn.compose.ColumnTransformer 和有所改动的 sklearn.preprocessing.OneHotEncoder

ColumnTransformer

假设现在有这样一个场景:有一个数据集,每个样本包含n个数值型(numeric)特征,m个标称型(categorical)特征,我们在使用这个数据集训练模型之前,需要对n个数值型特征做归一化,对m个标称型特征做one-hot编码?这个要如何实现?

其实这个不难,但挺麻烦的。一般的方式是把数值型的特征数据列和标称型数据分别拿出来,然后分别做预处理,处理完之后再拼在一起训练模型。这样一方面是麻烦,另一方面比较难保证原来特征的顺序(虽然顺序一般没什么影响)。scikit-learn在0.20.0版本中新增了一个 sklearn.compose.ColumnTransformer 类,通过这个类我们可以对输入的特征分别做不同的预处理,并且最终的结果还在一个特征空间里面。描述太抽象,直接看官方的里一个 例子

# Author: Pedro Morales <part.morales@gmail.com>
#
# License: BSD 3 clause

from __future__ import print_function

import pandas as pd
import numpy as np

from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, GridSearchCV

np.random.seed(0)

# Read data from Titanic dataset.
titanic_url = ('https://raw.githubusercontent.com/amueller/'
               'scipy-2017-sklearn/091d371/notebooks/datasets/titanic3.csv')
data = pd.read_csv(titanic_url)

# We will train our classifier with the following features:
# Numeric Features:
# - age: float.
# - fare: float.
# Categorical Features:
# - embarked: categories encoded as strings {'C', 'S', 'Q'}.
# - sex: categories encoded as strings {'female', 'male'}.
# - pclass: ordinal integers {1, 2, 3}.

# We create the preprocessing pipelines for both numeric and categorical data.
numeric_features = ['age', 'fare']
numeric_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler())])

categorical_features = ['embarked', 'sex', 'pclass']
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='constant', fill_value='missing')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))])

preprocessor = ColumnTransformer(
    transformers=[
        ('num', numeric_transformer, numeric_features),
        ('cat', categorical_transformer, categorical_features)])

# Append classifier to preprocessing pipeline.
# Now we have a full prediction pipeline.
clf = Pipeline(steps=[('preprocessor', preprocessor),
                      ('classifier', LogisticRegression(solver='lbfgs'))])

X = data.drop('survived', axis=1)
y = data['survived']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

clf.fit(X_train, y_train)
print("model score: %.3f" % clf.score(X_test, y_test))

# output:
# model score: 0.790

例子很简单,里面的注释已经表述的比较清楚了:读入了 titanic3.csv 数据集,里面包含了2个数值型特征( age , fare )和3个标称型特征( embarked , sex , pclass ),然后对数值型特征做缺失值处理和归一化,对标称型特征做缺失值处理和One-Hot编码。例子里面使用Pipeline将这些操作串了起来。

我们看下 sklearn.compose.ColumnTransformer 的原型:

class sklearn.compose.ColumnTransformer(transformers, remainder=’drop’, sparse_threshold=0.3, n_jobs=None, transformer_weights=None)

简单介绍一下 transformersremainder 两个参数:

  • transformers:该参数是一个由元组组成的列表(list of tuples),每个元组的结构为:(name, transformer, column):

    • name: transformer的名字,随便起一个字符串即可;
    • transformer: 支持 fittransform 的estimator或者 passthrough 或者 drop . passthrough表示透传,不对column指定的列做任何转换;drop表示丢弃指定column指定的列。
    • column: 指定对哪些列做转换操作,所以可以是下标、列名等。
  • remainder:这个参数的值可以是支持 fittransform 的estimator或者 passthrough 或者 drop ,默认值是drop,其功能和transformers参数非常像:

    • drop:表示将column指定的列之外的其他列都丢弃;
    • passthrough:表示将column指定的列之外的其他列透传;
    • estimator:表示对column指定的列之外的其他列执行该estimator代表的转换。

新功能的使用还是非常容易的。

OneHotEncoder

scikit-learn 0.20版本里面另外一个比较重要的改动就是 sklearn.preprocessing.OneHotEncoder 除了支持整数外,还支持字符串。这样如果特征是字符串,就省去了原来需要做 sklearn.preprocessing.LabelEncoder 的步骤。

老的 sklearn.preprocessing.OneHotEncoder 原型:

class sklearn.preprocessing.OneHotEncoder(n_values=’auto’, categorical_features=’all’, dtype=<class ‘numpy.float64’>, sparse=True, handle_unknown=’error’)

新的 sklearn.preprocessing.OneHotEncoder 原型:

class sklearn.preprocessing.OneHotEncoder(n_values=None, categorical_features=None, categories=None, sparse=True, dtype=<class ‘numpy.float64’>, handle_unknown=’error’)

可以看到新老API的主要差别是新API增加了一个 categories 参数,这个参数是为了替换里面的 n_values 参数;后者在0.22版本中就去掉了。而且如果要OneHotEncoder支持字符串的话,就必须使用 categories ,不能使用 n_values 了。我们简单介绍一下 categories 这个参数,该参数的可取值为: 'auto' ( 默认值,表示根据训练数据自己决定categories;)或一个 list of list/array 。前者很容易理解,后者稍微难理解一些,我们通过例子来看。

>>> enc = preprocessing.OneHotEncoder()
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)  
OneHotEncoder(categorical_features=None, categories=None,
       dtype=<... 'numpy.float64'>, handle_unknown='error',
       n_values=None, sparse=True)
>>> enc.transform([['female', 'from US', 'uses Safari'],
...                ['male', 'from Europe', 'uses Safari']]).toarray()
array([[1., 0., 0., 1., 0., 1.],
       [0., 1., 1., 0., 0., 1.]])

# 可以通过categories_属性查看所有类别
>>> enc.categories_
[array(['female', 'male'], dtype=object),
 array(['from Europe', 'from US'], dtype=object),
 array(['uses Firefox', 'uses Safari'], dtype=object)]

上例中, categories 采用默认值,如果我们需要使用list实现等效的效果的话,可以按照如下方式改写上面代码:

>>> enc_new = preprocessing.OneHotEncoder(categories=[['male', 'female'],['from Europe', 'from US'],['uses Firefox', 'uses Safari']])
>>> enc_new.fit(X)
OneHotEncoder(categorical_features=None,
       categories=[['male', 'female'], ['from Europe', 'from US'], ['uses Firefox', 'uses Safari']],
       dtype=<class 'numpy.float64'>, handle_unknown='error',
       n_values=None, sparse=True)
>>> enc_new.transform([['female', 'from US', 'uses Safari'],
...                ['male', 'from Europe', 'uses Safari']]).toarray()
array([[1., 0., 0., 1., 0., 1.],
       [0., 1., 1., 0., 0., 1.]])
>>> enc_new.categories_
[array(['male', 'female'], dtype=object),
 array(['from US', 'from Europe'], dtype=object),
 array(['uses Safari', 'uses Firefox'], dtype=object)]

例子已经展示的很清楚了, categories 的值取list of list/array时候,里面的 categories[i] 表示第i列特征的categories。同时需要注意:**在单个特征的list/array里面,其值要么是numeric要么是string,不能混用;如果是numeric,还需要是 排序 的。

Reference:


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Introduction to Semi-Supervised Learning

Introduction to Semi-Supervised Learning

Xiaojin Zhu、Andrew B. Goldberg / Morgan and Claypool Publishers / 2009-6-29 / USD 40.00

Semi-supervised learning is a learning paradigm concerned with the study of how computers and natural systems such as humans learn in the presence of both labeled and unlabeled data. Traditionally, le......一起来看看 《Introduction to Semi-Supervised Learning》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具