实战1:人力资源项目分析(离职因素)

一、分析背景

企业培养人才需要大量的成本,为防止人才流失,因此对于员工离职因素的分析十分重要。通过员工离职的主要因素,可以预测未来的员工离职状况,从而进一步减少员工流失,为公司降低人才培养成本。

二、分析目标

基本分析目标:导致员工离职的因素。
预测:员工离职可能性预测。

三、分析思路

提出问题

  1. 哪些因素和离职相关性较大?(初步判定)
  2. 哪些因素导致员工离职?(某个因素的具体数值范围确定)
  3. 产生这些因素的原因有?如何解决?

分析流程确立

  1. 描述性分析:看基本数据分布情况。
  2. 相关性分析:初步判定影响较大的因素。
  3. 变量分析:针对每一个变量探索对离职的影响,并找到变量影响的具体数值范围。

四、分析步骤

0 数据理解

data = pd.read_csv('../data/HR_comma_sep.csv')  #读取数据
print('共有',data.shape[0],'条记录,',data.shape[1],'个字段')
data.head()
image.png

初步了解数据文件的基本信息:14999条数据,10个字段。
再来看看该每个字段的含义与数据类型。

data.info()
image.png

从上面输出结果可以知一下信息:

  • 10个字段中:8个数值型数据,2个分类数据。

再对分类数据进一步查看:

data.describe(include=['O'])
image.png
print(data.sales.unique())
print(data.salary.unique())
image.png

综上,可以看出整个表结构和分类变量取值范围如下表所示。


image.png

1 数据清洗与整理

1.1 检查缺失值

data.isnull().sum()
image.png

不存在缺失值。

1.2 检查异常值

利用箱型图来检测异常值。

fig, ax = plt.subplots(1,5, figsize=(15, 3))
for i in range(5):
    sns.boxplot(x=df.columns[i], data=df, ax=ax[i])
plt.show()
image.png

除了工作年限意外,没有异常值存在。异常值可能为公司元老级人物,不用排除。

从1.1和1.2步骤来看,整体数据很干净,可以直接进行处理。

1.2 修改字段名与字段顺序

适当修改数据字段名和顺序方便数据理解与使用。字段名修改如下:

  • sales 》 department
  • promotion_last_5years 》 promotion
  • Work_accident 》work_accident
df = data.rename(columns = {"sales":"department","promotion_last_5years":"promotion","Work_accident":"work_accident"})

本次分析重点是对离职状态(left)进行相关因素的探索,所有将left放在最后一列方便查看。(当然也可以不移动)

cols = df.columns
cols = list(cols[:6]) + list(cols[7:])+[cols[6]] 
print('Reordered Columns:',cols)

1.3 量化类别数据

  1. 转换为Category类型
df['department'] = df['department'].astype('category')
df['salary'] = df['salary'].astype('category')
df.info()
image.png
  1. 保存类别与数据值的映射字典
    这一步主要是方便后面处理使用。
salary_dict = dict(enumerate(df['salary'].cat.categories))
department_dict = dict(enumerate(df['department'].cat.categories))
salary_dict,department_dict
image.png
  1. 将类别数值化表示
    利用映射字典作为数据的类别表示。
for feature in df.columns:
    if str(df[feature].dtype) == 'category':
        df[feature] = df[feature].cat.codes
        df[feature] = df[feature].astype('int64') 
df.head()
image.png

2 数据分析

2.1 描述性分析

df.describe().T
image.png

上述描述性分析结果显示:


image.png

2.2 相关性分析

通过求person相关系数、绘制热力图,来识别两个特征之间的相关性,给出初步的变量分析方向。

corr = df.corr().round(3) # pearson相关系数

# 构造下三角掩码矩阵
mask = np.zeros_like(corr) 
mask[np.tril_indices_from(mask)]=True # np.tril_indices_from()将列表索引分成两个数组返回,形成下三角。

# 绘制热力图
sns.set_style('white')
fig = plt.figure(figsize = (10,8))  # 设置图的大小
ax = sns.heatmap(corr,
            xticklabels = True, yticklabels=True,
            cmap = 'RdBu',  #颜色
            mask = mask,  #使用掩码,只绘制一部分
            fmt = '.3f',  #格式设置
            annot = True,  #方格内是否写入数据
            linewidths = .5, # 热力图矩阵之间的间隔大小
            vmax = .4,  #图例中最大值
            square = True)
