kaggle员工离职预测案例(1)

机器学习 同时被 2 个专栏收录
3 篇文章 0 订阅
2 篇文章 0 订阅

传送门🚪

建模处理过程请看《kaggle员工离职预测案例(2)
模型评估《kaggle员工离职预测案例(3)》

背景

朋友圈无意中看到了老师分享的一篇关于模型评估的文章《机器学习模型评估教程!》,文章对建模后的模型评估进行了深入浅出的评估思路梳理和解读。文章的重点在于模型评估部分,数据梳理和建模部分较为基础故省略不谈。作为一名机器学习的初学者,这简直是一次绝佳的案例学习的机会。so,废话不多说,找到文中的给到的数据来源,开整!

等等…开整之前先简单说一下案例的背景。简单来讲,就是通过已有的数据集来建模预测员工的离职情况。是否会离职?(YES OR NO)很明显一个简单的二分类问题。数据集中包含了很多项关于员工的数据维度,比如基本的个人信息,教育程度,员工满意度,薪资情况等等。详细的数据解读会在后面说明。

数据来源

此案例数据集来源kaggle中的一个比赛项目,数据集下载链接如下:
https://www.kaggle.com/pavansubhasht/ibm-hr-analytics-attrition-dataset

Do It !

数据展示:

因变量(y):
(1)Attrition:员工是否已经离职,1表示已经离职,2表示未离职,这是目标预测值;
自变量(X):
(1)Age:员工年龄 ;
(2)MonthlyRate:月薪;
(3)BusinessTravel:商务差旅频率,Non-Travel不出差,Travel_Rarely不经常出差,Travel_Frequently经常出差;
(4)Department:员工所在部门,Sales销售部,Research & Development研发部,Human Resources人力资源部;
(5)DistanceFromHome:公司跟家庭住址的距离,从1到29,1最近,29最远;
(6)Education:员工的教育程度,从1到5,5教育程度最高;
(7)EducationField:员工所学习的专业领域,Life Sciences生命科学,Medical医疗,Marketing市场营销,Technical Degree技术学位,Human Resources人力资源,Other其他;
(8)EmployeeNumber:员工号码;
(9)EnvironmentSatisfaction:员工对于工作环境的满意程度,从1到4,1的满意程度最低,4的满意程度最高;
(10)Gender:员工性别,Male男性,Female女性;
(11)JobInvolvement:员工工作投入度,从1到4,1为投入度最低,4为投入度最高;
(12)JobLevel:职业级别,从1到5,1为最低级别,5为最高级别;
(13)JobRole:工作角色:Sales Executive销售主管,Research Scientist科学研究员,Laboratory Technician实验室技术员,Manufacturing Director制造总监,Healthcare Representative医疗代表,Manager经理,Sales Representative销售代表,Research Director研究总监,Human Resources人力资源;
(14)JobSatisfaction:工作满意度,从1到4,1满意程度最低,4满意程度最高;
(15)MaritalStatus:员工婚姻状况,Single单身,Married已婚,Divorced离婚;
(16)MonthlyIncome:员工月收入,范围在1009到19999之间;
(17)NumCompaniesWorked:员工曾经工作过的公司数;
(18)Over18:年龄是否超过18岁;
(19)OverTime:是否加班,Yes表示加班,No表示不加班;
(20)PercentSalaryHike:工资提高的百分比;
(21)PerformanceRating:绩效评估;
(22)RelationshipSatisfaction:关系满意度,从1到4,1满意度最低,4满意度最高;
(23)StandardHours:标准工时;
(24)StockOptionLevel:股票期权水平;
(25)TotalWorkingYears:总工龄;
(26)TrainingTimesLastYear:上一年的培训时长,从0到6,0没有培训,6培训时间最长;
(27)WorkLifeBalance:工作与生活平衡程度,从1到4,1平衡程度最低,4平衡程度最高;
(28)YearsAtCompany:在目前公司工作年数;
(29)YearsInCurrentRole:在目前工作职责的工作年数
(30)YearsSinceLastPromotion:距离上次升职时长
(31)YearsWithCurrManager:跟目前的管理者共事年数;
(32)DailyRate:日薪;
(33)EmployeeCount:员工人数;
(34)HourlyRate:时薪;
(35)MonthlyRate:月薪;

