DC員工離職預(yù)測訓(xùn)練賽

該比賽為DC練習(xí)賽观挎,要求使用邏輯回歸的方法琳袄,從給定的影響員工離職的因素和員工是否離職的記錄玖喘,建立一個(gè)邏輯回歸模型預(yù)測有可能離職的員工贡蓖。

相關(guān)數(shù)據(jù)的介紹曹鸠,請參考:比賽地址

1.探索數(shù)據(jù)

import numpy as np
import pandas as pd

# 讀取數(shù)據(jù)
train = pd.read_csv('pfm_train.csv')
test = pd.read_csv('/pfm_test.csv')
print('train size:{}'.format(train.shape))  # train size:(1100, 31)
print('test size:{}'.format(test.shape))  #test size:(350, 30)
# 查看數(shù)據(jù)集中是否含有缺失值:無缺失值
# train.isnull().mean()

1.1 數(shù)據(jù)分析

# EmployeeNumber為員工ID,將其刪除
train.drop(['EmployeeNumber'], axis = 1, inplace = True)

# 將Attrition(該字段為標(biāo)簽)移至最后一列斥铺,方便索引
Attrition = train['Attrition']
train.drop(['Attrition'], axis = 1, inplace = True)
train.insert(0, 'Attrition', Attrition)

使用pyecharts從各維度上對離職人數(shù)以及離職率進(jìn)行分析

from pyecharts import Bar,Line,Grid
from pyecharts import Overlap

# 通過圖表分析哪些因素是主要影響員工離職的因素
def get_chatrs(train, col):
    data = train.groupby([col])['Attrition']
    data_sum = data.sum() # 離職人數(shù)
    data_mean = data.mean()  # 離職率
    
    bar = Bar(col, title_pos="45%")
    bar.add('離職人數(shù)', data_sum.index, data_sum.values, mark_point = ['max'],
            yaxis_formatter =  '人', yaxis_max = 200 , legend_pos="40%", legend_orient="vertical", 
            legend_top="95%", bar_category_gap = '25%')

    line = Line()
    line.add('離職率', data_mean.index, data_mean.values, mark_point = ['max'], mark_line = ['average'],
        yaxis_max = 0.8)

    overlap = Overlap(width=900, height=400)
    overlap.add(bar)
    overlap.add(line, is_add_yaxis=True, yaxis_index=1)

    return overlap
    

from pyecharts import Page
page = Page()
for col in train.columns[1:]:
    page.add(get_chatrs(train, col))
page.render('pages.html')
page

運(yùn)行此段代碼后彻桃,發(fā)現(xiàn)圖表數(shù)據(jù)顯示有錯(cuò)誤,檢查代碼沒有發(fā)現(xiàn)問題晾蜘,手動的在圖表中刷新數(shù)據(jù)后邻眷,問題得到解決

# 公司總體的離職率在16.2%
train['Attrition'].mean()