plt.title('Correlation') #图表名称
label_x = ax.get_xticklabels() # 获取横坐标
plt.setp(label_x,rotation=45,horizontalalignment='right') #设置横坐标表示
plt.show()
热力图.png

【图表解读】
从热力图中可以看出:

  • 离职(left):
    • 满意度工伤晋升呈较强的负相关,与薪酬有较弱的负相关
    • 工作年限呈较强的正相关,与平均每月工作时间所在部门有较弱的正相关。
  • 满意度(satisfaction_level):与绩效呈现正相关,与完成项目数量在职年限也有一定的负相关性。
  • 绩效(last_evaluation):与项目数平均每月工作时间呈现较强的正相关
  • 项目数(number_object):与平均每月工作时间呈较强的正相关

2.3 变量分析

2.3.1 离职 vs 在职

首先,从整体上来看离职和在职员工比例。

colors = ['#81ecec','#ff7675']
plt.pie(left_count.left_count, 
        labels =['not left','left'], 
        autopct = '%.2f%%', 
        colors = colors, 
        startangle = 90, 
        wedgeprops = {'width' : 0.4},
        counterclock = False)
plt.axis('square')
plt.legend(loc='upper right')
plt.show()
image.png

从可以看出约24%的员工离职,在职员工有76%左右。


接下来进行单变量分析。

2.3.2 满意度 vs 离职

  1. 分布情况
sns.distplot(df.loc[df['left']==1,'satisfaction_level'],color='b',label='left')
sns.distplot(df.loc[df['left']==0,'satisfaction_level'],color='r',label='no_left')
plt.legend()
plt.show()
image.png
  1. 箱型图
sat_box = sns.boxplot(data=df,
             x='left',
            y='satisfaction_level')

# 计算中位数
satisfaction_median= df.groupby(['left'])['satisfaction_level'].median()
vertical_offset = df['satisfaction_level'].median()* 0.05 #偏移量
 
# 相对的中位数偏移:
for xtick in sat_box.get_xticks():
    sat_box.text(xtick,satisfaction_median[xtick] + vertical_offset,satisfaction_median[xtick], 
            horizontalalignment='center',
            color='w',
            weight='semibold')
image.png

结论:从满意度的箱型图来看,离职人员对公司满意度相对较低,并且波动较大。
从满意度的分布情况来看,离职员工满意度呈现多峰分布,分别在0.1、0.3-0.5、0.8左右时,出现了3个峰值。

  • 满意度在0.1左右时,即低满意度离职,员工对公司不满导致离职。
  • 满意度在0.3~0.5时,即较低满意度离职,离职员工对公司满意度较低而离职,有深入原因。
  • 满意度在0.7~0.9右时,即高满意度离职,可能是有更好的工作机会出现,使得员工跳槽。

2.3.2 工伤 vs 离职

# 数据透视表
workacc_left_tabel = pd.crosstab(index=df['work_accident'],columns=df['left'])
workacc_left_tabel['p'] = round(workacc_left_tabel[1] / (workacc_left_tabel[1] +workacc_left_tabel[0]),3)
# 用ployly条形图
data = []
annotation =[]
work_acc_dict = {0:'没受过伤',1:'受过伤'}
left_eles = df.left.unique() # 在职和离开的数值表示
for l in left_eles:
    trace = Bar(x = workacc_left_tabel.index, 
                y = workacc_left_tabel[l], 
               name = ('离职' if l == 1 else '在职'),
               marker = dict(color = colors[l+4]))
    data.append(trace)

for i in df.work_accident.unique():
    adict=dict(x=i,y=workacc_left_tabel.loc[i,1],
              text = workacc_left_tabel.loc[i,'p'].round(3))
    annotation.append(adict)
    
layout = Layout(title = '员工是否有工伤与离职是否有关',
               width = 500,height = 500,
                barmode = 'stack',
                annotations=annotation,
               xaxis = dict(tickmode = 'array',
                            tickvals = list(work_acc_dict.keys()),
                            ticktext=list(work_acc_dict.values())))
iplot(Figure(data=data,layout=layout))

image.png

结论

  • 有工伤的员工离职率低约7.8%;没有工伤的员工离职率高,为26.5%。
  • 可推测公司对于工作事故的处理方式较好。

