Почему истощение?

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

О наборе данных



Убыток и производительность сотрудников IBM HR Analytics
Прогнозируйте уход ваших ценных сотрудников www.kaggle.com



«Это вымышленный набор данных, созданный специалистами IBM по данным». Этот набор данных содержит около 1470 строк и 35 атрибутов, которые состоят из 8 категориальных переменных и 26 числовых переменных, а целевой меткой для набора данных является «истощение». Выявите факторы, которые приводят к увольнению сотрудников, и изучите важные вопросы, такие как «Покажите мне разбивку расстояния от дома по должностям и увольнению» или «сравните среднемесячный доход по образованию и убыткам».

В этом проекте я сделал.

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

Импорт библиотек

import numpy as np # линейная алгебра
import pandas as pd # обработка данных, ввод-вывод файла CSV (например, pd.read_csv)
импортировать seaborn как sns
импортировать matplotlib.pyplot как plt
% matplotlib встроенный

# Операторы импорта, необходимые для Plotly
# Plotly используются для получения деталей при наведении
import plotly.offline as py
py.init_notebook_mode (connected = True)
import plotly.graph_objs as перейти
импортировать plotly.tools как tls

from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (precision_score, log_loss, classification_report)
from imblearn.over_sampling import SMOTE
import xgboo

# Импорт и подавление предупреждений
импорт предупреждений
warnings.filterwarnings («игнорировать»)

1. Исследовательский анализ данных

## Чтение входных данных для IBM Employee Attrition
attrition = pd.read_csv (‘C: / Users / Aditya / Desktop / Data Sets / Hr.csv’)

Проверка нулевых значений.

Чтобы найти любые нулевые значения, мы можем просто вызвать вызов isnull следующим образом

# Looking for NaN
display(attrition.isnull().any())
Age                         False
Attrition                   False
BusinessTravel              False
DailyRate                   False
Department                  False
DistanceFromHome            False
Education                   False
EducationField              False
EmployeeCount               False
EmployeeNumber              False
EnvironmentSatisfaction     False
Gender                      False
HourlyRate                  False
JobInvolvement              False
JobLevel                    False
JobRole                     False
JobSatisfaction             False
MaritalStatus               False
MonthlyIncome               False
MonthlyRate                 False
NumCompaniesWorked          False
Over18                      False
OverTime                    False
PercentSalaryHike           False
PerformanceRating           False
RelationshipSatisfaction    False
StandardHours               False
StockOptionLevel            False
TotalWorkingYears           False
TrainingTimesLastYear       False
WorkLifeBalance             False
YearsAtCompany              False
YearsInCurrentRole          False
YearsSinceLastPromotion     False
YearsWithCurrManager        False
dtype: bool

attrition.Attrition.value_counts (). plot (kind = ’bar’, color = «blue», alpha = .65)
plt.title («Разбивка по истощению»)

Набор данных несбалансирован, поэтому мы применили технику передискретизации SMOTE на последних этапах.

Разбивка данных атрибуции по полу

pd.crosstab (attrition.Gender, attrition.Attrition) .plot (kind = 'bar')
plt.title ('Ability on Gender')
plt.xlabel ('Gender') < br /> plt.ylabel ('Частота истощения')

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

Разбивка данных атрибуции по отделам

pd.crosstab (истощение. Отделение, истощение. Истощение) .plot (kind = 'bar', stacked = True)
plt.title ('Истощение по отношению к отделу')
plt.xlabel (' Департамент ')
plt.ylabel (' Частота истощения ')
plt.xticks (ротация = 40)

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

Разбивка данных атрибуции по EducationField

pd.crosstab (истощение ['EducationField'], истощение ['истощение']). plot (kind = 'bar', stacked = False)
plt.title ('Истощение относительно EducationField')
plt.xlabel ('EducationField')
plt.ylabel ('Частота истощения')

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

Распространение набора данных

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

# Построение графиков KDEplots
f, axes = plt.subplots (3, 3, figsize = (10, 8),
sharex = False, sharey = False)

# Определение нашей схемы цветовой карты
s = np.linspace (0, 3, 10)
cmap = sns.cubehelix_palette (start = 0.0, light = 1, as_cmap = True)

# Сгенерировать и отобразить
x = истощение ['Возраст']. Значения
y = истощение ['TotalWorkingYears']. Значения
sns.kdeplot (x, y, cmap = cmap, shade = Верно, cut = 5, ax = axes [0,0])
axes [0,0] .set (title = 'Возраст по отношению к общему количеству рабочих лет')

