![Проблема разногласий: объяснимость и объяснители в ИИ](https://c.mql5.com/2/72/The_Disagreement_Problem_Diving_Deeper_into_The_Complexity_Explainability_in_AI_600x314.jpg)
Проблема разногласий: объяснимость и объяснители в ИИ
Проблема разногласий
Разногласие является открытой сферой исследований в междисциплинарной области, известной как объяснимый искусственный интеллект (Explainable Artificial Intelligence, XAI). Объяснимый искусственный интеллект пытается помочь нам понять, как наши модели приходят к своим решениям. К сожалению, на практике все сложнее.
Мы все знаем, что модели машинного обучения и доступные наборы данных становятся все больше и сложнее. На самом деле специалисты по данных, разрабатывающие алгоритмы машинного обучения, не могут точно объяснить поведение своих алгоритмов на всех возможных наборах данных. Объяснимый искусственный интеллект (XAI) должен помочь объяснить функциональность моделей и подтвердить, что модели готовы к практическому использованию. Как бы многообещающе это ни звучало, данная статья покажет читателю, почему мы не можем слепо доверять никаким объяснениям, которые мы можем получить от любого применения технологии объяснимого искусственного интеллекта.
Содержание
- Введение
- Обзор методов объяснительного ИИ
- Глобальные и локальные объяснения
- Независимые от модели и специфичные для модели объяснения
- Определение проблемы разногласий и сопутствующих факторов
- Примеры
- Заключение
- Рекомендации
Введение
Машинное обучение позволяет изучать отношения и взаимодействия, существующие в данных. Но как мы при этом можем изучить отношения и взаимодействия, существующие в самой модели? Лучший способ ответить на этот вопрос — использовать методы модельного объяснения. В этой статье мы с вами рассмотрим несколько различных методов объяснения. Методы модельного объяснения позволяют ответить на такие вопросы:- Какие признаки наша модель сочла наиболее информативными?
- Если в нашем наборе данных 1000 признаков, как определить наиболее и наименее информативные?
- Как меняется выходная информация нашей модели при изменении одного признака?
- Какие признаки могут стоить дальнейшего проектирования?
Ответы на эти вопросы очень важны, но при этом существует серьезный барьер. Проблема в том, что иногда мы сталкиваемся с разногласиями между объяснениями, оценивающими одну и ту же модель. К сожалению, на момент написания не существует каких-либо всемирно признанных решений этой проблемы. Но сегодня мы попытаемся создать собственную систему, которая хоть как-то смягчит ее.
Существует глобальная тенденция, направленная на интеграцию искусственного интеллекта в более широкий спектр приложений. Однако чтобы доверять моделям, нужно быть в состоянии подробно объяснить сами модели, любые изученные ассоциации и процесс принятия решений. Это называется «объяснимостью». Объяснимый искусственный интеллект (Explainable Artificial Intelligence, XAI) умеет отслеживать то, как та или иная модель достигает своих прогнозов. Объяснимый ИИ появился как возможное решение проблемы: по мере того, как наши методы моделирования становятся более сложными, наша способность интерпретировать их постепенно уменьшается.
Для начала рассмотрим простой пример, используя концепции, знакомые большинству читателей. Начнем с достаточно простой задачи, чтобы постепенно развить интуицию в отношении различных методов объяснения. После изучения этого примера мы должны быть готовы применить навыки к любой модели машинного обучения, обученной на реальных рыночных данных, которые мы получаем из терминала MetaTrader 5.
Простой пример, с которого мы начнем, представляет собой простую задачу оценки зарплаты спортсмена с учетом его физических способностей. Для нас очевидно, что по мере развития физических способностей спортсменов они могут рассчитывать на более высокую зарплату, но вопрос в том, какие физические способности оказывают наибольшее влияние на повышение зарплаты?
В нашем примере мы будем использовать выборку на данных, собранных титанами видеоигр Electronic Arts в рамках их серии видеоигр Madden NFL, в которой игроки могут моделировать матчи, играя за своего любимого профессионального американского футболиста. Набор данных содержит подробную статистику по профессиональным игрокам в американский футбол. Мы обучим четыре разные модели, чтобы прогнозировать зарплату игрока на основе таких характеристик игрока, как его возраст, скорость спринта и сила. После этого мы применим различные методы объяснения моделей и посмотрим, какую информацию мы можем узнать о взаимосвязи между характеристиками игрока и его зарплатой. Мы увидим, как интерпретируется каждый метод объяснения, а затем посмотрим, есть ли у нас какие-либо противоречивые объяснения. Мы выделим разногласия, попытаемся определить, что может способствовать разногласиям, и обсудим возможные решения.
Рис. 1. Видеоигра Madden NFL от Electronic Arts.
Обзор методов объяснительного ИИ
Вообще говоря, методы объяснимости можно классифицировать по-разному. Самый простой способ — разделить их на два класса: объяснители «белого ящика» и объяснители «черного ящика». В предыдущей статье мы обсуждали модели стеклянного ящика и модели черного ящика. Сегодня нас не интересуют прогнозные модели, поэтому черный ящик, о котором мы будем говорить, не является сложной и трудно интерпретируемой моделью машинного обучения. Сейчас имеется в виду алгоритмы объяснительности, которые помогают интерпретировать лежащую в основе модель.
Техника объяснения черного ящика предназначена для использования в моделях любого типа. Такой тип также называют модельно-агностическими объяснителями.
Техника объяснения белого ящика предназначена для использования структуры определенного типа базовой модели для предоставления объяснений, которые могут быть более точными для базовой модели.
Ожидаемо, разные методы объяснительности будут:
- Придерживайтесь различных предположений о форме и структуре базовых данных.
- Определять и оценивать различные показатели, чтобы понять модель.
- Не справляться в определенных условиях.
Алгоритмы объяснимости также можно разделить по их методологии. Например, существуют методы объяснения, которые позволяют получить представление, корректируя входные данные каждого признака по одному и наблюдая за последующими изменениями в предсказаниях. Эти методы можно отнести к методам, основанным на возмущениях. С другой стороны, существуют некоторые алгоритмы объяснительности, которые стремятся понять, насколько чувствительна модель к изменениям характеристик. Эти методы можно классифицировать как методы, основанные на градиенте, поскольку они берут производную от выходных данных модели по ее характеристикам.
Сегодня мы рассмотрим лишь несколько различных типов объяснительных алгоритмов. Существует множество других методов объяснения, которые не покрывает наше обсуждение, и поэтому этот список не претендует на то, чтобы быть исчерпывающим.
Наконец, также важно управлять своими ожиданиями. Построение модели, способной прогнозировать цену ценной бумаги с точностью более 50%, необязательно гарантирует прибыльную торговлю.
Глобальные и локальные объяснения
Если нужно узнать больше о важности функций и общем поведении нашей модели, необходимо использовать методы глобального объяснения. И наоборот, если мы хотим подробно понять, как наша модель пришла к одному конкретному прогнозу, нам потребуются локальные объяснения.
Локальные объяснения позволяют понять взаимосвязь между признаками, на основе чего мы можем лучше доверять к предсказаниям нашей модели. Кроме того, мы также сможем лучше понять, какие признаки способствуют ложным прогнозам, и рассмотреть возможность разработки этих признаков, чтобы извлечь из них более полезную информацию.
Итак, вернемся к нашему простому примеру. Чтобы узнать, какие признаки важны для прогнозирования зарплаты спортсмена, нужно применить глобальные методы объяснения, такие как важность перестановок. Более того, если нужно более подробно понять прогноз одного конкретного спортсмена, понадобятся локальные методы объяснения, такие как LIME.
На нашем примере разберемся для начала с глобальными объяснениями нашей модели.
Как всегда, начинаем с установки необходимых нам зависимостей.
Настраиваем:
- Shap
- eli5
- Lime
- Interpret
- alibi
pip install alibi shap lime eli5 interpret
Далее загружаем наши обычные зависимости.
import pandas as pd import numpy as np import matplotlib.pyplot as plt
Теперь мы можем прочитать набор данных.
csv = pd.read_csv("/add/your/path/here/to/the/madden/csv")
Давайте посмотрим на несколько строк и несколько столбцов из набора данных.
Рис. 2. Пример набора данных.
Для простоты мы сохраним только некоторые числовые характеристики. Категориальные признаки требуют определенных методов и деталей, которые не входят в рамки нашего обсуждения.
predictors = ["awareness_rating","throwPower_rating","kickReturn_rating", "leadBlock_rating","strength_rating","catchInTraffic_rating", "pursuit_rating", "catching_rating","acceleration_rating", "height","tackle_rating","yearsPro","throwUnderPressure_rating", "throwAccuracyDeep_rating","throwAccuracyShort_rating","speed_rating", "jumping_rating","toughness_rating","kickPower_rating", "kickAccuracy_rating","agility_rating","passBlock_rating","age" ] csv[predictors].dtypes
awareness_rating int64
throwPower_rating int64
kickReturn_rating int64
Теперь определим цель.
target = "totalSalary"
Теперь мы настроим модели, которые будем использовать.
from sklearn.linear_model import LinearRegression from sklearn.neighbors import KNeighborsRegressor from sklearn.ensemble import RandomForestRegressor from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.callbacks import EarlyStopping
После импорта нужных зависимостей и перед инициализацией наших моделей машинного обучения мы применили шаги предварительной обработки для масштабирования и стандартизации данных, а также чтобы разделить данные на обучение и тестирование. В описании статьи я опустил эти шаги, чтобы не перегружать излишними деталями. Разделили данные на обучающие и тестовые, получили переменные для обучающих данные x_train и y_train, переменные для проверочных данных x_valid и y_valid» и переменные для тестирования x_test и y_test.
Переходим к настройке каждой из моделей, с которыми сегодня будем работать.
lm = LinearRegression() rf = RandomForestRegressor() knn = KNeighborsRegressor(n_neighbors=10) dnn = keras.Sequential([ layers.Dense(units=30,activation="relu",input_shape=[scaled_data.shape[1]]), layers.Dense(units=20,activation="relu"), layers.Dropout(0.3), layers.Dense(units=10,activation="relu"), layers.Dense(units=1) ])
Затем обучаем каждую из моделей
#Fitting the linear regression lm.fit(x_train,y_train) #Fitting the k-nearest neighbor regressor knn.fit(x_train,y_train) #Fitting the random forest model rf.fit(x_train,y_train) #Fitting the deep neural network early_stopping = EarlyStopping( min_delta=0.001, patience=20, restore_best_weights=True ) dnn.compile(optimizer="adam",loss="mae") dnn.fit( x_train,y_train, validation_data=(x_validation,y_validation), batch_size = 60, epochs=100, verbose=0, callbacks=[early_stopping] )
Глобальные объяснения
Мы начнем с глобального объяснения нашей модели линейной регрессии. Техника, которую мы будем использовать, — важность перестановок. Это глобальный метод объяснения черного ящика.
import eli5 from sklearn.metrics import mean_squared_error from eli5.sklearn import PermutationImportance from eli5.permutation_importance import get_score_importances
Получим глобальные объяснения модели линейной регрессии
permutation = PermutationImportance(lm).fit(x_test,y_test) eli5.show_weights(permutation,feature_names = predictors)
Рис. 3. Глобальные объяснения нашей модели линейной регрессии.
Переходим к интерпретации результатов. Важность перестановки предполагает, что каждый столбец в наборе данных независим. Поэтому он может изменять один столбец за раз, чтобы наблюдать за изменением показателей ошибок модели и использовать их для принятия решения о том, какие признаки важны. Если признак была важным, то перетасовка его значений приведет к увеличению показателей ошибок модели, и наоборот, если признак не был важным, тогда показатели ошибок модели фактически уменьшатся после перетасовки значений в этом столбце. В тех случаях, когда предположение о независимости не соответствует действительности, нужно интерпретировать эти результаты с долей скептицизма.
В таблице выше важные признаки имеют положительные коэффициенты, а неважные — отрицательные. yearsPro — многолетний опыт спортсмена, имеет отрицательный коэффициент, но мы знаем, что на самом деле это имеет значение: обнаружила ли наша модель явление, о котором мы не знаем, или наш объяснитель не дает нам точного представления о правде?
Важность перестановки может нереально перетасовать опыт спортсмена, потенциально делая его слишком молодым для своего уровня знаний или имеющим больше опыта, чем его общий возраст. Кроме того, этот метод игнорирует любые взаимодействия, которые могут присутствовать в наборе данных, и приписывает все изменения в ошибке модели только этому объекту. Следовательно, результаты могут быть потенциально нереалистичными. Это еще раз подчеркивает, как важно быть осторожными и хорошо понимать алгоритм, а не слепого применять его.
А вот длина пробежки может дать нам ценную информацию о наиболее важных признаках модели. В данном случае способность спортсмена ловить мяч и его ловкость являются одними из наиболее важных признаков. Это имеет смысл, потому что в футболе от вас ждут способности ловить широкие пасы от товарищей по команде, даже если вы находитесь под сильным давлением. Кроме того, после того, как вы поймаете мяч, нужно уйти от как можно большего количества соперников, не потеряв мяч, поэтому важность, придаваемая этим признакам, кажется правдивой.
Локальные объяснения
Как мы заявляли ранее, локальные объяснения помогают понять, как каждой признак влияет на каждый отдельный прогноз, который делает наша модель.
Мы получим местные объяснения ожиданий нашей глубокой нейронной сети относительно зарплаты Ришара ЛеКонта.
Рис. 4: Ричард ЛеКонтIII
Сначала импортируем LIME.
LIME — это аббревиатура от Locally Interpretable Model-Agnostic Explanations (локально интерпретируемые модельно-агностические объяснения). Метод объясняет, какие функции повлияли на выходные данные модели и повлияли ли эти факторы на выходные данные в лучшую или худшую сторону.
import lime from lime import lime_tabular
explainer = lime_tabular.LimeTabularExplainer(training_data = np.array(x_train),mode='regression',feature_names=predictors) exp = explainer.explain_instance(data_row=scaled_data.iloc[test],predict_fn=lm.predict) exp.show_in_notebook(show_table=True)
Рис. 5. Объяснения LIME для ожидаемой заработной платы нашей глубокой нейронной сети по игроку Ришару ЛеКонту
Графики содержат массу информации: прежде всего можно увидеть, какие физические способности ЛеКонта увеличивают его ожидаемую зарплату, а какие уменьшают. Наша нейросеть ожидала, что рейтинг стойкости ЛеКонта снизит его ожидаемую зарплату, и это имеет смысл, поскольку ЛеКонт имеет средний показатель стойкости. Более того, глубокая нейросеть правильно определила сильные стороны ЛеКонта и ожидала, что его зарплата увеличится за счет сильных сторон. Именно такое поведение мы и ожидали. Локальные объяснения позволяют проверить модель, а не слепо доверять ей.
Независимые от модели и специфичные для модели объяснения
В тех случаях, когда нам известна структура базовой модели, мы можем использовать методы объяснения, разработанные специально для этой архитектуры модели. Их обычно называют объяснителями белого ящика. На практике объяснители белого ящика могут быть более эффективными в вычислительном отношении, чем их аналоги черного ящика.
Объяснители черного ящика не зависят от модели, то есть могут интерпретировать и объяснить любую представленную им модель. Алгоритм LIME, который мы только что рассмотрели, является примером объяснителя черного ящика, о чем и говорится в названии: Locally Interpretable Model-Agnostic Explanations — локально интерпретируемое не зависящее от модели объяснение.
Объяснители белого ящика можно использовать, когда мы точно знаем структуру базовой модели. При этом они позволяют получить более точные объяснения поведения нашей модели. При этом объяснители черного ящика часто привносят некоторый уровень предвзятости при объяснении наших моделей. Объяснители черного ящика делают некоторые упрощающие предположения о форме модели, с которой они имеют дело. И если эти предположения не оправдываются, мы получаем неверные объяснения.
Как правило, если вы точно знаете свойства модели, в лучше использовать объяснители белого ящика.
Давайте посмотрим на объяснитель черного ящика в действии. В библиотеке SHAP есть реализации объяснителей черного ящика SHAP. Посмотрим на один из них.
Импорт SHAP
Импорт SHAP
Расчет значений SHAP
explainer = shap.Explainer(xgb.predict,scaled_data.loc[test:test_end,predictors]) shap_values = explainer(scaled_data.loc[test:test_end,predictors])
Построение объяснения черного ящика
shap.plots.beeswarm(shap_values)
Рис. 6. Объяснения черного ящика SHAP для нашей модели XGB
Ширина каждой строки определяется выбросами и не несет никакой информации о важности объекта. Мы оцениваем важность объекта, учитывая вертикальное расположение объекта на графике. Чем выше находится объект, тем более важным он воспринимается алгоритмом SHAP.
Кроме того, обратите внимание, что на некоторых объектах синие и розовые точки хорошо разделены, тогда как в других рядах они перемешаны. Когда точки перемешаны, это обычно является признаком эффекта взаимодействия между этим признаком и другим или набором признаков. И весь этот объем информации отображается на одном графике SHAP.
Каждая точка представляет значение Шепли для каждой точки данных. Это позволяет быстро оценить, как каждая отдельная точка данных повлияла на прогноз модели на детальном уровне. Цвет точки представляет направление и величину влияния точки данных на прогноз нашей модели. Синий цвет указывает на снижение выхода модели, а розовый — на увеличение. Обратите внимание, что алгоритм SHAP предполагает, что объекты независимы, или, другими словами, он игнорирует любые взаимодействия в наборе данных. Если это предположение не оправдывается, алгоритм получается ненадежным.
Теперь рассмотрим объяснитель белого ящика, предназначенный для древовидных моделей, таких как наша модель XGB. Мы используем специальный метод TreeExplainer(), предназначенный для объяснения древовидных моделей.
tree_explainer = shap.TreeExplainer(xgb) tree_shap_values = explainer(x_test)
Далее можем построить объяснения белого ящика.
shap.plots.beeswarm(tree_shap_values)
Рис. 7. Объяснения белого ящика SHAP для нашей модели XGB
Сравните 4 наиболее важные особенности объяснения SHAP для черного ящика и белого ящика. Видите проблему разногласий?
Определение проблемы разногласий и сопутствующих факторов
Итак, мы с вами познакомились с объяснителями моделей. Далее перейдем непосредственно к проблеме разногласий. Начнем с рассмотрения того, что такое разногласие.Давайте разберем, что представляет собой разногласие в области объяснений важности функций:
- Перестановки функций. Первая форма разногласий — это когда перестановки функций различаются. Если определенный порядок важности функций имеет значение в вашем рабочем процессе, появление различных перестановок в объяснениях становится ключевым предметом конфликта. Это особенно важно, когда детальная последовательность функций имеет значение для анализа.
- Наборы функций с лучшим рейтингом. Если копнуть глубже, разногласия распространяются и на наборы функций с лучшим рейтингом. Когда строгое соблюдение точной перестановки важности функций ослабляется, внимание переключается на набор главных функций. Несоответствие в первых 3, 5 или любых n характеристиках, определенных разными объяснителями для одной и той же модели, становится заметной точкой расхождения.
- Колебание знака коэффициента. Показатели многих объяснителей зависят от коэффициентов, присвоенных признакам, указывающих их положительный или отрицательный вклад в желаемый результат. Иногда можно наблюдать изменение знака этого коэффициента между двумя объяснениями одной и той же модели. Такие изменения служат индикаторами разногласий. В таком случае нужно более внимательно изучить внутреннюю работу модели.
- Относительное упорядочение интересующих особенностей. При более пристальном рассмотрении конкретных интересующих особенностей разногласия приобретают еще одно измерение. Если сосредоточиться на сопоставлении важности одной функции по сравнению с другой, изменения в порядке этих двух функций в разных объяснениях становятся причиной разногласий.
Что не является разногласием?
Важно учитывать, что не все различия означают разногласия. Рассмотрим такие случаи:
- Расходящиеся значения важности. Бывает, что значения важности признаков, рассчитанные разными объяснителями, не совпадают точно. Это не является разногласием. Суть в том, что различные алгоритмы дают разные вычисления, что затрудняет прямое сравнение. Акцент при этом делается не на числовом равенстве значений важности, а на последовательных выводах, полученных в результате различных объяснений.
- Последовательное понимание точных значений. Суть правильного анализа — стремление к последовательному пониманию, а не поиск точного числового равенства. Мы и не можем ожидать от объяснителей, что они дадут очень точную оценку с конкретными значениями. Здесь нужно взглянуть на вещи шире и понять, что объяснения, хотя и различаются численно, могут сходиться, например, в направлении.
- Сложность модели и проблемы оценки. С увеличением сложности модели сложность точной оценки внутренней ее работы растет прямо пропорционально. Просто нужно признать эту внутреннюю сложность. Поэтому, когда мы имеем дело с очень сложными моделями, расхождение в значениях объяснителей становится скорее ожидаемой проблемой, чем поводом для тревоги. Эта точка зрения согласуется с развивающейся природой ИИ, где стремление к прозрачности сталкивается с растущими сложностями.
Почему объяснители не согласны друг с другом?
Есть много причин, по которым объяснители могут не соглашаться друг с другом, давайте вместе попробуем разобраться в нескольких случаях.
Сравнение глобальных и локальных объяснителей
Одна из причин, по которой мы можем наблюдать разногласия, заключается в том, что мы можем сравнивать глобальные и локальные объяснения. Хотя это очевидное объяснение, все равно хочется убедиться, что мы никогда не попадемся на эту ошибку. Глобальные и локальные объяснения нельзя просто напрямую сравнивать друг с другом. Если у вас нет детального понимания того, как алгоритмы реализованы под капотом, сравнивать глобальные и локальные объяснения нецелесообразно, поскольку это, вероятно, приведет к разным объяснениям.Сравнение объяснителей черного и белого ящика
Более того, нельзя напрямую сравнивать объяснители черного ящика и белого ящика. Помните, что объяснители черного ящика пытаются показать полезность возможности объяснить любой алгоритм, поэтому они делают определенные упрощающие предположения о модели или ее поведении. Эти предположения позволяют объяснителям черного ящика работать в широком диапазоне обстоятельств, однако такие предположения не всегда оправдываются, а допущения могут быть слишком большими. Соответственно, объяснения черного и белого ящика будут различаться.
Изменение порядка признаков
Неожиданным поводом для разногласий могут стать любые изменения порядка изложения признаков. Одни методы объяснения чувствительны к порядку входных данных модели, другие нет. Например, метод взаимной информации (Mutual Information) не чувствителен к порядку ввода, в отличие от SHAP. Следовательно, вполне возможно, что объяснитель SHAP не сможет прийти к согласию сам с собой после наблюдения идентичных моделей.
Например, ниже показаны два объяснения SHAP, полученные от двух идентичных XGBRegressor. Единственная разница между двумя моделями — это порядок признаков, которые они принимают в качестве входных данных. При этом они обучаются на одном и том же наборе данных и имеют одну и ту же цель.
Рис. 8. Начальные значения SHAP
Рис. 9. Значения SHAP после изменения порядка элементов.
Более того, разные реализации одной и той же техники объяснения могут не согласовываться друг с другом из-за небольших различий в их расчетах. Например, реализация важности перестановок в eli5 чувствительна к порядку входных данных, а реализация той же техники в sklearn — нет. Потому что одна и та же техника объяснения может быть реализована разными способами.
Чтобы продемонстрировать, что реализация важности перестановок в eli5 чувствительна к порядку входных данных, ниже я покажу два объяснения, полученные с использованием реализации важности перестановок в eli5. Мы получили результаты от двух идентичных XGBRegressor. Единственная разница между двумя моделями — это порядок признаков, которые они принимают в качестве входных данных. При этом они обучаются на одном и том же наборе данных и имеют одну и ту же цель.
Рис. 10. Начальная важность перестановки
Рис. 11. Перемешанная важность перестановки
Обратите внимание, что параметр kickPower_rating изначально имел положительный коэффициент, но после изменения порядка функций имеет отрицательный коэффициент! Такие нестабильные колебания считаются сильными разногласиями. Изменились наиболее важные признаки, также изменился относительный порядок между признаками.
Наконец, одним из самых явных моментов будет методологическое расхождение. Оно порождает интересный феномен, когда объяснители не соглашаются друг с другом, хотя оба объясняют одну и ту же модель. Поскольку каждый объяснитель рассчитывает разные показатели модели, каждый из них может интерпретировать модель в разном свете.
К счастью, в XGB реализована функция, позволяющая оценить важность функций. Давайте воспользуемся этой функцией и посмотрим, какой метод объяснения дает достоверное представление истины. Я также сразу добавил сюда результаты предыдущих объяснений, чтобы вам не нужно было прокручивать вверх и вниз.
Рис. 12. Важность признаков XGB
Рис. 13. Важность перестановки XGB
Рис. 14: Объяснения белого ящика SHAP
Рис. 15. Объяснения черного ящика SHAP
Рис. 16. Важность функции модели на основе дерева, стеклянный ящик
Рейтинг осведомленности был самой важной особенностью модели, однако небольшой набор методов объяснения черного ящика не смог объяснить это, и вообще не справился с тремя основными признаками. Это еще одно напоминание о том, что объяснения — это всего лишь оценки важности признаков, а не абсолютная истина. Кроме того, обратите внимание, что yearsPro неоднократно занимал верхние позиции, но на самом деле это было не так важно. То есть не нужно полагаться на то, что признаки, которые несколько раз занимают высокие места в разных тестах, действительно по своей сути важны.
Объяснитель черного ящика, который мы применили к нашей модели XGB, противоречит объяснителю белого ящика. Но в конечном итоге оба объяснителя оказались неправильными. Выяснять, какой объяснитель точнее, будет пустой тратой вашего времени, потому что ни один из них не приближает нас к истине.
Я также запустил ema на данных, чтобы посмотреть, можно ли использовать модель стеклянного ящика в качестве прокси для оценки важности признаков. И хотя ей удалось правильно определить наиболее важную особенность из набора данных, это не всегда подходящий вариант, особенно если ваша модель не основана на дереве. К сожалению, модель стеклянного ящика также обнаружила, что признак yearsPro информативен, хотя это не так. Это означает, что объяснители кроме прочего могут согласиться с ложной информацией!
Примеры
Теперь мы готовы начать работу с реальными рыночными данными. Сначала получим данные из терминала MetaTrader 5. Для эффективного извлечения и преобразования данных, разработаем скрипт на MQL5. Начнем с объявления глобальных переменных.//---Our handlers for our indicators int ma_handle; int rsi_handle; int cci_handle; int ao_handle; int bbands_handle; int atr_handle;
Далее создадим массивы для хранения значений индикаторов. Здесь мы методично собираем и затем используем результаты индикаторов на протяжении всего выполнения скрипта.
//---Data structures to store the readings from our indicators double ma_reading[]; double rsi_reading[]; double cci_reading[]; double ao_reading[]; double bb_high_reading[]; double bb_low_reading[]; double bb_mid_reading[]; double atr_reading[];
Создадим CSV-файл.
//---File name string file_name = "The Dissagrement Problem Data.csv";
Далее нужно создать переменную для хранения количества баров, которые нужно запросить.
//---Amount of data requested int size = 10000; int size_fetch = size + 50;
Переходим к настройке обработчиков индикаторов. Чтобы настроить работу с индикатором, необходимо указать символ и таймфрейм, на которых мы будем его использовать. Далее, в зависимости от индикатора, может потребоваться указать период индикатора, параметр сдвига, метод сглаживания и тип цен для расчета.
void OnStart() { //---Setup our technical indicators ma_handle = iMA(_Symbol,PERIOD_CURRENT,20,0,MODE_EMA,PRICE_CLOSE); rsi_handle = iRSI(_Symbol,PERIOD_CURRENT,60,PRICE_CLOSE); cci_handle = iCCI(_Symbol,PERIOD_CURRENT,10,PRICE_CLOSE); ao_handle = iAO(_Symbol,PERIOD_CURRENT); bbands_handle = iBands(_Symbol,PERIOD_CURRENT,120,0,0.2,PRICE_CLOSE); atr_handle = iATR(_Symbol,PERIOD_CURRENT,14);
Далее нужно перенести значения из хэндлов индикатора в структуры данных.
//---Set the values as series CopyBuffer(ma_handle,0,0,size_fetch,ma_reading); ArraySetAsSeries(ma_reading,true); CopyBuffer(rsi_handle,0,0,size_fetch,rsi_reading); ArraySetAsSeries(rsi_reading,true); CopyBuffer(cci_handle,0,0,size_fetch,cci_reading); ArraySetAsSeries(cci_reading,true); CopyBuffer(ao_handle,0,0,size_fetch,ao_reading); ArraySetAsSeries(ao_reading,true); CopyBuffer(bbands_handle,0,0,size_fetch,bb_mid_reading); ArraySetAsSeries(bb_mid_reading,true); CopyBuffer(bbands_handle,1,0,size_fetch,bb_high_reading); ArraySetAsSeries(bb_high_reading,true); CopyBuffer(bbands_handle,2,0,size_fetch,bb_low_reading); ArraySetAsSeries(bb_low_reading,true); CopyBuffer(atr_handle,0,0,size_fetch,atr_reading); ArraySetAsSeries(atr_reading,true);
Прежде чем мы начнем процесс записи файла, обязательно в скрипт нужно включить обработчик файлов. Эти настройки позволят корректно создать выходной файл и работать с ним.
//---Write to file int file_handle=FileOpen(file_name,FILE_WRITE|FILE_ANSI|FILE_CSV,",");
Далее важный этап в нашем скрипте: идем по массивам исторических цен и значений индикаторов, чтобы записать нужные данные в файл CSV.
for(int i=-1;i<=size;i++){ if(i == -1){ FileWrite(file_handle,"Time","Open","High","Low","Close","MA 20","RSI 60","CCI 10","AO","BBANDS 120 MID","BBANDS 120 HIGH","BBANDS 120 LOW","ATR 14"); } else{ FileWrite(file_handle,iTime(_Symbol,PERIOD_CURRENT,i), iOpen(_Symbol,PERIOD_CURRENT,i), iHigh(_Symbol,PERIOD_CURRENT,i), iLow(_Symbol,PERIOD_CURRENT,i), iClose(_Symbol,PERIOD_CURRENT,i), ma_reading[i], rsi_reading[i], cci_reading[i], ao_reading[i], bb_mid_reading[i], bb_high_reading[i], bb_low_reading[i], atr_reading[i]); } } FileClose(file_handle); }
Рис. 17. Рыночные данные из терминала MetaTrader 5.
Теперь мы готовы обработать данные и проверить то, что мы узнали из примера выборки.
Импортируем зависимости.
#Import Dependencies import pandas as pd import numpy as np import matplotlib.pyplot as plt import shap import lime from lime import lime_tabular import eli5 from eli5.sklearn import PermutationImportance from sklearn.feature_selection import mutual_info_regression
Загружаем зависимостей для IntepretML.
from interpret import set_visualize_provider from interpret.provider import InlineProvider set_visualize_provider(InlineProvider()) from interpret import show from interpret.blackbox import MorrisSensitivity
Читаем csv.
csv = pd.read_csv("/enter/your/path/here")
Настроим цель.
csv["Target"] = csv["Close"].shift(-30)
Отбросить все строки с пропущенными значениями.
csv.dropna(axis=0,inplace=True)
Создадим список предикторов.
drop = ["Time","Target"] predictors = csv.columns.tolist() predictors = [col for col in predictors if col not in drop] predictors
Масштабируем данные.
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() print(scaler.fit(csv.loc[:,predictors])) scaled_data = pd.DataFrame(scaler.transform(csv.loc[:,predictors]), index = csv.index, columns = predictors) scaled_data
Рис. 18. Масштабированные рыночные данные
Настройка алгоритмов черного ящика
#Black box models from xgboost import XGBRegressor from sklearn.linear_model import LinearRegression from xgboost import plot_importance from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.callbacks import EarlyStopping
Разделение данных на обучающую и тестовую выборку
train = 0 train_end = 5000 test = train_end + 40
Настройка линейной модели
lm = LinearRegression()
lm.fit(scaled_data.loc[train:train_end,predictors],csv.loc[train:train_end,"Target"])
Настройка модели XGB
#XGBModel xgb = XGBRegressor() xgb.fit(scaled_data.loc[train:train_end,predictors],csv.loc[train:train_end,"Target"])
Настройка модели глубокой нейросети
dnn = keras.Sequential([ layers.Dense(units=30,activation="relu",input_shape=[scaled_data.shape[1]]), layers.Dense(units=20,activation="relu"), layers.Dropout(0.3), layers.Dense(units=10,activation="relu"), layers.Dense(units=1) ])
early_stopping = EarlyStopping( min_delta=0.001, patience=20, restore_best_weights=True )
dnn.compile(optimizer="adam",loss="mae")
dnn.fit( scaled_data.loc[train:train_end,predictors],csv.loc[train:train_end,"Target"], validation_data=(csv.loc[validation:validation_end,predictors],csv.loc[validation:validation_end,"Target"]), batch_size = 60, epochs=100, verbose=0, callbacks=[early_stopping] )
Получение глобальных объяснений для глубокой нейронной сети
Мы воспользуемся пакетом alibi, чтобы получить объяснения для нашей глубокой сети. В пакете alibi есть полезная реализация объяснительной техники "Накопленные локальные эффекты" (Accumulated Local Effects, ALE). Метод ALE достаточно надежен и может обрабатывать сильно коррелированные признаки. При этом в нем нет четких предположений о независимости признаков, его можно визуально интерпретировать, он эффективен в вычислительном отношении и, в отличие от некоторых других методов объяснения, ALE не полагается на предположения о линейности, что делает его хорошо подходящим для выявления сложных взаимосвязей в данных.
Сначала рассчитываем значения ALE.
dnn_ale = ALE(dnn.predict, feature_names = predictors,target_names=["Close 30 Steps"])
Затем мы преобразуем входные данные в формат NumPy, чтобы можно было построить графики ALE.
X = scaled_data.loc[train:train_end,predictors].to_numpy() dnn_alibi =dnn_ale.explain(X) plot_ale(dnn_alibi,n_cols=4, fig_kw={'figwidth': 20, 'figheight': 10}, sharey=None)
Графики ALE помогают интерпретировать, как изменения в каждом признаке влияют на выходные данные модели. Например, ниже показан график ALE для нашего Awesome Oscillator. Как видим, Awesome Oscillator может помочь нашей глубокой нейронной сети предвидеть, когда цена упадет. Мы наблюдаем нисходящий наклон на графике ALE по мере увеличения значения Awesome Oscillator.
Рис. 19. График ALE для Awesome Oscillator
Более того, неинформативные признаки будут иметь график ALE, напоминающий горизонтальную линию, а это означает, что изменения в этом признаке мало повлияют на цель. В нашем исследовании не был информативным индекс RSI.
Рис. 20. ALE RSI
Получение глобальных объяснений от независимого от модели объяснения SHAP
explainer = shap.Explainer(xgb.predict,scaled_data.loc[test:,predictors]) shap_values = explainer(scaled_data.loc[test:,predictors]) shap.plots.beeswarm(shap_values)
Рис. 21. График SHAP Black-box Beeswarm для XGB
Диаграмма beeswarm показывает, что Awesome Oscillator является наиболее важным признаком в этом наборе данных. Помните, что ширина каждой строки на графике не несет никакой информации. Кроме того, мы замечаем, что синие и розовые точки не перепутаны, а это означает, что в наборе данных может не быть сильных членов взаимодействия.
Важность признака в соответствии с взаимной информацией (Mutual Information, MI)
mi_scores = mutual_info_regression(scaled_data.loc[test:,predictors], csv.loc[test:,"Target"]) mi_scores = pd.Series(mi_scores, name="MI Scores", index=scaled_data.columns) mi_scores = mi_scores.sort_values(ascending=False) mi_scores
BBANDS 120 MID 1.739039
BBANDS 120 HIGH 1.731220
BBANDS 120 LOW 1.716019
MA 20 1.525800
High 1.172096
Open 1.155583
Close 1.143642
Low 1.140613
ATR 14 0.421772
AO 0.232608
RSI 60 0.181932
CCI 10 0.016491
MI полностью противоречит нашему объяснению SHAP в том, что касается четырех основных признаков. Это только вызывает больше сомнений в нашем и без того запутанном деле. Хуже того, объяснитель SHAP был действительно прав в отношении того, что Awesome Oscillator является наиболее важной функцией в этом случае. Таким образом, использование нескольких объяснителей на самом деле является палкой о двух концах: с одной стороны, это защищает от предвзятости, унаследованной от любого используемого объяснения, но с другой стороны, создает большее пространство вероятности возникновения разногласий. Трудно сказать, какой случай эмпирически лучше, потому что все зависит от конкретного набора данных, конкретной модели и многих других переменных.
Наконец, рассмотрим анализ чувствительности Морриса (Morris Sensitivity Analysis)
msa = MorrisSensitivity(xgb, scaled_data.loc[train:train_end,predictors]) show(msa.explain_global())
Рис. 22: Morris Sensitivity Analysis
Фактические показатели важности из нашей модели XGB.
Рис. 23. Важность рыночных данных XGB
Скользящая средняя была самой важной функцией в выборке, за ней следовал Awesome Oscillator. В данном конкретном случае анализ чувствительности Морриса дал относительно лучшие объяснения, однако в большинстве случаев у нас нет доступа к истине, поэтому как выбрать, какому объяснению придать больший вес? Как быть уверенным в своем решении? Как проверить решения относительно важности функций, если нет доступа к таблицам истинной важности функций?
Заключение
Как мы видим, здесь нет простых ответов. Слишком много составных частей. Необходимо учитывать форму и структуру данных, базовую модель, наличие условий взаимодействия в данных и, прежде всего, внутреннюю работу каждого объяснителя. Более того, в контролируемом примере видно, что все объяснители могут ошибаться, поэтому в такой ситуации попытка разрешить любые разногласия была бы бесполезной тратой времени. Таким образом, выгода, которую мы получаем от объяснительных методов, не всегда оправдывает сложность, которую они могут привнести. Будем надеяться, что со временем мы сможем реализовать более эффективные объяснительные методы и более совершенные алгоритмы.
Рекомендации
С учетом всего этого, возможно, лучшим решением проблемы разногласий может быть больше полагаться на модели машинного обучения, которые легче интерпретировать. Например, обобщенные аддитивные модели (GAM) или объяснимые повышающие машины (EBM). Они прекрасно заменяют собой необходимость объяснений. На сегодняшний день не существует общепризнанных решений для всех возможных случаев проблемы разногласий. Но, поскольку это известная проблема, возможно, однажды мы сможем уверенно объяснить любую модель машинного обучения, которую мы создаем.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/13729
![Maxim Dmitrievsky Maxim Dmitrievsky](https://c.mql5.com/avatar/2024/3/66034e17-bb79.jpg)
![Особенности написания Пользовательских Индикаторов](https://c.mql5.com/2/16/77_1.gif)
![Разрабатываем мультивалютный советник (Часть 14): Адаптивное изменение объёмов в риск-менеджере](https://c.mql5.com/2/83/Developing_a_multi-currency_advisor_Part_13__LOGO.png)
![Алгоритм искусственного электрического поля — Artificial Electric Field Algorithm (AEFA)](https://c.mql5.com/2/83/Artificial_Electric_Field_Algorithm___LOGO.png)
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования