Press "Enter" to skip to content

动手实操丨基于随机森林算法进行硬盘故障预测

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

 

摘要:业界期望使用机器学习技术来构建硬盘故障预测的模型,更准确地提前感知硬盘故障,降低运维成本,提升业务体验。本案例将使用随机森林算法来训练一个硬盘故障预测模型。

 

本文分享自华为云社区《基于随机森林算法进行硬盘故障预测》
,原文作者:山海之光。

 

实验目标

 

1. 掌握使用机器学习方法训练模型的基本流程;

 

2. 掌握使用 pandas 做数据分析的基本方法;

 

3. 掌握使用 scikit-learn 进行随机森林模型的构建、训练、保存、加载、预测、统计准确率指标和查看混淆矩阵的方法;

 

案例内容介绍

 

随着互联网、云计算的发展,数据的存储需求与日倍增,大规模海量数据存储中心是必不可少的基础性设施。虽然新的存储介质例如 SSD,已经很多方面拥有了比磁盘更好的性能,但就目前来讲,其高昂的花费仍然使大部分数据中心难以负担,因此,大型数据中心依然会采用传统的机械硬盘作为存储介质。

 

机械硬盘生命周期通常为 3 到 5 年,在 2 到 3 年后故障率明显升高,导致换盘量陡增。据统计,在服务器硬件故障中,硬盘故障占比达到 48%+,是影响服务器运行可靠性的重要因素。早在上个世纪九十年代,人们就意识到数据的宝贵性远胜于硬盘自身价值,渴望有种技术能对硬盘故障进行预测并实现相对安全的数据保护,因此 S.M.A.R.T.技术应运而生。

 

S.M.A.R.T.,全称为“Self-Monitoring Analysis and ReportingTechnology”,即“自我监测、分析及报告技术”,是一种自动的硬盘状态检测与预警系统和规范。通过在硬盘硬件内的检测指令对硬盘的硬件如磁头、盘片、马达、电路的运行情况进行监控、记录并与厂商所设定的预设安全值进行比较,若监控情况将或已超出预设安全值的安全范围,就可以通过主机的监控硬件或软件自动向用户作出警告并进行轻微的自动修复,以提前保障硬盘数据的安全。除一些出厂时间极早的硬盘外,现在大部分硬盘均配备该项技术。关于该技术的更多介绍,请查看 S.M.A.R.T.-百度百科。

 

虽然硬盘厂商采用了 S.M.A.R.T.技术来监测硬盘的健康状态,但是大多数厂商都是基于设计规则制定的故障预测手段,预测效果非常差,不能满足日渐严格的提前预测硬盘故障的需求。因此,业界期望使用机器学习技术来构建硬盘故障预测的模型,更准确地提前感知硬盘故障,降低运维成本,提升业务体验。

 

本案例将带大家使用一份开源的 S.M.A.R.T.数据集和机器学习中的随机森林算法,来训练一个硬盘故障预测模型,并测试效果。

 

关于随机森林算法的理论讲解,可参考此视频

 

注意事项

 

1. 如果你是第一次使用 JupyterLab,请查看《ModelAtrs JupyterLab使用指导
》了解使用方法;

 

2. 如果你在使用 JupyterLab 过程中碰到报错,请参考《ModelAtrs JupyterLab常见问题解决办法
》尝试解决问题。

 

实验步骤

 

1. 数据集介绍

 

本案例使用的数据集是来自于 Backblaze 公司的开源数据集,它是一家计算机备份和云存储服务提供商。自 2013 年以来,Backbreze 每年都会公开发布他们的数据中心所使用硬盘的 S.M.A.R.T.日志数据,有效地推动了使用机器学习技术进行硬盘故障预测的发展

 

由于 Backblaze 公司发布的 S.M.A.R.T.日志数据量较大,本案例为快速演示使用机器学习构建硬盘故障预测模型的过程,仅使用了该公司发布的 2020 年的数据,相关数据已经准备好,放在 OBS 中,运行如下代码即可下载这部分数据。

 

