小言_互联网的博客

数据挖掘算法和实践(二十一):kaggle经典-职场离职率分析案例解读

422人阅读  评论(0)

本节使用kaggle经典数案例一起学习数据挖掘流程和工具使用,使用决策树和随机森林预测员工离职率,帮助人事部门理解员工为何离职, 预测员工离职的可能性,数据来源: kaggle数据集地址

使用jupyterlab,能够保存中间结果并且流程较清晰,小数据集可以考虑使用,但从模块化思想来看可以用VsCode和其他工具,一如既往首先引入需要的包,这里plot和seaborn都引入了,plot更偏底层可以定制化作图,seaborn作图更方便和炫酷但定制化作图能力弱,想了解seaborn作图包可以参照之前的博客: 数据挖掘算法和实践(六):seaborn数据可视化探索(tips 数据集)

一、数据导入

这里读取本地文件,该数据集较小,只有14999条数据,包含10个特征属性,最后left列为标签;


  
  1. import pandas as pd
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. import matplotlib as matplot
  5. import seaborn as sns
  6. %matplotlib inline
  7. # 读入数据到Pandas Dataframe "df"
  8. df = pd.read_csv( 'HR_comma_sep.csv', index_col= None)

二、数据预处理

1、数据探索

将数据读取到pandas.dataframe容器后,用提供的shape,dtypes,head(),isnull(),describe()观察数据类型和分布,发现14999×10数列不存在空值,第1步把字段名称修改为自己熟悉或者可以接受的字段名称,这里把是否离职放在第一列了;


  
  1. # 共14999个样本,每一个样本中包含10个特征
  2. df.shape
  3. # 特征数据类型.
  4. df.dtypes
  5. # 检测是否有缺失数据
  6. df.isnull().any()
  7. # 数据的样例
  8. df.head()
  9. # 整数数据分布描述
  10. df.describe()
  11. # 重命名
  12. df = df.rename(columns={ 'satisfaction_level': 'satisfaction',
  13. 'last_evaluation': 'evaluation',
  14. 'number_project': 'projectCount',
  15. 'average_montly_hours': 'averageMonthlyHours',
  16. 'time_spend_company': 'yearsAtCompany',
  17. 'Work_accident': 'workAccident',
  18. 'promotion_last_5years': 'promotion',
  19. 'sales' : 'department',
  20. 'left' : 'turnover'
  21. })
  22. # 将预测标签‘是否离职’放在第一列
  23. front = df[ 'turnover']
  24. df.drop(labels=[ 'turnover'], axis= 1, inplace = True)
  25. df.insert( 0, 'turnover', front)
  26. df.head()

第1步可以算是数据探索,下一步就是牵扯到业务逻辑的探索,比如探究离职率、离职或不离职的其他属性的平均值情况;


  
  1. # 离职率
  2. turnover_rate = df.turnover.value_counts() / len(df)
  3. turnover_rate
  4. # 离职或者不离职的人其他特征的一些平均数据统计
  5. turnover_Summary = df.groupby( 'turnover')
  6. turnover_Summary.mean()

2、相关性分析

更进一步,考察特征属性间的相关性,相关性分析能够做到特征规约和整合,即多个特征可以合并,或者被舍弃;


  
  1. # 相关性矩阵
  2. corr = df.corr()
  3. sns.heatmap(corr,
  4. xticklabels=corr.columns.values,
  5. yticklabels=corr.columns.values)
  6. corr

正相关的特征:

  • projectCount VS evaluation: 0.349333
  • projectCount VS averageMonthlyHours: 0.417211
  • averageMonthlyHours VS evaluation: 0.339742

负相关的特征:

  • satisfaction VS turnover: -0.388375

思考:

  • 什么特征的影响最大?
  • 什么特征之间相关性最大?

3、单变量探索

满意度字段:未离职员工满意度: 0.666809590479524,离职员工满意度: 0.4400980117614114;


  
  1. # 比较离职和未离职员工的满意度
  2. emp_population = df[ 'satisfaction'][df[ 'turnover'] == 0].mean()
  3. emp_turnover_satisfaction = df[df[ 'turnover']== 1][ 'satisfaction'].mean()
  4. print( '未离职员工满意度: ' + str(emp_population))
  5. print( '离职员工满意度: ' + str(emp_turnover_satisfaction) )

