<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
import numpy as np
from sqlalchemy import create_engine
import sys
import re
import pickle
import nltk
from nltk.tokenize import word_tokenize,sent_tokenize
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier,AdaBoostClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer, TfidfVectorizer
from sklearn.multioutput import MultiOutputClassifier
from sklearn.pipeline import Pipeline
from sklearn.metrics import precision_recall_fscore_support,accuracy_score,label_ranking_average_precision_score
from sklearn.model_selection  import GridSearchCV

nltk.download(['punkt','stopwords','wordnet'])
def load_data(db_path='workspace/data/DisasterResponse.db',tablename='disastertab'):
    """
    Function: load data from database and return X and y.
    Args:
      db_path(str): database file name included path
      tablename:(str): table name in the database file.
    Return:
      X(pd.DataFrame): messages for X
      y(pd.DataFrame): labels part in messages for y
    """
    # load data from database
    engine = create_engine('sqlite:///'+db_path)
    df=pd.read_sql_table(tablename, engine)
    X = df['message']
    # result is multiple classifty.
    y = df.iloc[:,4:]
    return X, y
X,y=load_data()
print(X[:5].values.tolist())
#need sent_tokenize to parse X.<jupyter_output>['Weather update - a cold front from Cuba that could pass over Haiti', 'Is the Hurricane over or is it not over', 'Looking for someone but no name', 'UN reports Leogane 80-90 destroyed. Only Hospital St. Croix functioning. Needs supplies desperately.', 'says: west side of Haiti, rest of the country today and tonight']<jupyter_text>2. Write a tokenization function to process your text data<jupyter_code>def tokenize(text):
    """
    Function: tokenize the text
    Args:  source string
    Return:
    clean_tokens(str list): clean string list
    
    """
    #normalize text
    text = re.sub(r'[^a-zA-Z0-9]',' ',text.lower())
    
    #token messages
    words = word_tokenize(text)
    tokens = [w for w in words if w not in stopwords.words("english")]
    
    #sterm and lemmatizer
    lemmatizer = WordNetLemmatizer()
    clean_tokens = []
    for tok in tokens:
        clean_tok = lemmatizer.lemmatize(tok).strip()
        clean_tokens.append(clean_tok)

    return clean_tokens<jupyter_output><empty_output><jupyter_text>3. Build a machine learning pipeline- You'll find the [MultiOutputClassifier](http://scikit-learn.org/stable/modules/generated/sklearn.multioutput.MultiOutputClassifier.html) helpful for predicting multiple target variables.<jupyter_code>pipeline = Pipeline([
    ('vect',TfidfVectorizer(tokenizer=tokenize)),
    ('clf', MultiOutputClassifier(RandomForestClassifier(n_estimators=200)))
])<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,test_size=0.2, random_state=42)
pipeline.fit(X_train,y_train)<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>def display_results(Y_test, y_pred):
    
    result=precision_recall_fscore_support(Y_test, y_pred)
    for i, col in enumerate(Y_test.columns.values):
        accu=accuracy_score(Y_test.loc[:,col],y_pred[:,i])
        score = ('{}\n Accuracy:  {:.4f}   % Precision: {:.4f}   % Recall {:.4f} '.format(
                  col,accu,result[0][i],result[1][i]))
        print(score)
    avg_precision = label_ranking_average_precision_score(Y_test, y_pred)
    avg_score= ('label ranking average precision: {}'.format(avg_precision))
    print(avg_score)
    
    
y_pred=pipeline.predict(X_test)
display_results(y_test, y_pred)
pipeline.get_params()
from sklearn.externals import joblib
model = joblib.load("workspace/models/classifier.pkl")
print(model.best_params_)
p1=model.best_estimator_
p1.get_params()<jupyter_output>{'clf__estimator__min_samples_leaf': 1, 'clf__estimator__max_features': 'auto', 'vect__smooth_idf': True}<jupyter_text>pipeline = Pipeline([        ('vect',TfidfVectorizer(tokenizer=tokenize)),        ('clf', MultiOutputClassifier(RandomForestClassifier(n_estimators=200,random_state=20)))    ])    parameters = {        'clf__estimator__min_samples_leaf': [1,10],        'clf__estimator__max_features': ['auto','log2'],        'vect__smooth_idf':[True]    }      6. Improve your modelUse grid search to find better parameters.<jupyter_code>parameters = {
    'clf__estimator__min_samples_leaf': [1,10],
    'clf__estimator__max_features': ['auto','log2'],
    'vect__smooth_idf':[True]
}