通過觀察圖表發(fā)現(xiàn)以下問題
Q1研發(fā)部門離職人數(shù)最多,這主要是因?yàn)樵摴狙邪l(fā)部門人數(shù)最多的原因剔交,雖然人數(shù)多肆饶,但是研發(fā)部門離職率最低,離職率最高的部門是HR岖常,該部門也是公司人數(shù)最少的部門驯镊,人員架構(gòu)不太穩(wěn)定?(綜合其他因素如’Education‘竭鞍、’JobRole‘等板惑,也發(fā)現(xiàn),HRD離職率很高

Department.png

Q2: 18歲-23歲員工離職率超過40%偎快,23歲-33歲員工離職率在20%-40%

Age.png

Q3: 工作投入度為1等級的員工離職率有近40%冯乘,達(dá)到了38%!I辜小往湿!

JobInvolvement.png

Q4: 加班的員工離職率是不加班員工的三倍!M锵贰领追!

OverTime.png

進(jìn)一步探索

部門&加班&收入

收入在較低水平的銷售部門員工在加班的況下離職率達(dá)80%,且該部門員工在加班情況下响逢,無論收入水平如何绒窑,離職率都高于公司的整體離職率

部門工作滿意度

HRD員工離職的原因之一:工作滿意度比較低,是否存在辦公室政治的原因舔亭?

2.數(shù)據(jù)處理&特征處理

2.1 數(shù)據(jù)處理

# 在分析中發(fā)現(xiàn)有一些字段的值是單一的,進(jìn)一步驗(yàn)證
single_value_feature = []
for col in train.columns:
    lenght = len(train[col].unique())
    if lenght == 1:
        single_value_feature.append(col)

single_value_feature  # ['Over18', 'StandardHours']

'Over18', 'StandardHours'這兩個(gè)字段的值是唯一的些膨,刪除這兩個(gè)字段

# 刪除這兩個(gè)字段
train.drop(['Over18', 'StandardHours'], axis = 1, inplace = True)
train.shape  # (1100, 28)

由于數(shù)據(jù)集中沒有缺失值蟀俊,這里不需要對缺失值做處理

2.2 特征處理

主要是對部分特征進(jìn)行分組以及one-hot編碼

# 對收入進(jìn)行分箱
print(train['MonthlyIncome'].min())  # 1009
print(train['MonthlyIncome'].max())  # 19999
print(test['MonthlyIncome'].min())  # 1051
print(test['MonthlyIncome'].max())  # 19973

為了在train和test中的MonthlyIncome進(jìn)行分組后的區(qū)間一致,需要保持兩個(gè)數(shù)據(jù)集中MonthlyIncome的最大值和最小值一致订雾,這里使用等寬分組

由于test數(shù)據(jù)集中MonthlyIncome的最小值比train數(shù)據(jù)集中的最小值大肢预,最大值比train數(shù)據(jù)集中的最大值小,需要人工插入最大值最小值后才能進(jìn)行分組洼哎,這樣在test數(shù)據(jù)集中MonthlyIncome的分組區(qū)間才能與train中MonthlyIncome分組一致烫映,這個(gè)后面會進(jìn)行具體操作

# 使用pandas的cut進(jìn)行分組,分為10組
train['MonthlyIncome'] = pd.cut(train['MonthlyIncome'], bins=10)
# 將數(shù)據(jù)類型為‘object’的字段名提取出來噩峦,并使用one-hot-encode對其進(jìn)行編碼
col_object = []
for col in train.columns[1:]:
    if train[col].dtype == 'object':
        col_object.append(col)
col_object

對train數(shù)據(jù)集進(jìn)行one-hot編碼

train_encode = pd.get_dummies(train)

保存數(shù)據(jù)集锭沟,方便日后使用

train.to_csv('trainwithoutencode.csv')
train_encode.to_csv('train.csv')

2.3 特征共線性處理

corr = train.corr()

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

sns.heatmap(corr, xticklabels=corr.columns.values, yticklabels=corr.columns.values)
plt.show()

特征共線性

'TotalWorkingYears' & 'JobLevel'
'YearsAtCompany' & 'YearsWithCurrManager'存在共線性,選擇刪除其中一個(gè)特征即可

train_encode.drop(['TotalWorkingYears', 'YearsWithCurrManager'], axis = 1, inplace = True)

3. 建模預(yù)測

3.1 建模

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

X = train_encode.iloc[:, 1:]
y = train_encode.iloc[:, 0]

# 劃分訓(xùn)練集以及測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)

lr = LogisticRegression()
lr.fit(X_train, y_train)
lr.score(X_train, y_train)  # 0.8886363636363637

由于存在隨機(jī)性识补,最終在訓(xùn)練集上的score大約在0.88~0.9波動

pred = lr.predict(X_test)
np.mean(pred == y_test)  # 0.8863636363636364

結(jié)果在測試集上的結(jié)果與訓(xùn)練集差不多族淮,下面看一下預(yù)測結(jié)果的混淆矩陣是怎樣的

from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_score, recall_score, f1_score

#對整個(gè)train數(shù)據(jù)集的混淆矩陣
y_pred = lr.predict(X)
confmat= confusion_matrix(y_true=y,y_pred=y_pred)#輸出混淆矩陣
fig,ax = plt.subplots(figsize=(2.5,2.5))
ax.matshow(confmat,cmap=plt.cm.Blues,alpha=0.3)
for i in range(confmat.shape[0]):
    for j in range(confmat.shape[1]):
        ax.text(x=j,y=i,s=confmat[i,j],va='center',ha='center')
plt.xlabel('predicted label')
plt.ylabel('true label')
plt.show()

#召回率、準(zhǔn)確率凭涂、F1
print ('precision:%.3f' %precision_score(y_true=y,y_pred=y_pred))
print ('recall:%.3f' %recall_score(y_true=y,y_pred=y_pred))
print ('F1:%.3f' %f1_score(y_true=y,y_pred=y_pred))

混淆矩陣

發(fā)現(xiàn)準(zhǔn)確率和召回率都是很很滿意祝辣,然后嘗試調(diào)參,lr中可調(diào)整的參數(shù)不多切油,調(diào)整后發(fā)現(xiàn)模型的精度提高不是很大

3.2 預(yù)測

# test數(shù)據(jù)集處理
test.drop(['EmployeeNumber', 'Over18', 'StandardHours'], axis = 1, inplace = True)
test_MonthlyIncome = pd.concat((pd.Series([1009, 19999]), test['MonthlyIncome'])) 
# 在指定位置插入與train中MonthlyIncome的max蝙斜、min一致的數(shù)值,之后再刪除
test['MonthlyIncome'] = pd.cut(test_MonthlyIncome, bins=10)[2:]  # 分組并去除對應(yīng)的值
test_encode = pd.get_dummies(test)
test_encode.drop(['TotalWorkingYears', 'YearsWithCurrManager'], axis = 1, inplace = True)# 輸出結(jié)果
sample = pd.DataFrame(lr.predict(test_encode))
sample.to_csv('sample.csv')

按照要求修改sample的格式后上傳

結(jié)果排名

上傳結(jié)果后白翻,排在60名乍炉,top5%绢片,還算可以的結(jié)果

4. 反思

  • 對于邏輯回歸滤馍,在參數(shù)上調(diào)整空間比較小,應(yīng)該注重在特征工程上的處理底循,除了使用one-hot編碼的方法外巢株,還可以嘗試使用歸一化、標(biāo)準(zhǔn)表等等熙涤,使用交叉驗(yàn)證的方式查看模型的穩(wěn)定性
  • 也可以使用隨機(jī)森林阁苞、GBDT等方法
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市祠挫,隨后出現(xiàn)的幾起案子那槽,更是在濱河造成了極大的恐慌,老刑警劉巖等舔,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骚灸,死亡現(xiàn)場離奇詭異,居然都是意外死亡慌植,警方通過查閱死者的電腦和手機(jī)甚牲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門义郑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丈钙,你說我怎么就攤上這事非驮。” “怎么了雏赦?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵劫笙,是天一觀的道長。 經(jīng)常有香客問我喉誊,道長邀摆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任伍茄,我火速辦了婚禮栋盹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘敷矫。我一直安慰自己例获,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布曹仗。 她就那樣靜靜地躺著榨汤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怎茫。 梳的紋絲不亂的頭發(fā)上收壕,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機(jī)與錄音轨蛤,去河邊找鬼蜜宪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛祥山,可吹牛的內(nèi)容都是我干的圃验。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼缝呕,長吁一口氣:“原來是場噩夢啊……” “哼澳窑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起供常,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤摊聋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后栈暇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體麻裁,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了悲立。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鹿寨。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖薪夕,靈堂內(nèi)的尸體忽然破棺而出脚草,到底是詐尸還是另有隱情,我是刑警寧澤原献,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布馏慨,位于F島的核電站,受9級特大地震影響姑隅,放射性物質(zhì)發(fā)生泄漏写隶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一讲仰、第九天 我趴在偏房一處隱蔽的房頂上張望慕趴。 院中可真熱鬧,春花似錦鄙陡、人聲如沸冕房。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耙册。三九已至,卻和暖如春毫捣,著一層夾襖步出監(jiān)牢的瞬間详拙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工蔓同, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饶辙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓牌柄,卻偏偏與公主長得像畸悬,于是被迫代替她去往敵國和親侧甫。 傳聞我的和親對象是個(gè)殘疾皇子珊佣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,898評論 2 89
  • 我很羨慕一些人的堅(jiān)持,可是他這么告訴我披粟,有些堅(jiān)持咒锻,只是因?yàn)樵?jīng)太不努力;后來守屉,我也竟然和他一樣惑艇,有的堅(jiān)持是曾經(jīng)太不...
    遺棄小屋閱讀 467評論 0 2
  • 它是調(diào)皮的.它在你面前出現(xiàn)的時(shí)候總是玩著隱身術(shù),它一靠近你,就會令你莫名其妙的大笑又或者大哭,等到你發(fā)覺它曾經(jīng)來過...
    真夏的素顏閱讀 230評論 -2 3
  • 今天的文章,來肅正一些不正之風(fēng)恭取。 首當(dāng)其沖的就是:【抑郁癥的人泰偿,究竟是怎樣的?】 每當(dāng)我發(fā)表一篇文章蜈垮,評論里總會冒...
    左燈右右右行閱讀 6,872評論 97 122
  • 我們每天都會有很多問題耗跛。為什么交通這么堵?為什么孩子不聽話攒发?為什么工作這么多调塌?為什么老板不待見我?為什么我每天都有...
    鄧男神Sweety閱讀 705評論 0 0