数据分析:

导入一些必需包,涉及建模的包后面会有。

import csv
import pandas as pd  
import numpy as np
from scipy import stats #
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
# 忽略警告
warnings.filterwarnings('ignore') 
# 使用 ggplot 画图风格
plt.style.use('ggplot')
%matplotlib inline;
data = pd.read_csv('WA_Fn-UseC_-HR-Employee-Attrition.csv')
data.tail()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
缺失值验证

a = data.loc[data['Attrition']=='No'].count()[0]
b = data.loc[data['Attrition']=='Yes'].count()[0]
labels = ['0','1']
explo=[0.1,0]
plt.pie([a,b],labels=labels,explode=explo,shadow=True,startangle=0,autopct='%1.2f%%',wedgeprops={'edgecolor':'black'})
plt.show()

在这里插入图片描述
分析:


  1. 数据结构1470行(样本容量)*35列(变量),其中数值型变量26个,文本型变量9个。
  2. 35个变量中EmployeeCount,EmployeeNumber,Over18,StandardHours的这四个,常识上认为员工编号与是否离职关系不大(否则过于玄学,哈哈),另外三个变量所有员工都一致,对最终的结果影响不大,可以删除上述四个变量
  3. 数值型变量需要考虑离散程度,是否需要数据标准化;文本型变量需要考虑one-hot编码
  4. 因变量离职情况分布不,离职的样本只占全体样本的16%,这种情况可能会导致模型在很大程度上学到的都是未离职的特征,离职的样本过少而导致没有学习到,sad。针对这种情况需要考虑降采法或者过采法进行数据样本平衡。看到这里你一定会问哪一种方法更好?说实话我也不知道,所以后面我们两种方法都试一遍,看看哪种方法模型的精度更好。

 #删除上述四个无关变量
data = data.drop(['EmployeeCount','EmployeeNumber','Over18','StandardHours'], axis='columns')  
#对删除后的数据依旧类型分类,文本型和数值型。
category=[f for f in data.columns if data.dtypes[f] =='object'] 
numeric=[f for f in data.columns if data.dtypes[f] !='object']

可以分别打印出来看一下,很好,删除了得到了新的data。
在这里插入图片描述

 #展示数值型变量和因变量Attrition的关系,这里用
plt.figure(figsize = (30,30))
for i in numeric:
    plt.subplot(5,6,numeric.index(i)+1)
    sns.boxplot(x = 'Attrition',y = i,data = data)

在这里插入图片描述

 #展示数值型变量的数据分别情况
data.hist(edgecolor='black', linewidth=1.2, figsize=(20, 20));

在这里插入图片描述

 #热力图展示
data.Attrition[data['Attrition']=='Yes']=int(1)
data.Attrition[data['Attrition']=='No']=int(0)
data[['Attrition']] = data[['Attrition']].astype(int)

corrmat = data.corr()
k = len(corrmat[abs(corrmat['Attrition'])>0.04].index)
# 获取前k个重要的特征名
cols = corrmat.nlargest(k,'Attrition')['Attrition'].index.tolist()
plt.figure(figsize=(20,15))
sns.heatmap(data[cols].corr(),annot=True,square=True)

在这里插入图片描述
分析:


  1. 从箱型图中可以看出单个变量中哪一种情况对Attrition的影响更大。比如Age变量中可以看出,年纪轻的比年纪大的更容易离职。
  2. 热力图中可以看出某个变量特征和Attrition的相关性数据。越接近1表示正相关性越高,越接近-1表示负相关性越高,越接近0表示相关性越低。
  3. 数据分布图中可以看出像AgeEducation特征它们的数据分类类似正太分布;但是像 DistanceFromHomeMonthlyIncomeYearsAtCompanyYearsInCurrentRole等这类特征它们的数据分布很明显的呈现右偏,也可以说成正偏态,这种情况可以考虑通过.log1p( ) 函数进行纠正


