Nick Doiron / Jul 02 2019
Remix of Python by Nextjournal

XAI Experiments: Alibi

pip install numpy sklearn spacy alibi
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
import spacy
from alibi.explainers import AnchorText
from alibi.datasets import movie_sentiment
from alibi.utils.download import spacy_model
data, original_labels = movie_sentiment()
# data is an array of strings, and labels is an array of corresponding numbers for the class in the classifier 
# let's change the content
import random
labels = []
for i in range(0, len(data)):
  destiny_class = random.randint(0, 2)
  if destiny_class == 0:
    data[i] = 'apples ' + data[i]
  elif destiny_class == 1:
    data[i] = 'oranges ' + data[i]
  else:
    # nothing happens
    cheat = 0
  labels.append(destiny_class)
print(data[0] + ' = ' + str(labels[0]))
train, test, train_labels, test_labels = train_test_split(data, labels, test_size=.2, random_state=42)
train, val, train_labels, val_labels = train_test_split(train, train_labels, test_size=.1, random_state=42)
train_labels = np.array(train_labels)
test_labels = np.array(test_labels)
val_labels = np.array(val_labels)
vectorizer = CountVectorizer(min_df=1)
vectorizer.fit(train)
CountVectoriz...cabulary=None)
np.random.seed(0)
clf = LogisticRegression(solver='liblinear')
clf.fit(vectorizer.transform(train), train_labels)
LogisticRegre...m_start=False)
predict_fn = lambda x: clf.predict(vectorizer.transform(x))
preds_train = predict_fn(train)
preds_val = predict_fn(val)
preds_test = predict_fn(test)
print('Train accuracy', accuracy_score(train_labels, preds_train))
print('Validation accuracy', accuracy_score(val_labels, preds_val))
print('Test accuracy', accuracy_score(test_labels, preds_test))
model = 'en_core_web_md'
spacy_model(model=model)
nlp = spacy.load(model)
explainer = AnchorText(nlp, predict_fn)
class_names = ['Apples', 'Oranges', 'Neither']

Predictions of the Cheatable Classifier

Neither

text = 'This is a good book .'
pred = class_names[predict_fn([text])[0]]
alternative =  class_names[1 - predict_fn([text])[0]]
print('Prediction: %s' % pred)
np.random.seed(0)
explanation = explainer.explain(text, threshold=0.95, use_proba=False, use_unk=True)
print('Anchor: %s' % (' AND '.join(explanation['names'])))
print('Precision: %.2f' % explanation['precision'])
print('\nExamples where anchor applies and model predicts %s:' % pred)
print(explanation)
print("\n\n")

Apples

text2 = 'Apples This is a test .'
pred2 = class_names[predict_fn([text2])[0]]
alternative2 =  class_names[1 - predict_fn([text2])[0]]
print('Prediction: %s' % pred2)
np.random.seed(0)
explanation2 = explainer.explain(text2, threshold=0.95, use_proba=True, use_unk=False)
print('Anchor: %s' % (' AND '.join(explanation2['names'])))
print('Precision: %.2f' % explanation2['precision'])
print('\nExamples where anchor applies and model predicts %s:' % pred2)
print('\n'.join([x[0] for x in explanation2['raw']['examples'][-1]['covered_true']]))
print('\nExamples where model predicted a different class:')
print('\n'.join([x[0] for x in explanation2['raw']['examples'][-1]['covered_false']]))