2.3.3 晋升 vs 离职

promotion_left_table = pd.crosstab(index=df['promotion'],columns=df['left'])
promotion_left_table['p'] = promotion_left_table[1]/(promotion_left_table[1]+promotion_left_table[0])
promotion_dict={0:'没有升职',1:'升过职'}
data= []
annodatin = []
for  i in df.left.unique():
    trace = Bar(x = promotion_left_table.index,
               y = promotion_left_table[i],
               name=('在职' if i == 0 else '离职'),
               marker = dict(color = colors[i+4]))
    data.append(trace)

for i in df.promotion.unique():
    adict=dict(x=i,y=promotion_left_table.loc[i,1],
              text = promotion_left_table.loc[i,'p'].round(3))
    annodatin.append(adict)
    
layout=Layout(title='员工过去5年是否升职对离职的影响',
             width=500,height=550,
             annotations=annodatin,
             barmode = 'stack',
             xaxis=dict(tickmode='array',
                        tickvals=list(promotion_dict.keys()),
                       ticktext=list(promotion_dict.values())))
iplot(Figure(data=data,layout=layout))
image.png

结论

  • 离职员工主要存在于没有升职的员工中;升过职的员工离职极少。
  • 良好的晋升通道设定可以防止员工流失。

2.3.4 部门 vs 离职

depart_left_table = pd.crosstab(index=df['department'],columns=df['left']) # 创建数据透视表
depart_left_table['p']=depart_left_table[1]/depart_left_table[0]
data = []
left_eles = df.left.unique() # 在职和离开的数值表示
for l in left_eles:
    trace = Bar(x = depart_left_table[l], # 数量
                y = depart_left_table.index, #部门
               name = ('离职' if l == 1 else '在职'),
               orientation = 'h',
                text=depart_left_table['p'].round(2),
                hoverinfo='x+y+text',
               marker = dict(color = colors[l+4]))
    data.append(trace)
layout = Layout(title = '每个部门的离职员工数量与在职员工数对比',
               barmode = 'stack',
               width = 800,height = 500,
               yaxis = dict(title = '部门',
                            tickmode = 'array',
                            tickvals = list(department_dict.keys()),
                            ticktext = list(department_dict.values())))

iplot(Figure(data=data,layout=layout))
image.png
data = []
left_eles = df.left.unique() # 在职和离开的数值表示
for l in left_eles:
    trace = Bar(x = depart_left_table.index,
                y = depart_left_table['p'].round(2), #部门
               name = ('离职' if l == 1 else '在职'),
                hoverinfo='x+y',
               marker = dict(color = colors[l+2]))
    data.append(trace)
layout = Layout(title = '部门离职比率',
               width = 700, height = 400,
                xaxis = dict(title = '部门',
                            tickmode = 'array',
                            tickvals = list(department_dict.keys()),
                            ticktext = list(department_dict.values())))
iplot(Figure(data = [trace], layout = layout))
image.png

结论

  • 单从部门离职人数来看,大部分离职员工为sales、support、technica部门l;management离职人数较低。(离职人数是虚荣指标)
  • 从离职占比来看,hr离职率最高,accounting次之,随后才是离职人员比较多的sales、support、technical。
  • 对于每个部门离职原因需要进一步分析。

2.3.5 薪资 vs 离职

salary_left_table = pd.crosstab(index=df['salary'],columns=df['left'])
salary_left_table['p'] = salary_left_table[1]/(salary_left_table[1]+salary_left_table[0])
data = []
annodatin = []
for i in df.left.unique():
    trace = Bar(x = salary_left_table.index,
               y = salary_left_table[i],
               name = ('在职' if i == 0 else '离职'),
               marker = dict(color = colors[i+4]))
    data.append(trace)
    
for i in df.salary.unique():
    adict=dict(x=i,y=salary_left_table.loc[i,1],
              text = salary_left_table.loc[i,'p'].round(3))
    annodatin.append(adict)

layout = Layout(title='员工薪资对离职的影响',
               width=580,height=350,
                barmode = 'stack',
                annotations=annodatin,
               xaxis = dict(tickmode='array',
                           tickvals=list(salary_dict.keys()),
                           ticktext=list(salary_dict.values())))
iplot(Figure(data=data,layout=layout))

image.png

