# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] id="3nUFFixdJbqY" colab_type="text"
# # RE19-classification: interpretable ML via Skope Rules
#

# + [markdown] colab_type="text" id="c4LfzHoKRUwk"
# ## 0. Set up (optional)
#
# Run the following install functions if running Jupyter on a cloud environment like Colaboratory, which does not allow you to install the libraries permanently on your local machine

# + colab_type="code" id="inoDnAn5savZ" outputId="4bc74bd4-c8c7-451f-9a9f-d4c6fb5195bc" executionInfo={"status": "ok", "timestamp": 1554573127342, "user_tz": -120, "elapsed": 11901, "user": {"displayName": "<NAME>", "photoUrl": "", "userId": "18123037798605808834"}} colab={"base_uri": "https://localhost:8080/", "height": 348}
# #!git clone https://github.com/rulematrix/rule-matrix-py.git
# #!pip install rule-matrix-py/.
# #!pip install mdlp-discretization
# #!pip install pysbrl==0.4.2rc0
# #!pip install fim
# !pip install cython numpy
# !pip install skope-rules

# + [markdown] colab_type="text" id="D9z9eI1OReXJ"
# ## 1. Import libraries

# + colab_type="code" id="5nFWJMhhsjed" outputId="190e69ac-7f0d-4e42-a84c-d811d5cd04e5" executionInfo={"status": "ok", "timestamp": 1554573127924, "user_tz": -120, "elapsed": 12096, "user": {"displayName": "<NAME>", "photoUrl": "", "userId": "18123037798605808834"}} colab={"base_uri": "https://localhost:8080/", "height": 17}
#import rulematrix
#from rulematrix.surrogate import rule_surrogate
from skrules import SkopeRules
from sklearn.neural_network import MLPClassifier
from sklearn import svm
from sklearn.svm import SVC
from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_validate, StratifiedKFold
from sklearn.metrics import recall_score, precision_score, f1_score, roc_curve, precision_recall_curve, auc, confusion_matrix, accuracy_score
from imblearn.over_sampling import ADASYN 

from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer, load_iris

import matplotlib.pyplot as plt
from matplotlib import cm
from scipy import interp

import numpy as np
import pandas as pd

# Set the ipython display in such a way that helps the visualization of the rulematrix outputs.
from IPython.display import display, HTML

display(HTML(data="""
<style>
    div#notebook-container    { width: 95%; }
    div#menubar-container     { width: 65%; }
    div#maintoolbar-container { width: 99%; }
</style>
"""))

def split_tr_te(dataset, target, to_drop, tsize=0.25):
     return train_test_split(dataset.drop(to_drop, axis=1), dataset[target], test_size=tsize, random_state=42)
  
def compute_y_pred_from_query(X, rule):
    score = np.zeros(X.shape[0])
    X = X.reset_index(drop=True)
    score[list(X.query(rule).index)] = 1
    return(score)

def compute_performances_from_y_pred(y_true, y_pred, index_name='default_index'):
    df = pd.DataFrame(data=
        {
            'precision':[sum(y_true * y_pred)/sum(y_pred)],
            'recall':[sum(y_true * y_pred)/sum(y_true)]
        },
        index=[index_name],
        columns=['precision', 'recall']
    )
    return(df)

def compute_train_test_query_performances(X_train, y_train, X_test, y_test, rule):

    y_train_pred = compute_y_pred_from_query(X_train, rule)
    y_test_pred = compute_y_pred_from_query(X_test, rule)

    performances = None
    performances = pd.concat([
        performances,
        compute_performances_from_y_pred(y_train, y_train_pred, 'train_set')],
        axis=0)
    performances = pd.concat([
        performances,
        compute_performances_from_y_pred(y_test, y_test_pred, 'test_set')],
        axis=0)

    return(performances)
  
def drop_descriptive_columns(dataset):
    for c in dataset.columns:
        if c in ['RequirementText', 'Class', 'ProjectID', 'Length','det', 'punct', 'TreeHeight', 'DTreeHeight', 'SubTrees']:
            dataset = dataset.drop(c, axis = 1)
    return dataset


# + [markdown] id="0lN0XVxcjPjq" colab_type="text"
# ## 2. Skope rules

# + id="I9JJmvw9jTAr" colab_type="code" outputId="33d4f1a8-5fd2-47a2-cd58-02adb630d5a2" executionInfo={"status": "ok", "timestamp": 1554554975684, "user_tz": -120, "elapsed": 288396, "user": {"displayName": "<NAME>", "photoUrl": "https://lh5.googleusercontent.com/-dJU__MJ08Ww/AAAAAAAAAAI/AAAAAAAAbsA/YkubKaeFgQo/s64/photo.jpg", "userId": "01259263475584376287"}} colab={"base_uri": "https://localhost:8080/", "height": 59864}
folder_datasets = './'
filenames = ['promise-reclass', 'INDcombined', '8combined']
targets = ['IsFunctional', 'IsQuality', 'OnlyFunctional', 'OnlyQuality']
feature_sets = ['allext', 'sd', 'sdsb8sel02ext']

