<jupyter_start><jupyter_text>Training the Applicability Domain classification modelThis notebook trains and saves the applicability domain (AD) model, which classifies molecules as inliers or outliers based on their molecular descriptors.<jupyter_code>import numpy as np
np.random.seed(0)

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, Imputer
from sklearn.decomposition import PCA
from sklearn.feature_selection import VarianceThreshold

import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns
sns.set(color_codes=True)

%matplotlib inline
# Load the training and testing datasets
from ysi_utils.descriptors import dragon
from ysi_utils.validation import y_train as y
from ysi_utils.validation import y_test

X = dragon.loc[y.index]
X_test = dragon.loc[y_test.index]<jupyter_output><empty_output><jupyter_text>Here we create the descriptor pipeline and train it on the training set<jupyter_code># Descriptor outlier classification
from sklearn.ensemble import IsolationForest

outlier_pipeline = Pipeline([
    ('imputer', Imputer()),
    ('filter', VarianceThreshold()),
    ('scaler', StandardScaler()),
    ('feature_extraction', PCA(n_components=5)),
    ('outlier_clf', IsolationForest(contamination=0.075)),
    ])

outlier_pipeline.fit(X.values, y.values)
valid_classes = outlier_pipeline.predict(X)

y['inlier'] = (valid_classes == 1)<jupyter_output><empty_output><jupyter_text>In choosing the hyperparameters of the outlier selection method, we are looking for a function that is able to distinguish between molecules similar to those in the training set and those that are not.We therefore use the high-ysi dataset published in http://dx.doi.org/10.1016/j.combustflame.2006.11.003 and http://dx.doi.org/10.1016/j.proci.2008.06.197 as examples of molecules sufficiently different from the training set as a comparison<jupyter_code>high_ysi = pd.read_pickle('high_ysi/high.p')
high_descriptors = pd.read_csv('high_ysi/high_descriptors.tsv',
                               sep='\t', index_col=0).set_index('NAME', drop=True)
high_descriptors = high_descriptors.loc[high_ysi.SMILES]
high_inliers = outlier_pipeline.predict(high_descriptors) == 1
with sns.axes_style('ticks'):
    fig, axmatrix = plt.subplots(nrows=1, ncols=2, figsize=(8,3))
    
    
    axmatrix[0].hist([y.YSI[y.inlier], y.YSI[~y.inlier]],
                     stacked=True, bins=25, rwidth=1., edgecolor='w',
                     linewidth=1., color=['b','r'], label=['Inlier', 'Outlier'])
    
    axmatrix[1].hist([high_ysi.YSI[high_inliers], high_ysi.YSI[~high_inliers]],
                     stacked=True, bins=25, rwidth=1., edgecolor='w',
                     linewidth=1., color=['b','r'])
    
    fig.tight_layout()
    sns.despine()
    
    axmatrix[0].set_title('Low YSI database')
    axmatrix[1].set_title('High YSI database')
    
    axmatrix[0].set_ylabel('Number of Molecules')
    axmatrix[1].set_ylabel('Number of Molecules')

    axmatrix[0].set_xlabel('YSI (Low Range)')
    axmatrix[1].set_xlabel('YSI (High Range)')
    
    axmatrix[0].legend(loc='upper right')

    fig.tight_layout()
    #fig.savefig('outlier_classification.svg', transparent=True)<jupyter_output><empty_output><jupyter_text>The PCA step condenses the ~5000 descriptors (~3000 after variance threshold) into the 5 most important principle components. This reduced dimensionality captures ~67% of the total variance.<jupyter_code>pca = outlier_pipeline.steps[3][1]
np.cumsum(pca.explained_variance_ratio_)[-1]<jupyter_output><empty_output><jupyter_text>We also use the test set compounds to verify that we are not over-fitting the applicability domain method. There should be a similar proportion of outliers in the test and training datasets<jupyter_code>valid_classes_test = outlier_pipeline.predict(X_test)

print('{:.2%} of Training set marked as outliers'.format(
        1 - sum(valid_classes == 1) / len(valid_classes)))
print('{:.2%} of Test set marked as outliers'.format(
        1 - sum(valid_classes_test == 1) / len(valid_classes_test)))
y[~y.inlier]
y_test[valid_classes_test == -1]
from sklearn.externals import joblib

joblib.dump(outlier_pipeline, '../ysi_utils/models/outliers.pkl', compress=9)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11254094525035097, 'fraction_numerical': 0.01918577445016378, 'mean_word_length': 4.896551724137931, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '345906', 'license': 'MIT', 'n_tokens_mistral': 1462, 'n_tokens_neox': 1365, 'n_words': 334, 'path': 'qspr_model/outlier_classification.ipynb', 'repo_name': 'pstjohn/ysi_qsar_energy_fuels', 'size': '4274'}