结论

  • 离职员工的薪资主要处于中低水平。
  • 高薪资员工,离职人数少,基本不会离职。

进一步探索各部门薪资情况,是否每个部门离职员工是否有薪资影响。

depart_salary_table = pd.crosstab(index=df['department'],columns=df['salary'])
data = []
for i in df.salary.unique():
    trace = Bar(x = depart_salary_table.index,
               y = depart_salary_table[i],
               name = salary_dict[i],
               marker = dict(color=colors[i+2]))
    data.append(trace)
layout = Layout(title = '公司各部门的薪资情况',
               width = 800,height=450,
               xaxis = dict(tickmode = 'array',
                           tickvals = list(department_dict.keys()),
                           ticktext = list(department_dict.values())))
iplot(Figure(data=data,layout=layout))

image.png

结论

  • 中低收入员工主要存在于sales、support、technical部门,从部门离职情况来看,离职人数大部分也是属于这三个部门。
  • management高水平薪资相较于该部门而言占多数,且部门离职人员少,因此部门薪资情况不可忽视。

2.3.6 工作年限 vs 离职

  1. 箱型图
tspend_box = sns.boxplot(data=df,
             x='left',
            y='time_spend_company')

# 计算中位数
tspend_median= df.groupby(['left'])['time_spend_company'].median()
vertical_offset = df['time_spend_company'].median()* 0.05 #偏移量
 
# 相对的中位数偏移:
for xtick in sat_box.get_xticks():
    tspend_box.text(xtick,tspend_median[xtick] + vertical_offset,tspend_median[xtick], 
            horizontalalignment='center',
            color='w',
            weight='semibold')
image.png
  1. 条形图
time_left_table = pd.crosstab(index=df['time_spend_company'],columns=df['left'])
data = []
for i in df.left.unique():
    trace = Bar(x = time_left_table.index,
               y = time_left_table[i],
               name=('在职' if i == 0 else '离职'),
               marker=dict(color = colors[i+4]))
    data.append(trace)
layout = Layout(title='员工在职时间长短对离职的影响',
               width=700,height=500,
               barmode='stack',
               xaxis=dict(tickmode='array',tickvals=time_left_table.index))
iplot(Figure(data=data,layout=layout))

image.png

结论

  • 从箱型图看,离职员工工作年限相较于在职员工多1年。
  • 从条形图看,离职员工大部分已经工作3~6年,而工作7年以上的员工没有离开。

2.3.7 平均工作时间 vs 离职

  1. 箱型图
mhours_box = sns.boxplot(data=df,
             x='left',
            y='average_montly_hours')

# 计算中位数
mhours_median= df.groupby(['left'])['average_montly_hours'].median()
vertical_offset = df['average_montly_hours'].median()* 0.05 #偏移量
 
# 相对的中位数偏移:
for xtick in sat_box.get_xticks():
    mhours_box.text(xtick,mhours_median[xtick] + vertical_offset,mhours_median[xtick], 
            horizontalalignment='center',
            color='w',
            weight='semibold')
image.png
  1. 分布情况
sns.distplot(df.loc[df['left']==1,'average_montly_hours'],color='b',label='left')
sns.distplot(df.loc[df['left']==0,'average_montly_hours'],color='r',label='no_left')
plt.legend()
plt.show()

image.png

结论

  • 从平均每月工作时长的箱型图来看,离职人员每月工作时间相较偏长,平均每月多6小时,并且波动偏大。
  • 从平均每月工作时长的分布情况来看,离职员工平均每月工作时长呈现双峰分布,主要分布在125-165、215-285之间。在职员工平均每月工作时长主要分布在155-240之间。
  • 上述可以说明平均每月工作时长过短(日均6-7.5h)或者过长(日均10h以上)都可能导致员工离职。最好保持在155-240之间(日均7.5-10h)。

2.3.8 项目数 vs 离职

number_left_table = pd.crosstab(index=df['number_project'],columns=df['left'])
number_left_table['p'] = round(number_left_table[1] / (number_left_table[0]+number_left_table[1]),3)
data = []
annotation = []
left_eles = df.left.unique() # 在职和离开的数值表示
for l in left_eles:
    trace = Bar(x = number_left_table.index, 
                y = number_left_table[l], 
               name = ('离职' if l == 1 else '在职'),
               marker = dict(color = colors[l+4]))
    data.append(trace)

