Пошаговый рецепт Python.
Объяснение перекрестной проверки
Перекрестная проверка - это метод, позволяющий оценить производительность модели с меньшей дисперсией, чем при разбиении одного набора «поезд-тест». Он работает, разбивая набор данных на k частей (т.е. k = 5, k = 10). Каждый раз, когда мы разделяем данные, мы называем действие «складкой». Модель обучается на k-1 складках с одной отведенной назад и тестируется на удерживаемой задней части. Каждый сгиб должен быть как можно ближе к одному и тому же размеру записи. После выполнения перекрестной проверки вы получите k различных оценок производительности, которые мы суммируем, используя среднее значение и стандартное отклонение.
Предположим, у нас есть набор данных (всего n = 5000 записей), разделенный на k = 5 частей (каждая часть n = 1000). Мы помечаем части A, B, C, D и E. Модель будет обучена 5 раз. Каждый раз 4 (K-1) складки будут включены в тренировочную группу, а 5-я складка будет в тестовой группе. Группа тестирования меняется каждый раз при обучении модели. Пример модели перекрестной проверки k = 5:
- Тренировка 1: тренировочные складки = A, B, C, D, а E - тестовая складка.
- Тренировка 2: тренировочные складки = B, C, D, E, а A - тестовая складка.
- Тренировка 3: тренировочные складки = C, D, E, A, в то время как B - тестовая складка.
- Тренировка 4: тренировочные складки = D, E, A, B, в то время как C - тестовая складка.
- Тренировка 5: тренировочные складки = E, A, B, C, а D - тестовая складка.
Результатом является более надежная оценка производительности модели на новых данных. Это более точно, потому что модель обучается и оценивается несколько раз на разных данных. Выбор k должен позволять размеру каждого тестового раздела быть достаточно большим, чтобы быть разумным образцом проблемы, в то же время позволяя достаточно повторений оценки «поезд-тест», чтобы обеспечить справедливую оценку производительности модели на невидимых данных. Для многих наборов данных с тысячами или десятками тысяч записей обычно используются значения k 3, 5 и 10.
Пошаговое руководство по Python
# Load the required libraries import numpy as np import pandas as pd from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression from sklearn.metrics import confusion_matrix from sklearn.metrics import classification_report
Исходный набор данных находится на www.ibm.com.
# Load the data file. Add the correct directory path to reach the # file on your computer or network. df=pd.read_csv(r'WA_Fn-UseC_-Telco-Customer-Churn.csv')
Файл загружается и помещается в фрейм данных. Когда это возможно, я люблю просматривать все свои колонки. Я установил отображение всех столбцов и вывел заголовок из 5 строк, чтобы увидеть, как выглядят заголовки столбцов и первые несколько строк данных.
# Organize dataframe. Display the first five rows and column titles. pd.set_option('display.max_columns', None) # Display all columns df.head()
Очистка данных
Затем я хочу убедиться, что числовые данные имеют пригодный для использования формат (целое число или число с плавающей запятой).
df.columns.values
df.dtypes
К счастью, мы не пропустили этот шаг. Мы обнаруживаем, что столбец TotalCharges отображается как объект. Чтобы мы могли с ним работать, оно должно быть целым числом. Мы можем исправить это, преобразовав его в число. Кроме того, в это время я буду искать недостающие значения.
# Converting Total Charges to a numerical data type. Currently in dataframe as an object. df.TotalCharges = pd.to_numeric(df.TotalCharges, errors='coerce') df.isnull().sum() # Count the number of missing values
Мы переводим столбец TotalCharges в числовое значение, а затем определяем, что единственными недостающими данными являются 11 элементов в столбце TotalCharges. 11 минимален, поэтому я решил удалить эти наблюдения из набора данных. Поскольку у идентификатора клиента нет другой цели, кроме определения того, кому принадлежат данные, мы исключаем этот столбец из набора данных.
Затем в этом блоке кода нам нужно преобразовать наши переменные ответа и предиктора в пригодные для использования форматы. Churn - это наша переменная ответа, и мы преобразуем ее из объекта в целое число. Мы присваиваем каждому да = 1 и нет = 0. Наконец, мы должны преобразовать категориальные переменные-предикторы в (числовые) фиктивные переменные. Затем еще раз посмотрим на заголовок.
# Removing missing values df.dropna(inplace = True) # Remove customer IDs from the data set df2 = df.iloc[:,1:] # Converting the predictor variable into a binary numeric variable df2['Churn'].replace(to_replace='Yes', value=1, inplace=True) df2['Churn'].replace(to_replace='No', value=0, inplace=True) # Convert all the categorical variables into dummy variables df_dummies = pd.get_dummies(df2) df_dummies.head()
Этот заголовок сильно отличается от предыдущего. Все объекты преобразованы в 0 и 1. Теперь данные готовы для логистической регрессии.
Логистическая регрессия
Первым шагом в логистической регрессии является присвоение нашим переменным ответа (Y) и предиктора (x). В этой модели отток - наша единственная переменная ответа, а все остальные переменные будут переменными-предикторами.
# assign X to all the independent (predictor) variables, assign Y to the dependent (response) variable X = df_dummies[['SeniorCitizen','tenure','MonthlyCharges','TotalCharges','gender_Female','gender_Male','Partner_No','Partner_Yes','Dependents_No','Dependents_Yes','PhoneService_No','PhoneService_Yes','MultipleLines_No','MultipleLines_No phone service','MultipleLines_Yes','InternetService_DSL','InternetService_Fiber optic','InternetService_No','OnlineSecurity_No','OnlineSecurity_No internet service','OnlineSecurity_Yes','OnlineBackup_No','OnlineBackup_No internet service','OnlineBackup_Yes','DeviceProtection_No','DeviceProtection_No internet service','DeviceProtection_Yes','TechSupport_No','TechSupport_No internet service','TechSupport_Yes','StreamingTV_No','StreamingTV_No internet service','StreamingTV_Yes','StreamingMovies_No','StreamingMovies_No internet service','StreamingMovies_Yes','Contract_Month-to-month','Contract_One year','Contract_Two year','PaperlessBilling_No','PaperlessBilling_Yes','PaymentMethod_Bank transfer (automatic)','PaymentMethod_Credit card (automatic)','PaymentMethod_Electronic check','PaymentMethod_Mailed check' ]] Y = df_dummies['Churn']
После этого выполняется k-кратная логистическая регрессия с перекрестной проверкой.
# 5 folds selected kfold = KFold(n_splits=5, random_state=0, shuffle=True) model = LogisticRegression(solver='liblinear') results = cross_val_score(model, X, Y, cv=kfold) # Output the accuracy. Calculate the mean and std across all folds. print("Accuracy: %.3f%% (%.3f%%)" % (results.mean()*100.0, results.std()*100.0))
Это относится к точности классификации, то есть количеству правильных прогнозов в процентах от всех сделанных прогнозов. Наша модель дала точность 80,333% (среднее значение) со стандартным отклонением 1,080%. При просмотре базового набора данных я обнаружил, что примерно 26% клиентов компании уходили каждый период, в то время как 74% оставались клиентами (это было предоставлено в виде примечания к файлу данных).
Помимо указания размера разделения (k = 5), мы также указываем случайное начальное число (random_state = 0). Поскольку разделение данных является случайным, мы хотим обеспечить воспроизводимость результатов. Указав случайное начальное число, мы гарантируем, что каждый раз при запуске кода мы получаем одни и те же случайные числа и, в свою очередь, одно и то же разделение данных. Это важно, если мы хотим сравнить этот результат с оценкой точности другой модели. Чтобы гарантировать, что сравнение проводилось по принципу «яблоки против яблок», мы должны убедиться, что они обучены и протестированы на абсолютно одинаковых данных.
Интерпретация результатов модели
Наилучшая точность достигается при одинаковом количестве наблюдений в каждом классе. Клиентов осталось примерно в 3 раза больше, чем тех, кто ушел, поэтому точность может быть не лучшим способом увидеть наш ответ. Поскольку нам нравится статистика, давайте копнем немного глубже, чтобы получить еще несколько значимых чисел с другой моделью. Пришло время создать матрицу путаницы, используя размер обучения = 0,67 с размером теста = 0,33 в том же наборе данных.
# Construct a confusion matrix test_size = 0.33 seed = 0 X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=test_size, random_state=seed) model = LogisticRegression(solver='liblinear') model.fit(X_train, Y_train) predicted = model.predict(X_test) matrix = confusion_matrix(Y_test, predicted) print(matrix)
Матрица путаницы (снимок экрана выше) может быть одним из наименее информативных визуальных элементов во всем языке Python. К счастью, есть способ сделать его более значимым.
#transform confusion matrix into array #the matrix is stored in a vaiable called confmtrx confmtrx = np.array(matrix) #Create DataFrame from confmtrx array #rows for test: Churn, No_Churn designation as index #columns for preds: Pred_Churn, Pred_NoChurn as column pd.DataFrame(confmtrx, index=['No_Churn','Churn'], columns=['Predicted_No_Churn', 'Predicted_Churn', ])
Так намного лучше. Эта диаграмма позволяет нам более четко понимать квадранты. Мы видим, что модель предсказывала «отсутствие оттока» 1799 раз (1522 + 277). Он был правильным 1522 раза и неправильным 277 раз (85% правильных), когда предсказывал «отсутствие оттока». Модель предсказала «отток» 522 раза (178 + 344). Когда прогнозировался «отток», это было правильным 344 раза и неверным 178 раз (66% правильных). Теперь, помимо 80%, у нас есть 85% и 66%. Что правильно? К счастью, мы можем создать отчет о классификации, который поможет нам во всем разобраться.
# Create a classification report. Use the same test size and same # seed number before. test_size = 0.33 seed = 0 X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=test_size, random_state=seed) model = LogisticRegression(solver='liblinear') model.fit(X_train, Y_train) predicted = model.predict(X_test) report = classification_report(Y_test, predicted) print(report)
На скриншоте выше показан отчет о классификации. Есть четыре статистических столбца: точность, отзыв, оценка f1 и поддержка. Точность относится к тому, какой процент наших прогнозов оказался верным. Отсюда и возникли 85% и 66%. Среднее макроэкономическое значение рассчитывается как (0,85 + 0,66) / 2. Модель использует большую точность, чем два десятичных знака, и округляет до двух десятичных знаков. В итоге получаем 0,80 = (1700/2321) *. 85 + (621/2321) *. 66.
Напоминание - это процент положительных (или отрицательных) случаев, которые модель смогла обнаружить. В этом сценарии (1522/1700) = 0,90 и (344/621) = 0,55. Макро-среднее и средневзвешенное значение вычисляются с использованием тех же методов, которые показаны для точности.
F1-оценка - это взвешенное гармоническое среднее значение точности и запоминания, где наилучшая возможная оценка - 1,0, а наихудшая - 0,0. Считается, что для сравнения моделей лучше использовать средневзвешенную оценку F1, а не глобальную оценку точности. В этой модели оба значения равны 0,80, поэтому нет никакой разницы между глобальной точностью и взвешенной F1-оценкой.
Столбец поддержки предоставляет пользователю количество наблюдений в каждой строке и столбце.
Резюме
Модель, использующая k-кратную перекрестную проверку (k = 5), показала точность 80,333% со стандартным отклонением 1,080%. Модель отчета о матрице путаницы / классификации сообщила, что средневзвешенный балл F1 = 80% и глобальный балл точности = 80%. Модель k-кратной перекрестной проверки была почти идентична результатам модели отчета о матрице неточностей / классификации.
Пожалуйста, попробуйте эту k-кратную перекрестную проверку и дайте мне знать, если у вас возникнут вопросы или возникнут проблемы.
Больше контента на plainenglish.io