机器学习相关操作方法分享(一)

目录

1 数据简介及数据读取<br>2 数据清洗<br>3 探索性数据分析<br>  3.1 各部门团队的组成情况<br>  3.2 员工生产率分布情况<br>  3.3. 数据相关性分析<br>4 特征工程<br>5 预测员工生产率<br>  5.1 训练集测试集划分<br>  5.2 线性回归<br>  5.3 回归决策树<br>  5.4 Bagging回归<br>6 总结<br>

<div id="1"></div>

1 数据简介及数据读取

服装厂员工生产率数据集共包含1197行、15列,其中actual_productivity一列为我们最终需要进行预测的员工实际生产率,各字段类型和含义如下表所示:

date

字符型

日期 MM-DD-YYYY

quarter

字符型

每月第几周

department

字符型

部门

day

字符型

星期

team

整型

团队编号

targeted_productivity

浮点型

目标生产率

smv

浮点型

标准分钟值,任务分配的时间

wip

浮点型

在制品,包括产品未完成项的数量

over_time

整型

代表每个团队的超时时间,以分钟为单位

incentive

整型

激励特定行动的奖金

idle_time

浮点型

由于多种原因导致生产中断的时间

idle_men

整型

因生产中断而闲置的工人数

no_of_style_change

整型

特定产品风格的变化次数

no_of_workers

浮点型

每个团队的工人数量

actual_productivity

浮点型

工人交付的实际生产率百分比,取值范围是0-1

首先,我们使用Pandas库读取数据,并查看数据的基本信息。

import pandas as pd

import numpy as np

import seaborn as sns

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签

plt.rcParams['axes.unicode_minus']=False #用来正常显示负号

plt.rcParams['font.family'] = ['sans-serif']

import warnings

不显示警告

warnings.filterwarnings('ignore')

读取数据,查看数据前五行

garments = pd.read_csv('./input/garments_worker_productivity.csv')garments.loc[garments.department=='finishing ', 'department'] = 'finishing'garments.head()cols = [f for f in garments.columns if f not in ['date','quarter','department','day']]garments[cols].corr()garments.info()数据集共包含1197行、15列,其中datequarterdepartmentday字段数据类型为object,其余为数字类型。同时可以发现,wip一列存在缺失值。下面我们查看一下数据的基本统计信息:garments['quarter'].value_counts()garments.describe(include='all')从结果中可以看出actual_productivity实际生产率的最大值为1.120437,而该字段实际取值范围为0-1,后续我们会对其进行处理。<div id="2"></div>

2 数据清洗

在上一部分我们发现wip一列存在缺失值,在处理之前我们先计算一下缺失值的比例:

查看wip缺失值比例

round(garments.wip.isnull().sum()/len(garments.wip),2)wip中有42%的缺失值,由于占比较大,这里我们直接删去该字段。

删去wip这一列

garments.drop(columns=['wip'], inplace=True)接下来使用pd.to_datetime()函数将date一列数据类型改为日期类型,并将其设置为索引:

将日期转换为时间类型,设置为索引

garments.date = pd.to_datetime(garments.date)

garments.set_index(['date'],inplace=True)

查看日期范围

garments.index可以看到数据是从2015年1月1日到2015年3月11日期间收集的。我们根据日期在数据集中添加月份month一列:

添加月份

garments['month'] = garments.index.month_name().valuesgarments.head()从数据中发现,over_time每个团队的超时时间字段数值较大,这是由于该字段以分钟为单位,为了便于观察我们将单位转化为小时。

将超时时间over_time改为以小时为单位

garments['over_time'] = garments['over_time']/60garments.head()数据中team团队编号一列为数值型,而实际分析中应将其视为离散型变量,这里使用astype方法将其转为object

将团队编号team类型改为object

garments['team'] = garments['team'].astype('object')现在,我们开始分析数据中是否存在异常值,通过观察发现,department部门字段中的唯一值存在异常:

查看部门字段的唯一取值

garments['department'].value_counts()garments['department'].unique()garments.groupby(['department'])[['targeted_productivity','actual_productivity']].agg({'mean','max','min'})该字段的取值出现拼写错误及空格问题,我们将该列的取值进行统一:sewing为缝纫部门,finishing为精加工车间。

# 修改为finishing和sewing

garments['department'] = garments.department.apply(lambda x: 'finishing' if 'finishing' in x else 'sewing')

garments['department'].value_counts()

数据中缝纫部有691条记录,精加工车间有506条记录。最后,我们将actual_productivity实际生产率大于1的值统一为1。

将生产率大于1的设置为1

garments.actual_productivity = garments.actual_productivity.apply(lambda x: 1 if x>1 else x)

<div id="3"></div>

3 探索性数据分析

在这一部分,我们将结合可视化分析方法对数据进行初步的了解,首先查看各部门团队的组成情况,及记录数量的比例。<div id="3.1"></div>

3.1 各部门团队的组成情况

分组聚合统计各部门各个团队的记录数量

