分类模型之职员离职分析

2023-11-04

今天要带来的是机器学习中几种重要的分类模型。分别是:逻辑回归、支持向量机、决策树、随机森林这四种算法模型。这里就不主要介绍模型背后的理论知识了,直接上数据,在数据分析中再来谈这些算法模型。
今天要讨论的是Kaggle上的公司职员离职数据集。这个数据集很有意思,因为它与生活贴近且是人们关注的事情。好了,下面我们进入主题。
首先,引入必要的包和库,再使用pandas包导入数据。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
data = pd.read_csv("HR_Analytics.csv")
data.head()

数据显示

# 再查看数据类型
data.info()

这里写图片描述
可以看出一共有14999个样本,而且,没有一个属性有缺失值。但是,有两个特征是object数据类型,对于机器学习算法来说它只能处理数字型而不能处理字符型数据,所以后面我们要将object转化为int型。从上到下特征分别代表:员工对公司的满意度、公司对员工的满意度、员工做的项目个数、平均一个月的工作时间、员工在公司待的时间、工作中是否发生事故、离职、5年内是否有晋升、部门、薪资。
下面,继续进行数据分析。

数据预处理

先来看各特征与离职之间的相关图。

# satisfaction_level and left
g = sns.FacetGrid(data, col="left")
g.map(plt.hist, "satisfaction_level")

这里写图片描述

bins = np.linspace(0.0001, 1.0001, 21)
plt.hist(data[data['left']==1]['satisfaction_level'], bins=bins, alpha=0.7, label='Employees Left')
plt.hist(data[data['left']==0]['satisfaction_level'], bins=bins, alpha=0.5, label='Employees Stayed')
plt.xlim((0,1.05))
plt.xlabel('satisfaction_level')
plt.legend(loc='best');
# 大于0.5的满意程度留下来的人最多

这里写图片描述
通过这两张图可以看出:当满意度大于0.5时,留下的人多于离职的人,反之则相反了。

再来看公司对员工满意程度与离职有何关系

# Last evaluation
plt.style.use("fivethirtyeight")
bins = np.linspace(0.3501, 1.0001, 14)
plt.hist(data[data['left']==1]['last_evaluation'], bins=bins, alpha=1, label='Employees Left')
plt.hist(data[data['left']==0]['last_evaluation'], bins=bins, alpha=0.4, label='Employees Stayed')
plt.xlabel('last_evaluation')
plt.legend(loc='best');
# 评价大于0.5留下的人最多

这里写图片描述
接着再来看所在部门与离职有何关系:

fig, ax = plt.subplots(1,1,figsize=(6,8))
sns.barplot("department", "left", data=data, ax=ax)
plt.xticks(rotation=45, horizontalalignment='right', fontsize= 13)
plt.xlabel("department", fontsize= 18)
plt.ylabel("left", fontsize= 18)

这里写图片描述
可以看出HR的离职率最高。
最后,我们再来看薪资与离职有何关系呢。

salary_left = dict(zip(*np.unique(data[data["left"]==1]["salary"], return_counts=True)))
salary_stayed = data[data["left"]==0]["salary"].value_counts()
salary_left_value = []
salary_left_key = []
for key, value in salary_left.items():
    salary_left_key.append(key)
    salary_left_value.append(value)
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
explode= [0,0.04,0]
plt.pie(salary_left_value, labels=salary_left_key, autopct='%1.1f%%', explode=explode, shadow= True)
plt.ylabel("salary_level")
plt.title("salary level and employees left")
plt.subplot(1,2,2)
explode= [0.04,0,0]
plt.pie(salary_stayed.values, labels=salary_stayed.index, autopct='%1.1f%%', explode=explode, shadow=True)
plt.ylabel("salary_level")
plt.title("salary level and employees stayed")

这里写图片描述


第一张图是离开的人与薪资高低的关系,显然工资低的人离开的多。
第二张图是留下的人与薪资高低的关系,从图上可以看出工资高的反而留下的人少,这个解释可能是薪资高也许只是针对公司来说,但是对于这些人来说,远达不到他们心里的报价吧(有点牵强。。。)


现在,我们接着之前的问题如何将object转化为int类别。这里介绍两种常用的编码:labelencoding和onehotencoding。labelencoding编码是将一列属性中的所有小属性用不同的数字表示,而onehotencoding是将小属性变为只含0和1的大属性。各有各的好处,labelencoding可以不增加属性的情况下进行机器学习,但是,在本数据中如果想要知道不同部门对离职有没有影响的话,这时就要用onehotencoding编码了。labelencoding不会特定某个值为某个小属性,都是随机的。而onehotencoding编码可以。