注意:本步下载数据的代码需要在华为云ModelArts Codelab
上运行

 

import osimport moxing as moxif not os.path.exists('./dataset_2020.zip'):    mox.file.copy('obs://modelarts-labs-bj4/course/ai_in_action/2021/machine_learning/hard_drive_disk_fail_prediction/dataset_2020.zip', './dataset_2020.zip')    os.system('unzip dataset_2020.zip')
if not os.path.exists('./dataset_2020'):    raise Exception('错误!数据不存在!')
!ls -lh ./dataset_2020INFO:root:Using MoXing-v1.17.3-INFO:root:Using OBS-Python-SDK-3.20.7total 102M-rw-r--r-- 1 ma-user ma-group  51M Mar 21 11:56 2020-12-08.csv-rw-r--r-- 1 ma-user ma-group  51M Mar 21 11:56 2020-12-09.csv-rw-r--r-- 1 ma-user ma-group 1.2M Mar 21 11:55 dataset_2020.csv-rw-r--r-- 1 ma-user ma-group 3.5K Mar 22 15:59 prepare_data.py

 

 

数据解释:

 

2020-12-08.csv:从 backblaze 公司发布的 2020Q4 数据集中抽取出来的 2020-12-08 这天的 S.M.A.R.T.日志数据

 

2020-12-09.csv:从 backblaze 公司发布的 2020Q4 数据集中抽取出来的 2020-12-09 这天的 S.M.A.R.T.日志数据

 

dataset_2020.csv:已经处理过的 2020 年全年 S.M.A.R.T.日志数据,下文中“第 2.6 节 类别均衡度分析”会解释如何得到这部分数据

 

prepare_data.py: 运行该脚本,会下载 2020 年全年 S.M.A.R.T.日志数据,并进行处理,得到 dataset_2020.csv。运行该脚本需要 20G 的本地存储空间

 

2. 数据分析

 

使用机器学习构建任何模型之前,都需要先对数据集进行分析,了解数据集的规模、属性名、属性值、各类统计指标及空值情况。因为我们要先了解数据,才能用好数据。

 

2.1 读取 csv 文件

 

pandas 是常用的 python 数据分析模块,我们先用它来加载数据集中的 csv 文件。以 2020-12-08.csv 为例,我们先加载该文件来分析 S.M.A.R.T.日志数据的情况

 

import pandas as pddf_data = pd.read_csv("./dataset_2020/2020-12-08.csv")type(df_data)pandas.core.frame.DataFrame

 

 

2.2 查看单个 csv 文件数据的规模

 

print('单个csv文件数据的规模,行数:%d, 列数:%d' % (df_data.shape[0], df_data.shape[1]))单个csv文件数据的规模,行数:162008, 列数:149

 

 

2.3 查看头 5 行数据

 

使用 pandas 加载 csv 后,得到的是一个 DataFrame ,可以理解为一个表格,调用该对象的 head()函数,可以查看表格的头 5 行数据

 

df_data.head()

 

5 rows × 149 columns

 

如上所示是表格的头 5 行数据,表头是属性名,属性名下面是属性值,backblaze 网站解释了属性值的含义,翻译为如下:

2.4 查看数据的统计指标

 

查看完表格的头 5 行数据,我们再调用 DataFrame 对象的 describe()函数,计算表格数据的统计指标

 

df_data.describe()

 

8 rows × 146 columns

 

如上所示是表格数据的统计指标,describe()函数默认对数值类型的列进行统计分析,由于表格的前三列’date’、‘serial_number’、’model’是字符串类型,所以这三列没有统计指标。

 

各行统计指标的含义解释如下:count: 该列有多少个非空值 mean: 该列的均值 std: 该列数值的标准差 min: 该列数值的最小值 25%: 该列数值的 25%中位值 50%: 该列数值的 50%中位值 75%: 该列数值的 75%中位值 max: 该列数值的最大值

 

