Абстрактный

Этот пост является подведением итогов проекта Data Scientist Capstone, завершенного в рамках Udacity Data Scientist Capstone Nano Degree. В отчете подробно описывается исследовательский анализ, контролируемое моделирование машинного обучения, и объяснимость модели, проведенная на наборе данных, подробно описывающих удовлетворенность клиентов авиакомпанией. Мы запустили десять моделей, используя окончательный набор данных, состоящий из семнадцати признаков — пятнадцать с самым высоким p-значением хи-квадрата и два добавленных для целей объяснения. Последним выбранным конвейером был классификатор Extreme Gradient Boosting Classifier, который показал точность обучения 94,3, точность теста 95, ROC 98,7, точность 95 и отзыв 92.

Введение

Удовлетворенность клиентов авиакомпаниями неуклонно растет в течение последних нескольких лет. Для многих этой проблеме в последние годы стало уделяться больше внимания, поскольку индустрия авиаперевозок возобновила работу после полной остановки, вызванной пандемией COVID-19. Однако это проблема, с которой перевозчики сталкивались за годы до пандемии. Неудобные сиденья, переполненные рейсы, задержки и некачественные удобства — это жалобы, которые клиенты высказывают в последнее время.

Удовлетворенность клиентов — это то, на что обращают внимание все больше и больше перевозчиков и стремятся улучшить. Отличное обслуживание клиентов, особенно по сравнению с вашими конкурентами, является ключом к конкурентоспособности, продажам и удержанию клиентов. И наоборот — низкие рейтинги обслуживания клиентов могут привести к оттоку клиентов и плохой репутации компании.

Бизнес-задача.Определите факторы, которые больше всего влияют на удовлетворенность клиентов, и проверьте их с помощью машинного обучения.

Будучи учеником команды IBM Data Science в области клиентской инженерии, часть нашего основного погружения включает в себя участие в клиентских проектах, а также внесение вклада и получение впечатляющих результатов. Этот проект призван отразить этот процесс от начала до конца.

Я люблю путешествовать и считаю себя энтузиастом авиации, поэтому я выбрал своим «клиентом» авиакомпанию, которая ищет вариант использования науки о данных для обслуживания клиентов.

Источники данных и зависимости

Этот проект был собран в среде Python 3.9 с использованием Jupyter Notebooks. Для исследовательского анализа использовались библиотеки Pandas, Numpy, Seaborn и Matplotlib. XGBoost и Scikit-Learn использовались для создания пайплайнов моделирования и получения метрик, и, наконец, SHAP использовался как наша библиотека для пояснения модели.