salary_dummy = pd.get_dummies(data["salary"])
department_dummy = pd.get_dummies(data["department"])
data = pd.concat([salary_dummy, department_dummy, data], axis=1)
data = data.drop(["department", "salary"], axis=1)
data.head()

这里写图片描述

红色框框标记的都是新增的属性。


下面就进行重要的一步——模型构建

X = data.drop("left", axis=1).values
y = data["left"].values
# Split Training Set from Testing Set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.3, random_state=33)
print(len(X_train))
print(len(X_test))
# 标准化数据
from sklearn.preprocessing import StandardScaler
stds = StandardScaler()
X_train_stds = stds.fit_transform(X_train)
X_test_stds = stds.transform(X_test)

**

逻辑回归分类模型

**


# default logistic regression(模型内不含任何参数)
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
# 交叉验证用于评估模型性能和进行参数调优(模型选择)
from sklearn.model_selection import cross_val_score
scores = cross_val_score(lr, X_train_stds, y_train, cv=5, scoring="accuracy")
print("accuracy of each flod is:")
print(scores)
print("cv accuracy is:%.4f" % scores.mean())

accuracy of each flod is:
[ 0.79666667 0.80761905 0.78666667 0.79095238 0.78894712]
cv accuracy is: 0.7942


正则化逻辑回归

from sklearn.grid_search import GridSearchCV
# 正则(L1和L2)
penaltys = ["l1", "l2"]
Cs = [0.001, 0.01, 0.1, 1, 10, 100, 1000]
tuned_parameters = dict(penalty = penaltys, C = Cs)
lr_penalty = LogisticRegression()
grid = GridSearchCV(lr_penalty, tuned_parameters, cv=5)
grid.fit(X_train_stds, y_train)

# examine the best model
print(grid.best_score_)
print(grid.best_params_)

0.7942661205829127
{‘C’: 10, ‘penalty’: ‘l1’}
模型基本上没有提升,可能是此数据量还不够大的原因,使惩罚项作用不大。


LogisticRegressionCV实现正则化的 Logistic Regression

from sklearn.linear_model import LogisticRegressionCV
Cs = [1, 10, 100, 1000]
lr_cv = LogisticRegressionCV(Cs = Cs, cv = 10, penalty = "l1", solver = "liblinear")
lr_cv.fit(X_train_stds, y_train)
lr_cv.scores_

scores = lr_cv.scores_[1]
scores.mean()

0.79436143265695214
得分也是没有多大差别。接着我们逐步提升模型复杂度,来看看有没有差别。


SVM分类

首先,还是来看缺省的支持向量机

# default SVM
from sklearn.svm import LinearSVC
svc1 = LinearSVC().fit(X_train_stds, y_train)

y_predict = svc1.predict(X_test_stds)
from sklearn import metrics
from sklearn.metrics import confusion_matrix
print("Classification report for classifier %s: \n%s\n"
      % (svc1, metrics.classification_report(y_test, y_predict)))
print("Confusion matrix: \n%s" % confusion_matrix(y_test, y_predict))

可视化混淆矩阵:

# 可视化混淆矩阵
def plot_confusion_matrix(cm, classes, 
                          title="Confusion matrix", 
                          cmap=plt.cm.Blues):
    sns.set_style("ticks")
    fig, ax = plt.subplots(figsize=(6,5))
    plt.imshow(cm, interpolation="nearest", cmap=cmap)
    plt.title(title, fontsize=20)
    plt.colorbar()
    ax.title.set(y=1.05)
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=0, fontsize= 15)
    plt.yticks(tick_marks, classes, fontsize= 15)

    thresh = cm.max() / 2.
    for i , j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, cm[i, j], fontsize=20,
                 horizontalalignment= "center", 
                 color="white" if cm[i,j] > thresh else "black")
    plt.tight_layout()
    plt.ylabel("True label", fontsize= 18)
    plt.xlabel("Predicted label", fontsize= 18)            
import itertools
import matplotlib as mpl
#mpl.rcParams["xtick.labelsize"] = 15
#mpl.rcParams["ytick.labelsize"] = 15
np.set_printoptions(precision=2)
cm = confusion_matrix(y_test, y_predict)
plot_confusion_matrix(cm, classes=[0,1])

我们做出混淆矩阵看看分类的情况。
这里写图片描述


这里写图片描述

正确度为75%,召回率为78%,比逻辑回归还不如,但是,能不能再有所提升呢?我们接着看增加参数的线性SVM。


线性SVM正则参数调优