2.5 查看数据空值情况

 

从上面的输出可以观察到,某些属性的 count 指标比较小,比如 smart_2_raw 的 count 数就比 df_train 的总行数要小很多,因此我们要再进一步看看各列属性的空值情况,执行如下代码可以查看空值情况

 

df_data.isnull().sum()date                         0serial_number                0model                        0capacity_bytes               0failure                      0smart_1_normalized         179smart_1_raw                179smart_2_normalized      103169smart_2_raw             103169smart_3_normalized        1261smart_3_raw               1261smart_4_normalized        1261smart_4_raw               1261smart_5_normalized        1221smart_5_raw               1221smart_7_normalized        1261smart_7_raw               1261smart_8_normalized      103169smart_8_raw             103169smart_9_normalized         179smart_9_raw                179smart_10_normalized       1261smart_10_raw              1261smart_11_normalized     161290smart_11_raw            161290smart_12_normalized        179smart_12_raw               179smart_13_normalized     161968smart_13_raw            161968smart_15_normalized     162008                         ...  smart_232_normalized    160966smart_232_raw           160966smart_233_normalized    160926smart_233_raw           160926smart_234_normalized    162008smart_234_raw           162008smart_235_normalized    160964smart_235_raw           160964smart_240_normalized     38968smart_240_raw            38968smart_241_normalized     56030smart_241_raw            56030smart_242_normalized     56032smart_242_raw            56032smart_245_normalized    161968smart_245_raw           161968smart_247_normalized    162006smart_247_raw           162006smart_248_normalized    162006smart_248_raw           162006smart_250_normalized    162008smart_250_raw           162008smart_251_normalized    162008smart_251_raw           162008smart_252_normalized    162008smart_252_raw           162008smart_254_normalized    161725smart_254_raw           161725smart_255_normalized    162008smart_255_raw           162008Length: 149, dtype: int64

 

 

这种显示方式不太方便查看,我们把可以空值的数量绘制成曲线图,看起来更直观

 

import numpy as npimport matplotlib.pyplot as plt%matplotlib inline
df_data_null_num = df_data.isnull().sum()x = list(range(len(df_data_null_num)))y = df_data_null_num.valuesplt.plot(x, y)plt.show()

 

从上面的结果可以看出,表格中的某些属性有大量的空值。

 

在机器学习领域中,数据集中存在空值是很常见的现象,引起空值的原因有很多种,比如一份用户画像中有很多个属性,但又不是所有用户都有对应的属性值,这时就产生了空值。或者某些数据因为传输超时,导致没有采集上来,也可能会出现空值。

 

2.6 类别均衡度分析

 

我们要实现的任务是“硬盘故障预测”,即预测某个硬盘在某个时间是正常还是损坏,这就是一个故障预测问题或异常检测问题,这类问题有个特点就是:正常样本非常多,故障样本非常少,两类样本的数量差异非常大。

 

比如,执行如下代码,可以看到 df_data 中硬盘正常的样本有 16 万个以上,故障的样本却只有 8 个,类别极度不均衡。

 

valid = df_data[df_data['failure'] == 0]failed = df_data[df_data['failure'] == 1]print("valid hdds:",len(valid))print("failed hdds:",len(failed))valid hdds: 162000failed hdds: 8

 

 

由于大多数机器学习方法的学习过程都是基于统计学的思路来进行学习的,如果直接使用上面这样类别不均衡的数据进行训练,那幺模型的能力可能会明显偏向于类别多的样本,类别少的样本就会被“淹没”掉了,在学习过程中发挥不了作用,因此我们需要平衡不同类别的数据。

 

为了获得更多的故障样本数据,我们可以从 backblaze 公司发布的 2020 年全年 S.M.A.R.T.日志数据中将所有的故障样本都挑选出来,同时也随机挑出相同数量的正常样本,可以通过下面的代码来实现。

 