数据处理:

step 1:对数据进行归一化处理。

这里挑选了部分数值型变量进行归一化,使它们的参考系处于同一标准,比如0-1之间。
(为什么要这么做?可以参考《机器学习之数据的偏态分布和数据的标准化》)

 #采用MinMaxScaler对数据进行标准化
from sklearn.preprocessing import MinMaxScaler
data_norm = data
lst = ['Age',
 'DailyRate',
 'DistanceFromHome',
 'Education',
 'EnvironmentSatisfaction',
 'HourlyRate',
 'JobInvolvement',
 'JobLevel',
 'JobSatisfaction',
 'MonthlyIncome',
 'MonthlyRate',
 'NumCompaniesWorked',
 'PercentSalaryHike',
 'PerformanceRating',
 'RelationshipSatisfaction',
 'StockOptionLevel',
 'TotalWorkingYears',
 'TrainingTimesLastYear',
 'WorkLifeBalance',
 'YearsAtCompany',
 'YearsInCurrentRole',
 'YearsSinceLastPromotion',
 'YearsWithCurrManager']
for i in lst:
    data_norm['{}_norm'.format(i)] = MinMaxScaler().fit_transform(data[i].values.reshape(-1,1))
#删除原有变量    
data_norm = data_norm.drop(lst,axis='columns')
data_norm

在这里插入图片描述

step 2: 对文本型变量进行One-Hot编码处理

 #先把文本型变量找出来储存为新的datafrme-data1_norm
category=[f for f in data_norm.columns if data_norm.dtypes[f] =='object'] 
data1_norm =  data_norm[category]
data1_norm

一共7个,完美

 #可以分别检查一下其中有没有特殊值
for i in category:
    print(data1_norm[i].value_counts())
    print('*'*40)

在这里插入图片描述

 #使用pandas的.get_dummies()方法可以轻易的将他们进行one-hot编码操作。
data_dummies = pd.get_dummies(data1_norm)
print(list(data_dummies))
data_dummies  

在这里插入图片描述

 #将编码后的data与原始data 合并,并删除原有的文本型变量。
data_final_norm = pd.concat((data_norm.drop(list(data1_norm), axis='columns'),data_dummies),axis=1)

在这里插入图片描述
经过一系列的处理,原本35列数据变成52列数据,我们把得到的最终数据保存为一个新的CSV文件,以防丢失(后面建模就用到我们这个最终的数据啦。)

data_final_norm.to_csv('data_final_norm.csv',index=0) #不保存行索引

step 3.1: 降采样

降采样的目的就是让多的情况(未离职)的样本数量变的和少的情况(离职)的数量一样多。我们要做的就是在(未离职)的样本中随机取出n个样本,n=(离职)的数量。

# 得到所有离职样本的索引
number_Attrition = len(data_final_norm[data_final_norm.Attrition == 1])
Attrition_indices = np.array(data_final_norm[data_final_norm.Attrition == 1].index)

# 得到所有非离职样本的索引
normal_indices = data_final_norm[data_final_norm.Attrition == 0].index

# 在正常样本中随机采样出指定个数的样本,并取其索引
random_normal_indices = np.random.choice(normal_indices, number_Attrition, replace = False) #注意replace参数的使用
random_normal_indices = np.array(random_normal_indices)

# 有了正常和异常样本后把它们的索引都拿到手
under_sample_indices = np.concatenate([Attrition_indices,random_normal_indices])

# 根据索引得到降采样所有样本点
under_sample_data = data_final_norm.iloc[under_sample_indices,:]

# 降采样 样本比例
print("正常样本所占整体比例: ", len(under_sample_data[under_sample_data.Attrition == 0])/len(under_sample_data))
print("异常样本所占整体比例: ", len(under_sample_data[under_sample_data.Attrition == 1])/len(under_sample_data))
print("降采样策略总体样本数量: ", len(under_sample_data))

可以把最终结果打印出来,平衡了,木问题。
在这里插入图片描述

