<jupyter_start><jupyter_text>Data<jupyter_code># Load data 
datapath = '../data/single-cell/data.csv'
data_df = pd.read_csv(datapath)
sns.countplot(data_df.category)

#scale the data from 0 to 1
min_max_scaler = MinMaxScaler(feature_range=(0, 1), copy=True)
data = min_max_scaler.fit_transform(data_df.drop('category', axis=1).values)
data_df = pd.DataFrame(
    np.append(data, data_df['category'].values[:, None], axis=1), index=data_df.index, columns=data_df.columns
)

#  split as in traing of the model
train_df, test_df = train_test_split(data_df, test_size=0.33, random_state=42, stratify=data_df.category)
test_df, valid_df = train_test_split(test_df, test_size=0.67, stratify=test_df.category)


train_df.head()
CellTyper.celltype_names<jupyter_output><empty_output><jupyter_text>Loading a pretrained modelis actually done under the hood by a child implementation of `depiction.models.Model`  Change `filename` (there's also `cache_dir`) to load a different model.<jupyter_code># Import trained classifier
classifier = CellTyper(filename='celltype_model.h5')
classifier.model.summary()<jupyter_output><empty_output><jupyter_text>Layer weights<jupyter_code>weights = classifier.model.layers[0].get_weights()[0]
sns.heatmap(pd.DataFrame(
    weights,
    index=data_df.columns[:-1],
#     columns=CellTyper.celltype_names.values()
).T)<jupyter_output><empty_output><jupyter_text>Compare qualitatively to __B__ and **C** (thought the image is not depicting this exact dataset)![manual_gated](https://science.sciencemag.org/content/sci/332/6030/687/F2.large.jpg?width=800&height=600&carousel=1)from https://science.sciencemag.org/content/332/6030/687/tab-figures-data  Interpretability methodshelper functions and a widget to sample from a class<jupyter_code>def random_from_class(label):
    id_sample_to_explain = test_df.reset_index().query('category==@label').sample(n=1).index[0]
    print('Interpreting sample with index {} in test_df'.format(id_sample_to_explain))
    return id_sample_to_explain


def interpret_with_lime(id_sample_to_explain):
# Create a LIME tabular interpreter
    explanation_configs = {
        'top_labels': 1
    }
    interpreter_params = {
        'training_data': train_df.values[:, :-1],
        'training_labels': train_df.values[:, -1],
        'feature_names': train_df.columns[:-1],
        'verbose': True,
        'class_names': classifier.celltype_names.values(),
        'discretize_continuous': False,
        'sample_around_instance': True
    }

    explainer = UWModel("lime", Task.CLASSIFICATION, DataType.TABULAR, explanation_configs, **interpreter_params)

    # explain the chosen instance wrt the chosen labels
    explainer.interpret(classifier.predict, test_df.values[id_sample_to_explain, :-1])


def interpret_with_anchor(id_sample_to_explain):
    explanation_configs = {}
    interpreter_params = {
        'feature_names': train_df.columns[:-1],
        'class_names': classifier.celltype_names.values(),
        'categorical_names': {}
    }

    explainer = UWModel('anchor', Task.CLASSIFICATION, DataType.TABULAR, explanation_configs, **interpreter_params)
    X_train = train_df.values[:, :-1]
    y_train = train_df.values[:, -1].astype(np.int)
    X_valid = valid_df.values[:, :-1]
    y_valid = valid_df.values[:, -1].astype(np.int)
    explainer.explainer.fit(
        X_train, y_train, X_valid, y_valid
    )

    # explain the chosen instance wrt the chosen labels
    def new_predict(sample, **kwargs):
        return np.argmax(classifier.predict(sample,**kwargs), axis=1)
    explainer.interpret(new_predict, test_df.values[id_sample_to_explain, :-1])


def visualize_logits(id_sample_to_explain):
    sample = test_df.iloc[id_sample_to_explain,:-1]
    logits = pd.DataFrame(classifier.predict([[sample]]), columns=CellTyper.celltype_names.values()).T
    sns.heatmap(logits)


def visualize(id_sample_to_explain, layer):
    sample = test_df.iloc[id_sample_to_explain,:-1]
    if layer is None:
        visualize_logits(id_sample_to_explain)
        return
    elif layer==0:
        # output of last "layer" is the sample
        layer_output = sample.values.transpose()
    else:
        # for vizualization of output of a layer we access the model
        activation_model = keras.models.Model(
            inputs=classifier.model.input,
            outputs=classifier.model.layers[layer-1].output
        )
        layer_output = activation_model.predict([[sample]])[0]
    
    weights = classifier.model.layers[layer].get_weights()[0]
    weighted_output = (weights.transpose() * layer_output)
    sns.heatmap(weighted_output)


def visualize_random_from_class(label, layer):
    visualize(random_from_class(label), layer)

    
def interpret_random_from_class(label, interpreter):
    id_sample_to_explain = random_from_class(label)
    if interpreter == 'lime':
        interpret_with_lime(id_sample_to_explain)
    elif interpreter == 'anchor':
        interpret_with_anchor(id_sample_to_explain)
interact_manual(
    visualize_random_from_class,
    label=[(v, k) for k, v in classifier.celltype_names.items()],
    layer=dict(
        **{layer.name: i for i, layer in enumerate(classifier.model.layers)}, logits=None
    )
);
visualize_logits(4368)
interact_manual(interpret_random_from_class, label=[(v, k) for k, v in classifier.celltype_names.items()],
         interpreter=['lime', 'anchor']
);
interpret_with_anchor(4368)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11990451707675358, 'fraction_numerical': 0.013587954461990452, 'mean_word_length': 4.7276550998948474, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 2, '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': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '198344', 'license': 'Apache-2.0', 'n_tokens_mistral': 1890, 'n_tokens_neox': 1820, 'n_words': 319, 'path': 'notebooks/celltype_interpretability.ipynb', 'repo_name': 'animesh/dl-interpretability-compbio', 'size': '5446'}