这段代码已被注释掉,如需运行,需要 20G 的本地存储空间。您也可以不必运行这段代码,因为本案例开头已经下载了 dataset_2020.zip,这个压缩包中已经提供了 dataset_2020.csv,该 csv 就是运行下面这段代码得到的文件

 

# if not os.path.exists('./dataset_2020/dataset_2020.csv'):#     os.system('python ./dataset_2020/prepare_data.py')import gcdel df_data   # 删除 df_data 对象gc.collect()  # 由于接下来的代码将加载日志数据到df_data对象中,为避免内存溢出的风险,可以在此处先手动回收内存,因为jupyterlab在运行过程中不会自动回收环境中的内存

 

 

2.7 加载类别均衡的数据集

 

dataset_2020.csv 是已经经过类别均衡处理的硬盘 S.M.A.R.T.日志数据,下面我们加载该文件,再确认一下类别均衡情况

 

df_data = pd.read_csv("./dataset_2020/dataset_2020.csv")valid = df_data[df_data['failure'] == 0]failed = df_data[df_data['failure'] == 1]print("valid hdds:", len(valid))print("failed hdds:", len(failed))valid hdds: 1497failed hdds: 1497

 

 

可以看到,正常样本和故障样本都是 1497 个

 

3. 特征工程

 

准备好可用的训练集之后,接下来要做特征工程,通俗地讲,特性工程就是要选择表格中的哪些属性来构建机器学习模型。人工设计特征的好坏,很大程度上决定了机器学习模型效果的好坏,所以机器学习领域的研究人员需耗费大量精力在人工设计特征上,是一项比较耗时、耗力,且需要专家经验的工程。

 

3.1 SMART 属性与硬盘故障的相关研究

 

(1)BackBlaze 分析了其 HDD 故障和 SMART 属性之间的相关性,并发现了 SMART 5、187、188、197、198 与 HDD 故障的相关率最高,这些 SMART 属性还与扫描错误,重新分配计数和试用计数有关[1];

 

(2)El-Shimi 等发现在随机森林模型中除了以上 5 个特征外,还有 SMART 9、193、194、241、242 这 5 个属性有最大权重[2];

 

(3)Pitakrat 等人评估了 21 种用于预测硬盘故障的机器学习算法,发现在测试的 21 种机器学习算法中,随机森林算法在 ROC 曲线下有最大面积,而 KNN 分类器具有最高的 F1 值[3];

 

(4)Hughes 等人也研究用于预测硬盘故障的机器学习方法,他们分析了 SVM、朴素贝叶斯的表现,SVM 实现了最高性能,检测率为 50.6%,误报率为 0%[4];

 

[1] Klein,Andy. “What SMART Hard Disk Errors Actually Tell Us.” Backblaze Blog Cloud Storage & Cloud Backup,6 Oct.2016, www.backblaze.com/blog/what-smart-stats-indicate-hard-drive-failures/

 

[2] El-Shimi, Ahmed. “Predicting Storage Failures.” VAULT-Linux Storage and File Systems Conference.VAULT-Linux Storageand File Systems Conference, 22 Mar. 2017, Cambridge.

 

[3] Pitakrat, Teerat, André van Hoorn, and LarsGrunske. “A comparison of machine learning algorithmsfor proactive hard disk drive failure detection.”Proceedings of the 4th international ACM Sigsoft symposium on Architectingcritical systems. ACM, 2013.

 

[4] Hughes, Gordon F., et al. “Improved disk-drivefailure warnings.” IEEE Transactions on Reliability51.3 (2002):350-357.

 

如上就是前人的一些研究成果,本案例计划采用随机森林模型,因此可以根据上面第 2 条研究成果,选择 SMART 5, 9, 187, 188, 193, 194,197, 198, 241, 242 这些属性来作为特征,它们的含义分别是:

 

SMART 5: 重映射扇区计数

 

SMART 9: 通电时间累计

 

SMART 187: 无法校正的错误

 

SMART 188: 指令超时计数

 

