1 简介
制造业是国民经济的主体,近十年来,嫦娥探月、祝融探火、北斗组网,一大批重大标志性创新成果引领中国制造业不断攀上新高度。作为制造业的核心,机械设备在工业生产的各个环节都扮演着不可或缺的重要角色。但是,在机械设备运转过程中会产生不可避免的磨损、老化等问题,随着损耗的增加,会导致各种故障的发生,影响生产质量和效率。
实际生产中,若能根据机械设备的使用情况,提前预测潜在的故障风险,精准地进行检修维护,维持机械设备稳定运转,不但能够确保整体工业环境运行具备稳定性,也能切实帮助企业提高经济效益。
某企业机械设备的使用情况及故障发生情况数据见“train data.xlsx”,用于设备故障预测及故障主要相关因素的探究。数据包含 9000 行,每一行数据记录了机械设备对应的运转及故障发生情况记录。因机械设备在使用环境以及工作强度上存在较大差异,其所需的维护频率和检修问题也通常有所不同。
数据提供了实际生产中常见的机械设备使用环境和工作强度等指标,包含不同设备所处厂房的室温(单位为开尔文K),其工作时的机器温度(单位为开尔文K)、转速(单位为每分钟的旋转次数rpm)、扭矩(单位为牛米Nm)及机器运转时长(单位为分钟min)。除此之外,还提供了机械设备的统一规范代码、质量等级及在该企业中的机器编号,其中质量等级分为高、中、低(H\M\L)三个等级。对于机械设备的故障情况,数据提供了两列数据描述——“是否发生故障” 和“具体故障类别”。其中“是否发生故障”取值为 0/1,0 代表设备正常运转,1 代 表设备发生故障;“具体故障类别”包含 6 种情况,分别是NORMAL、TWF、HDF、PWF、OSF、RNF,其中,NORMAL代表设别正常运转(与是否发生故障”为 0相对应),其余代码代表的是发生故障的类别,包含 5 种,其中TWF代表磨损故障,HDF代表散热故障,PWF代表电力故障,OSF代表过载故障,RNF代表其他故障。
2 需要解决的问题
基于赛题提供的数据,自主查阅资料,选择合适的方法完成如下任务:
任务 1:观察数据“train data.xlsx”,自主进行数据预处理,选择合适的指标用于机械设备故障的预测并说明原因。
任务 2:设计开发模型用于判别机械设备是否发生故障,自主选取评价方式和评价指标评估模型表现。
3 Python代码实现
'''~~~~~~~~~~~~~~~~~~任务1~~~~~~~~~~~~~~~~~''' '''1 读取数据''' import pandas as pd shuju=pd.read_excel('train_data.xlsx') print(shuju.head(10)) #======查看数据基本信息=============== print(shuju.info()) #看起来是没有缺失值的,再用isnull来查看一下是否又缺失值: print(shuju.isnull().sum()) #查看数据有哪些特征: print(shuju.columns) shuju2=shuju.drop(['机器编号', '统一规范代码','具体故障类别'],axis=1) print(shuju2.head()) '''2 数据预处理''' #(1)机器质量等级,这个特征属于离散变量而且是字符型,所以需要进行编码处理。先查看这一列有多少等级: print(shuju2['机器质量等级'].unique()) #unique():返回参数数组中所有不同的值,并按照从小到大排序 #通过映射的方式对它们进行编码: mapping = { 'L': 3, 'M': 2, 'H': 1} shuju2['机器质量等级'] =shuju2['机器质量等级'].map(mapping) print(shuju2.head()) '''~~~~~~~~~~~~~~~~~~任务2~~~~~~~~~~~~~~~~~~~~~~~~~~~''' #建议使用独热编码,独热编码很适合用来解决类别型数据的离散值问题。 shuju3=pd.get_dummies(shuju2,columns=['机器质量等级']) print(shuju3.head()) #====(2)查看类的分布,解决不平衡问题=========== df1=shuju3['是否发生故障'].value_counts() print(df1) #可以看出有明显的类不平衡问题,等会需要解决它 #===(3)提取自变量和因变量:======== X = shuju3.drop('是否发生故障',axis=1)# 特征 y = shuju3['是否发生故障'] # 目标变量 print(X) #执行欠采样技术,解决类不平衡的问题: # 欠采样 from collections import Counter from imblearn.under_sampling import ClusterCentroids cc = ClusterCentroids(random_state=2022) X_resampled, y_resampled = cc.fit_resample(X, y) print(sorted(Counter(y_resampled).items())) #=====(4)分割数据:===== from sklearn.model_selection import train_test_split X_train,X_test,y_train,y_test=train_test_split(X_resampled,y_resampled,test_size=0.2,random_state=100) #=====(5)使用逻辑回归模型预测======= # 导入模型 from sklearn.linear_model import LogisticRegression # 初始化模型,使用默认参数 logreg = LogisticRegression() # 用数据训练模型 logreg.fit(X_train,y_train) # 使用模型预测 y_pred=logreg.predict(X_test) print(y_pred) #评估: from sklearn import metrics print("Accuracy:",metrics.accuracy_score(y_test, y_pred)) #准确率 print("Precision:",metrics.precision_score(y_test, y_pred)) #查准率 print("Recall:",metrics.recall_score(y_test, y_pred)) #召回率 #====(6)使用决策树模型预测======= from sklearn.tree import DecisionTreeClassifier # 导入决策树 # 选择基尼系数作为判断标准,树深度为3 clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=3, random_state=0) clf_gini.fit(X_train, y_train) #训练模型 y_pred_gini = clf_gini.predict(X_test) # 预测模型 print(y_pred_gini[0:5]) # 预测前五个结果 #评估: from sklearn import metrics print("Accuracy:",metrics.accuracy_score(y_test, y_pred_gini)) print("Precision:",metrics.precision_score(y_test, y_pred_gini)) print("Recall:",metrics.recall_score(y_test, y_pred_gini)) #可视化一下: import matplotlib.pyplot as plt plt.figure(figsize=(12,8)) from sklearn import tree tree.plot_tree(clf_gini.fit(X_train, y_train)) plt.show() #可视化混淆矩阵: # 可视化混淆矩阵 from sklearn.metrics import plot_confusion_matrix plot_confusion_matrix(clf_gini , X_test, y_test) plt.show() #这个结果好吗?不,我们来寻优找到最佳参数。 #========(7)寻优找到最佳参数========== #~~~1)确定max_depth最优~~~~~ ## 确定最佳深度 import numpy as np from sklearn.tree import DecisionTreeClassifier # 导入决策树 score_all=[] # range(start, stop[, step]) for i in range(1,100,1): # 选择基尼系数作为判断标准,树深度为3 clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=i, random_state=0) clf_gini.fit(X_train, y_train) #训练模型 y_pred_gini = clf_gini.predict(X_test) # 预测模型 y_pred_gini[0:5] # 预测前五个结果 from sklearn.metrics import accuracy_score acc=accuracy_score(y_test, y_pred_gini) # print(acc) score_all.append([i,acc]) ScoreAll = np.array(score_all) max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] #找出最高得分对应的索引 print("最优参数以及最高得分:",ScoreAll[max_score]) plt.figure(figsize=[20,5]) plt.plot(ScoreAll[:,0],ScoreAll[:,1]) plt.show() #~~~~~~2)确定min_samples_split最优~~~~~~~ # 分割内部节点所需的最小样本数 ## 确定最佳深度max_depth import numpy as np import matplotlib.pyplot as plt from sklearn.tree import DecisionTreeClassifier # 导入决策树 score_all=[] # range(start, stop[, step]) # 带入最佳深度后,再遍历2到20的内部最小样本数 for i in range(2,20,1): # 选择基尼系数作为判断标准,树深度为3 clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=9, min_samples_split=i,random_state=0) clf_gini.fit(X_train, y_train) #训练模型 y_pred_gini = clf_gini.predict(X_test) # 预测模型 y_pred_gini[0:5] # 预测前五个结果 from sklearn.metrics import accuracy_score acc=accuracy_score(y_test, y_pred_gini) # print(acc) score_all.append([i,acc]) ScoreAll = np.array(score_all) max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] #找出最高得分对应的索引 print("最优参数以及最高得分:",ScoreAll[max_score]) plt.figure(figsize=[20,5]) plt.plot(ScoreAll[:,0],ScoreAll[:,1]) plt.show() # 结果显示默认的2就是最佳 #~~~~~~~~3)确定min_samples_leaf参数~~~~~~~~~~~~~ # 确定 # 分割内部节点所需的最小样本数min_samples_split ## 确定最佳深度max_depth import numpy as np import matplotlib.pyplot as plt from sklearn.tree import DecisionTreeClassifier # 导入决策树 score_all=[] # range(start, stop[, step]) # 带入最佳深度=12,min_samples_split=2,遍历min_samples_leaf = i for i in range(1,20,1): # 选择基尼系数作为判断标准,树深度为3 clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=9, min_samples_split=5,min_samples_leaf = i,random_state=0) clf_gini.fit(X_train, y_train) #训练模型 y_pred_gini = clf_gini.predict(X_test) # 预测模型 y_pred_gini[0:5] # 预测前五个结果 from sklearn.metrics import accuracy_score acc=accuracy_score(y_test, y_pred_gini) score_all.append([i,acc]) ScoreAll = np.array(score_all) max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] #找出最高得分对应的索引 print("最优参数以及最高得分:",ScoreAll[max_score]) plt.figure(figsize=[20,5]) plt.plot(ScoreAll[:,0],ScoreAll[:,1]) plt.show() # 最佳参数还是2 '''根据我们前边的一系列操作,我们确定因为max_depth在9附近,min_samples_split在5附近, min_samples_leaf在2附近是最优参数,所以我们分别在这个附近利用网格搜索得到最优参数。 因为要涉及到三个参数联调,这里就要用到网格搜索函数。代码如下:''' # 网格搜索确定内联最佳 from sklearn.model_selection import GridSearchCV param_grid = { 'max_depth':np.arange(6, 12), 'min_samples_leaf':np.arange(3, 7), 'min_samples_split':np.arange(1, 4)} rfc = DecisionTreeClassifier(random_state=66) GS = GridSearchCV(rfc,param_grid,cv=10) GS.fit(X_train, y_train) print(GS.best_params_) print(GS.best_score_) #这里三个参数和我们前边所暂定的参数都不一样。证明三者之间确实是相互影响的。最终确定还是选取开始的三个。 #从而得到最佳参数:‘max_depth’: 6, ‘min_samples_leaf’: 5, ‘min_samples_split’: 2},此时准确率为0.983460884353741
'''1 读取数据''' import pandas as pd shuju=pd.read_excel('train_data.xlsx') print(shuju.head(10)) #======查看数据基本信息=============== print(shuju.info()) #看起来是没有缺失值的,再用isnull来查看一下是否又缺失值: print(shuju.isnull().sum()) #查看数据有哪些特征: print(shuju.columns) shuju2=shuju.drop(['机器编号', '统一规范代码','具体故障类别'],axis=1) print(shuju2.head()) '''2 数据预处理''' #(1)机器质量等级,这个特征属于离散变量而且是字符型,所以需要进行编码处理。先查看这一列有多少等级: print(shuju2['机器质量等级'].unique()) #unique():返回参数数组中所有不同的值,并按照从小到大排序 #通过映射的方式对它们进行编码: mapping = { 'L': 3, 'M': 2, 'H': 1} shuju2['机器质量等级'] =shuju2['机器质量等级'].map(mapping) print(shuju2.head()) '''~~~~~~~~~~~~~~~~~~任务2~~~~~~~~~~~~~~~~~~~~~~~~~~~''' #建议使用独热编码,独热编码很适合用来解决类别型数据的离散值问题。 shuju3=pd.get_dummies(shuju2,columns=['机器质量等级']) print(shuju3.head()) #====(2)查看类的分布,解决不平衡问题=========== df1=shuju3['是否发生故障'].value_counts() print(df1) #可以看出有明显的类不平衡问题,等会需要解决它 #===(3)提取自变量和因变量:======== X = shuju3.drop('是否发生故障',axis=1)# 特征 y = shuju3['是否发生故障'] # 目标变量 print(X) #执行欠采样技术,解决类不平衡的问题: # 欠采样 from collections import Counter from imblearn.under_sampling import ClusterCentroids cc = ClusterCentroids(random_state=2022) X_resampled, y_resampled = cc.fit_resample(X, y) print(sorted(Counter(y_resampled).items())) #=====(4)分割数据:===== from sklearn.model_selection import train_test_split X_train,X_test,y_train,y_test=train_test_split(X_resampled,y_resampled,test_size=0.2,random_state=100) #=====(5)使用逻辑回归模型预测======= # 导入模型 from sklearn.linear_model import LogisticRegression # 初始化模型,使用默认参数 logreg = LogisticRegression() # 用数据训练模型 logreg.fit(X_train,y_train) # 使用模型预测 y_pred=logreg.predict(X_test) print(y_pred) #评估: from sklearn import metrics print("Accuracy:",metrics.accuracy_score(y_test, y_pred)) #准确率 print("Precision:",metrics.precision_score(y_test, y_pred)) #查准率 print("Recall:",metrics.recall_score(y_test, y_pred)) #召回率 #====(6)使用决策树模型预测======= from sklearn.tree import DecisionTreeClassifier # 导入决策树 # 选择基尼系数作为判断标准,树深度为3 clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=3, random_state=0) clf_gini.fit(X_train, y_train) #训练模型 y_pred_gini = clf_gini.predict(X_test) # 预测模型 print(y_pred_gini[0:5]) # 预测前五个结果 #评估: from sklearn import metrics print("Accuracy:",metrics.accuracy_score(y_test, y_pred_gini)) print("Precision:",metrics.precision_score(y_test, y_pred_gini)) print("Recall:",metrics.recall_score(y_test, y_pred_gini)) #可视化一下: import matplotlib.pyplot as plt plt.figure(figsize=(12,8)) from sklearn import tree tree.plot_tree(clf_gini.fit(X_train, y_train)) plt.show() #可视化混淆矩阵: # 可视化混淆矩阵 from sklearn.metrics import plot_confusion_matrix plot_confusion_matrix(clf_gini , X_test, y_test) plt.show() #这个结果好吗?不,我们来寻优找到最佳参数。 #========(7)寻优找到最佳参数========== #~~~1)确定max_depth最优~~~~~ ## 确定最佳深度 import numpy as np from sklearn.tree import DecisionTreeClassifier # 导入决策树 score_all=[] # range(start, stop[, step]) for i in range(1,100,1): # 选择基尼系数作为判断标准,树深度为3 clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=i, random_state=0) clf_gini.fit(X_train, y_train) #训练模型 y_pred_gini = clf_gini.predict(X_test) # 预测模型 y_pred_gini[0:5] # 预测前五个结果 from sklearn.metrics import accuracy_score acc=accuracy_score(y_test, y_pred_gini) # print(acc) score_all.append([i,acc]) ScoreAll = np.array(score_all) max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] #找出最高得分对应的索引 print("最优参数以及最高得分:",ScoreAll[max_score]) plt.figure(figsize=[20,5]) plt.plot(ScoreAll[:,0],ScoreAll[:,1]) plt.show() #~~~~~~2)确定min_samples_split最优~~~~~~~ # 分割内部节点所需的最小样本数 ## 确定最佳深度max_depth import numpy as np import matplotlib.pyplot as plt from sklearn.tree import DecisionTreeClassifier # 导入决策树 score_all=[] # range(start, stop[, step]) # 带入最佳深度后,再遍历2到20的内部最小样本数 for i in range(2,20,1): # 选择基尼系数作为判断标准,树深度为3 clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=9, min_samples_split=i,random_state=0) clf_gini.fit(X_train, y_train) #训练模型 y_pred_gini = clf_gini.predict(X_test) # 预测模型 y_pred_gini[0:5] # 预测前五个结果 from sklearn.metrics import accuracy_score acc=accuracy_score(y_test, y_pred_gini) # print(acc) score_all.append([i,acc]) ScoreAll = np.array(score_all) max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] #找出最高得分对应的索引 print("最优参数以及最高得分:",ScoreAll[max_score]) plt.figure(figsize=[20,5]) plt.plot(ScoreAll[:,0],ScoreAll[:,1]) plt.show() # 结果显示默认的2就是最佳 #~~~~~~~~3)确定min_samples_leaf参数~~~~~~~~~~~~~ # 确定 # 分割内部节点所需的最小样本数min_samples_split ## 确定最佳深度max_depth import numpy as np import matplotlib.pyplot as plt from sklearn.tree import DecisionTreeClassifier # 导入决策树 score_all=[] # range(start, stop[, step]) # 带入最佳深度=12,min_samples_split=2,遍历min_samples_leaf = i for i in range(1,20,1): # 选择基尼系数作为判断标准,树深度为3 clf_gini = DecisionTreeClassifier(criterion='gini', max_depth=9, min_samples_split=5,min_samples_leaf = i,random_state=0) clf_gini.fit(X_train, y_train) #训练模型 y_pred_gini = clf_gini.predict(X_test) # 预测模型 y_pred_gini[0:5] # 预测前五个结果 from sklearn.metrics import accuracy_score acc=accuracy_score(y_test, y_pred_gini) score_all.append([i,acc]) ScoreAll = np.array(score_all) max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] #找出最高得分对应的索引 print("最优参数以及最高得分:",ScoreAll[max_score]) plt.figure(figsize=[20,5]) plt.plot(ScoreAll[:,0],ScoreAll[:,1]) plt.show() # 最佳参数还是2 '''根据我们前边的一系列操作,我们确定因为max_depth在9附近,min_samples_split在5附近, min_samples_leaf在2附近是最优参数,所以我们分别在这个附近利用网格搜索得到最优参数。 因为要涉及到三个参数联调,这里就要用到网格搜索函数。代码如下:''' # 网格搜索确定内联最佳 from sklearn.model_selection import GridSearchCV param_grid = { 'max_depth':np.arange(6, 12), 'min_samples_leaf':np.arange(3, 7), 'min_samples_split':np.arange(1, 4)} rfc = DecisionTreeClassifier(random_state=66) GS = GridSearchCV(rfc,param_grid,cv=10) GS.fit(X_train, y_train) print(GS.best_params_) print(GS.best_score_) #这里三个参数和我们前边所暂定的参数都不一样。证明三者之间确实是相互影响的。最终确定还是选取开始的三个。 #从而得到最佳参数:‘max_depth’: 6, ‘min_samples_leaf’: 5, ‘min_samples_split’: 2},此时准确率为0.9834608843537413