for i in df.number_project.unique():
    adict=dict(x=i,y = number_left_table.loc[i,1],
              text = number_left_table.loc[i,'p'])
    annotation.append(adict)
    
layout = Layout(title = '员工负责项目数与离职是否有关',
               width = 500,height = 500,
                barmode = 'stack',
                annotations = annotation,
               xaxis = dict(tickmode = 'array',
                            tickvals = list(number_left_table.index)))
iplot(Figure(data=data,layout=layout))

image.png

结论

  • 只有2个和6个项目的员工一半以上选择离职,有7个项目的员工全部离职,有3个项目的员工离职率最低。
  • 说明项目数量小于2时,员工工作不够,可能未被重视导致离职;而有6个项目以上的员工,可能过度劳累导致离职。
  • 每位员工负责的项目数量保持在3~4个较好。

2.3.9 绩效 vs 离职

  1. 箱型图
evaluation_box = sns.boxplot(data=df,
             x='left',
            y='last_evaluation')

# 计算中位数
evaluation_median= df.groupby(['left'])['last_evaluation'].median()
vertical_offset = df['last_evaluation'].median()* 0.05 #偏移量
 
# 相对的中位数偏移:
for xtick in sat_box.get_xticks():
    evaluation_box.text(xtick,evaluation_median[xtick] + vertical_offset,evaluation_median[xtick], 
            horizontalalignment='center',
            color='w',
            weight='semibold')
image.png

2.分布情况

fig=plt.figure(figsize=(10,5))
sns.distplot(df.loc[df['left']==1,'last_evaluation'],color='b',label='left')
sns.distplot(df.loc[df['left']==0,'last_evaluation'],color='r',label='no_left')
plt.legend()
plt.show()

image.png

结论

  • 从箱型图来看,离职员工绩效在0.79左右,在职员工在0.71左右,离职人员平均绩效比在职人员高(需要注意,为什么平均绩效偏高反而离职?)
  • 从分布情况来看,离职员工绩效呈现双峰分布:
    • 绩效为0.45~0.55,绩效低离职人数多,可能原因是绩效较差导致离职;
    • 绩效为0.8~1,绩效高离职人数多,可能找到更好的工作机会或个人家庭等原因导致离职,具体需要进一步探索。
  • 绩效在0.6~0.8之间有较好的员工留存率。

多变量分析,探索共同作用原因。

2.3.10 项目数 + 平均工作时长 vs 离职

sns.boxplot(data = df,
           x = 'number_project',
           y = 'average_montly_hours',
           hue = 'left')

image.png

结论

  • 随着项目数量增加,在职员工平均月工作时间变化不大;而离职员工平均月工作时间随之增加;说明项目数量与平均月工作时间的正相关,主要由离职员工所带动。
  • 在项目数量相同的情况下,离职员工平均月工作时间比在职员工长。说明工作时长的不平衡可能导致员工离职。

2.3.11 项目数 + 绩效 vs 离职

sns.boxplot(data = df,
           x = 'number_project',
           y = 'last_evaluation',
           hue = 'left')

image.png

结论

  • 随着项目数量增加,离职员工绩效随着增高,而在职员工绩效变化不大,说明绩效与项目数的正相关主要由离职员工带动,要注意优秀员工离职带来的公司绩效影响。
  • 项目数量为2时,离职员工绩效比在职员工低,可能个人工作能力不足导致离职。
  • 在项目数量为4~6时,离职人员绩效相较于在职人员高出较多。

2.3.12 绩效 + 平均每月工作时间 vs 离职

sns.lmplot(data = df,
          x = 'average_montly_hours',
          y = 'last_evaluation',
          hue = 'left',
          fit_reg = False)

image.png

结论

  • 整个分布来看,离职集群有两个:
    • 平均月工作时间在150左右,绩效在0.55左右时,员工离职人数多。主要原因可能是员工自身不努力。
    • 平均月工作时间在255左右,绩效在0.9左右时,排除员工自身努力的原因,则主要原因可能是过度劳累或找到更好的工作机会离职。
  • 总体看来,绩效和平均月工作时间分别维持在0.60.8,155255之间员工较为稳定。

2.3.13 绩效 + 满意度 vs 离职

sns.lmplot(data = df,
          x = 'satisfaction_level',
          y = 'last_evaluation',
          hue = 'left',
          fit_reg = False)

