熱線電話:13121318867

登錄
首頁大數據時代員工一言不合就離職怎么破?我有python員工流失預警模型
員工一言不合就離職怎么破?我有python員工流失預警模型
2020-08-24
收藏

CDA數據分析師 出品

作者:真達、Mika

數據:真達

后期:澤龍

【導讀】

今天教大家如何用Python寫一個員工流失預測模型。Show me data,用數據說話。我們聊一聊員工離職,說到離職的原因,可謂多種多樣。人們歸總了兩點:

1. 錢沒給到位

2. 心受委屈了

有人離職是因為“世界那么大,我想去看看”,也有人覺得“懷有絕技在身,不怕天下無路”。

另一方面,員工離職對于企業而言有什么影響呢?

要知道,企業培養人才需要大量的成本,為了防止人才再次流失,員工流失分析就顯得十分重要了。這不僅僅是公司評估員工流動率的過程,通過找到導致員工流失的主要因素,預測未來的員工離職狀況,從而進一步減少員工流失。

那么,哪些因素最容易導致員工離職呢?

這次我們用數據說話,

教你如何用Python寫一個員工流失預測模型。

01、數據理解

我們分析了kaggle平臺分享的員工離職相關的數據集,共有10個字段14999條記錄。數據主要包括影響員工離職的各種因素(員工滿意度、績效考核、參與項目數、平均每月工作時長、工作年限、是否發生過工作差錯、5年內是否升職、部門、薪資)以及員工是否已經離職的對應記錄。字段說明如下:

02、讀入數據

# 讀入數據 df = pd.read_csv('HR_comma_sep.csv')
df.head() 
# 讀入數據 df = pd.read_csv('HR_comma_sep.csv')
df.head() 
# 讀入數據 df = pd.read_csv('HR_comma_sep.csv')
df.head() 
# 查看缺失值 print(df.isnull().any().sum()) 
# 查看缺失值 print(df.isnull().any().sum()) 
# 查看缺失值 print(df.isnull().any().sum()) 

可以發現,數據質量良好,沒有缺失數據。

03、探索性分析

描述性統計

df.describe().T

從上述描述性分析結果可以看出:

  • 員工滿意度:范圍0.09~1, 中位數0.640, 均值0.613, 總體來說員工對公司比較滿意;
  • 績效考核:范圍0.36~1, 中位數0.72, 均值0.716, 員工平均考核水平在中等偏上;
  • 參與項目數:范圍2~7, 中位數4, 均值3.8, 平均參加項目數約4個;
  • 平均每月工作時長:范圍96~310小時, 中位數200, 均值201。
  • 工作年限:范圍2~10年, 中位數3, 均值3.5。

離職人數占比

整理數據后發現,總共有14999人,其中紅色部分代表離職人群,用數字1表示,藍色為未離職人群,用數字0表示。離職人數為3571,占總人數的23.8%。

員工滿意度

直方圖可以看出,離職員工的滿意度評分明顯偏低,平均值為0.44。滿意度低于0.126分的離職率為97.2%??梢娞嵘龁T工滿意度可以有效防止人員流失。

df.groupby('left')['satisfaction_level'].describe() 
def draw_numeric_graph(x_series, y_series, title):     # 產生數據     sat_cut = pd.cut(x_series, bins=25) 
    cross_table = round(pd.crosstab(sat_cut, y_series, normalize='index'),4)*100     x_data = cross_table.index.astype('str').tolist()
    y_data1 = cross_table[cross_table.columns[1]].values.tolist()
    y_data2 = cross_table[cross_table.columns[0]].values.tolist() 

    條形圖     bar = Bar(init_opts=opts.InitOpts(width='1350px', height='750px'))
    bar.add_xaxis(x_data)
    bar.add_yaxis(str(cross_table.columns[1]), y_data1, stack='stack1', category_gap='0%')
    bar.add_yaxis(str(cross_table.columns[0]), y_data2, stack='stack1', category_gap='0%')
    bar.set_global_opts(title_opts=opts.TitleOpts(title), 
                        xaxis_opts=opts.AxisOpts(name=x_series.name, name_location='middle', name_gap=30),
                        yaxis_opts=opts.AxisOpts(name='百分比', name_location='middle', name_gap=30, min_=0, max_=100),
                        legend_opts=opts.LegendOpts(orient='vertical', pos_top='15%', pos_right='2%'))
    bar.set_series_opts(label_opts=opts.LabelOpts(is_show=False), 
                        itemstyle_opts=opts.ItemStyleOpts(border_color='black', border_width=0.3))
    bar.set_colors(['#BF4C51''#8CB9D0']) 

    return bar 
