<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>from sklearn.svm import LinearSVC
import pandas as pd
from sqlalchemy import create_engine
import re
import nltk
nltk.download(['punkt', 'wordnet','stopwords','averaged_perceptron_tagger'])
from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.multioutput import MultiOutputClassifier
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.model_selection import train_test_split, GridSearchCV
import numpy as np
from sklearn.metrics import confusion_matrix
from sklearn.metrics import make_scorer, accuracy_score, f1_score, fbeta_score, classification_report
from sklearn.base import BaseEstimator, TransformerMixin
import pickle
from sklearn.svm import SVC
# load data from database
engine = create_engine('sqlite:///Database.db')
df = pd.read_sql_table('df',engine)
X = df.message
y = df[df.columns[4:]]<jupyter_output><empty_output><jupyter_text>2. Write a tokenization function to process your text data<jupyter_code>def tokenize(text):
    
    text = re.sub(r"[^a-zA-Z0-9]"," ",text)
    tokens = word_tokenize(text)
    lemmatizer = WordNetLemmatizer()
    

    clean_tokens = []
    for tok in tokens:
        if tok not in stopwords.words("english"):
            clean_tok = lemmatizer.lemmatize(tok).lower().strip()
            clean_tokens.append(clean_tok)

    return clean_tokens
print(tokenize(X[10]))<jupyter_output>['there', 'nothing', 'eat', 'water', 'starving', 'thirsty']<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>last=MultiOutputClassifier(RandomForestClassifier())
pipeline = Pipeline([
        ("vect",CountVectorizer(tokenizer=tokenize)),
        ("tdidf",TfidfTransformer()),
        ("clf",last)
    ])<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)
pipeline.fit(X_train,y_train)

# predict on test data

y_pred=pipeline.predict(X_test)
# display results<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>"""
y_pred_pd = pd.DataFrame(y_pred, columns = y_test.columns)
for column in y_test.columns:
    print('------------------------------------------------------\n')
    print('FEATURE: {}\n'.format(column))
    print(classification_report(y_test[column],y_pred_pd[column]))
"""    
print(classification_report(y_test.iloc[:,1:].values, np.array([x[1:] for x in y_pred]), target_names=y.columns))<jupyter_output>precision    recall  f1-score   support

               related       0.80      0.43      0.56      1091
               request       0.00      0.00      0.00        30
                 offer       0.75      0.60      0.67      2716
           aid_related       0.52      0.05      0.09       550
          medical_help       0.79      0.09      0.16       326
      medical_products       0.55      0.06      0.11       179
     search_and_rescue       0.00      0.00      0.00       127
              security       0.69      0.12      0.20       230
              military       0.00      0.00      0.00         0
           child_alone       0.81      0.48      0.60       393
                 water       0.83      0.46      0.59       706
                  food       0.82      0.24      0.37       554
               shelter       0.71      0.12      0.21        83
              clothing       0.70      0.06      0.10       127
                 money       0.50      [...]<jupyter_text>6. Improve your modelUse grid search to find better parameters.<jupyter_code>parameters = {'clf__estimator__n_estimators': [100, 200],
              'clf__estimator__min_samples_leaf':[2, 5],
              'clf__estimator__max_depth': [2, 5, None],
                 }

cv = GridSearchCV(pipeline, parameters)<jupyter_output><empty_output><jupyter_text>7. Test your modelShow the accuracy, precision, and recall of the tuned model.  Since this project focuses on code quality, process, and  pipelines, there is no minimum performance metric needed to pass. However, make sure to fine tune your models for accuracy, precision and recall to make your project stand out - especially for your portfolio!<jupyter_code>cv.fit(X_train,y_train)
y_pred_2 = cv.predict(X_test)
print(classification_report(y_test.iloc[:,1:].values, np.array([x[1:] for x in y_pred_2]), target_names=y.columns))<jupyter_output><empty_output><jupyter_text>8. Try improving your model further. Here are a few ideas:* try other machine learning algorithms* add other features besides the TF-IDF  8.1 Create Startingverbextractorfunction<jupyter_code>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>8.2 new model pipelineThe new model will have:- The startingverbextractor function- The AdaBoostClassifier() algorithm<jupyter_code>def model_pipeline():
    pipeline = Pipeline([
        ('features', FeatureUnion([

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

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

        ('clf', MultiOutputClassifier(AdaBoostClassifier()))
    ])

    return pipeline<jupyter_output><empty_output><jupyter_text>8.3 train new model<jupyter_code>X_train, X_test, y_train, y_test = train_test_split(X, y)
model_pipeline.fit(X_train,y_train)

# predict on test data
y_pred_improved=model_pipeline.predict(X_test)<jupyter_output><empty_output><jupyter_text>8.4 show results<jupyter_code>print(classification_report(y_test.iloc[:,1:].values, np.array([x[1:] for x in y_pred_improved]), target_names=y.columns))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10128661374212976, 'fraction_numerical': 0.029290993703805092, 'mean_word_length': 3.2334878331402086, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 43, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '361719', 'license': 'MIT', 'n_tokens_mistral': 2346, 'n_tokens_neox': 2232, 'n_words': 563, 'path': 'models/ML Pipeline Preparation.ipynb', 'repo_name': 'sergioperezz/Disaster-response-Pipeline-UND', 'size': '7306'}