# create grid search object
cv = GridSearchCV(pipeline, param_grid=parameters,n_jobs=-1)<jupyter_output><empty_output><jupyter_text>parameters_bak = {    'clf__estimator__n_estimators': [200,100],    'clf__estimator__max_depth': [3,15],    'clf__estimator__min_samples_leaf': [1,8],    'vect__smooth_idf': [True,False],    'vect__sublinear_tf':[True,False]}<jupyter_code>cv.fit(X_train, y_train)
y_pred = cv.predict(X_test)<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>display_results(y_test, y_pred)<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<jupyter_code>pipeline = Pipeline([
    ('vect',TfidfVectorizer(tokenizer=tokenize)),
    ('clf',  MultiOutputClassifier(AdaBoostClassifier()))
])
pipeline.get_params()
parameters = {
    'vect__smooth_idf': [True,False],
}
# create grid search object
cv = GridSearchCV(pipeline, param_grid=parameters,n_jobs=-1)
cv.fit(X_train, y_train)
y_pred = cv.predict(X_test)   
display_results(y_test, y_pred)<jupyter_output><empty_output><jupyter_text>9. Export your model as a pickle file<jupyter_code>with open('classifer.pkl', 'wb') as f:
    pickle.dump(cv, f)<jupyter_output><empty_output><jupyter_text>10. Use this notebook to complete `train.py`Use the template file attached in the Resources folder to write a script that runs the steps above to create a database and export a model based on a new dataset specified by the user.<jupyter_code>import pandas as pd
import numpy as np
from sqlalchemy import create_engine
import sys
import re
import pickle
import nltk
from nltk.tokenize import word_tokenize,sent_tokenize
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier,AdaBoostClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer, TfidfVectorizer
from sklearn.multioutput import MultiOutputClassifier
from sklearn.pipeline import Pipeline
from sklearn.metrics import precision_recall_fscore_support,accuracy_score
from sklearn.model_selection  import GridSearchCV

nltk.download(['punkt','stopwords','wordnet'])

def load_data(db_path='workspace/data/DisasterResponse.db',tablename='disastertab'):
    """
    Function: load data from database and return X and y.
    Args:
      db_path(str): database file name included path
      tablename:(str): table name in the database file.
    Return:
      X(pd.DataFrame): messages for X
      y(pd.DataFrame): labels part in messages for y
    """
    # load data from database
    engine = create_engine('sqlite:///'+db_path)
    df=pd.read_sql('SELECT * from '+tablename, engine)
    X = df['message']
    # result is multiple classifty.
    y = df.iloc[:,4:]
    return X, y

def tokenize(text):
    """
    Function: tokenize the text
    Args:  source string
    Return:
    clean_tokens(str list): clean string list
    
    """
    #normalize text
    text = re.sub(r'[^a-zA-Z0-9]',' ',text.lower())
    
    #token messages
    words = word_tokenize(text)
    tokens = [w for w in words if w not in stopwords.words("english")]
    
    #sterm and lemmatizer
    lemmatizer = WordNetLemmatizer()
    clean_tokens = []
    for tok in tokens:
        clean_tok = lemmatizer.lemmatize(tok).strip()
        clean_tokens.append(clean_tok)

    return clean_tokens

def build_model(): 
    """
    Function: build model that consist of pipeline
    Args:
      N/A
    Return
      cv(model): Grid Search model 
    """
    
    pipeline = Pipeline([
        ('vect',TfidfVectorizer(tokenizer=tokenize)),
        ('clf', MultiOutputClassifier(RandomForestClassifier(n_estimators=200,random_state=20)))
    ]) 
    
    parameters = {
        'clf__estimator__criterion':['entropy']
    }
    
    # create grid search object
    cv = GridSearchCV(pipeline, param_grid=parameters,n_jobs=-1)
    return cv

def evaluate_model(y_test, y_pred):
    result=precision_recall_fscore_support(Y_test, y_pred)
    for i, col in enumerate(category_names):
        accu=accuracy_score(Y_test.loc[:,col],y_pred[:,i])
        print('{}\n Accuracy: {:.4f}    % Precision: {:.4f}   % Recall {:.4f} '.format(
            col,accu,result[0][i],result[1][i]))
    
def save_model(cv):
    """
    Function: save model as pickle file.
    Args:
      cv:target model
    Return:
      N/A
    """
    with open('classifer.pkl', 'wb') as f:
        pickle.dump(cv, f)    
def main(): 
    print("Load data")
    X,y=load_data()
    X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2, random_state=42)
    print("Build model")
    model=build_model()
    print("Train model")
    model.fit(X_train,y_train)
    y_pred=model.predict(X_test)
    print("Evaluation model")
    evaluate_model(y_test, y_pred)
    print("Save model")
    save_model(model)

if __name__ == "__main__":
    main()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10314270052987393, 'fraction_numerical': 0.007217248309884889, 'mean_word_length': 4.71644908616188, 'pattern_counts': {'":': 1, '<': 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': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '354637', 'license': 'MIT', 'n_tokens_mistral': 3639, 'n_tokens_neox': 3531, 'n_words': 875, 'path': 'ML Pipeline Preparation.ipynb', 'repo_name': 'pulkitjaiswal/Disaster-Response', 'size': '10946'}