Введение

В этом проекте мы сосредоточимся на данных из Индии. И наша цель — создать прогнозную модель, такую ​​как логистическая регрессия и т. д., чтобы, когда мы даем характеристики кандидата, модель могла предсказать, примут ли они на работу.

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

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

Эта статья была опубликована в рамках Блогатона по науке о данных.

Оглавление

  1. Этапы решения проблемы
  2. Подготовить данные
  3. Построить модель логистической регрессии
  4. Результаты модели логистической регрессии
  5. "Заключение"

Шаги, необходимые для решения проблемы

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

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

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

Вторая цель — создать модель логистической регрессии для прогнозирования пополнения. И наша третья цель — объяснить предсказания нашей модели с помощью отношения шансов.

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

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

Наконец, прежде чем погрузиться в работу, давайте познакомимся с библиотеками, которые мы будем использовать в проекте. Сначала мы импортируем наши данные из блокнота Google Colabe в библиотеку io. Затем, поскольку мы будем использовать модель логистической регрессии, мы импортируем ее из scikit-learn. После этого, также из scikit-learn, мы импортируем наши метрики производительности, показатель точности и сплит-тест-тренинг.

Мы будем использовать Matplotlib и seaborn для нашей визуализации, а NumPy будет только для небольшой математики.
Нам нужны панды для манипулирования нашими данными, labelencoder для кодирования наших категориальных переменных и стандартный масштабатор для нормализовать данные. Это будут библиотеки, которые нам нужны.

Приступим к подготовке данных.

#import libraries
import io 
import warnings 
import matplotlib.pyplot as plt 
import numpy as np 
import pandas as pd 
import seaborn as sns 
from sklearn.preprocessing import LabelEncoder 
from sklearn.linear_model import LogisticRegression 
from sklearn.metrics import accuracy_score 
from sklearn.model_selection import train_test_split 
from sklearn.preprocessing import StandardScaler 

warnings.simplefilter(action="ignore", category=FutureWarning)

Подготовить данные

Импортировать

Чтобы начать подготовку данных, давайте приступим к нашей важной работе. Сначала мы загружаем наш файл данных, а затем нам нужно поместить их в DataFrame `df`.

from google.colab import files uploaded = files.upload()

# Read CSV file 
df = pd.read_csv(io.BytesIO(uploaded["Placement_Data_Full_Class.csv"])) 
print(df.shape) df.head()

Мы видим наш красивый DataFrame, и у нас есть 215 записей и 15 столбцов, которые включают атрибут «status», нашу цель. Это описание всех функций.

Исследовать

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

# Inspect DataFrame
 df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 215 entries, 0 to 214