Наборы данных, используемые для этого проекта, взяты с Kaggle.com (https://www.kaggle.com/datasets/teejmahal20/airline-passenger-satisfaction). Наборы данных имеют формат .csv и были предварительно разделены на обучающую и тестовую части, составляющие 80% и 20% исходного набора данных соответственно; набор данных также поставляется с предварительно определенным целевым столбцом удовлетворенность.

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

Прием и очистка данных

Данные, использованные для этого проекта, включали в общей сложности 129 880 начальных строк с 25 начальными столбцами. Наборы данных были предварительно разделены на обучающий набор данных (19,8 МБ), содержащий 103 904 строки, и тестовый набор данных (5 МБ), содержащий 25 976 строк.

Training Data Set (air_train_df):
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 103904 entries, 0 to 103903
Data columns (total 25 columns):
 #   Column                             Non-Null Count   Dtype  
---  ------                             --------------   -----  
 0   Unnamed: 0                         103904 non-null  int64  
 1   id                                 103904 non-null  int64  
 2   Gender                             103904 non-null  object 
 3   Customer Type                      103904 non-null  object 
 4   Age                                103904 non-null  int64  
 5   Type of Travel                     103904 non-null  object 
 6   Class                              103904 non-null  object 
 7   Flight Distance                    103904 non-null  int64  
 8   Inflight wifi service              103904 non-null  int64  
 9   Departure/Arrival time convenient  103904 non-null  int64  
 10  Ease of Online booking             103904 non-null  int64  
 11  Gate location                      103904 non-null  int64  
 12  Food and drink                     103904 non-null  int64  
 13  Online boarding                    103904 non-null  int64  
 14  Seat comfort                       103904 non-null  int64  
 15  Inflight entertainment             103904 non-null  int64  
 16  On-board service                   103904 non-null  int64  
 17  Leg room service                   103904 non-null  int64  
 18  Baggage handling                   103904 non-null  int64  
 19  Checkin service                    103904 non-null  int64  
 20  Inflight service                   103904 non-null  int64  
 21  Cleanliness                        103904 non-null  int64  
 22  Departure Delay in Minutes         103904 non-null  int64  
 23  Arrival Delay in Minutes           103594 non-null  float64
 24  satisfaction                       103904 non-null  object 
dtypes: float64(1), int64(19), object(5)
memory usage: 19.8+ MB

Testing Set (air_test_df):
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 25976 entries, 0 to 25975
Data columns (total 25 columns):
 #   Column                             Non-Null Count  Dtype  
---  ------                             --------------  -----  
 0   Unnamed: 0                         25976 non-null  int64  
 1   id                                 25976 non-null  int64  
 2   Gender                             25976 non-null  object 
 3   Customer Type                      25976 non-null  object 
 4   Age                                25976 non-null  int64  
 5   Type of Travel                     25976 non-null  object 
 6   Class                              25976 non-null  object 
 7   Flight Distance                    25976 non-null  int64  
 8   Inflight wifi service              25976 non-null  int64  
 9   Departure/Arrival time convenient  25976 non-null  int64  
 10  Ease of Online booking             25976 non-null  int64  
 11  Gate location                      25976 non-null  int64  
 12  Food and drink                     25976 non-null  int64  
 13  Online boarding                    25976 non-null  int64  
 14  Seat comfort                       25976 non-null  int64  
 15  Inflight entertainment             25976 non-null  int64  
 16  On-board service                   25976 non-null  int64  
 17  Leg room service                   25976 non-null  int64  
 18  Baggage handling                   25976 non-null  int64  
 19  Checkin service                    25976 non-null  int64  
 20  Inflight service                   25976 non-null  int64  
 21  Cleanliness                        25976 non-null  int64  
 22  Departure Delay in Minutes         25976 non-null  int64  
 23  Arrival Delay in Minutes           25893 non-null  float64
 24  satisfaction                       25976 non-null  object 
dtypes: float64(1), int64(19), object(5)
memory usage: 5.0+ MB

В каждом из наборов данных 19 строк имели тип данных int, 1 — тип данных с плавающей запятой и 5 — категориальный тип данных (объект).

Есть два столбца, которые можно сразу отбросить. Столбцы id и unnamed можно убрать, так как они нам не нужны.

Что касается корректировок типов данных — мы наблюдаем несовпадение начальных типов данных в двух колонках задержки. Столбец прибытия имеет тип данных с плавающей запятой, а столбец отправления — целочисленный тип данных. Независимо от того, необходимо это или нет, я буду сопоставлять два типа данных как числа с плавающей запятой для согласованности при выполнении дальнейших анализов.

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

В столбце «Задержка прибытия» также присутствуют нулевые значения: 310 отсутствуют в обучающем наборе и 83 отсутствуют в тестовом наборе. Поскольку мы не можем сделать обоснованное предположение о том, указывают ли эти нулевые значения на безупречную своевременную работу (задержка 0 минут), мы будем приписывать им среднее значение столбца.

В оцененных столбцах набора данных есть строки, которые необходимо очистить. Эти столбцы представляют собой оцениваемые переменные, которые должны оцениваться по шкале от 1 до 5. Простой подсчет значений показывает наличие нулевых значений, которые по их количеству можно интерпретировать как значения по умолчанию для нулевых ответов. Мы будем удалять строки, в которых существуют эти столбцы.

Наконец — при очистке данных я решил упростить имена столбцов и нормализовать текст, а также сгенерировать агрегированные столбцы для задержек. Эти столбцы будут представлять собой двоичный столбец, указывающий, была ли задержка рейса (отправление или прибытие), и столбец общего количества времени, которое рейс провел с задержкой.

def clean_data(orig_df):
    '''
    This function applies 5 steps to the dataframe to clean the data.
    1. Dropping of unnecessary columns
    2. Uniformize datatypes in delay column
    3. Normalizing column names.
    4. Normalizing text values in columns.
    5. Imputing numeric null values with the mean value of the column.
    6. Dropping "zero" values from ranked categorical variables.
    7. Creating aggregated flight delay column
    
    Return: Cleaned DataFrame, ready for analysis - final encoding still to be applied.
    ''' 
    
    df = orig_df.copy()
    
    '''1. Dropping off unnecessary columns'''
    df.drop(['Unnamed: 0', 'id'], axis = 1, inplace = True)
    '''2. Uniformizing datatype in delay column'''
    df['Departure Delay in Minutes'] = df['Departure Delay in Minutes'].astype(float)
    '''3. Normalizing column names'''
    df.columns = df.columns.str.lower()
    '''Replacing spaces and other characters with underscores, this is more 
    for us to make it easier to work with them and so that we can call them using dot notation.'''
    special_chars = "/ -" 
    for special_char in special_chars:
        df.columns = [col.replace(special_char, '_') for col in df.columns]    
    '''4. Normalizing text values in columns'''
    cat_cols = ['gender', 'customer_type', 'class', 'type_of_travel', 'satisfaction']

    for column in cat_cols:
        df[column] = df[column].str.lower()        
    '''5. Imputing the nulls in the arrival delay column with the mean.
    Since we cannot safely equate these nulls to a zero value, the mean value of the column is the
    most sensible method of replacement.'''
    df['arrival_delay_in_minutes'].fillna(df['arrival_delay_in_minutes'].mean(), inplace = True)
    df.round({'arrival_delay_in_minutes' : 1})    
    '''6. Dropping rows from ranked value columns where "zero" exists as a value
    Since these columns are meant to be ranked on a scale from 1 to 5, having zero as a value 
    does not make sense nor does it help us in any way.'''
    rank_list = ["inflight_wifi_service", "departure_arrival_time_convenient", "ease_of_online_booking", "gate_location",
                "food_and_drink", "online_boarding", "seat_comfort", "inflight_entertainment", "on_board_service",
                "leg_room_service", "baggage_handling", "checkin_service", "inflight_service", "cleanliness"]    
    '''7. Creating aggregated and categorical flight delay columns'''
    df['total_delay_time'] = (df['departure_delay_in_minutes'] + df['arrival_delay_in_minutes'])
    df['was_flight_delayed'] = np.nan
    df['was_flight_delayed'] = np.where(df['total_delay_time'] > 0, 'yes', 'no')

    for col in rank_list:
        df.drop(df.loc[df[col]==0].index, inplace=True)
    
    cleaned_df = df
    
    return cleaned_df

Исследовательский анализ

Какова доля нашей целевой переменной? Довольных клиентов недовольным?

Первое, что я хотел изучить при изучении данных, — это распределение удовлетворенных клиентов среди неудовлетворенных клиентов. Любая значительная диспропорция данных послужит основой для будущих анализов.

Хотя данные не идеально сбалансированы, это нормально. Пропорции — примерно 55% нейтральных или неудовлетворенных и 45% удовлетворенных — не показывают дисбаланса, который может привести к вводящим в заблуждение прогнозам позже, во время обучения модели и прогнозирования. Поэтому я не вижу немедленной необходимости в повторной выборке данных.

Как конкретные группы реагируют с точки зрения удовлетворенности? (Пол и статус клиента)

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

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

Влияет ли класс или цель поездки на удовлетворенность пассажиров?

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

А как насчет пассажиров, которые путешествуют по делам, а не для личного отдыха?

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

Есть ли разница в удовлетворенности среди разных возрастных групп?

Интересно отметить разницу между возрастом и удовлетворенностью. Существует заметная пропасть между возрастной группой 37–61 и остальными, где эта группа гораздо более удовлетворена своим опытом путешествий, чем путешественники в других группах. Еще одно интересное наблюдение из приведенного выше графика кошек заключается в том, что уровень удовлетворенности путешественников неуклонно растет по мере их взросления, до 61 года, когда уровни неудовлетворенности отражают уровни на другом конце распределения. Должна быть получена дополнительная информация путем сравнения этого столбца с различными оцениваемыми переменными.

Влияет ли продолжительность полета на удовлетворенность?

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

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

Многомерный анализ

Как дальность полета влияет на рейтинговые аспекты обслуживания в опросе?

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

Существует более высокий процент довольных клиентов, которые высоко оценили Wi-Fi в полете и простоту онлайн-бронирования.

Влияет ли возраст на оценку этих аспектов обслуживания?

Для многих из этих категорий обслуживания клиентов индивидуальное распределение удовлетворенности и неудовлетворенности по каждому рейтингу обслуживания клиентов напрямую отражает двумерное распределение возраста и удовлетворенности. В большинстве этих распределений наблюдается заметный пик в возрастной группе 37–60 лет.

Некоторые параметры обслуживания клиентов (обслуживание клиентов в полете, обработка багажа, пространство для ног, качество обслуживания на борту и развлечения на борту) оцениваются пассажирами как удовлетворенные, несмотря на низкую оценку столбца обслуживания. В категории места для ног большое количество молодых путешественников недовольны, несмотря на высокие оценки в колонке.

Есть интересное распределение в категории онлайн-интернатов, где возрастная группа 40–60 лет оценивается как удовлетворенная, несмотря на то, что колонке услуги присвоена самая низкая оценка, и как неудовлетворенная, несмотря на то, что колонка услуги получила максимально возможную оценку.

Как класс и цель путешествия влияют на то, как пассажиры оценивают свои услуги?

Эти распределения говорят мне, что класс салона и цель поездки будут важными факторами, определяющими удовлетворенность пассажиров. Существуют явные пики удовлетворенности и неудовлетворенности услугами Wi-Fi в полете, онлайн-посадкой, комфортом сидений, развлечениями в полете, обслуживанием клиентов на борту, пространством для ног и обслуживанием клиентов в полете.

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

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

Интересный сюжет - колонка услуги wi-fi в полете. Высокие рейтинги оказывают большое влияние на удовлетворенность водителей пассажиров, летающих эконом-классом и эконом-классом. Кажется, что это не так сильно влияет на удовлетворенность путешественников бизнес-класса, но посредственные или низкие оценки, по-видимому, сильно влияют на неудовлетворенность путешественников в этом салоне. Точно так же то, как респонденты оценили наличие Wi-Fi на борту, было огромным фактором, определяющим общую удовлетворенность деловых путешественников и неудовлетворенность пассажиров, путешествующих для личного отдыха.

Подготовка данных и выбор признаков

Подготовка данных

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

def encode_data(orig_df):
    '''
    Encodes remaining categorical variables of data frame to be ready for model ingestion
    
    Inputs:
       Dataframe
       
    Manipulations:
        Encoding of categorical variables.    
    
    Return: 
        Encoded Column Values
    '''
   
    df = orig_df.copy()
    
    #Ordinal encode of scored rating columns.
    encoder = OrdinalEncoder()
    
    for j in score_cols:
        df[j] = encoder.fit_transform(df[[j]]) 
    
    # Replacement of binary categories.
    df.was_flight_delayed.replace({'no': 0, 'yes' : 1}, inplace = True)
    df['satisfaction'].replace({'neutral or dissatisfied': 0, 'satisfied': 1},inplace = True)
    df.customer_type.replace({'disloyal customer': 0, 'loyal customer': 1}, inplace = True)
    df.type_of_travel.replace({'personal travel': 0, 'business travel': 1}, inplace = True)
    df.gender.replace({'male': 0, 'female' : 1}, inplace = True)
    
    encoded_df = pd.get_dummies(df, columns = ['class'])
    
    return encoded_df

Выбор функции

После кодирования модели я хотел сразу провести отбор признаков — не только для того, чтобы моя модель работала эффективно, но и для того, чтобы сами модели имели меньшую размерность для уменьшения шума и возможного переобучения. Для выбора функций я использовал встроенную функцию выбора функций Scikit-Learn, используя K-Best в качестве селектора и значения хи-квадрата в качестве критериев. Хи-квадрат показался мне наиболее подходящим критерием, учитывая, что в наборе данных есть несколько категориальных переменных.

# Pre-processing and scaling dataset for feature selection
from sklearn import preprocessing

r_scaler = preprocessing.MinMaxScaler()
r_scaler.fit(air_train_encoded)
 
air_train_scaled = pd.DataFrame(r_scaler.transform(air_train_encoded), columns = air_train_encoded.columns)
air_train_scaled.head()

# Feature selection, applying Select K Best and Chi2 to output the 15 most important features
from sklearn.feature_selection import SelectKBest, chi2

X = air_train_scaled.loc[:,air_train_scaled.columns!='satisfaction']
y = air_train_scaled[['satisfaction']]

selector = SelectKBest(chi2, k = 10)
selector.fit(X, y)
X_new = selector.transform(X)

features = (X.columns[selector.get_support(indices=True)])
features
Output:

Index(['type_of_travel', 'inflight_wifi_service', 'online_boarding',
       'seat_comfort', 'inflight_entertainment', 'on_board_service',
       'leg_room_service', 'cleanliness', 'class_business', 'class_eco'],
      dtype='object')

В результате я получил такие функции, как тип путешествия, услуга Wi-Fi в полете, процесс онлайн-посадки, комфорт сиденья, развлечения на борту, бортовое обслуживание клиентов, пространство для ног, чистота и класс обслуживания (бизнес или эконом).

Моделирование

Сводка каналов-кандидатов

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

Конвейерами моделей, которые я обучал, были модель логистической регрессии, классификатор Adaptive Boost, классификатор случайный лес, категориальный наивный байесовский классификатор. модель классификации и классификатор Extreme Gradient Boosting (XGBoost). Я сравнил все конвейеры по их точности обучения и точности тестирования, точности, отзыву и значению ROC.

# Model activation and result plot function
def get_model_metrics(model, X_train, X_test, y_train, y_test):
   
    '''
    Model activation function, takes in model as a parameter and returns metrics as specified.
    
    Inputs: 
        model,  X_train, y_train, X_test, y_test
    Output: 
        Model output metrics, confusion matrix, ROC AUC curve
    '''
    
    # Mark of current time when model began running
    t0 = time.time()
    
    # Fit the model on the training data and run predictions on test data
    model.fit(X_train,  y_train)
    y_pred = model.predict(X_test)
    y_pred_proba = model.predict_proba(X_test)[:,1]
    # Obtain training accuracy as a comparative metric using Sklearn's metrics package
    train_score = model.score(X_train, y_train)
    # Obtain testing accuracy as a comparative metric using Sklearn's metrics package
    accuracy = accuracy_score(y_test, y_pred)
    # Obtain precision from predictions using Sklearn's metrics package
    precision = precision_score(y_test, y_pred)
    # Obtain recall from predictions using Sklearn's metrics package
    recall = recall_score(y_test, y_pred)
    # Obtain ROC score from predictions using Sklearn's metrics package
    roc = roc_auc_score(y_test, y_pred_proba)
    # Obtain the time taken used to run the model, by subtracting the start time from the current time
    time_taken = time.time() - t0
    # Obtain the resources consumed in running the model
    memory_used = int(getrusage(RUSAGE_SELF).ru_maxrss / 1024)

    # Outputting the metrics of the model performance
    print("Accuracy on Training = {}".format(train_score))
    print("Accuracy on Test = {} • Precision = {}".format(accuracy, precision))
    print("Recall = {} • ROC Area under Curve = {}".format(recall, roc))
    print("Time taken = {} seconds • Memory consumed = {} Bytes".format(time_taken, memory_used))

    # Plotting the confusion matrix of the model's predictive capabilities
    plot_confusion_matrix(model, X_test, y_test, cmap = plt.cm.Blues, normalize = 'all')
    # Plotting the ROC AUC curve of the model 
    plot_roc_curve(model, X_test, y_test)    
    plt.show()
    
    return model, train_score, accuracy, precision, recall, roc, time_taken, memory_used

Перед выполнением конвейера модели я также провел рандомизированный поиск, чтобы найти идеальные параметры оптимизации для модели.

Каждая из моделей с примененной оптимизацией параметров показала точность не менее 88% на обучающих данных и точность 87% на тестовых данных.

Модель, которую я выбираю для продвижения (в случае участия это будет модель, которую мы передаем для дальнейшей оптимизации, объяснимости и доставки клиенту), — это классификатор экстремального повышения градиента. Эта модель в конечном итоге показала лучшие результаты, показав высокую производительность как при обучении, так и при тестировании. Модель выдает точность (тестирование) 95, значение ROC 98, точность 95 и полноту 92.

Хотя эта модель не работала наиболее эффективно, выходная производительность, которую она обеспечивает, намного перевешивает ценность эффективного выполнения. Чаще всего — то, насколько эффективно работает модель, не является ключевой бизнес-целью. Модель, которая работает наиболее эффективно и решает описанную бизнес-проблему, является основным результатом.

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

Важность встроенной функции XGBoost

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

С точки зрения веса функции (количество раз, когда функция использовалась для разделения данных) — наша модель больше всего полагалась на функцию комфорта сиденья, чтобы разделить данные по всем возможным деревьям в нашей модели. ; затем онлайн-посадка, развлечения на борту, качество обслуживания на борту, пространство для ног, Wi-Fi в полете и чистота.

Объясняемость модели и функции в SHAP

Чтобы проанализировать влияние функций модели на SHAP, я начал с травления модели с помощью библиотеки pickle Python. Затем я создал объяснитель в Shap, используя конвейер модели и выбранные мной функции, и применил его к моему набору данных X_train.

# Saving test model. 
pickle.dump(model_xgb, open('./Models/model_xgb.pkl', 'wb'))

explainer = shap.Explainer(model_xgb, feature_names = features)
shap_values = explainer(X_train)

Принимая во внимание среднее значение SHAP в качестве нашей метрики важности функции, мы можем заметить, что услуга Wi-Fi в полете является наиболее важной характеристикой наших данных, за которой следуют тип путешествия и онлайн-посадка.

Глядя на сводный график SHAP (или пчелиный поток), который обеспечивает более информативную иллюстрацию значения признака каждого отдельного наблюдения в наших данных и его влияния на выходные данные модели, мы можем получить более полную картину общего влияния признака на нашу модель. . Функции упорядочены по их влиянию на предсказание, но это также показывает нам, как более высокие и более низкие значения каждого отдельного наблюдения функции повлияют на результат.

Почти для каждой функции высокие значения характеристик оказывают положительное влияние на предсказание, а низкие значения характеристик отрицательно влияют на предсказание. Услуга Wi-Fi в полете, по-видимому, является наиболее важной особенностью нашего набора данных, за которой следуют тип путешествия и процесс онлайн-посадки.

Объяснение влияния функции Wi-Fi на борту

Я хотел поближе познакомиться с функцией Wi-Fi в полете. Во-первых, потому что это функция, которая оказала наибольшее влияние на определение выходных данных модели; но также, в частности, потому, что это была особенность, которая привлекла мое внимание во время исследовательского анализа, поскольку определенные ценности оказывали большое влияние на удовлетворенность и неудовлетворенность среди различных классов путешествий и типов путешествий.

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

Также можно заметить, что для деловых путешественников, независимо от того, как они оценили услугу Wi-Fi, есть часть, которая удовлетворена (положительное значение SHAP над отрицательным). Однако группа деловых путешественников, которые показали отрицательные значения SHAP или были недовольны, поставили низкие оценки своему опыту использования Wi-Fi на борту.

Объяснение влияния функции онлайн-посадки

Я также хотел кратко взглянуть на влияние онлайн-интернатов на SHAP. Это еще одна функция, которая показала высокий потенциал воздействия, независимо от цели поездки или класса.

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

Выводы

На этом этапе я мог бы с уверенностью представить клиенту, что у нас есть основанные на данных рекомендации о том, где они могут улучшить обслуживание клиентов, о чем свидетельствует интерпретируемый конвейер машинного обучения XGBoost, который демонстрирует точность 95% и точность 94,6%.

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

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

Независимо от салона или цели путешествия, высокие оценки возможностей Wi-Fi — это огромная возможность для повышения удовлетворенности клиентов и расширения конкурентных преимуществ. Повышение доступности и бесплатный доступ к Wi-Fi во всех каютах привлечет больше клиентов, у которых есть доступ к потоковому видео и музыке. Улучшение возможностей — это то, что привлечет больше деловых путешественников, зная, что они могут повысить производительность в воздухе.

Эффективность доставки людей на борт самолета также требует улучшения. Это не относится к одному классу обслуживания или цели путешествия — это универсально. Сообщалось, что пассажиры, которые поставили более высокие оценки при посадке в самолет, были удовлетворены своим путешествием, в то время как пассажиры, которые поставили посредственные или низкие оценки, не были удовлетворены.

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

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

Ссылки

Набор данных об удовлетворенности пассажиров авиакомпаний (Kaggle): https://www.kaggle.com/datasets/teejmahal20/airline-passenger-satisfaction

Пассажиры американских авиакомпаний недовольны. Вот почему (CNN): https://www.cnn.com/travel/article/jd-power-2022-north-american-airline-satisfaction-survey-results/index.html

Удовлетворенность путешественников снижается по мере того, как самолеты заполняются, а стоимость авиабилетов растет, показал опрос (CNBC): https://www.cnbc.com/2022/05/11/air-travel-satisfaction.html.

Репозиторий GitHub: https://github.com/chrisbacani/Udacity-Data-Scientist-Capstone