SMART 193: 磁头加载/卸载计数

 

SMART 194: 温度

 

SMART 197: 等待被映射的扇区数

 

SMART 198: 报告给操作系统的无法通过硬件 ECC 校正的错误

 

SMART 241: 逻辑块寻址模式写入总数

 

SMART 242: 逻辑块寻址模式读取总数

 

另外,由于不同硬盘厂商的不同型号硬盘记录 SMART 日志数据的标准可能不一样,所以我们最好将同一型号的硬盘数据挑出来作为训练数据,专门训练一个预测该型号硬盘是否故障的模型。如果需要预测多个不同型号的硬盘是否故障,则可能需要分别训练多个模型。

 

3.2 硬盘型号选择

 

执行下面的代码,看一下每种型号的硬盘数据量有多少

 

df_data.model.value_counts()ST12000NM0007                         664ST4000DM000                           491ST8000NM0055                          320ST12000NM0008                         293TOSHIBA MG07ACA14TA                   212ST8000DM002                           195HGST HMS5C4040BLE640                  193HGST HUH721212ALN604                  153TOSHIBA MQ01ABF050                     99ST12000NM001G                          53HGST HMS5C4040ALE640                   50ST500LM012 HN                          40TOSHIBA MQ01ABF050M                    35HGST HUH721212ALE600                   34ST10000NM0086                          29ST14000NM001G                          23HGST HUH721212ALE604                   21ST500LM030                             15HGST HUH728080ALE600                   14Seagate BarraCuda SSD ZA250CM10002     12WDC WD5000LPVX                         11WDC WUH721414ALE6L4                    10ST6000DX000                             9TOSHIBA MD04ABA400V                     3ST8000DM004                             2ST18000NM000J                           2Seagate SSD                             2ST4000DM005                             2ST8000DM005                             1ST16000NM001G                           1DELLBOSS VD                             1TOSHIBA HDWF180                         1HGST HDS5C4040ALE630                    1HGST HUS726040ALE610                    1WDC WD5000LPCX                          1Name: model, dtype: int64

 

 

可以看到 ST12000NM0007 型号的硬盘数据量最多,因此我们把该型号硬盘的数据过滤出来

 

df_data_model = df_data[df_data['model'] == 'ST12000NM0007']

 

 

3.3 特征选择

 

选取上文提到的 10 个属性作为特征

 

features_specified = []features = [5, 9, 187, 188, 193, 194, 197, 198, 241, 242]for feature in features:    features_specified += ["smart_{0}_raw".format(feature)]X_data = df_data_model[features_specified]Y_data = df_data_model['failure']X_data.isnull().sum()smart_5_raw      1smart_9_raw      1smart_187_raw    1smart_188_raw    1smart_193_raw    1smart_194_raw    1smart_197_raw    1smart_198_raw    1smart_241_raw    1smart_242_raw    1dtype: int64

 

 

有空值存在,所以先要填充空值

 

X_data = X_data.fillna(0) print("valid hdds:", len(Y_data) - np.sum(Y_data.values))print("failed hdds:", np.sum(Y_data.values))valid hdds: 325failed hdds: 339

 

 

3.4 划分训练集和测试集

 

使用 sklearn 的 train_test_split 即可划分训练集和测试集,test_size 表示测试集的比例,一般取值为 0.3、0.2 或 0.1

 

from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X_data, Y_data, test_size=0.2, random_state=0) 

 

 

4. 开始训练

 

4.1 构建模型

 

准备好训练集和测试集之后,就可以开始构建模型了,构建模型的步骤非常简单,直接调用机器学习框架 sklearn 中的 RandomForestClassifier 即可

 

from sklearn.ensemble import RandomForestClassifier 
rfc = RandomForestClassifier()

 

 

随机森林算法的超参数有很多个,取不同的参数值构建模型会得到不同的训练效果,对于初学者,可以直接使用库中提供的默认参数值,在对随机森林算法的原理有一定的了解之后,可以尝试修改模型的参数来调整模型的训练效果。

 