Data columns (total 15 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   sl_no           215 non-null    int64  
 1   gender          215 non-null    object 
 2   ssc_p           215 non-null    float64
 3   ssc_b           215 non-null    object 
 4   hsc_p           215 non-null    float64
 5   hsc_b           215 non-null    object 
 6   hsc_s           215 non-null    object 
 7   degree_p        215 non-null    float64
 8   degree_t        215 non-null    object 
 9   workex          215 non-null    object 
 10  etest_p         215 non-null    float64
 11  specialisation  215 non-null    object 
 12  mba_p           215 non-null    float64
 13  status          215 non-null    object 
 14  salary          148 non-null    float64
dtypes: float64(6), int64(1), object(8)
memory usage: 25.3+ KB

Теперь, когда мы смотрим на информацию `df`, есть пара вещей, которые мы ищем, у нас есть 215 строк в нашем фрейме данных, и вопрос, который мы хотим задать себе, заключается в том, есть ли какие-то недостающие данные? И если мы посмотрим сюда, кажется, у нас нет недостающих данных, кроме столбца зарплаты, как и ожидалось, из-за кандидатов, которые не были приняты на работу.

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

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

df.drop(columns="salary", inplace=True)

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

Мы знаем, что наша цель имеет два класса. Мы разместили кандидатов и не разместили кандидатов. Вопрос в том, какова относительная пропорция этих двух классов? Они примерно одного баланса? Или одно намного больше другого? Это то, на что вам нужно обратить внимание, когда вы решаете задачи классификации. Так что это важный шаг в нашей EDA.

# Plot class balance 
df["status"].value_counts(normalize=True).plot(
     kind="bar", xlabel="Class", ylabel="Relative Frequency",
     title="Class Balance");

Наш положительный класс «размещено» составляет более 65% наших наблюдений, а наш отрицательный класс «не размещено» составляет около 30%. Теперь, если бы они были супер несбалансированными, например, если бы их было около 80 или даже больше, я бы сказал, что это несбалансированные классы. И нам нужно проделать некоторую работу, чтобы убедиться, что наша модель будет работать правильно. Но это нормальный баланс.

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

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

fig,ax=plt.subplots(5,2,figsize=(15,35)) 
for index,i in enumerate(df.select_dtypes("number").drop(columns="sl_no")):
    plt.suptitle("Visualizing Distribution of Numerical Columns Indivualy and by Class",size=20) 
    sns.histplot(data=df, x=i, kde=True, ax=ax[index,0]) 
    sns.boxplot(data=df, x='status', y=i, ax=ax[index,1]
);

В первом столбце нашего графика мы видим, что все распределения соответствуют нормальному распределению, а большая часть учебных достижений кандидата находится в пределах 60–80%.

Во втором столбце у нас есть двойная диаграмма с классом «Размещено» справа, а затем классом «Не размещено» слева. Для функций «etest_p» и «mba_p» в этих двух дистрибутивах нет большой разницы с точки зрения построения модели. Существует значительное перекрытие в распределении по классам, поэтому эти функции не будут хорошим предиктором нашей цели. Что касается остальных признаков, то они достаточно различны, чтобы считать их потенциальными хорошими предикторами нашей цели. Перейдем к категориальным характеристикам. И чтобы исследовать их, мы будем использовать график подсчета.

fig,ax=plt.subplots(7,2,figsize=(15,35)) 
for index,i in enumerate(df.select_dtypes("object").drop(columns="status")):
    plt.suptitle("Visualizing Count of Categorical Columns",size=20) 
    sns.countplot(data=df,x=i,ax=ax[index,0]) 
    sns.countplot(data=df,x=i,ax=ax[index,1],hue="status"
);

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

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

corr = df.select_dtypes("number").corr() 
# Plot heatmap of `correlation` 
plt.title('Correlation Matrix') 
sns.heatmap(corr, vmax=1, square=True, annot=True, cmap='GnBu');

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

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

# Check for high- and low-cardinality categorical features 
df.select_dtypes("object").nunique() 

gender            2
ssc_b             2
hsc_b             2
hsc_s             3
degree_t          3
workex            2
specialisation    2
status            2
dtype: int64

Я не вижу столбцов, в которых количество уникальных значений равно единице или чему-то сверхвысокому. Но я думаю, что здесь не хватает одного столбца категориального типа. И причина в том, что он закодирован не как объект, а как целое число. Столбец «sl_no» не является целым числом в известном нам смысле. Эти кандидаты ранжируются в определенном порядке. Просто уникальный тег имени и имя похоже на категорию, верно? Итак, это категориальная переменная. И у него нет никакой информации, поэтому нам нужно его удалить.

df.drop(columns="sl_no", inplace=True)

Особенности кодирования

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

lb = LabelEncoder () 
cat_data = ['gender', 'ssc_b', 'hsc_b', 'hsc_s', 'degree_t', 'workex', 'specialisation', 'status'] 
for i in cat_data: 
    df[i] = lb.fit_transform(df[i]) 

df.head()

Расколоть

Мы импортировали и очистили наши данные. Мы провели небольшой исследовательский анализ данных, и теперь нам нужно разделить наши данные. У нас есть два типа разделения: вертикальное разделение или функции-цель и горизонтальное разделение или обучающие тестовые наборы. Начнем с вертикального. Мы создадим нашу матрицу признаков «X» и целевой вектор «y». Наша цель — «статус». Нашими функциями должны быть все столбцы, оставшиеся в «df».

#vertical split 
target = "status" 
X = df.drop(columns = target) 
y = df[target]

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

scaler = StandardScaler() 
X = scaler.fit_transform(X)

Теперь давайте сделаем горизонтальный сплит или тренировочные тесты. Нам нужно разделить наши данные (X и y) на обучающие и тестовые наборы, используя рандомизированное разделение обучения и тестирования. наш тестовый набор должен составлять 20% наших общих данных. И не забываем установить random_state для воспроизводимости.

X_train, X_test, y_train, y_test = train_test_split( 
    X, y, test_size = 0.2, random_state = 42) 

print("X_train shape:", X_train.shape) 
print("y_train shape:", y_train.shape) 
print("X_test shape:", X_test.shape) 
print("y_test shape:", y_test.shape) 

X_train shape: (172, 12) 
y_train shape: (172,) 
X_test shape: (43, 12) 
y_test shape: (43,)

Создайте модель логистической регрессии

Базовый уровень

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

Теперь, какова оценка точности? Оценка точности в машинном обучении — это показатель оценки, который измеряет количество правильных прогнозов, сделанных моделью, по отношению к общему количеству сделанных прогнозов. Мы вычисляем его, разделив количество правильных прогнозов на общее количество прогнозов. Это означает, что показатель точности колеблется между 0 и 1. Ноль — это нехорошо. Вот где вы не хотите быть, и один идеален. Итак, давайте помнить об этом и помнить, что базовая линия — это модель, которая снова и снова дает один прогноз, независимо от того, что представляет собой наблюдение, только одно предположение для нас.

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

Мы можем использовать метод «value_counts» с аргументом «normalize = True» для вычисления базовой точности:

acc_baseline = y_train.value_counts(normalize=True).max() 

print("Baseline Accuracy:", round(acc_baseline, 2)) 

Baseline Accuracy: 0.68

Мы видим, что наша базовая точность составляет 68% или 0,68 в пропорции. Таким образом, чтобы добавить полезности, мы хотим подняться выше этого числа и приблизиться к единице. Это наша цель, а теперь давайте начнем строить нашу модель.

Итерация

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

Допустим, по оси X у меня есть p_степени кандидатов в нашем наборе данных. И по мере того, как я двигаюсь справа налево, градусы становятся все выше и выше, а затем по оси Y у меня есть возможные классы для размещения: ноль и один.

Итак, если бы нам нужно было построить наши точки данных, как бы это выглядело? Наш анализ показывает, что кандидат с высоким показателем «p_степень» будет принят на работу с большей вероятностью. Таким образом, это, вероятно, будет выглядеть примерно так, где кандидат с маленькой `p_степенью` будет равен нулю. И кандидат с высоким `p_степенью` будет на единицу.

Теперь предположим, что мы хотели сделать с этим линейную регрессию. Допустим, мы хотели построить линию.
Теперь, если бы мы это сделали, то линия была бы построена таким образом, чтобы попытаться пройти как можно ближе ко всем точкам. И поэтому мы, вероятно, закончим с линией, которая выглядит примерно так. Будет ли это хорошей моделью?

Не совсем. Что произойдет, так это то, что независимо от p_степени кандидата мы всегда будем получать какое-то значение. И это нам не поможет, потому что цифры в данном контексте ничего не значат. Эта проблема классификации должна быть равна нулю или единице. Таким образом, это не сработает.

С другой стороны, поскольку это линия, что, если у нас есть кандидат с очень низким p_степенью? Внезапно наша оценка оказалась отрицательной. И опять же, это не имеет никакого смысла. Нет отрицательного числа, оно должно быть либо нулем, либо единицей. И точно так же, если у нас есть кандидат с очень высоким p_степенью, у меня может быть положительный результат, что-то выше единицы. И опять же, это не имеет никакого смысла. Нам нужен либо ноль, либо единица.

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

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

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

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

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

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

Что я имею в виду? Это означает, что когда я делаю прогноз, я получаю некоторое значение с плавающей запятой от 0 до 1. И что я буду делать, так это рассматривать его как вероятность того, что мой прогноз принадлежит к положительному классу.

Таким образом, я получаю значение до 0,9999. Я скажу, что вероятность того, что этот кандидат принадлежит к нашему положительному, размещенному классу, составляет 99%. Так что я почти уверен, что он принадлежит к положительному классу. И наоборот, если он упадет до отметки 0,001 или около того, я скажу, что это число низкое. Вероятность того, что это конкретное наблюдение относится к положительному, размещенному классу, практически равна нулю. Итак, я собираюсь сказать, что он принадлежит к нулевому классу.

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

Итак, теперь у меня есть функция, которая дает мне прогноз между нулем и единицей, и я рассматриваю это как вероятность. И если эта вероятность выше 0,5 или 50%, я говорю, хорошо, положительный класс один. А если ниже 50%, я говорю, что это отрицательный класс, ноль. Так работает логистическая регрессия. И теперь мы это понимаем, давайте закодируем и подгоним. Я установлю для гиперпараметра «max_iter» значение 1000. Этот параметр относится к максимальному количеству итераций для сходимости решателей.

# Build model 
model = LogisticRegression(max_iter=1000) 
# Fit model to training data 
model.fit(X_train, y_train) 

LogisticRegression(max_iter=1000)

Оценивать

Теперь пришло время посмотреть, как работает наша модель. Пришло время оценить модель логистической регрессии. Итак, давайте вспомним, что на этот раз метрика производительности, которая нас интересует, — это оценка точности, и нам нужна точная оценка. И мы хотим побить базовый уровень 0,68. Точность модели можно рассчитать с помощью функции precision_score. Функция требует два аргумента: истинные метки и предсказанные метки.

acc_train = accuracy_score(y_train, model.predict(X_train)) 
acc_test = model.score(X_test, y_test) 
print("Training Accuracy:", round(acc_train, 2)) 
print("Test Accuracy:", round(acc_test, 2)) 

Training Accuracy: 0.9 
Test Accuracy: 0.88

Мы видим, что наша точность обучения составляет 90%. Он превосходит базовый уровень. Точность нашего теста была немного ниже — 88%. Он также превзошел базовый уровень и был очень близок к нашей тренировочной точности. Так что это хорошая новость, потому что это означает, что наша модель не переоснащается или что-то в этом роде.

Результаты модели логистической регрессии

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

model.predict(X_train)[:5] 

array([0, 1, 1, 1, 1])

Таковы были окончательные прогнозы, но каковы вероятности, стоящие за ними? Чтобы получить их, нам нужно сделать немного другой код. Вместо использования метода «прогнозировать» с нашей моделью я буду использовать «прогноз_проба» с нашими обучающими данными.

y_train_pred_proba = model.predict_proba(X_train) 
print(y_train_pred_proba[:5]) 

[[0.92003219 0.07996781]
 [0.03202019 0.96797981]
 [0.00678421 0.99321579]
 [0.03889446 0.96110554]
 [0.00245525 0.99754475]]

Мы видим своего рода вложенный список с двумя разными столбцами в нем. Столбец слева представляет вероятность того, что кандидат не будет размещен, или наш отрицательный класс «Не размещен». Другой столбец представляет положительный класс «Размещено» или вероятность того, что кандидат будет размещен. Мы сосредоточимся на втором столбце. Если мы посмотрим на первую оценку вероятности правильно, то увидим, что она равна 0,07. Так как это ниже 50%, говорит наша модель, мой прогноз равен нулю. И для следующих прогнозов мы видим, что все они выше 0,5, и поэтому наша модель в итоге предсказала один.

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

# Features names 
features = ['gender', 'ssc_p', 'ssc_b', 'hsc_p', 'hsc_b', 'hsc_s', 'degree_p' ,'degree_t', 'workex', 'etest_p', 'specialisation', 'mba_p'] 
# Get importances 
importances = model.coef_[0] 
# Put importances into a Series 
odds_ratios = pd.Series(np.exp(importances), index= features).sort_values() 
# Review 
odds_ratios.head() 


mba_p             0.406590
degree_t          0.706021
specialisation    0.850301
hsc_b             0.876864
etest_p           0.877831
dtype: float64

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

# Horizontal bar chart, five largest coefficients 
odds_ratios.tail().plot(kind="barh") 
plt.xlabel("Odds Ratio") 
plt.ylabel("Feature") 
plt.title("High Importance Features");

Теперь я хочу, чтобы вы представили себе вертикальную линию прямо в точке 5, и я хочу начать с того, что посмотрю на нее. Давайте поговорим о каждом из них в отдельности или только о первой паре. Итак, давайте начнем с «ssc_p», который относится к «проценту среднего образования — 10-й класс». И мы видим, что отношение шансов равно 30. Что это значит? Это означает, что если у кандидата высокий «ssc_p», шансы на его размещение в шесть раз выше, чем у других кандидатов, при прочих равных условиях. Таким образом, другой способ думать об этом - когда у кандидата есть `ssc_p`, вероятность вербовки кандидата увеличивается в шесть раз.

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

odds_ratios.head().plot(kind="barh") 
plt.xlabel("Odds Ratio") 
plt.xlabel("Odds Ratio") 
plt.ylabel("Feature") 
plt.title("Low Importance Features");

Первое, что нам нужно здесь увидеть, это то, что по оси x все равно единице или ниже. Что это значит? Итак, давайте посмотрим на наше наименьшее отношение шансов. Это mba_p, который относится к проценту MBA. Мы видим, что он готов примерно в 0,45. Что это значит? Ну, разница между 0,45 и 1 составляет 0,55. Все в порядке? И что означает это число? Кандидаты со степенью MBA имеют меньше шансов быть принятыми на работу на 55% при прочих равных условиях. Все в порядке? Таким образом, это уменьшило шансы на вербовку в 0,55 раза или на 55%. И это справедливо для всего здесь.

Заключение

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

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

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

Исходный код проекта: https://github.com/SawsanYusuf/Campus-Recruitment.git

Медиафайлы, показанные в этой статье, не принадлежат Analytics Vidhya и используются по усмотрению автора.

Первоначально опубликовано на https://www.analyticsvidhya.com 5 марта 2023 г.