image.png

结论

  • 从整体分布来看,离职集群有3个:
    • 满意度在0.1,绩效在0.8~1范围,优秀员工对公司工作不满(注意保留);
    • 满意度在0.4,绩效在0.45~0.58范围,这部分员工离职有公司和自身不努力等原因共同作用。
    • 满意度在0.85,绩效在0.8以上,优秀员工对公司满意却离职,可能有更好的工作机会或自身家庭原因等作用。

2.4 总结

  1. 离职员工在工作年限、项目数、绩效、平均月工作时间上偏高,优秀员工离职比例较大。
  2. 大部分离职人员的主要特征
    image.png

    对公司满意度低,薪资处于中低水平平均月工作时间较长约,工作年限在3~6年,过去5年没有晋升,负责项目数量偏低(2个)和偏高(6,7个),主要来自于salse、support、techenical部门(人员流动或工作压力较大的部门)。
  3. HR和accounting离职比例高,这两个部门需要重点关注与分析离职的主要原因。此外,受过工伤的员工离职率低,公司对员工意外事故处理这部分处理得当。
  4. 离职率与满意度、薪酬呈负相关,说明低满意度、薪资水平较低产生了较高的离职率。
  5. 从绩效来看,员工离职并不仅仅因为自身业绩不好。对于绩效高且满意度高绩效高且平均每月工作时间长绩效高且负责项目多的这部分优秀员工存在较高的离职率。侧面反映了优秀员工未能通过自身努力得到升职加薪、实现个人价值而导致离职。

目前看来,公司需要注意的方面主要有以下两点:

  1. 优秀员工(高绩效)的留存:要优化绩效考核制度,建立良好的晋升通道和薪资提升标准,使得员工在公司有较好的职业发展。
  2. 提升员工的满意度:主要从工作时长、项目安排和薪资上进行优化调整,降低员工平均工作时长(建议每日工作时长保持在7.5~10h之间)、合理分配项目(建议人均负责项目在3~4个),提高人效。

3 建模分析

建模分析基于sklearn机器学习库。

3.1 数据预处理

在之前进行描述分析时,使用的类别数据转换方式,未能按照薪资水平大小进行顺序赋值,需要重新编码。此外,部门类别并没有顺序意义,重新采用one-hot进行编码。

# 定序
df['salary'] = df.salary.map({"low": 0, "medium": 1, "high": 2})
df['salary'] = df['salary'].astype('int64') 
df.salary.unique()

#定类
df = pd.get_dummies(df,prefix='department')

对于连续型数据需要进行标准化,这里采用归一化的方式处理。
由于satisfaction_level和last_evaluation取值范围为[0,1],则不用进行归一化。
对number_project,average_montly_hours,time_spend_company采用max-min进行归一化。

min_max_scaler = preprocessing.MinMaxScaler()
df.loc[:,['number_project','average_montly_hours','time_spend_company']] = min_max_scaler.fit_transform(df.loc[:,['number_project','average_montly_hours','time_spend_company']])
df
image.png

3.2 数据集划分

其中训练集占原始数据的80%,测试集占20%。

from sklearn.model_selection import train_test_split

y = df.left
X = df.drop('left',axis=1)
X_train,X_test,y_train,y_test = train_test_split(X, y, test_size = 0.2,random_state = 1) 

3.3 模型试验

3.3.1 逻辑回归

from sklearn.linear_model import LogisticRegression

# 简单逻辑回归
LR = LogisticRegression() #创建模型
LR.fit(X_train,y_trian)
print('训练集准确性',LR.score(X_train,y_trian))
print('测试集准确性',LR.score(X_test,y_test))
image.png

准确性一般,在基于该模型上进行调参,看是否能提高准确性。

随机梯度下降
LR2 = LogisticRegression(solver='saga')
LR2.fit(X_train,y_trian)
print('训练集准确性',LR2.score(X_train,y_trian))
print('测试集准确性',LR2.score(X_test,y_test))

模型没有提升,可能是数据量不够大,惩罚项作用不大。

交叉验证
from sklearn.linear_model import LogisticRegressionCV
# 利用10折交叉验证选择合适的参数C
Cs = 10 ** np.linspace(-10, 10, 400)
LR_cv = LogisticRegressionCV(Cs=Cs, cv=10, penalty='l2', solver='saga',  max_iter=10000, scoring='accuracy')
LR_cv.fit(X_train, y_train)
LR_cv.C_
image.png