team = garments.groupby(['department','team'])['team'].count()teamgarments.groupby(['department','team'])[['targeted_productivity','actual_productivity']].agg({'mean','max','min'})team_c = round(garments.groupby(['department','team'])['no_of_workers'].mean())team_c

3.2 员工生产率分布情况

在分析完各部门团队组成之后,我们将一起来观察各部门生产率的分布情况。

设置颜色

my_colors = ["#F1B5B9", "#AAC8D1"]sns.set_palette( my_colors )

fig, ax =plt.subplots(figsize=(8,4))

dpt_g = garments.groupby('department')['actual_productivity']

sns.distplot(dpt_g.get_group('finishing'),label='精加工车间')sns.distplot(dpt_g.get_group('sweing'), label='缝纫部')

plt.title('各部门生产率分布情况',size=15)plt.legend()plt.xlabel('生产率', size=12)plt.ylabel('频次', size=12)

plt.show()两部门生产率整体均集中于0.6至1之间,同时较少员工生产率低于0.5。相比之下,缝纫部员工更多集中在0.8左右,精加工车间较多员工生产率接近于1,但整体分布较为分散。下面我们通过绘制箱线图,查看两部门各个团队生产率的分散情况。fig, ax =plt.subplots(figsize=(12,4))

sns.boxplot(x='team',y='actual_productivity',data=garments,hue='department')

plt.title('各团队生产率分散情况',size=15)plt.xlabel('团队编号', size=12)plt.ylabel('生产率', size=12)plt.legend(loc='lower left')

plt.show()从上图可知,缝纫部各团队生产率均比较集中,但同时存在较多生产率偏低的异常点。精加工车间中团队6和11生产率最分散,团队1-5、10、11和12生产率均较高。接着我们将探究不同时间对员工生产率的影响。fig, ax =plt.subplots(3,1,figsize=(8,10))

设置颜色

my_colors = ["#F1B5B9", "#AAC8D1"]sns.set_palette( my_colors )

sns.boxplot(x='day',y='actual_productivity',data=garments,hue='department', order=['Monday','Tuesday','Wednesday','Thursday','Saturday','Sunday'], ax=ax[0])sns.boxplot(x='quarter',y='actual_productivity',data=garments,hue='department', ax=ax[1])sns.boxplot(x='month',y='actual_productivity',data=garments,hue='department', ax=ax[2])

ax[0].set_title('不同星期对员工生产率的影响',size=15)ax[1].set_title('每月各周对员工生产率的影响',size=15)ax[2].set_title('不同月份对员工生产率的影响',size=15)

ax[0].legend(loc='lower right')ax[1].legend(loc='lower right')ax[2].legend(loc='lower right')

#设置默认的间距plt.tight_layout()plt.show()从上面三幅图可知,不同时间对员工生产率并无明显影响,仅在每月第五周两部门员工生产率略有提升。<div id="3.3"></div>

3.3 数据相关性分析

最后,我们使用数据中的连续型字段绘制相关系数矩阵热力图。import seaborn as snsimport matplotlib.pyplot as pltimport numpy as np

# 正常显示中文标签

plt.rcParams['font.sans-serif'] = ['SimHei']

# 正常显示负号

plt.rcParams['axes.unicode_minus'] = False

全局字体的大小设置

plt.rcParams.update({'font.size': 9})

计算相关系数

cols = [f for f in garments.columns if f not in ['quarter','department','day','month']]corr = garments[cols].corr()

fig = plt.figure(figsize=(7,7))

cmap = sns.diverging_palette(220,10,as_cmap=True)mask = np.zeros_like(corr)mask[np.triu_indices_from(mask)] = True

sns.heatmap(corr, annot=True, square=True,linewidths=1.5, cmap=cmap, mask=mask, center=0, cbar_kws={"shrink": .5})

plt.title("特征间的相关性",fontsize=15)

plt.show()从图中能够发现,no_of_workers每个团队的员工人数、smv任务分配时间及over_time每个团队超时时间之间有明显的正相关关系。此外,idle_time生产中断时间和idle_men因中断而闲置的工人数也存在较强的正相关性。<div id="4"></div>

4 特征工程

在这一部分,我们将进行特征工程。首先,对department进行数值编码,缝纫部sewing为1,精加工车间finishing为0。from sklearn.preprocessing import LacbelEncoder

le = LabelEncoder()garments['department'] = le.fit_transform(garments['department'])

garments.head()接下来,我们对数据集中的离散型变量进行独热编码。

添加特征

tmp_df = garments.groupby(['department','team'])[['actual_productivity','targeted_productivity','smv','incentive','over_time','idle_time','idle_men','no_of_style_change','no_of_workers']].agg({'mean','max','min'})tmp_df = tmp_df.reset_index()

tmp_df.columns = ['department','team'] + ['_'.join(f) for f in tmp_df.columns if f[0] not in ['department','team']]tmp_df.head()garments = garments.merge(tmp_df, on=['department','team'], how='left')garments = pd.get_dummies(garments)garments.head()<div id="5"></div>