bar1 = draw_numeric_graph(df['satisfaction_level'], df['left'], title='滿意度評分與是否離職')
bar1.render() 

績效考核

平均來看,績效考核成績在離職/未離職員工之間差異不大。在離職員工中,績效考核低、能力不夠和績效考核較高但工作壓力大、滿意度低、對薪資不滿意可能成為離職的原因。

平均每月工作時長

直方圖可以看出,月工作時長正常的員工離職率最低。而工時過低、過高的員工離職人數最多。證明恰當的工作任務分配是非常重要的。

參加項目數

從圖中可以看出:除項目數為2以外,隨著項目數的增多,離職率在增大,且項目數是7的時候,離職率達到了100%以上。綜上兩點,項目數2的離職率高,可能是這部分人工作能力不被認可。項目數6、7的總體少,離職率高,體現了他們的工作能力強,但同時工作壓力太大導致他們離職。

員工工齡

可以看到7年及以上工齡的員工基本沒有離職,只有工齡為5年的員工離職人數超過在職人數??梢姽g長于6年的員工,由于種種原因,其“忠誠度”較高。

而員工進入公司工作的第5年是一個較為“危險”的年份,也許是該企業的“5年之癢”,應當重點關注該階段的員工滿意度、職業晉升等情況,以順利過渡。

工作事故

從圖中可看出,是否發生工作事故對員工離職的影響較小,可推測該企業處理工作事故的方式有可取之處。

職位晉升

條形圖可以看出,在過去5年內獲得未晉升的員工離職率為24.2%,比獲得晉升的員工高4倍。設定良好的晉升通道可以很好的防止員工流失。

薪資水平

可明顯看出,薪資越高離職人數越少。證明為了減少離職率,提升員工福利待遇是一個可行的手段。

不同部門

可見各部門離職率如上圖,離職率由高到低,前三位分別是:人力部、財務部、科技部。之后依次是:支持部、銷售部、市場部、IT部門、產品部、研發部、管理部。對于離職率過高的部門,應進一步分析關鍵原因。

04、數據預處理

由于sklearn在建模時不接受類別型變量,我們主要對數據做以下處理,以方便后續建模分析:

  • 薪資水平salary為定序變量, 因此將其字符型轉化為數值型。
  • 崗位是定類型變量, 對其進行one-hot編碼。
# 數據轉換 df['salary'] = df['salary'].map({"low": 0, "medium": 1, "high": 2}) # 啞變量 df_dummies = pd.get_dummies(df,prefix='sales')
df_dummies.head() 

05、建模分析

我們使用決策樹隨機森林進行模型建置,首先導入所需包:

from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, f1_score, roc_curve, plot_roc_curve

然后劃分訓練集和測試集,采用分層抽樣方法劃分80%數據為訓練集,20%數據為測試集。

train_pred = GS.best_estimator_.predict(X_train)
test_pred = GS.best_estimator_.predict(X_test) print('訓練集:', classification_report(y_train, train_pred)) print('-' * 60)  print('測試集:', classification_report(y_test, test_pred))

決策樹

我們使用決策樹進行建模,設置特征選擇標準為gini,樹的深度為5。輸出分類的評估報告:

# 訓練模型 clf = DecisionTreeClassifier(criterion='gini', max_depth=5, random_state=25)
clf.fit(X_train, y_train)
train_pred = clf.predict(X_train)
test_pred = clf.predict(X_test)   print('訓練集:', classification_report(y_train, train_pred)) print('-' * 60)  print('測試集:', classification_report(y_test, test_pred))
訓練集:               precision    recall  f1-score   support            0       0.98      0.99      0.98      9142            1       0.97      0.93      0.95      2857     accuracy                           0.98     11999    macro avg       0.97      0.96      0.97     11999 weighted avg       0.98      0.98      0.97     11999 ------------------------------------------------------------ 測試集:               precision    recall  f1-score   support            0       0.98      0.99      0.98      2286            1       0.97      0.93      0.95       714     accuracy                           0.98      3000    macro avg       0.97      0.96      0.97      3000 weighted avg       0.98      0.98      0.98      3000 