利用该参数进行预测

LR3 = LogisticRegression(solver='saga', penalty='l2', C=37.92690191)
LR3.fit(X_train,y_train)
print("训练集准确率: ", LR3.score(X_train, y_train))
print("测试集准确率: ", LR3.score(X_test, y_test))
image.png

准确性稍微有所提高。

分别利用混淆矩阵和ROC进行模型评估。

混淆矩阵

from sklearn import metrics

X_train_pred = LR3.predict(X_train)
X_test_pred = LR3.predict(X_test)
print('训练集混淆矩阵:')
print(metrics.confusion_matrix(y_train, X_train_pred))
print('测试集混淆矩阵:')
print(metrics.confusion_matrix(y_test, X_test_pred))
image.png
from sklearn.metrics import classification_report
print('训练集:')
print(classification_report(y_train, X_train_pred))
print('测试集:')
print(classification_report(y_test, X_test_pred))
image.png

在训练集有0.83的精准率和0.93的召回率, 在测试集上有0.83的精准率和0.92的召回率。

ROC

from sklearn.metrics import roc_curve

lr_fpr, lr_tpr, lr_thresholds = roc_curve(y_test, LR3.predict_proba(X_test)[:,1]) # 返回假正率、真正率、阈值
lr_roc_auc = metrics.auc(lr_fpr, lr_tpr) # 计算auc值
lr_roc_auc
image.png

auc即为ROC曲线下的面积,面积越大代表模型预测效果越好。

后面的模型省略中间求准确度、混淆矩阵的步骤。

3.3.2 朴素贝叶斯

from sklearn.naive_bayes import GaussianNB

gnb = GaussianNB()
gnb.fit(X_train, y_train)
gnb_fpr, gnb_tpr, gnb_thresholds = roc_curve(y_test, gnb.predict_proba(X_test)[:,1]) # 返回假正率、真正率、阈值
gnb_roc_auc = metrics.auc(gnb_fpr, gnb_tpr) # 计算auc值

3.3.3 决策树

import sklearn.tree as sk_tree

skt = sk_tree.DecisionTreeClassifier()
skt.fit(X_train,y_train)
skt_fpr, skt_tpr, skt_thresholds = roc_curve(y_test, skt.predict_proba(X_test)[:,1]) # 返回假正率、真正率、阈值
skt_roc_auc = metrics.auc(skt_fpr, skt_tpr) # 计算auc值

3.3.4 支持向量机SVM

import sklearn.svm as sk_svm
svm = sk_svm.SVC(probability=True)
svm.fit(X_train,y_train)
svm_fpr, svm_tpr, svm_thresholds = roc_curve(y_test, svm.predict_proba(X_test)[:,1]) # 返回假正率、真正率、阈值
svm_roc_auc = metrics.auc(svm_fpr, svm_tpr) # 计算auc值

3.3.5 随机森林模型

from sklearn.ensemble import RandomForestClassifier

RR = RandomForestClassifier()
RR.fit(X_train, y_train)
rr_fpr, rr_tpr, rr_thresholds = roc_curve(y_test, RR.predict_proba(X_test)[:,1]) # 返回假正率、真正率、阈值
rr_roc_auc = metrics.auc(rr_fpr, rr_tpr) # 计算auc值

ROC综合评价

plt.figure(figsize=(8, 5))
plt.plot([0, 1], [0, 1],'--', color='r')
plt.plot(lr_fpr, lr_tpr, label='LogisticRegression(area = %0.2f)' % lr_roc_auc)
plt.plot(gnb_fpr, gnb_tpr, label='GaussianNB(area = %0.2f)' % gnb_roc_auc)
plt.plot(skt_fpr, skt_tpr, label='DecisionTree(area = %0.2f)' % skt_roc_auc)
plt.plot(svm_fpr, svm_tpr, label='SVM(area = %0.2f)' % svm_roc_auc)
plt.plot(rr_fpr, rr_tpr, label='RandomForest(area = %0.2f)' % rr_roc_auc)

plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.title('ROC')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend()
plt.show()
image.png

从上图可以看出,应用随机森林模型效果最好。

你可能感兴趣的:(实战1:人力资源项目分析(离职因素))