step 3.2 过采样

降采样的目的就是让少的情况(离职)的样本数量变的和多的情况(未离职)的数量一样多。我们要做的就是随机生成n个(离职)样本,n=(未离职)的数量 减去(离职)的数量。
因为要随机生成一些样本数据,我们这里直接调用imblearn库的RandomOverSampler(ROSP)方法。关于具体说明,可以参考《》。

from imblearn.over_sampling import RandomOverSampler

columns=data_final_norm.columns
# 在特征中去除掉标签
features_columns=columns
features=data_final_norm[features_columns]
labels=data_final_norm['Attrition']

features_train, features_test, labels_train, labels_test = train_test_split(features, 
                                                                            labels, 
                                                                           test_size=0.3, 
                                                                          random_state=0)
#需要先初始化一下,然后传入数据特征和标签
oversampler = RandomOverSampler(random_state=0)
os_features,os_labels=oversampler.fit_resample(features_train,labels_train)

#查看一下生成的数据量
len(os_labels[os_labels==1])  # 输出862                                                                   
 #可以可视化展示过采后的结果,离职和未离职数据一样多了。
sns.countplot('Attrition',data=os_features)
c = os_features[os_features['Attrition']==0]
d = os_features[os_features['Attrition']==1]
print(c.shape[0])
print(d.shape[0]

在这里插入图片描述
对上面两种方法不清楚的可以参考我的老师写的一个案例博客《逻辑回归案例模板——信用卡欺诈检测》,里面有非常详细的解释。我的代码也是参考的这个案例。

训练集、测试集划分:

因为我们要验证降采和过采哪一种方案会更好,所以要分别对降采后的数据和过采后的数据进行数据集划分。

1. 降采后的数据

from sklearn.model_selection import train_test_split

X_undersample = under_sample_data.iloc[:, under_sample_data.columns != 'Attrition']
y_undersample = under_sample_data.iloc[:, under_sample_data.columns == 'Attrition']

#取出所有的特征数据和标签数据
X = data_final_norm.iloc[:, data_final_norm.columns != 'Attrition']
y = data_final_norm.iloc[:, data_final_norm.columns == 'Attrition']

#整个数据集进行划分,注意random_state一定要设置一样的,因为要进行过采样的对比
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3, random_state = 0)

#降采样数据进行划分
X_train_undersample, X_test_undersample, y_train_undersample, y_test_undersample = train_test_split(
X_undersample,y_undersample,test_size = 0.3,random_state = 0
)

2.过采后的数据

 #可以可视化展示过采后的结果,离职和未离职数据一样多了。
X_oversample = os_features.iloc[:, os_features.columns != 'Attrition']
y_oversample = os_features.iloc[:, os_features.columns == 'Attrition']

X_train_oversample, X_test_oversample, y_train_oversample, y_test_oversample = train_test_split(
    X_oversample,y_oversample,test_size = 0.3,random_state = 0)
 #可以可视化展示过采后的结果,离职和未离职数据一样多了。
print('初始训练集包含样本数量:',len(X_train))
print('初始测试集包含样本数量:',len(X_test))
print('初始样本总数:',len(X_train) + len(X_test))
print("")
print("过采样训练集包含样本数量: ", len(X_train_oversample))
print("过采样测试集包含样本数量: ", len(X_test_oversample))
print("过采样样本总数: ", len(X_train_oversample)+len(X_test_oversample))
print("")
print("降采样训练集包含样本数量: ", len(X_train_undersample))
print("降采样测试集包含样本数量: ", len(X_test_undersample))
print("降采样样本总数: ", len(X_train_undersample)+len(X_test_undersample))

降采后和过采后的数据比较:
在这里插入图片描述
写到这里,数据的处理的工作已经完成了。后面需要做的就是选择不同的模型进行训练学习,并选择其中最好的一个模型进行评估。请继续看《kaggle员工离职预测案例(2)》

这里需要特别说明的是,本文没有对偏态数据进行纠正处理。

  • 4
    点赞
  • 2
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值