Код Python для реализации AHP: пример лидеров
В этой статье:
- Поделюсь практической реализацией AHP на Python,
- Я не буду подробно объяснять теорию AHP,
- Будем реализовывать пример из Википедии,
- Я поделюсь с вами полным кодом.
Вот — пример лидера из Википедии.
В этом примере есть 3 лидера, и нам нужно выбрать лучший вариант с помощью AHP. Критериями являются опыт, образование, харизма и возраст.
Приступаем к реализации.
Импортировать необходимые библиотеки:
import numpy as np import pandas as pd from sklearn.preprocessing import normalize
Реализуйте основной метод:
(Если вас не интересуют подробности этого метода, перейдите к следующему разделу: Начать выбор.)
Самая важная часть нашего кода Python — это наш основной метод: compute_priorities
.
Этот метод выполняет базовые расчеты AHP. Он получает общий балл и список функций и распределяет этот общий балл по функциям. Таким образом, приоритеты вычисляются и возвращаются в виде словаря.
Первый ввод: функции (2-й список)
Этот 2d список имеет 2 строки. Первая строка содержит имена функций, тогда как вторая строка содержит шкалы AHP по сравнению с первой функцией.
Пример ввода: [['A','B','C','D'], [2,5,6]]
Вторая строка содержит n-1 (имеется n признаков) количество целых чисел от 1 до 9, которые находятся в шкале AHP.
В примере А является наиболее важной функцией.
Второй ввод: total_point (целое число)
По заданным баллам AHP рассчитываются веса. Затем в соответствии с весами распределяются общие баллы для определения приоритетов.
Общее количество очков равно 1 или 100 в начале дерева AHP.
Вывод словаря:
Возвращается словарь, который содержит имена функций в качестве ключей и приоритеты в качестве значений.
Важные примечания к методу:
- Первая функция входного списка должна быть одной из самых важных функций.
- Каждая функция сравнивается только с первой функцией.
Код Python:
def calculate_priorities(features, total_point): # There are n features, so an n*n 'ones' matrix is composed. # The elements on the diagonal are all one. n = len(features[0]) ahp_matrix = np.ones([n,n]) # The matrix is filled according to ahp calculations. for i in range(0,n): for j in range(0,n): # The element (j,i) equals 1/(i,j) if i<j: if i==0: # The first row is the second row of the input list. ahp_matrix[i,j] = float(features[1][j-1]) # Then, the first column is filled. ahp_matrix[j,i] = 1/float(ahp_matrix[i,j]) else: # The rest of the cells are filled according to firs row. if ahp_matrix[0,j]>ahp_matrix[0,i]: ahp_matrix[i,j] = ahp_matrix[0,j]-ahp_matrix[0,i]+1 else: ahp_matrix[i,j] = 1/((ahp_matrix[0,i]-ahp_matrix[0,j])+1) ahp_matrix[j,i] = 1/float(ahp_matrix[i,j]) # The matrix is normalized according to axis 0 normed_matrix = normalize(ahp_matrix, axis=0, norm='l1') # Weights are calculated weights = normed_matrix.mean(1) # The total point is distributed according to weights points = total_point*weights # Feature names and points are stored in a dataframe return dict(zip(features[0],points))
После определения наиболее важного метода давайте посмотрим, как его вызвать.
Начать выбор
На первом уровне дерева будем сравнивать критерии друг с другом.
На изображении вы видите сравнение критериев по шкалам AHP. В этом образе есть некоторое несоответствие.
Например, в первом ряду Образование равно 4, а Обаяние равно 3. Итак, когда мы сравниваем их друг с другом, должно быть 2, но вы видите, что в третьей строке 3.
Мы будем реализовывать наш код с наименьшим несоответствием, и поэтому мы будем использовать только строку, не содержащую дробей. В данном случае это первый ряд: 1, 4, 3, 7. Опыт — самый важный.
critetia = [['Experience','Education','Charisma','Age'],[4,3,7]] total_point = 1 main_dict = calculate_priorities(critetia, total_point) main_dict
Результаты немного отличаются от Википедии из-за проблемы несоответствия.
Теперь мы распределим эти очки между тремя лидерами.
Начнем с опыта.
Поскольку строки несовместимы, мы будем использовать строку, не содержащую дробей. На этот раз это второй ряд: 4, 1, 9. У Дика больше всего опыта, поэтому он будет в начале списка.
experience_feature = [['Dict','Tom','Harry'],[4,9]] experience_dict = calculate_priorities(experience_feature, main_dict['Experience']) experience_dict
Результаты отличаются по 2 причинам:
- Мы реализуем с наименьшим несоответствием.
- Мы распределили общее количество очков опыта, тогда как Википедия распределила 1. (Википедия позже умножает очки опыта на эти результаты.)
Настало время сравнить уровень образования лидеров.
Мы используем третью строку в качестве уровней приоритета: 5, 7, 1. На этот раз у Гарри самый высокий приоритет. (Значит, он в начале списка.)
education_feature = [['Harry','Tom','Dict'],[5,7]] education_dict = calculate_priorities(education_feature, main_dict['Education']) education_dict
Результат причины отличается от причины, указанной выше. В итоге вы увидите, что разница в результатах очень мала.
Пришло время сравнить харизму.
Мы будем использовать первую строку, и на этот раз Том впереди: 1, 5, 9.
charisma_feature = [['Tom','Dict','Harry'],[5,9]] charisma_dict = calculate_priorities(charisma_feature, main_dict['Charisma']) charisma_dict
Остался только возраст.
На этот раз второй ряд. Дик впереди.
age_feature = [['Dict','Tom','Harry'],[3,9]] age_dict = calculate_priorities(age_feature, main_dict['Age']) age_dict
Соберем всех вместе.
df = pd.DataFrame([experience_dict, education_dict, charisma_dict, age_dict]) df.index = main_dict.keys() df
Итак, мы получили приоритеты для 4 фич и 3 лидеров. Теперь мы можем суммировать результаты, чтобы получить общее количество баллов.
total = df.sum() total.name = 'Total' df = pd.concat([df,total.to_frame().T]) df
Дикт - победитель отбора, и Том следует за ним. Ниже приведены результаты из Википедии.
Том получил 0,358 в Википедии, а мы дали 0,359, тогда как Dict получил 0,492 из Википедии, а мы дали 0,478.
Причина, как я уже сказал, несоответствие в Википедии.
Это все, что касается реализации AHP в Python. Вот полный код.
import numpy as np import pandas as pd from sklearn.preprocessing import normalize def calculate_priorities(features, total_point): # There are n features, so an n*n 'ones' matrix is composed. # The elements on the diagonal are all one. n = len(features[0]) ahp_matrix = np.ones([n,n]) # The matrix is filled according to ahp calculations. for i in range(0,n): for j in range(0,n): # The element (j,i) equals 1/(i,j) if i<j: if i==0: # The first row is the second row of the input list. ahp_matrix[i,j] = float(features[1][j-1]) # Then, the first column is filled. ahp_matrix[j,i] = 1/float(ahp_matrix[i,j]) else: # The rest of the cells are filled according to firs row. if ahp_matrix[0,j]>ahp_matrix[0,i]: ahp_matrix[i,j] = ahp_matrix[0,j]-ahp_matrix[0,i]+1 else: ahp_matrix[i,j] = 1/((ahp_matrix[0,i]-ahp_matrix[0,j])+1) ahp_matrix[j,i] = 1/float(ahp_matrix[i,j]) # The matrix is normalized according to axis 0 normed_matrix = normalize(ahp_matrix, axis=0, norm='l1') # Weights are calculated weights = normed_matrix.mean(1) # The total point is distributed according to weights points = total_point*weights # Feature names and points are stored in a dataframe return dict(zip(features[0],points)) critetia = [['Experience','Education','Charisma','Age'],[4,3,7]] total_point = 1 main_dict = calculate_priorities(critetia, total_point) experience_feature = [['Dict','Tom','Harry'],[4,9]] experience_dict = calculate_priorities(experience_feature, main_dict['Experience']) education_feature = [['Harry','Tom','Dict'],[5,7]] education_dict = calculate_priorities(education_feature, main_dict['Education']) charisma_feature = [['Tom','Dict','Harry'],[5,9]] charisma_dict = calculate_priorities(charisma_feature, main_dict['Charisma']) age_feature = [['Dict','Tom','Harry'],[3,9]] age_dict = calculate_priorities(age_feature, main_dict['Age']) df = pd.DataFrame([experience_dict, education_dict, charisma_dict, age_dict]) df.index = main_dict.keys() total = df.sum() total.name = 'Total' df = pd.concat([df,total.to_frame().T]) df
Надеюсь, вам понравится и принесет пользу.
Подпишитесь на мою ленту. (Получите мои истории в свой почтовый ящик.)
Стать участником и (или просто) обратиться ко мне. (Поддержите меня своим членским взносом.)
Подпишитесь на DDIntel Здесь.
Посетите наш сайт здесь: https://www.datadriveninvestor.com
Примените код: DDI2022, чтобы получить СКИДКУ 30% на РАСПРОДАЖУ в Черную пятницу.