Узнайте, как применить популярный метод объяснимого искусственного интеллекта (XAI) LIME для объяснения классификаторов изображений.

Объяснения локальной интерпретируемой модели, не зависящие от модели (LIME) — это один из самых популярных методов объяснимого искусственного интеллекта (XAI), используемых для объяснения работы моделей машинного и глубокого обучения. LIME может предоставить независимые от модели локальные объяснения для решения задач как регрессии, так и классификации, и его можно применять как к структурированным наборам данных, так и даже к неструктурированным наборам данных, таким как текст и изображения. В этой статье вы получите гораздо более глубокое практическое знакомство с использованием LIME для объяснения классификаторов изображений на основе глубокого обучения, а также пошаговое руководство по коду.

Если вы не очень хорошо знакомы с концепциями XAI, я настоятельно рекомендую посмотреть одну из прошлых сессий по XAI, представленную на AI Accelerator Festival APAC, 2021:

Вы также можете ознакомиться с моей книгой Прикладные методы объяснимости машинного обучения и заглянуть в репозиторий кода, чтобы получить практическое представление о других методах XAI. В этой статье я буду ссылаться на практическое применение LIME для классификаторов изображений, представленное в книге Прикладные методы объяснения машинного обучения.



Если вы хотите получить подробный отзыв о книге, вам может быть полезно это видео:

Теперь давайте начнем!

Применение LIME для классификаторов изображений

Объяснять наборы табличных данных по-прежнему легко, используя традиционные методы определения важности признаков и другие фреймворки, такие как LIME и SHAP. Однако основная проблема всегда возникает при объяснении сложных моделей глубокого обучения, обученных на неструктурированных данных, таких как изображения.

Как правило, модели глубокого обучения намного эффективнее, чем обычные модели машинного обучения для данных изображений, поскольку эти модели могут выполнять автоматическое извлечение признаков. Они могут извлекать сложные элементы низкого уровня, такие как полосы, края, контуры, углы и мотивы, и даже элементы более высокого уровня, такие как более крупные формы и определенные части объекта. Эти функции более высокого уровня обычно называются областями интереса (RoI) на изображении или суперпикселями, так как они представляют собой наборы пикселей изображения, которые охватывают определенный область изображения.

Теперь функции низкого уровня не могут быть интерпретированы человеком, но функции высокого уровня могут быть интерпретированы человеком, поскольку любой нетехнический конечный пользователь будет относиться к изображениям по отношению к функциям более высокого уровня. LIME работает аналогичным образом. Алгоритм пытается выделить суперпиксели на изображениях, которые положительно или отрицательно влияют на процесс принятия решений моделью. Итак, давайте посмотрим, как LIME можно использовать для объяснения классификаторов изображений.



Настройка необходимых модулей Python

Прежде чем мы начнем пошаговое руководство по коду, пожалуйста, проверьте блокнот, предоставленный в репозитории кода. Блокнот содержит необходимые детали, необходимые для практического применения понятий. В этом разделе я познакомлю вас с кодом и объясню все шаги, описанные в учебнике по блокноту. Используйте следующую команду для установки обновленных версий библиотек Python, если они еще не установлены:

!pip install --upgrade pandas numpy matplotlib seaborn tensorflow lime scikit-image

Импортируйте установленные модули в блокнот Python Jupyter.

import warnings
warnings.filterwarnings("ignore")
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as c_map
from IPython.display import Image, display
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.applications.xception import Xception, preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image

import lime
from lime import lime_image
from lime import submodular_pick

from skimage.segmentation import mark_boundaries

np.random.seed(123)

Вы можете распечатать версию tensorflow, установленную в вашей установке.

print(f" Version of tensorflow used: {tf.__version__}")
Version of tensorflow used: 2.3.1

Загрузка данных

Поскольку нам больше интересно проверить, как можно объяснить классификаторы изображений черного ящика с помощью LIME, мы сосредоточимся только на части вывода. Давайте загрузим любые общие данные изображения. Для этого примера мы возьмем данные из этого источника: https://unsplash.com/photos/GBDkr3k96DE

def load_image_data_from_url(url):
    '''
    Function to load image data from online
    '''
    # The local path to our target image
    image_path = keras.utils.get_file(
    "shark.jpg", url
    )

    display(Image(image_path))
    return image_path

image_path = load_image_data_from_url(url = "https://images.unsplash.com/photo-1560275619-4662e36fa65c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1200&q=80")

Мы выполним некоторую предварительную обработку исходных данных с изображениями.

IMG_SIZE = (299, 299)
def transform_image(image_path, size):
    '''
    Function to transform an image to normalized numpy array
    '''
    img = image.load_img(image_path, target_size=size)
    img = image.img_to_array(img)# Transforming the image to get the shape as [channel, height, width]
    img = np.expand_dims(img, axis=0) # Adding dimension to convert array into a batch of size (1,299,299,3)
    img = img/255.0 # normalizing the image to keep within the range of 0.0 to 1.0
    
    return img

normalized_img = transform_image(image_path, IMG_SIZE)

Использование предварительно обученной модели TensorFlow в качестве модели черного ящика

