Объяснимый ИИ или XAI - это подкатегория ИИ, в которой решения, принимаемые моделью, могут интерпретироваться людьми, в отличие от моделей «черного ящика». По мере того как ИИ переходит от исправления орфографии и таргетинга рекламы к вождению автомобилей и диагностике пациентов, необходимость проверки и обоснования сделанных выводов становится все более приоритетной.
Чтобы начать углубляться в эту область, давайте рассмотрим одну простую модель XAI: дерево решений. Деревья решений могут быть легко прочитаны и даже имитируют человеческий подход к принятию решений, разбивая выбор на множество мелких подвыборов. Простой пример - как можно оценивать местные университеты после окончания средней школы. Учитывая, что студент имеет в виду курс, простой процесс принятия решения может быть следующим:
То, как студент пришел к своему выводу, можно легко обосновать, если третье лицо имеет доступ к «модели» и необходимым переменным.
Та же самая структура может быть применена к контролируемому обучению с целью создания дерева решений, которое лучше всего описывает данные обучения. Затем эту модель можно использовать для понимания взаимосвязи между переменными или в прогностическом приложении.
Алгоритм
Построение дерева решений выполняется как рекурсивный процесс.
- Оцените, какая переменная дает наибольший информационный поток. Прирост информации - это уменьшение энтропии зависимой переменной, когда состояние независимой переменной известно.
Там много громких слов.
По сути, это измеряет, насколько более организована независимая переменная, когда мы разбиваем ее на группы в соответствии со значением зависимой переменной. - Выбирается зависимая переменная, которая обеспечивает наибольший рост организации, и набор данных разделяется в соответствии с этой переменной.
- На этом этапе должно выполняться одно из трех:
- Теперь зависимая переменная принимает только одно значение. В этом случае ветвь дерева завершена, и мы достигли «решения».
- Зависимая переменная принимает ›1 значение. Здесь мы просто возвращаемся к шагу 1 и пытаемся сузить его еще больше.
-Зависимая переменная принимает ›1 значение, но у нас больше нет независимых переменных, по которым можно разделить данные. Здесь мы просто говорим, какие значения может принимать решение, и оцениваем вероятность для каждого в соответствии с относительными пропорциями каждого варианта.
Расчет прироста информации
Во-первых, нам нужна формула для организации или энтропии. Чтобы вычислить энтропию нашей зависимой переменной, мы используем:
На следующей диаграмме показано, как энтропия Y (где Y имеет два состояния) изменяется с вероятностью каждого состояния. Поскольку вероятность одного состояния равна 0, энтропия также равна 0, поскольку в этом случае Y наиболее организован, в то время как когда Y равномерно разделен между двумя состояниями, энтропия максимальна.
Расширяя это, чтобы добавить эффект знания независимой переменной X на энтропию:
Прирост информации теперь выражается как разница между энтропией, когда мы знаем X, и когда нет.
Дай мне код!
Некоторые функции для вычисления энтропии и создания графики сюда не включены.
def decide(Y, X_dict, previous_node): #Calc info gain for each X max_IG = 0 var_to_split = None #Calculate information gain to find out which variable to split on for x in X_dict.keys(): IG = InfoGain(Y, X_dict[x]) if IG > max_IG: max_IG = IG var_to_split = x #See if all variables have been used and none are left. if var_to_split == None: Y_options = list(set(Y)) tot = float(len(Y)) count = [0 for _ in range(len(Y_options))] for op in range(len(Y_options)): for i in range(len(Y)): if Y[i] == op: count[op] += 1 #Format Node label Prob = "" for op in range(len(Y_options) - 1): Prob += "P(" Prob += str(Y_options[op]) + ")-> " P = float(count[op]) / tot Prob += "{0:.2f}".format(P) #Make a new node nodename = node(Prob, color = "orange") edge(previous_node, nodename) else: print("Splitting on {0}".format(var_to_split)) X_options = list(set(X_dict[var_to_split])) #Make decision variable node Var_nodename = node(var_to_split, color = "red") edge(previous_node, Var_nodename) #Init new data for each new branch of the tree for X_option in X_options: X_nodename = node(str(X_option)) edge(Var_nodename, X_nodename) New_X_dict = {} #get remaining variables for key in X_dict.keys(): if key != var_to_split: New_X_dict[key] = [] New_Y = [] #Populate for i in range(len(Y)): if X_dict[var_to_split][i] == X_option: New_Y.append(Y[i]) for key in New_X_dict.keys(): New_X_dict[key].append(X_dict[key][i]) #Check if this is a terminal node: if len(set(New_Y)) == 1: nodename = node(str(New_Y[0]), color = "green") edge(X_nodename, nodename) else: #No terminal node, so try again decide(New_Y, New_X_dict, X_nodename) Y, X_dict = import_golf('golf.csv') #import data root_node = node("root", color = "blue") #Create the first node decide(Y, X_dict, root_node) #start the tree
Для набора данных по гольфу выводится следующее дерево, которое является простым способом интерпретации процесса принятия решения.