def fit_grid_point_Linear(C, X_train, y_train, X_test, y_test):
    # 在训练集是那个利用SVC训练
    SVC2 = LinearSVC(C = C)
    SVC2 = SVC2.fit(X_train, y_train)

    # 在校验集上返回accuracy
    accuracy = SVC2.score(X_test, y_test)
    print("accuracy: {}".format(accuracy))
    return accuracy
# 需要调优的参数
C_s = np.logspace(-5, 5, 11)  # logspace(a,b,N)把10的a次方到10的b次方区间分成N份 
# penalty_s = ["l1","l2"]

accuracy_s = []
for i, oneC in enumerate(C_s):
    tmp = fit_grid_point_Linear(oneC, X_train_stds, y_train, X_test_stds, y_test)
    accuracy_s.append(tmp)

x_axis = np.log10(C_s)
plt.style.use("ggplot")
plt.plot(x_axis, np.array(accuracy_s), "b-")
plt.legend()
plt.xlabel( 'log(C)' )                                                                                                      
plt.ylabel( 'accuracy' )
# pyplot.savefig('SVM_Otto.png' )

plt.show()

这里写图片描述

看图发现,accuracy最好的也就78%,结果都没有逻辑回归模型好,那么,接下来我们试试非线性的SVM。


SVM加RBF核调优

from sklearn.svm import SVC

def fit_grid_point_RBF(C, gamma, X_train, y_train, X_test, y_test):
    # 在训练集是那个利用SVC训练
    SVC3 = SVC(C=C, kernel="rbf", gamma= gamma)
    SVC3 = SVC3.fit(X_train, y_train)
    # 在校验集上返回accuracy
    accuracy = SVC3.score(X_test, y_test)

    print("accuracy: {}".format(accuracy))
    return accuracy

#需要调优的参数
C_s = np.logspace(-2, 2, 5)
gamma_s = np.logspace(-2, 2, 5)

accuracy_s = []
for i , oneC in enumerate(C_s):
    for j , gamma in enumerate(gamma_s):
        tmp = fit_grid_point_RBF(oneC, gamma, X_train_stds, y_train, X_test_stds, y_test)
        accuracy_s.append(tmp)

然后,画出参数图:
这里写图片描述
可以看出一下子从78%提升到了最高96.8%
那还能提升吗?我们接着来试试决策树


决策树

from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import roc_auc_score

model_tree = DecisionTreeClassifier()
model_tree.fit(X_train_stds, y_train)

y_prob = model_tree.predict_proba(X_test_stds)[:,1]
y_pred = np.where(y_prob > 0.5, 1, 0)
model_tree.score(X_test_stds,y_test)

print("The AUC of default decision tree is", roc_auc_score(y_test, y_pred))

The AUC of default decision tree is 0.973320989018


同时,我们还可以看特征的重要性。

这里写图片描述
从这个结果可以看出这20个特征中对离职影响最大的是:员工对公司的满意度。这也是合情合理的,其次是公司对员工的满意度和一个月工作的时间这些。通过对特征的重要性进行选择,我们可以去除一些无关特征,提高模型效率。
接着,我再引入一些参数,让模型更丰富。
决策树的参数有:
max_depth(树的深度)
max_leaf_nodes(叶子结点的数目)
max_features(最大特征数目)
min_samples_leaf(叶子结点的最小样本数)
min_samples_split(中间结点的最小样本数)
min_weight_fraction_leaf(叶子节点的样本权重占总权重的比例)
min_impurity_split(最小不纯净)也是可以调整

model_DD = DecisionTreeClassifier()

max_depth = range(1, 10, 1)
min_samples_leaf = range(1, 10, 2)
max_features = range(1, 21, 1)
tuned_parameters = dict(max_depth= max_depth, 
                        min_samples_leaf= min_samples_leaf, max_features= max_features)

DD = GridSearchCV(model_DD, tuned_parameters, cv= 10)
DD.fit(X_train_stds, y_train) 
print("Best : %f using %s" % (DD.best_score_, DD.best_params_))                   

Best : 0.980570 using {‘max_depth’: 9, ‘max_features’: 18, ‘min_samples_leaf’: 1}
模型性能再次得到提升


随机森林模型

Default Random Forest

from sklearn.ensemble import RandomForestClassifier

model_RR = RandomForestClassifier()
model_RR.fit(X_train_stds, y_train)

y_prob = model_RR.predict_proba(X_test_stds)[:,1]
y_pred = np.where(y_prob > 0.5, 1, 0)
print("The AUC of Default Random Forest is", roc_auc_score(y_test, y_pred))

The AUC of Default Random Forest is 0.973035385151