5 预测员工生产率

<div id="5.1"></div>

5.1 训练集测试集划分

在训练模型之前,我们先将训练集测试集按照4:1进行划分,并将特征进行Z-Score标准化处理。from sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import StandardScaler

X=garments.drop(['actual_productivity'], axis=1)y=garments['actual_productivity']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)

数据标准化

s = StandardScaler()

X_train_sm = s.fit_transform(X_train)

X_test_sm = s.transform(X_test)

X_train_sm = X_trainX_test_sm = X_test<div id="5.2"></div>

5.2 线性回归

首先,在训练集上训练线性回归模型,并在测试集上进行预测和评估,输出决定系数R2和均方误差:from sklearn.linear_model import LinearRegressionfrom sklearn.metrics import r2_score,mean_squared_error

mlr = LinearRegression()mlr.fit(X_train_sm, y_train)y_pred_sm = mlr.predict(X_test_sm)

print(f'R2 为 {round(r2_score(y_test,y_pred_sm),4)}')print('均方误差 (MSE): %.4f' % mean_squared_error(y_test, y_pred_sm))

可视化

plt.figure(figsize=(6, 4))

plt.scatter(x=y_test,y=y_pred_sm, alpha=.5)

plt.xlabel('实际值')plt.ylabel('预测值')plt.title('实际值预测值对比',size=15)

plt.show()from sklearn.linear_model import LinearRegression, Ridgefrom sklearn.metrics import r2_score,mean_squared_error

mlr = Ridge()mlr.fit(X_train_sm, y_train)y_pred_sm = mlr.predict(X_test_sm)

print(f'R2 为 {round(r2_score(y_test,y_pred_sm),4)}')print('均方误差 (MSE): %.4f' % mean_squared_error(y_test, y_pred_sm))

可视化

plt.figure(figsize=(6, 4))

plt.scatter(x=y_test,y=y_pred_sm, alpha=.5)

plt.xlabel('实际值')plt.ylabel('预测值')plt.title('实际值预测值对比',size=15)

plt.show()决定系数仅为0.19,模型预测效果较差。<div id="5.3"></div>

5.3 回归决策树

接下来我们尝试构建回归决策树模型,设置树的最大深度为10:from sklearn.model_selection import KFoldfrom sklearn.tree import DecisionTreeRegressor

skf = KFold(n_splits=5, shuffle=True, random_state=2021)for train_index, test_index in skf.split(X,y):

dtreg = DecisionTreeRegressor(max_depth=10,random_state=0)

dtreg.fit(X.loc[train_index], y[train_index])

y_pred = dtreg.predict(X.loc[test_index])

print(f'R2 为 {round(r2_score(y[test_index],y_pred),4)}')
print('均方误差 (MSE): %.4f' % mean_squared_error(y[test_index], y_pred))

使用回归决策树

from sklearn.tree import DecisionTreeRegressorfrom sklearn import tree

dtreg = DecisionTreeRegressor(max_depth=10,random_state=0)

dtreg.fit(X_train_sm, y_train)

y_pred_sm = dtreg.predict(X_test_sm)

print(f'R2 为 {round(r2_score(y_test,y_pred_sm),4)}')print('均方误差 (MSE): %.4f' % mean_squared_error(y_test, y_pred_sm))

可视化

plt.figure(figsize=(6, 4))

plt.scatter(x=y_test, y=y_pred_sm, alpha=.5)

plt.xlabel('实际值')plt.ylabel('预测值')plt.title('实际值预测值对比',size=15)

plt.show()模型在测试集上决定系数R2为0.43,均方误差 (MSE)为 0.02,预测效果略有提高。<div id="5.4"></div>

5.4 Bagging回归

最后使用BaggingRegressor构建模型,我们使用回归决策树作为基模型。from sklearn.ensemble import BaggingRegressorfrom sklearn import tree

br = BaggingRegressor(n_estimators=800, random_state=11)

br.fit(X_train_sm, y_train)

y_pred_sm = br.predict(X_test_sm)

print(f'R2 为 {round(r2_score(y_test,y_pred_sm),4)}')print('均方误差 (MSE): %.4f' % mean_squared_error(y_test, y_pred_sm))

可视化

plt.figure(figsize=(6, 4))

plt.scatter(x=y_test,y=y_pred_sm, alpha=.5)

plt.xlabel('实际值')plt.ylabel('预测值')plt.title('实际值预测值对比',size=15)

plt.show()最终R2提升到了0.5052,均方误差为0.0155。<div id="6"></div>

6 总结

本案例我们使用了服装厂员工生产效率数据集,结合可视化分析方法探索了数据中隐藏的信息,并通过建立线性回归、回归决策树和Bagging回归三种模型预测员工实际生产率。

全部评论

相关推荐

亲切的00后在笔试:我也遇到了,所以我早他一步查看图片
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务