满意度的T-test,查看p值;T-Test 显示pvalue (0)非常小, 所以他们之间是显著不同的;


  
  1. import scipy.stats as stats
  2. # 满意度的t-Test
  3. stats.ttest_1samp(a = df[df[ 'turnover']== 1][ 'satisfaction'], # 离职员工的满意度样本
  4. popmean = emp_population) # 未离职员工的满意度均值
  5. degree_freedom = len(df[df[ 'turnover']== 1])
  6. # 临界值
  7. LQ = stats.t.ppf( 0.025,degree_freedom) # 95%致信区间的左边界
  8. RQ = stats.t.ppf( 0.975,degree_freedom) # 95%致信区间的右边界
  9. print ( 'The t-分布 左边界: ' + str(LQ))
  10. print ( 'The t-分布 右边界: ' + str(RQ))
  11. # 工作评价的概率密度函数估计
  12. fig = plt.figure(figsize=( 15, 4),)
  13. ax=sns.kdeplot(df.loc[(df[ 'turnover'] == 0), 'evaluation'] , color= 'b',shade= True,label= 'no turnover')
  14. ax=sns.kdeplot(df.loc[(df[ 'turnover'] == 1), 'evaluation'] , color= 'r',shade= True, label= 'turnover')
  15. ax.set(xlabel= '工作评价', ylabel= '频率')
  16. plt.title( '工作评价的概率密度函数 - 离职 V.S. 未离职')


  
  1. # 月平均工作时长概率密度函数估计
  2. fig = plt.figure(figsize=( 15, 4))
  3. ax=sns.kdeplot(df.loc[(df[ 'turnover'] == 0), 'averageMonthlyHours'] , color= 'b',shade= True, label= 'no turnover')
  4. ax=sns.kdeplot(df.loc[(df[ 'turnover'] == 1), 'averageMonthlyHours'] , color= 'r',shade= True, label= 'turnover')
  5. ax.set(xlabel= '月工作时长(时)', ylabel= '频率')
  6. plt.title( '月工作时长(时) - 离职 V.S. 未离职')
  7. # 员工满意度概率密度函数估计
  8. fig = plt.figure(figsize=( 15, 4))
  9. ax=sns.kdeplot(df.loc[(df[ 'turnover'] == 0), 'satisfaction'] , color= 'b',shade= True, label= 'no turnover')
  10. ax=sns.kdeplot(df.loc[(df[ 'turnover'] == 1), 'satisfaction'] , color= 'r',shade= True, label= 'turnover')
  11. plt.title( '员工满意度 - 离职 V.S. 未离职')

三、建模和评估

 


  
  1. from sklearn.preprocessing import LabelEncoder
  2. from sklearn.model_selection import train_test_split
  3. from sklearn.metrics import accuracy_score, classification_report, precision_score, recall_score, confusion_matrix, precision_recall_curve
  4. # 将string类型转换为整数类型
  5. df[ "department"] = df[ "department"].astype( 'category').cat.codes
  6. df[ "salary"] = df[ "salary"].astype( 'category').cat.codes
  7. # 产生X, y,即特征值与目标值
  8. target_name = 'turnover'
  9. X = df.drop( 'turnover', axis= 1)
  10. y = df[target_name]
  11. # 将数据分为训练和测试数据集
  12. # 注意参数 stratify = y 意味着在产生训练和测试数据中, 离职的员工的百分比等于原来总的数据中的离职的员工的百分比
  13. X_train, X_test, y_train, y_test = train_test_split(
  14. X, y, test_size= 0.15, random_state= 123, stratify=y)
  15. # 显示前5行数据
  16. df.head()

四、决策树和随机森林Decision Tree V.S. Random Forest

1、决策树和可视化


  
  1. from sklearn.metrics import roc_auc_score
  2. from sklearn.metrics import classification_report
  3. from sklearn.ensemble import RandomForestClassifier
  4. from sklearn import tree
  5. from sklearn.tree import DecisionTreeClassifier
  6. from sklearn.tree import export_graphviz
  7. from sklearn.externals.six import StringIO
  8. from IPython.display import Image
  9. import pydotplus
  10. # 实例化
  11. dtree = tree.DecisionTreeClassifier(
  12. criterion= 'entropy',
  13. #max_depth=3, # 定义树的深度, 可以用来防止过拟合
  14. min_weight_fraction_leaf= 0.01 # 定义叶子节点最少需要包含多少个样本(使用百分比表达), 防止过拟合
  15. )
  16. # 训练
  17. dtree = dtree.fit(X_train,y_train)
  18. # 指标计算
  19. dt_roc_auc = roc_auc_score(y_test, dtree.predict(X_test))
  20. print ( "决策树 AUC = %2.2f" % dt_roc_auc)
  21. print(classification_report(y_test, dtree.predict(X_test)))
  22. # 需安装GraphViz和pydotplus进行决策树的可视化
  23. # 特征向量
  24. feature_names = df.columns[ 1:]
  25. # 文件缓存
  26. dot_data = StringIO()
  27. # 将决策树导入到dot中
  28. export_graphviz(dtree, out_file=dot_data,
  29. filled= True, rounded= True,
  30. special_characters= True,feature_names = feature_names,class_names=[ '0', '1'])
  31. # 将生成的dot文件生成graph
  32. graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
  33. # 将结果存入到png文件中
  34. graph.write_png( 'diabetes.png')
  35. # 显示
  36. Image(graph.create_png())