for target in targets:
    for feature_set in feature_sets:
        for filename in filenames:
            print('======== Target '+target +' Feature set '+feature_set+' Dataset '+filename+ ' ========')
            appendix='-ling-'+feature_set

            # INPUT 1: File name
            data = pd.read_csv(folder_datasets+filename + appendix + '.csv', engine='python')
            data.rename(columns=lambda x: x.replace('+', '___'), inplace=True)
            data = drop_descriptive_columns(data)
            data = data.drop(data.columns[0], axis=1)
            to_drop = ['IsFunctional', 'IsQuality']
            if target == 'OnlyQuality':
                data['IsQuality'] = ~data['IsFunctional'] & data['IsQuality']
                target = 'IsQuality'

            if target == 'OnlyFunctional':
                data['IsFunctional'] = data['IsFunctional'] & ~data['IsQuality']
                target = 'IsFunctional'

            X_train, X_test, y_train, y_test = split_tr_te(data, target, to_drop)
            feature_names = X_train.columns


            # INPUT 2: Pick a trade-off between precision and recall!!!
            skope_rules_clf = SkopeRules(feature_names=feature_names, random_state=42, n_estimators=30,
                                           # recall_min=0.05, precision_min=0.8,
                                            recall_min=0.1, precision_min=0.7,
                                           max_samples=0.7,
                                           max_depth_duplication= 4, max_depth = 5)


            skope_rules_clf.fit(X_train, y_train)

            # Compute prediction scores
            classifier = svm.SVC(kernel='linear', probability=True, random_state=0)
            classifier.fit(X_train, y_train)
            baseline_svm = classifier.predict_proba(X_test)[:, 1]

            skope_rules_scoring = skope_rules_clf.score_top_rules(X_test)

            # Get number of survival rules created
            print(str(len(skope_rules_clf.rules_)) + ' rules have been built with ' +
                  'SkopeRules.\n')

            nrules = len(skope_rules_clf.rules_)

            # print('The most performing rules are the following one:\n')
            # for i_rule, rule in enumerate(skope_rules_clf.rules_):
            #     print("R" + str(i_rule + 1) + ". " + rule[0])
            #     #print('-> '+rules_explanations[i_rule]+ '\n')



            for i in range(nrules):
                print('Rule '+str(i+1)+':',skope_rules_clf.rules_[i][0])
                display(compute_train_test_query_performances(X_train, y_train,
                                                              X_test, y_test,
                                                              skope_rules_clf.rules_[i][0])
                       )
                
            
            y_pred_tr = skope_rules_clf.predict_top_rules(X_train, nrules)
            y_pred_test = skope_rules_clf.predict_top_rules(X_test, nrules)
            print('The performances reached with '+str(nrules)+' discovered rules are the following:')
            print(compute_performances_from_y_pred(y_train, y_pred_tr, 'train_set'))
            print(compute_performances_from_y_pred(y_test, y_pred_test, 'test_set'))
                
            print('========================================================================================')


# + id="daMBpjQ9nSMy" colab_type="code" outputId="6e508c2a-d5a2-4128-e2fe-da077cca9826" executionInfo={"status": "error", "timestamp": 1554556511704, "user_tz": -120, "elapsed": 900, "user": {"displayName": "<NAME>", "photoUrl": "", "userId": "18123037798605808834"}} colab={"base_uri": "https://localhost:8080/", "height": 246}
def plot_scores(y_true, scores_with_line=[], scores_with_points=[],
                        labels_with_line=['SVM'],
                        labels_with_points=['skope-rules']):
    gradient = np.linspace(0, 1, 10)
    color_list = [ cm.tab10(x) for x in gradient ]

    fig, axes = plt.subplots(1, 2, figsize=(12, 5),
                         sharex=True, sharey=True)
    ax = axes[0]
    n_line = 0
    for i_score, score in enumerate(scores_with_line):
        n_line = n_line + 1
        fpr, tpr, _ = roc_curve(y_true, score)
        ax.plot(fpr, tpr, linestyle='-.', c=color_list[i_score], lw=1, label=labels_with_line[i_score])
    for i_score, score in enumerate(scores_with_points):
        fpr, tpr, _ = roc_curve(y_true, score)
        ax.scatter(fpr[:-1], tpr[:-1], c=color_list[n_line + i_score], s=10, label=labels_with_points[i_score])
    ax.set_title("ROC", fontsize=20)
    ax.set_xlabel('False Positive Rate', fontsize=18)
    ax.set_ylabel('True Positive Rate (Recall)', fontsize=18)
    ax.legend(loc='lower center', fontsize=8)

    ax = axes[1]
    n_line = 0
    for i_score, score in enumerate(scores_with_line):
        n_line = n_line + 1
        precision, recall, _ = precision_recall_curve(y_true, score)
        ax.step(recall, precision, linestyle='-.', c=color_list[i_score], lw=1, where='post', label=labels_with_line[i_score])
    for i_score, score in enumerate(scores_with_points):
        precision, recall, _ = precision_recall_curve(y_true, score)
        ax.scatter(recall, precision, c=color_list[n_line + i_score], s=10, label=labels_with_points[i_score])
    ax.set_title("Precision-Recall", fontsize=20)
    ax.set_xlabel('Recall (True Positive Rate)', fontsize=18)
    ax.set_ylabel('Precision', fontsize=18)
    ax.legend(loc='lower center', fontsize=8)
    plt.show()
    
plot_scores(y_test,
                    scores_with_line=[baseline_svm],
                    scores_with_points=[skope_rules_scoring]
                   )

y_pred = skope_rules_clf.predict_top_rules(X_test, nrules)
y_pred2 = skope_rules_clf.predict_top_rules(X_train, nrules)


print('The performances reached with '+str(nrules)+' discovered rules are the following:')
print(compute_performances_from_y_pred(y_train, y_pred2, 'train_set'))
print(compute_performances_from_y_pred(y_test, y_pred, 'test_set'))


# + colab_type="code" id="73AF7PKDxCNA" colab={}


StarcoderdataJupyterScriptsDedupFiltered