import pandas as pd
import numpy as np
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, FunctionTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.compose import make_column_transformer
from sklearn.pipeline import make_pipeline
16 Workflow review #3
16.1 Recap of our workflow
In this chapter, we’re going to do one final review of the core workflow that we built throughout this book, including all of the features that we developed in the previous chapter.
We begin by importing pandas and NumPy, the four transformer classes we’re using, one modeling class, and two composition functions.
Next, we create a list of the eight columns we’re going to select from our data.
= ['Parch', 'Fare', 'Embarked', 'Sex', 'Name', 'Age', 'Cabin', 'SibSp'] cols
Then, we read in all of our training data and use it to define our X and y.
= pd.read_csv('http://bit.ly/MLtrain')
df = df[cols]
X = df['Survived'] y
And we read in all of the new data and use it to define X_new.
= pd.read_csv('http://bit.ly/MLnewdata')
df_new = df_new[cols] X_new
We create five instances of our transformers, namely two different instances of SimpleImputer, two different instances of OneHotEncoder, and one instance of CountVectorizer.
= SimpleImputer()
imp = SimpleImputer(strategy='constant', fill_value='missing')
imp_constant = OneHotEncoder()
ohe = OneHotEncoder(handle_unknown='ignore')
ohe_ignore = CountVectorizer() vect
We define two custom functions that will be used for feature engineering.
def first_letter(df):
return pd.DataFrame(df).apply(lambda x: x.str.slice(0, 1))
def sum_cols(df):
return np.array(df).sum(axis=1).reshape(-1, 1)
We convert two NumPy functions and our two custom functions into transformers.
= FunctionTransformer(np.ceil)
ceiling = FunctionTransformer(np.clip, kw_args={'a_min':5, 'a_max':60})
clip = FunctionTransformer(first_letter)
letter = FunctionTransformer(sum_cols) total
We create four Pipelines that combine the various transformers.
= make_pipeline(imp_constant, ohe)
imp_ohe = make_pipeline(imp, ceiling)
imp_ceiling = make_pipeline(imp, clip)
imp_clip = make_pipeline(letter, imp_constant, ohe_ignore) letter_imp_ohe
And then we build the ColumnTransformer, which imputes and one-hot encodes Embarked and Sex, vectorizes Name, imputes and takes the ceiling of Fare, imputes and clips Age, imputes and one-hot encodes the first letter of Cabin, and adds SibSp and Parch.
= make_column_transformer(
ct 'Embarked', 'Sex']),
(imp_ohe, ['Name'),
(vect, 'Fare']),
(imp_ceiling, ['Age']),
(imp_clip, ['Cabin']),
(letter_imp_ohe, ['SibSp', 'Parch'])) (total, [
We also create an instance of logistic regression.
= LogisticRegression(solver='liblinear', random_state=1) logreg
We create a two-step modeling Pipeline and fit the Pipeline to X and y.
= make_pipeline(ct, logreg)
pipe
pipe.fit(X, y) pipe
Pipeline(steps=[('columntransformer', ColumnTransformer(transformers=[('pipeline-1', Pipeline(steps=[('simpleimputer', SimpleImputer(fill_value='missing', strategy='constant')), ('onehotencoder', OneHotEncoder())]), ['Embarked', 'Sex']), ('countvectorizer', CountVectorizer(), 'Name'), ('pipeline-2', Pipeline(steps=[('simpleimputer', SimpleImputer()), ('functiontr... FunctionTransformer(func=)), ('simpleimputer', SimpleImputer(fill_value='missing', strategy='constant')), ('onehotencoder', OneHotEncoder(handle_unknown='ignore'))]), ['Cabin']), ('functiontransformer', FunctionTransformer(func= ), ['SibSp', 'Parch'])])), ('logisticregression', LogisticRegression(random_state=1, solver='liblinear'))])
ColumnTransformer(transformers=[('pipeline-1', Pipeline(steps=[('simpleimputer', SimpleImputer(fill_value='missing', strategy='constant')), ('onehotencoder', OneHotEncoder())]), ['Embarked', 'Sex']), ('countvectorizer', CountVectorizer(), 'Name'), ('pipeline-2', Pipeline(steps=[('simpleimputer', SimpleImputer()), ('functiontransformer', FunctionTransformer(func=<... ('pipeline-4', Pipeline(steps=[('functiontransformer', FunctionTransformer(func=)), ('simpleimputer', SimpleImputer(fill_value='missing', strategy='constant')), ('onehotencoder', OneHotEncoder(handle_unknown='ignore'))]), ['Cabin']), ('functiontransformer', FunctionTransformer(func= ), ['SibSp', 'Parch'])])
['Embarked', 'Sex']
SimpleImputer(fill_value='missing', strategy='constant')
OneHotEncoder()
Name
CountVectorizer()
['Fare']
SimpleImputer()
FunctionTransformer(func=)
['Age']
SimpleImputer()
FunctionTransformer(func=, kw_args={'a_max': 60, 'a_min': 5})
['Cabin']
FunctionTransformer(func=)
SimpleImputer(fill_value='missing', strategy='constant')
OneHotEncoder(handle_unknown='ignore')
['SibSp', 'Parch']
FunctionTransformer(func=)
LogisticRegression(random_state=1, solver='liblinear')
Finally, we use the fitted Pipeline to make predictions on X_new.
pipe.predict(X_new)
array([0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1,
1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1,
1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,
1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,
0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0,
1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1,
0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0,
0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0,
1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1,
0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1])
Keep in mind that there are many other steps you can incorporate into this workflow in order to potentially improve performance, including hyperparameter tuning, trying a different model, ensembling, feature selection, feature standardization, and additional feature engineering.
16.2 What’s the role of pandas?
If we can do all of our data transformations in scikit-learn, then you might be left wondering: What’s the role of pandas?
First is data exploration and visualization. A deep understanding of your dataset will help you with many steps of the Machine Learning workflow, especially selecting which features to use and deciding how you might want to transform your features.
Second is testing out data transformations for Machine Learning. If I’m thinking about building a custom transformer in scikit-learn, I first create it using pandas to make sure that it works.
Finally, if your goal is anything other than Machine Learning, then all of your data transformations should still be executed using pandas.
The bottom line is that pandas still has a huge role in the data science workflow. However, if your goal is Machine Learning, then it’s best to shift as much of your workflow as possible to scikit-learn.