*parameters of the random forest*

from sklearn.model_selection import ShuffleSplit
cv = ShuffleSplit(n_splits= 20, test_size= 0.3)
rf_model = RandomForestClassifier()
# 设置树的个数
rf_param = {"n_estimators" : range(1, 11)}
rf_grid = GridSearchCV(rf_model, rf_param, cv = cv)
rf_grid.fit(X_train_stds, y_train)
print("Parameter with best score:")
print(rf_grid.best_params_)
print('Cross validation score:', rf_grid.best_score_)

Parameter with best score:
{‘n_estimators’: 9}
Cross validation score: 0.983746031746
同样,我们可以将特征重要性找出来:
这里写图片描述

可以看出与决策树所得的特征重要性的结果相一致,只是比重有一些变化,随机森林比起决策树来说更好的规避了结果方差大,出现过拟合的情况。


通过这个例子,我们清楚的看出随着模型复杂度提升,它的性能也在提升。但是,是不是都是这样呢?显然不是的,所以,一个数据集只有不断的尝试才能找到最合适的。今天就讲到这里了,希望对大家有用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分类模型之职员离职分析 的相关文章

  • webm格式怎么转换成mp4?四招快速转换!

    众所周知 视频是我们生活工作中的重要内容 也是传播信息 促进交流的关键工具 随着各类短视频平台的兴起和发展 视频技术也在不断创新 目前 视频格式相对较多 而一些社交网站 短视频软件对视频格式有一定的限制 并不是所有的视频格式都能够被支持的
  • Python 流体动力学层流建模

    使用单相层流的有限差分法求解二维 Navier Stokes 方程 纳维 斯托克斯方程 并使用基准盖腔测试验证结果 介绍 在许多自然现象中都可以观察到流体流动 从舒缓的瀑布到计算机键盘上令人恼火的咖啡飞溅 看到损坏的键盘上的咖啡后 您的第一
  • Unity打开出现两个空白错误的解决方法

    直接上结论 将unity和hub全部重装 问题描述 unity上周还用的好好的 这周打开突然console出现了两个空白错误导致无法运行 版本 2019 4 21 网上的方法 重装unity 改中文路径 改C 改Net 改这改哪的 要么看不
  • CVTE校招笔试

    CVTE校招挺注重基础 并且很多ES6语法 1 变量提升 2 考察call apply bind 和ES6双冒号绑定符 fun bun 相当于 bun bind fun fun bun 相当于 bun apply fun 3树结构 4栈结构