4.2 数据拟合

 

模型训练的过程,也就是拟合训练数据的过程,实现也非常简单,调用 fit 函数即可开始训练

 

rfc.fit(X_train, Y_train)/home/ma-user/anaconda3/envs/XGBoost-Sklearn/lib/python3.6/site-packages/sklearn/ensemble/forest.py:248: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',            max_depth=None, max_features='auto', max_leaf_nodes=None,            min_impurity_decrease=0.0, min_impurity_split=None,            min_samples_leaf=1, min_samples_split=2,            min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=None,            oob_score=False, random_state=None, verbose=0,            warm_start=False)

 

 

5 开始预测

 

调用 predict 函数即可开始预测

 

Y_pred = rfc.predict(X_test)

 

 

5.1 统计预测准确率

 

在机器学习中,分类问题的性能指标,常用的有四种:accuracy(精度)、precision(查准率)、recall(查全率)、F1-Score,四种指标越接近 1,表示效果越好。sklearn 库中有这四种指标的函数,直接调用即可。

 

关于四种指标的理论解释,可参考此文章

 

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
print("Model used is: Random Forest classifier")   acc = accuracy_score(Y_test, Y_pred) print("The accuracy is {}".format(acc))   prec = precision_score(Y_test, Y_pred) print("The precision is {}".format(prec))   rec = recall_score(Y_test, Y_pred) print("The recall is {}".format(rec))   f1 = f1_score(Y_test, Y_pred) print("The F1-Score is {}".format(f1)) Model used is: Random Forest classifierThe accuracy is 0.849624060150376The precision is 0.9122807017543859The recall is 0.7761194029850746The F1-Score is 0.8387096774193548

 

 

每次进行随机森林模型的训练,会得到该模型不同的测试准确率指标,这是由于随机森林算法的训练过程具有一定的随机性导致的,是正常现象。但是同一模型、同一样本的预测结果是确定不变的。

 

5.2 模型保存、加载、再预测

 

模型保存

 

import picklewith open('hdd_failure_pred.pkl', 'wb') as fw:    pickle.dump(rfc, fw)

 

 

模型加载

 

with open('hdd_failure_pred.pkl', 'rb') as fr:    new_rfc = pickle.load(fr)

 

 

模型再预测

 

new_Y_pred = new_rfc.predict(X_test)new_prec = precision_score(Y_test, new_Y_pred)print("The precision is {}".format(new_prec))The precision is 0.9122807017543859

 

 

5.3 查看混淆矩阵

 

要分析分类模型的效果如何,还可以使用混淆矩阵来查看,混淆矩阵的横轴表示预测结果的各个类别,纵轴表示真实标签的类别,矩阵方格中的值就代表对应横纵坐标重叠的测试样本数量。

 

import seaborn as snsimport matplotlib.pyplot as pltfrom sklearn.metrics import confusion_matrix 
LABELS = ['Healthy', 'Failed'] conf_matrix = confusion_matrix(Y_test, Y_pred) plt.figure(figsize =(6, 6)) sns.heatmap(conf_matrix, xticklabels = LABELS,              yticklabels = LABELS, annot = True, fmt ="d"); plt.title("Confusion matrix") plt.ylabel('True class') plt.xlabel('Predicted class') plt.show() 

 

6. 改进模型的思路

 

如上内容是使用随机森林算法构建硬盘故障预测模型的过程演示,模型精度并不算高,有如下几个思路可以提升模型的精度:

 

(1)本案例只使用了 Backblaze 公司 2020 年的数据,您可以尝试使用更多的训练数据;

 

(2)本案例只使用了 10 个 SMART 属性作为特征,您可以尝试使用其他方法来构建特征;

 

(3)本案例使用了随机森林算法来训练模型,您可以尝试使用其他的机器学习算法;

 

点击进入华为云ModelArts Codelab
可直接运行本案例代码

 

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注