В этом руководстве мы использовали предварительно обученную модель TensorFlow Keras Xception в качестве модели черного ящика. Модель предварительно обучена на наборе данных ImageNet (https://www.image-net.org/), который является одним из самых популярных наборов данных для сравнительного анализа для классификации изображений. Предварительно обученную модель можно загрузить с помощью следующих строк кода:

from tensorflow.keras.applications.xception import Xception
model = Xception(weights="imagenet")

Давайте теперь воспользуемся предварительно обученной моделью XceptionNet для генерации прогнозов.

def get_model_predictions(data):
    model_prediction = model.predict(data)
    print(f"The predicted class is : {decode_predictions(model_prediction, top=1)[0][0][1]}")
    return decode_predictions(model_prediction, top=1)[0][0][1]

plt.imshow(normalized_img[0])
pred_orig = get_model_predictions(normalized_img)

Это будет предсказывать следующий вывод:

The predicted class is : tiger_shark

Изображение прогнозируется как Tiger Shark, что является правильным прогнозом, и модель черного ящика успешно может дать правильный прогноз. Теперь давайте даже взглянем на 5 лучших прогнозов вместе с достоверностью модели.

model_prediction = model.predict(normalized_img)
top5_pred = decode_predictions(model_prediction, top=5)[0]
for pred in top5_pred:
    print(pred[1])

5 лучших прогнозов, сгенерированных моделью:

tiger_shark
great_white_shark
hammerhead
scuba_diver
sturgeon

Как мы видим, хотя модель хорошо обучена для получения правильного прогноза, есть шансы, что модель смотрит не только на основной объект на изображении, но и на окружающий фон. Это видно из прогноза scuba_driver, присутствующего в списке 5 лучших прогнозов. Итак, нам важно понять, какие ключевые компоненты или части изображения изучает модель, чтобы сделать прогноз.



Объяснение модели с LIME

В этом подразделе мы увидим, как можно использовать структуру LIME для идентификации суперпикселей или областей изображения, используемого моделью для прогнозирования конкретного результата. Сначала нам нужно определить объект объяснения изображения:

explainer = lime_image.LimeImageExplainer()

Далее нам нужно будет передать данные логического вывода (normalized_img[0]) объекту объяснения и использовать структуру LIME, чтобы выделить суперпиксели, оказывающие максимальное положительное и отрицательное влияние на предсказание модели:

exp = explainer.explain_instance(normalized_img[0], 
                                 model.predict, 
                                 top_labels=5, 
                                 hide_color=0, 
                                 num_samples=1000)

Наш объект объяснения готов, но давайте визуализируем различные сегменты объяснения, созданные алгоритмом LIME.

plt.imshow(exp.segments)
plt.axis('off')
plt.show()

Теперь давайте используем верхние сегменты или суперпиксели, чтобы определить интересующую область изображения, используемого моделью для прогнозирования.

def generate_prediction_sample(exp, exp_class, weight = 0.1, show_positive = True, hide_background = True):
    '''
    Method to display and highlight super-pixels used by the black-box model to make predictions
    '''
    image, mask = exp.get_image_and_mask(exp_class, 
                                         positive_only=show_positive, 
                                         num_features=6, 
                                         hide_rest=hide_background,
                                         min_weight=weight
                                        )
    plt.imshow(mark_boundaries(image, mask))
    plt.axis('off')
    plt.show()
generate_prediction_sample(exp, exp.top_labels[0], show_positive = True, hide_background = True)

Как видно из приведенного выше изображения, модель смогла определить правильную область, что действительно указывает на правильное предсказание результата моделью.

generate_prediction_sample(exp, exp.top_labels[0], show_positive = True, hide_background = False)

Как видно из предыдущего изображения, мы также можем просто выделить контур суперпикселя и включить фон. Но мы также можем выделить положительные суперпиксели и отрицательные суперпиксели.

generate_prediction_sample(exp, exp.top_labels[0], show_positive = False, hide_background = False)

Приведенные выше примеры показывают нам, как мы можем скрыть или показать фон вместе с суперпикселями или даже выделить или выделить суперпиксели, чтобы определить интересующую область, используемую моделью для прогнозирования. То, что мы видим отсюда, действительно имеет смысл и позволяет нам повысить доверие к моделям черного ящика. Мы также можем сформировать тепловую карту, чтобы показать, насколько важен каждый суперпиксель для получения более детальной объяснимости.

def explanation_heatmap(exp, exp_class):
    '''
    Using heat-map to highlight the importance of each super-pixel for the model prediction
    '''
    dict_heatmap = dict(exp.local_exp[exp_class])
    heatmap = np.vectorize(dict_heatmap.get)(exp.segments) 
    plt.imshow(heatmap, cmap = 'RdBu', vmin  = -heatmap.max(), vmax = heatmap.max())
    plt.colorbar()
    plt.show()

explanation_heatmap(exp, exp.top_labels[0])



Краткое содержание

Как мы ясно видели в этой записной книжке, как LIME можно легко использовать для объяснения классификаторов изображений. В следующий раз, когда вы будете работать над обучением моделей глубокого обучения для классификации изображений, я настоятельно рекомендую вам попробовать LIME, чтобы объяснить вашу модель и выяснить, изучает ли модель нужные области изображения, чтобы сделать окончательный прогноз! Если вам понравилась эта статья и вы хотите узнать больше о том, как применять LIME для объяснения моделей машинного обучения, я рекомендую прочитать эту книгу: Прикладные методы объяснения машинного обученияи изучить Репозиторий GitHub для получение практических примеров кода.

ДРУГИЕ СТАТЬИ АВТОРА, СВЯЗАННЫЕ С XAI ПО TDS:

  1. Объяснимое машинное обучение для моделей, обученных на текстовых данных: сочетание SHAP с моделями-трансформерами
  2. EUCA — эффективная структура XAI для приближения искусственного интеллекта к конечным пользователям
  3. Понимание работы SHAP и значений Шепли, используемых в объяснимом ИИ


ССЫЛКА

  1. LIME Open Source Python Framework в GitHub — https://github.com/marcotcr/lime
  2. Прикладные методы объяснимости машинного обучения
  3. Репозиторий GitHub из книги Прикладные методы объяснимости машинного обученияhttps://github.com/PacktPublishing/Applied-Machine-Learning-Explainability-Techniques/