假設我們關注的是1類(即離職類)的F1-score,可以看到訓練集的分數為0.95,測試集分數為0.95。

# 重要性 imp = pd.DataFrame([*zip(X_train.columns,clf.feature_importances_)], columns=['vars''importance'])
imp.sort_values('importance'ascending=False)  
imp = imp[imp.importance!=0]
imp 

在屬性的重要性排序中,員工滿意度最高,其次是最新的績效考核、參與項目數、每月工作時長。

然后使用網格搜索進行參數調優。

parameters = {'splitter':('best','random'),
              'criterion':("gini","entropy"),
              "max_depth":[*range(120)],
             }

clf = DecisionTreeClassifier(random_state=25)
GS = GridSearchCV(clf, parameters, cv=10)
GS.fit(X_train, y_train) print(GS.best_params_) print(GS.best_score_) 
{'criterion''gini''max_depth': 15, 'splitter''best'}
0.9800813177648042

使用最優的模型重新評估訓練集和測試集效果:

train_pred = GS.best_estimator_.predict(X_train)
test_pred = GS.best_estimator_.predict(X_test) print('訓練集:', classification_report(y_train, train_pred)) print('-' * 60)  print('測試集:', classification_report(y_test, test_pred))
訓練集:               precision    recall  f1-score   support            0       1.00      1.00      1.00      9142            1       1.00      0.99      0.99      2857     accuracy                           1.00     11999    macro avg       1.00      0.99      1.00     11999 weighted avg       1.00      1.00      1.00     11999 ------------------------------------------------------------ 測試集:               precision    recall  f1-score   support            0       0.99      0.98      0.99      2286            1       0.95      0.97      0.96       714     accuracy                           0.98      3000    macro avg       0.97      0.98      0.97      3000 weighted avg       0.98      0.98      0.98      3000 

可見在最優模型下模型效果有較大提升,1類的F1-score訓練集的分數為0.99,測試集分數為0.96。

隨機森林

下面使用集成算法隨機森林進行模型建置,并調整max_depth參數。

rf_model = RandomForestClassifier(n_estimators=1000, oob_score=True, n_jobs=-1, 
                                  random_state=0)
parameters = {'max_depth': np.arange(3171) }
GS = GridSearchCV(rf_model, param_grid=parameters, cv=10)
GS.fit(X_train, y_train) print(GS.best_params_)  print(GS.best_score_) 
{'max_depth': 16} 0.988582151793161
train_pred = GS.best_estimator_.predict(X_train)
test_pred = GS.best_estimator_.predict(X_test) print('訓練集:', classification_report(y_train, train_pred)) print('-' * 60)  print('測試集:', classification_report(y_test, test_pred))
訓練集:               precision    recall  f1-score   support            0       1.00      1.00      1.00      9142            1       1.00      0.99      0.99      2857     accuracy                           1.00     11999    macro avg       1.00      1.00      1.00     11999 weighted avg       1.00      1.00      1.00     11999 ------------------------------------------------------------ 測試集:               precision    recall  f1-score   support            0       0.99      1.00      0.99      2286            1       0.99      0.97      0.98       714     accuracy                           0.99      3000    macro avg       0.99      0.99      0.99      3000 weighted avg       0.99      0.99      0.99      3000

可以看到在調優之后的隨機森林模型中,1類的F1-score訓練集的分數為0.99,測試集分數為0.98。

模型后續可優化方向:

  • 屬性:數值型數據常常是模型不穩定的來源,可考慮對其進行分箱;重要屬性篩選和字段擴充;
  • 算法:其他的集成方法;不同效能評估下的作法調整。

數據分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數據分析師資訊
更多

OK
客服在線
立即咨詢
日韩人妻系列无码专区视频,先锋高清无码,无码免费视欧非,国精产品一区一区三区无码
客服在線
立即咨詢