随机推荐

  • 《SystemVerilog验证测试平台编写指南》学习笔记——线程以及线程间的通信(三)

    一 旗语 1 旗语的操作 2 带多个钥匙的旗语 二 信箱 1 测试平台里的信箱 2 定容信箱 3 在异步线程间使用信箱通信 4 使用定容信箱和探视 peek 来实现线程的同步 5 使用信箱和事件来实现线程的同步 6 使用两个信箱来实现线程的
  • Python x64和x86平台下pyinstaller打包过程

    文章目录 使用目的 使用环境 安装x64和x86的Python 具体操作 升级pip 升级pip错误操作 升级pip正确操作 安装x64和x86的pyinstaller 分别打包x64和x86的程序 打包64位程序 打包32位程序 Pyth
  • 【前端异常】http://localhost:8080/user/login 登录失败,重新定向,再登录请求路径改为 http://localhost:8080/user/user/login

    问题 http localhost 8080 user login 登录失败 重新定向 再登录请求路径改为 http localhost 8080 user user login 分析
  • webshell管理工具-冰蝎(Behinder)的安装和基础使用(msf联动,流量特征)

    简介 冰蝎是一款基于Java开发的动态加密通信流量的新型Webshell客户端 由于通信流量被加密 传统的WAF IDS 设备难以检测 给威胁狩猎带来较大挑战 冰蝎其最大特点就是对交互流量进行对称加密 且加密密钥是由随机数函数动态生成 因此
  • C++中map类设为const时的初始化方法

    const map的初始化 首先 在C 中 一个被const修饰的变量是需要在声明时就进行赋值的 那么 对于复杂类型 该如何进行初始化 对于一个仅被const修饰的map 我们可以用如下方式进行初始化 相比C 的Dictionary的初始化
  • Unit Test 7--单元测试覆盖率表单生成交付,Jacoco的使用

    大家好 我是神韵 是一个技术 生活博主 出文章目的主要是两个 一是好记忆不如烂笔头 记录总结中提高自己 二是希望我的文章可以帮到大家 欢迎来点赞打卡 你们的行动将是我无限的动力 本篇主题是 单元测试覆盖率表单生成交付 Jacoco的使用 其
  • 手把手教你构建一个音视频小程序

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由腾讯视频云终端团队发表于云 社区专栏 腾讯云提供了全套技术文档和源码来帮助您快速构建一个音视频小程序 但是再好的源码和文档也有学习成本 为了尽快的能调试起来 我们还提供了一个免
  • 静态路由设置初涉_不同网段指静态路由可以互访 (转载)

    看着不错就转载了 简单明了 也不知道原作者是谁 以下为转载内容 着宽带接入的普及 很多家庭和小企业都组建了局域网来共享宽带接入 而且随着局域网规模的扩大 很多地方都涉及到2台或以上路由器的应用 当一个局域网内存在2台以上的路由器时 由于其下
  • 【算法】JS DP 二分 力扣6346. 打家劫舍 IV

    题目链接 6346 打家劫舍 IV 题目描述 沿街有一排连续的房屋 每间房屋内都藏有一定的现金 现在有一位小偷计划从这些房屋中窃取现金 由于相邻的房屋装有相互连通的防盗系统 所以小偷 不会窃取相邻的房屋 小偷的 窃取能力 定义为他在窃取过程
  • windows环境源码编译VLC2.2.1

    VLC是一款开源的跨平台的多媒体音频 视频播放器 支持多种格式 提供多种解码器 插件 有时候我们需要修改某些功能 插件不满足 那只能修改源码并重新编译了 在linux平台的编译相对简单 windows环境下编译相对就繁琐些了 本文就已成功编
  • 实用调试技巧【下篇】

    本文章是在 Visual Studio 2022 VS2022 编译环境下进行操作讲解 文章目录 3 2 调试的时候查看程序当前信息 3 2 1 查看临时变量的值 3 2 2 查看内存信息 3 2 3 查看调用堆栈 3 2 4 查看汇编信息
  • springboot整合jpa,步骤详细(图文结合讲解)

    编译器Intellij IDEA 关系型数据库MySql 5 7 对象关系映射框架JPA jpa可以通过实体类生成数据库的表 同时自带很多增删改查方法 大部分sql语句不需要我们自己写 配置完成后直接调用方法即可 很方便 1 首先新建spr
  • 索引与存储过程

    1 索引 1 概念 索引 是针对数据所建立的目录 作用 可以加快查询速度 负面影响 降低了增删改的速度 2 案例 设有新闻表15列 10列上有索引 共500W行数据 如何快速导入 1 把空表的索引全部删除 2 导入数据 3 数据导入完毕后
  • 03.模块一 前端基础html、css、js

    文章目录 HTML 详解 1 HTML介绍 规范 1 1 介绍 1 2 使用记事本开发第一个网页 1 3 下载和安装 VSCode 1 3 1 下载地址 1 3 2 初始中文设置 1 3 3 创建项目 1 3 4 运行页面 1 3 5 修改
  • 简要概述Spring中注解@Autowired和@Resource的区别

    在了解注解之前 首先需要明白什么是Bean 凡是子类及带有方法或属性的类 都要加注册Bean到Spring Ioc的注解 如 Component Repository Controller Service 在Spring中 标识一个 符号
  • ChatGPT的出现会不会导致底层程序员失业?我问了下多御ChatGPT

    它是这样说的
  • 1.2【Mask-RCNN训练自己的数据集】---- Part Two: 模型训练(全部流程总结+部分释义)

    二 编写模型训练代码 打开MaskRCNN文件夹下的samples文件夹 存在以下四个文件夹 下述模型训练代码将对shapes文件夹下的train shapes ipnyb 进行修改 这里是jupyter的文本格式 笔者不太习惯使用这种格式
  • Linux input 子系统详解

    1 模块概述 1 1 相关资料和代码研究 drivers input include uapi linux input event codes h 2 模块功能 linux核心的输入框架 3 模块学习 3 1 概述 Linux输入设备种类繁
  • [转] DSP缓存机制

    本文主要以DSP讲解cache原理 但原理与CPU是相通的 故转载 原文地址 DSP 缓存机制 桑迪亚哥的博客 CSDN博客 dsp的cache DSP 缓存机制 注 本文说明的DSP基于TI c6000系列的C66x DSP 目录 DSP
  • 分类模型之职员离职分析

    今天要带来的是机器学习中几种重要的分类模型 分别是 逻辑回归 支持向量机 决策树 随机森林这四种算法模型 这里就不主要介绍模型背后的理论知识了 直接上数据 在数据分析中再来谈这些算法模型 今天要讨论的是Kaggle上的公司职员离职数据集 这