决策树的特征重要性分析


  
  1. # 获取特征重要性
  2. importances = dtree.feature_importances_
  3. # 获取特征名称
  4. feat_names = df.drop([ 'turnover'],axis= 1).columns
  5. # 排序
  6. indices = np.argsort(importances)[:: -1]
  7. # 绘图
  8. plt.figure(figsize=( 12, 6))
  9. plt.title( "Feature importances by Decision Tree")
  10. plt.bar(range(len(indices)), importances[indices], color= 'lightblue', align= "center")
  11. plt.step(range(len(indices)), np.cumsum(importances[indices]), where= 'mid', label= 'Cumulative')
  12. plt.xticks(range(len(indices)), feat_names[indices], rotation= 'vertical',fontsize= 14)
  13. plt.xlim([ -1, len(indices)])
  14. plt.show()

2、随机森林和可视化


  
  1. # 实例化随机森林
  2. rf = RandomForestClassifier(
  3. criterion= 'entropy',
  4. n_estimators= 3,
  5. max_depth= None, # 定义树的深度, 可以用来防止过拟合
  6. min_samples_split= 10, # 定义至少多少个样本的情况下才继续分叉
  7. #min_weight_fraction_leaf=0.02 # 定义叶子节点最少需要包含多少个样本(使用百分比表达), 防止过拟合
  8. )
  9. # 模型训练
  10. rf.fit(X_train, y_train)
  11. # 计算指标参数
  12. rf_roc_auc = roc_auc_score(y_test, rf.predict(X_test))
  13. print ( "随机森林 AUC = %2.2f" % rf_roc_auc)
  14. print(classification_report(y_test, rf.predict(X_test)))
  15. # Graphviz中未提供多棵树的绘制方法,所以我们遍历森林中的树,分别进行绘制
  16. Estimators = rf.estimators_
  17. # 遍历
  18. for index, model in enumerate(Estimators):
  19. # 文件缓存
  20. dot_data = StringIO()
  21. # 将决策树导入到dot_data中
  22. export_graphviz(model , out_file=dot_data,
  23. feature_names=df.columns[ 1:],
  24. class_names=[ '0', '1'],
  25. filled= True, rounded= True,
  26. special_characters= True)
  27. # 从数据中生成graph
  28. graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
  29. # 将结果写入到png文件中
  30. graph.write_png( 'Rf{}.png'.format(index))
  31. # 绘制图像
  32. plt.figure(figsize = ( 20, 20))
  33. plt.imshow(plt.imread( 'Rf{}.png'.format(index)))
  34. plt.axis( 'off')

 


  
  1. # 特征的重要程度
  2. importances = rf.feature_importances_
  3. # 特征名称
  4. feat_names = df.drop([ 'turnover'],axis= 1).columns
  5. # 排序
  6. indices = np.argsort(importances)[:: -1]
  7. # 绘图
  8. plt.figure(figsize=( 12, 6))
  9. plt.title( "Feature importances by RandomForest")
  10. plt.bar(range(len(indices)), importances[indices], color= 'lightblue', align= "center")
  11. plt.step(range(len(indices)), np.cumsum(importances[indices]), where= 'mid', label= 'Cumulative')
  12. plt.xticks(range(len(indices)), feat_names[indices], rotation= 'vertical',fontsize= 14)
  13. plt.xlim([ -1, len(indices)])
  14. plt.show()

 

3、ROC曲线


  
  1. # ROC 图
  2. from sklearn.metrics import roc_curve
  3. # 计算ROC曲线
  4. rf_fpr, rf_tpr, rf_thresholds = roc_curve(y_test, rf.predict_proba(X_test)[:, 1])
  5. dt_fpr, dt_tpr, dt_thresholds = roc_curve(y_test, dtree.predict_proba(X_test)[:, 1])
  6. plt.figure()
  7. # 随机森林 ROC
  8. plt.plot(rf_fpr, rf_tpr, label= 'Random Forest (area = %0.2f)' % rf_roc_auc)
  9. # 决策树 ROC
  10. plt.plot(dt_fpr, dt_tpr, label= 'Decision Tree (area = %0.2f)' % dt_roc_auc)
  11. # 绘图
  12. plt.xlim([ 0.0, 1.0])
  13. plt.ylim([ 0.0, 1.05])
  14. plt.xlabel( 'False Positive Rate')
  15. plt.ylabel( 'True Positive Rate')
  16. plt.title( 'ROC Graph')
  17. plt.legend(loc= "lower right")
  18. plt.show()

 


转载:https://blog.csdn.net/yezonggang/article/details/112851271
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场