<jupyter_start><jupyter_text>ML Pipeline PreparationFollow the instructions below to help you create your ML pipeline. 1. Import libraries and load data from database.- Import Python libraries- Load dataset from database with [`read_sql_table`](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_sql_table.html)- Define feature and target variables X and Y<jupyter_code># import libraries
import pandas as pd
from sqlalchemy import create_engine
# load data from database
engine = create_engine('sqlite:///MesCat.db')
df = pd.read_sql_table('mescat_df',con=engine)
df.head()
X = df.message.values
cols = list(df.columns[3:])
Y = df[cols]
X[0]<jupyter_output><empty_output><jupyter_text>2. Write a tokenization function to process your text data<jupyter_code>import nltk
import re
from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer

from sklearn.pipeline import Pipeline,FeatureUnion
from sklearn.multioutput import MultiOutputClassifier
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.metrics import classification_report
from sklearn.model_selection import GridSearchCV
from sklearn.base import BaseEstimator, TransformerMixin
def tokenize(text):
    tokens = word_tokenize(text)
    lemmatizer = WordNetLemmatizer()

    clean_tokens = []
    for tok in tokens:
        clean_tok = lemmatizer.lemmatize(tok).lower().strip()
        clean_tokens.append(clean_tok)
        
    return clean_tokens

class StartingVerbExtractor(BaseEstimator, TransformerMixin):

    def starting_verb(self, text):
        sentence_list = nltk.sent_tokenize(text)
        for sentence in sentence_list:
            pos_tags = nltk.pos_tag(tokenize(sentence))
            first_word, first_tag = pos_tags[0]
            if first_tag in ['VB', 'VBP'] or first_word == 'RT':
                return True
        return False

    def fit(self, x, y=None):
        return self

    def transform(self, X):
        X_tagged = pd.Series(X).apply(self.starting_verb)
        return pd.DataFrame(X_tagged)<jupyter_output><empty_output><jupyter_text>3. Build a machine learning pipelineThis machine pipeline should take in the `message` column as input and output classification results on the other 36 categories in the dataset. You may find the [MultiOutputClassifier](http://scikit-learn.org/stable/modules/generated/sklearn.multioutput.MultiOutputClassifier.html) helpful for predicting multiple target variables.<jupyter_code>pipeline = Pipeline([
    ('features', FeatureUnion([

        ('text_pipeline', Pipeline([
            ('vect', CountVectorizer(tokenizer=tokenize)),
            ('tfidf', TfidfTransformer())
        ])),

        ('starting_verb', StartingVerbExtractor())
    ])),

    ('clf', MultiOutputClassifier(RandomForestClassifier()))
])<jupyter_output><empty_output><jupyter_text>4. Train pipeline- Split data into train and test sets- Train pipeline<jupyter_code>X_train, X_test, Y_train, Y_test = train_test_split(X, Y)
# train classifier
pipeline.fit(X_train, Y_train)
# predict on test data
Y_pred = pipeline.predict(X_test)<jupyter_output><empty_output><jupyter_text>5. Test your modelReport the f1 score, precision and recall for each output category of the dataset. You can do this by iterating through the columns and calling sklearn's `classification_report` on each.<jupyter_code>for i,col in enumerate(cols):
    print('\n\n')
    print('######%s######'%col)
    print(classification_report(Y_test[col], Y_pred[:,i]))<jupyter_output>######related######
             precision    recall  f1-score   support

          0       0.34      0.12      0.18      1524
          1       0.77      0.93      0.84      4980
          2       0.12      0.02      0.04        48

avg / total       0.66      0.73      0.68      6552




######request######
             precision    recall  f1-score   support

          0       0.84      0.98      0.90      5466
          1       0.38      0.07      0.11      1086

avg / total       0.76      0.83      0.77      6552




######offer######
             precision    recall  f1-score   support

          0       1.00      1.00      1.00      6527
          1       0.00      0.00      0.00        25

avg / total       0.99      1.00      0.99      6552




######aid_related######
             precision    recall  f1-score   support

          0       0.59      0.82      0.68      3809
          1       0.44      0.19      0.27      2743

avg / total       0.52      0.56      0.51     [...]<jupyter_text>6. Improve your modelUse grid search to find better parameters.<jupyter_code>pipeline.get_params().keys()
parameters = {
            # 'clf__estimator__n_estimators': [50, 100, 200],
            # 'clf__estimator__min_samples_split': [2, 3, 4],
            'features__transformer_weights': (
                {'text_pipeline': 1, 'starting_verb': 0.5},
                {'text_pipeline': 0.5, 'starting_verb': 1},
                {'text_pipeline': 0.8, 'starting_verb': 1},)
            }

cv = GridSearchCV(pipeline, param_grid=parameters)
cv.fit(X_train, Y_train)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10049580472921434, 'fraction_numerical': 0.039282990083905414, 'mean_word_length': 2.8090050835148874, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 24, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '466368', 'license': 'MIT', 'n_tokens_mistral': 1726, 'n_tokens_neox': 1598, 'n_words': 416, 'path': 'ML Pipeline Preparation.ipynb', 'repo_name': 'cissoidx/Disaster_Response_Pipelines', 'size': '5244'}