cmap = sns.cubehelix_palette (start = 0.333333333333, light = 1, as_cmap = True)
# Сгенерировать и отобразить
x = истощение ['Возраст']. значения
y = истощение ['DailyRate '] .values ​​
sns.kdeplot (x, y, cmap = cmap, shade = True, ax = axes [0,1])
axes [0,1] .set (title =' Возраст против дневной ставки ')

cmap = sns.cubehelix_palette (start = 0.666666666667, light = 1, as_cmap = True)
# Сгенерировать и отобразить
x = истощение ['YearsInCurrentRole']. значения
y = истощение ['Возраст '] .values ​​
sns.kdeplot (x, y, cmap = cmap, shade = True, ax = axes [0,2])
axes [0,2] .set (title =' Годы в роли против возраста ')

cmap = sns.cubehelix_palette (start = 1.0, light = 1, as_cmap = True)
# Создание и построение
x = истощение ['DailyRate']. values ​​
y = истощение ['DistanceFromHome '] .values ​​
sns.kdeplot (x, y, cmap = cmap, shade = True, ax = axes [1,0])
axes [1,0] .set (title =' Ежедневно Оценить по DistancefromHome ')

cmap = sns.cubehelix_palette (start = 1.333333333333, light = 1, as_cmap = True)
# Сгенерировать и отобразить
x = истощение ['DailyRate']. values ​​
y = истощение ['JobSatisfaction '] .values ​​
sns.kdeplot (x, y, cmap = cmap, shade = True, ax = axes [1,1])
axes [1,1] .set (title =' Ежедневно Оцените степень удовлетворенности работой »)

cmap = sns.cubehelix_palette (start = 1.666666666667, light = 1, as_cmap = True)
# Сгенерировать и отобразить
x = истощение ['YearsAtCompany']. values ​​
y = истощение ['JobSatisfaction '] .values ​​
sns.kdeplot (x, y, cmap = cmap, shade = True, ax = axes [1,2])
axes [1,2] .set (title =' Ежедневно Оценить по расстоянию ')

cmap = sns.cubehelix_palette (start = 2.0, light = 1, as_cmap = True)
# Сгенерировать и отобразить
x = истощение ['YearsAtCompany']. values ​​
y = истощение ['DailyRate '] .values ​​
sns.kdeplot (x, y, cmap = cmap, shade = True, ax = axes [2,0])
axes [2,0] .set (title =' Годы в компании против Daily Rate ')

cmap = sns.cubehelix_palette (start = 2.333333333333, light = 1, as_cmap = True)
# Создание и построение графика
x = attrition ['RelationshipSatisfaction']. values ​​
y = attrition ['YearsWithCurrManager '] .values ​​
sns.kdeplot (x, y, cmap = cmap, shade = True, ax = axes [2,1])
axes [2,1] .set (title =' Взаимосвязь Удовлетворение против лет работы с менеджером »)

cmap = sns.cubehelix_palette (start = 2.666666666667, light = 1, as_cmap = True)
# Создать и построить
x = attrition ['WorkLifeBalance']. values ​​
y = attrition ['JobSatisfaction '] .values ​​
sns.kdeplot (x, y, cmap = cmap, shade = True, ax = axes [2,2])
axes [2,2] .set (title =' WorklifeBalance против удовлетворения ')

f.tight_layout ()

Разделение данных на наборы для обучения и тестирования

attrition_tar = attrition.drop ([‘Attrition’], axis = 1) # Удаление целевого класса

y = истощение [«истощение»]

# Импортировать метод train_test_split
из sklearn.model_selection import train_test_split
# из sklearn.cross_validation import train_test_split
# из sklearn.cross_validation import StratifiedShuffleSplit

# Разделение данных на обучающие и тестовые наборы, а также для проверки и тестирования
x_train, x_test, y_train, y_test = train_test_split (attrition_tar,
y,
train_size = 0.80,
random_state = 0);

2. Разработка функций и категориальное кодирование

def encoding (data):
# Пустой список для хранения столбцов с категориальными данными
ategorical = []
для col, value в data.iteritems ():
if value.dtype == 'объект':
category.append (col)

# Сохранение числовых столбцов в числовом списке
числовой = data.columns.difference (категориальный)
attrition_cat = data [категориальный]
attrition_cat = pd.get_dummies (attrition_cat)
# Сохраните числовые характеристики в фрейме данных attrition_num
attrition_num = data [numeric]
# Соедините два фрейма данных вместе по столбцам
attrition_final = pd.concat ([attrition_num, attrition_cat], axis = 1) < br /> print (attrition_final.columns)
return attrition_final

x_train_encode = кодировка (x_train)
x_test_encode = кодировка (x_test)

Здесь мы разделяем набор данных на числовой тип данных и категориальный тип данных и сохраняем его в списке, и для каждого категориального столбца мы создали фиктивные значения, например, в случае столбца отдела есть три значения (НИОКР, человеческие ресурсы и продажи), которые становятся отдельные столбцы с числовыми значениями. Закодировав наши категориальные столбцы, а также разработав и создав некоторые новые функции из числовых данных, мы теперь можем приступить к объединению обоих фреймов данных в окончательный набор, с которым мы будем обучать и тестировать наши модели.

def target_encode (data):
# Определить словарь для целевого сопоставления
target_map = {'Yes': 1, 'No': 0}
# Использовать метод pandas apply для численного кодирования наша целевая переменная истощения
target = data.apply (lambda x: target_map [x])
return target

y_train_encode = target_encode (y_train)
y_test_encode = target_encode (y_test)

3. Внедрение моделей машинного обучения.

oversampler = SMOTE (random_state = 0)
smote_train, smote_target = oversampler.fit_sample (x_train_encode, y_train_encode)

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

Классификатор случайного леса

seed = 0 # Мы устанавливаем наше случайное семя на ноль для воспроизводимости
# Параметры случайного леса
rf_params = {
'n_jobs': -1,
'n_estimators': 1000, < br /> # 'warm_start': True,
'max_features': 0,3,
'max_depth': 4,
'min_samples_leaf': 2,
'max_features': 'sqrt ',
' random_state ': seed,
' verbose ': 0
}

rf = RandomForestClassifier (** rf_params)
rf.fit (smote_train, smote_target)

rf_predictions = rf.predict (x_test_encode)

print («Оценка точности: {}». format (precision_score (y_test_encode, rf_predictions)))
print («=» * 80)
print (classification_report (y_test_encode, rf_predictions))

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

features = x_train_encode.columns.values ​​
importances = rf.feature_importances_
index = np.argsort (значения)

plt.figure (figsize = (15,15))
plt.title ('Важность функций')
plt.barh (диапазон (len (индексы)), значения [индексы], color = 'b ', align =' center ')
plt.yticks (range (len (index)), [features [i] for i in index])
plt.xlabel (' Relative Importance ')
plt.show ()

Классификатор с градиентным усилением

# Параметры усиления градиента
gb_params = {
'n_estimators': 1500,
'max_features': 0,9,
'learning_rate': 0,25,
'max_depth': 4 ,
'min_samples_leaf': 2,
'subsample': 1,
'max_features': 'sqrt',
'random_state': seed,
'verbose' : 0
}

gb = GradientBoostingClassifier (** gb_params)
# Подгоните модель под наш поезд SMOTEd и нацелитесь
gb.fit (smote_train, smote_target)
# Получите наши прогнозы
gb_predictions = gb. предсказать (x_test_encode)

print (precision_score (y_test_encode, gb_predictions))
print («=» * 80)
print (классификации_report (y_test_encode, gb_predictions))

features = x_train_encode.columns.values ​​
importances = gb.feature_importances_
index = np.argsort (значения)

plt.figure (figsize = (15,15))
plt.title ('Важность функций')
plt.barh (диапазон (len (индексы)), значения [индексы], color = 'b ', align =' center ')
plt.yticks (range (len (index)), [features [i] for i in index])
plt.xlabel (' Relative Importance ')
plt.show ()

Древо решений

из дерева импорта sklearn
dt = tree.DecisionTreeClassifier ()
dt.fit (smote_train, smote_target)

dt_predictions = dt.predict (x_test_encode)

print («Оценка точности: {}». format (precision_score (y_test_encode, dt_predictions)))
print («=» * 80)
print (classification_report (y_test_encode, dt_predictions))

features = x_train_encode.columns.values ​​
importances = dt.feature_importances_
index = np.argsort (значения)

plt.figure (figsize = (15,15))
plt.title ('Важность функций')
plt.barh (диапазон (len (индексы)), значения [индексы], color = 'b ', align =' center ')
plt.yticks (range (len (index)), [features [i] for i in index])
plt.xlabel (' Relative Importance ')
plt.show ()

ВЫВОД

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

вот мой код на github.

Ссылки:



2. https://www.kaggle.com/arthurtok/employee-attrition .

3. https://www.kaggle.com/janiobachmann/attrition