【Intel校企合作课程实践】淡水质量预测

一、项目简介

1、问题描述

淡水是我们最重要和最稀缺的自然资源之一,仅占地球总水量的 3%。它几乎触及我们日常生活的方方面面,从饮用、游泳和沐浴到生产食物、电力和我们每天使用的产品。获得安全卫生的供水不仅对人类生活至关重要,而且对正在遭受干旱、污染和气温升高影响的周边生态系统的生存也至关重要。

2、预期解决方案

通过参考英特尔的类似实现方案,预测淡水是否可以安全饮用和被依赖淡水的生态系统所使用,从而可以帮助全球水安全和环境可持续性发展。这里分类准确度和推理时间将作为评分的主要依据。

要求使用 英特尔® ONEAPI AI分析工具包

可以参考英特尔提供的类似实现方案

3、数据集

数据集下载链接:https://filerepo.idzcn.com/hack2023/datasetab75fb3.zip

数据集解压后是一个 csv 文件,包含接近 600 万条数据。

数据集特征中包含:

  • Index:编号
  • pH:水资源的 pH 值
  • Iron:含铁量
  • Nitrate:硝酸盐含量
  • Chloride:氯化物含量
  • Lead:铅含量
  • Zinc:锌含量
  • Color:淡水颜色
  • Turbidity:浑浊度
  • Fluoride:氟化物含量
  • Copper:铜含量
  • Odor:气味
  • Sulfate:硫酸
  • Conductivity:导电率
  • Chlorine:氯含量
  • Manganese :氯含量
  • Total Dissolved Solids :总溶解固体
  • Source:来源
  • Water Temperature :温度
  • Air Temperature :空气温度
  • Month :取水的月份
  • Day :取水的日期
  • Time of Day :取水的时间
  • Target:是否为可使用淡水

4、相关技术

4.1、Intel oneAPI

Intel oneAPI 是一个跨平台、可移植的开发工具集,它支持多种处理器架构,包括英特尔 CPU、GPU、FPGA 和其他加速器。这套工具集旨在为开发者提供编写高性能并行应用程序的能力,并简化跨平台开发的过程,使开发者能够更轻松地利用不同处理器架构的优势。

同时,oneAPI 还提供了一套统一的编程模型和工具,使开发人员能够轻松地利用不同类型的处理器和加速器来加速应用程序的执行。其目标是实现代码的可移植性和可扩展性,使开发人员能够更高效地利用现代硬件。

4.2、Modin

Modin 使用 Ray、Dask 或 Unidist 提供一种轻松的方式来加速 pandas 、脚本和库。与其他分布式 DataFrame 库不同,Modin 提供与现有 pandas 代码的无缝集成和兼容性。即使使用 DataFrame 构造函数也是相同的。(加速读取数据时间)

4.3、daal4py

可将训练好的 xgboost 转换为 daal4py 模型,以便进一步改进预测时间性能,利用底层的英特尔® 高级矢量扩展指令集(英特尔® AVX-512)硬件,最大限度地提高英特尔® 至强® 处理器上的梯度提升性能。(未使用转换前,直接使用 predict 最优情况为 21 秒)

4.4、sklearnex

借助面向 Scikit-learn* 的英特尔® 扩展,加速 Scikit-learn,并且仍然完全符合所有 Scikit-Learn API 和算法。英特尔® Extension for Scikit-learn 是一款免费软件 AI 加速器,可为各种应用程序带来超过 10-100 倍的加速。

面向 Scikit-learn* 的英特尔® 扩展为您提供了一种加速现有 scikit-learn 代码的方法。加速是通过打补丁实现的:用扩展提供的优化版本替换现有的 scikit-learn 算法。

二、数据探索与处理

1、环境配置

导入项目所需的包:

import os
import time
import pandas as pd
# import modin.pandas as pd
import numpy as np
import datetime
import daal4py as d4p
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import f1_score
from sklearn.metrics import roc_curve
from sklearn.metrics import recall_score
from sklearn.metrics import accuracy_score
from sklearn.metrics import roc_auc_score
from sklearn.metrics import make_scorer
from sklearn.metrics import precision_score
from xgboost import XGBClassifier
from scipy import interp
from scipy.stats import pearsonr
from modin.config import Engine
from sklearnex import patch_sklearn
from imblearn.under_sampling import RandomUnderSampler

为了方便查看输出结果,对运行环境进行设置,使其支持中文显示,并配置 pandas 最大列数为 100,避免其对列数进行隐藏,这样利于后续查看各样本列的情况,代码如下:

os.environ["MODIN_ENGINE"] = "dask"
os.environ['NLSLANG']='SIMPLIFIED CHINESE_CHINA.UTF8'
pd.set_option( 'display.max_columns', 100)

Engine.put("dask")

patch_sklearn()

代码运行后可看到如下方的提示:

image1

2、数据读取与分析

使用 pandas 将用户相关的特征读取进来,转化为 DataFrame 对象,并将样本数量字段数量、数据类型,非空值数量等详细信息进行显示

查看前部分的数据:

df = pd.read_csv('./data/dataset.csv' ) 
print("Data shape: {}\n".format(df.shape))
display(df.head())

image2

查看数据类型和信息:

df_info = df.info()

image3

可以看到此 CSV 文件中含有 5956842 条数据,有 24 列,浮点型(float64)占 19 列,整型(int64)字段占 2 列,对象型(object)占 3 列,总共占用内存空间大约 1.1 GB。

打开 csv 文件粗略的查看数据就能看出数据集中存在空值,重复值,需要进行数据处理。再来查看一些数学分析,包括数据总数量、数据的分布情况、数据类型、最大值、最小值、均值、标准差等,另外重点查看变量的有效记录数的比例、完整百分比、有效记录数等作为字段筛选的依据,代码如下:

# 提取数值型的列
numeric_cols = df.select_dtypes(include=[np.number]).columns

# 计算描述性统计信息
desc_stats = df[numeric_cols].describe().T

# 计算偏度和峰度
skewness = df[numeric_cols].skew().rename("Skewness")
kurtosis = df[numeric_cols].kurtosis().rename("Kurtosis")

# 计算字段的有效记录数的比例
valid_ratio = (df.count() / len(df)).rename("Valid Records Ratio")

# 计算完整百分比
complete_percent = (1 - df.isnull().mean()).rename("Complete Percentage")

# 计算有效记录数
valid_records_count = df.notnull().sum().rename("Valid Records Count")

# 合并描述性统计信息、偏度和峰度
desc_stats = pd.concat([desc_stats, skewness, kurtosis, valid_ratio, complete_percent, valid_records_count], axis=1)

# 将数字型相关字段进行统计
desc_stats = desc_stats.iloc[:, :21]  # 提取数字型相关字段的统计信息

# 转置数据框
desc_stats_transposed = desc_stats.transpose()

# 添加背景色颜色梯度
styled_stats_df = desc_stats_transposed.style.background_gradient(cmap='OrRd')

# 显示结果
display(styled_stats_df)

代码运行后,将数字型相关(21 列)字段进行统计,其输出结果下图所示。

image4

从图可以看到,部分字段偏差值较高,比如 Iron、Lead 等,需要进一步做处理。

因为数据中存在 object 类型数据,这对于模型训练不利,所以这里使用了相应方法将其因子化转换为了数值型数据,这样所有的数据都可以进行相关的分析处理了

将 Color、Source、Month 等英文字段进行因子化(Farcotize)处理为数字型变量,代码如下:

factor = pd.factorize(df['Color'])
print(factor)
df.Color = factor[0]
factor = pd.factorize(df['Source'])
print(factor)
df.Source = factor[0]
factor = pd.factorize(df['Month'])
print(factor)
df.Month = factor[0]

输出结果:

image5

3、特征相关性分析

首先,使用 pandas 库中的 corr() 函数计算数据框 df 中各个列(除了 Target 列)与 Target 列的相关系数,并使用 abs() 函数将其转换为绝对值,然后使用 sort_values() 函数按照相关系数的大小进行排序,得到一个 Series 类型的 bar 变量,其中每个元素代表一个特征与 Target 的相关系数的绝对值。

然后,使用 matplotlib 库中的 bar() 函数画出一个条形图,其中 x 轴代表各个特征,y 轴代表它们与 Target 的相关系数的绝对值。条形图中每个条形的高度表示对应特征与 Target 的相关系数的绝对值大小。

接下来,使用 numpy 库中的 arange() 函数生成一个长度为数据框 df 中列数的等差数列,然后将其作为 x 轴上各个条形的位置坐标。

然后,使用 rcParams.update() 函数更新 matplotlib 库的参数,其中 'figure.figsize' 参数用于设置 x 轴间距。

接下来,使用 xticks() 函数设置 x 轴上各个条形的标签,并设置旋转角度和字体大小。

最后,使用 show() 函数显示图形,实现相关性的展示。

bar = df.corr()['Target'].abs().sort_values(ascending=False)[1:]

plt.bar(bar.index, bar, width=0.5)
# 设置figsize的大小
pos_list = np.arange(len(df.columns))
params = {
    'figure.figsize': '20, 10'
}
plt.rcParams.update(params)
plt.xticks(bar.index, bar.index, rotation=-60, fontsize=10)
plt.show()

image6

可以看见后续的特征数据的相关性都比较差,所以这里采取的做法为删除相关特征以及对应的列数据

删除代码为:

# 删除不相关的列
df = df.drop(columns=['Index', 'Day', 'Time of Day', 'Month', 'Water Temperature', 
                      'Source', 'Conductivity', 'Air Temperature'])

4、缺失值与重复值处理

前置中我们可以很明显的看见数据集中存在缺失值,利用如下代码进行查看:

# 查看样本缺失值、重复值情况
display(df.isna().sum())
missing = df.isna().sum().sum()
duplicates = df.duplicated().sum()
print("\n共{:,.0f} 缺失值 in the data.".format(missing))
print("共{:,.0f} 重复值 in the data.".format(duplicates))

输出结果:

image7

可以看出数据集重复值、缺失值比较多,需要进一步处理。本项目采用填充上下值的平均值的方法进行处理缺失值,并删除重复值,相关代码如下:

df = df.fillna(df.interpolate())
df = df.drop_duplicates()

这时再来查看数据集,就没有缺失值与重复值了。

display(df.isna().sum())
missing = df.isna().sum().sum()
duplicates = df.duplicated().sum()
print("\n处理后的结果:")
print("共 {:,.0f} 缺失值 in the data.".format(missing))
print("共 {:,.0f} 重复值 in the data.".format(duplicates))

image8

5、偏差值处理

下面进行偏差值处理,删除偏差值比较大的列。

通过以下代码对偏差值进行处理,通过检查皮尔逊相关系数与缺失值比例是否大于 20%,数值型特征方差是否小于 0.1 来进行删除特征操作。

首先,检查每个数值型特征的方差是否小于等于 0.1,如果小于等于 0.1,则将该特征从数据框中删除。

然后,使用 scipy.stats 库中的 pearsonr() 函数计算数据框 df 中各个列与最后一列的皮尔逊相关系数,并检查每个特征与最后一列的相关性是否显著(p 值小于 0.05),如果不显著,则将该特征从数据框中删除。

最后,输出处理后的数据框 df 中剩余的特征及其数量。

variables = df.columns
df = df

var = df.var()
numeric = df.columns
df = df.fillna(df.interpolate())
for i in range(0, len(var) - 1):
    if var[i] <= 0.1:  # 方差小于等于10%
        print(variables[i])
        df = df.drop(numeric[i],axis=1)
variables = df.columns

for i in range(0, len(variables)):
    x = df[variables[i]]
    y = df[variables[-1]]
    if pearsonr(x, y)[1] > 0.05:
        print(variables[i])
        df = df.drop(variables[i],axis=1)

variables = df.columns
print(variables)
print(len(variables))

输出结果:

image9

可以看到处理之后删除了 Lead 所对应的列数据,只剩余偏差值正常的 15 列

display(df.head())

image10

6、数据不平衡处理

先查看正负样本比例

print(df.Target.value_counts())

# 计算正负样本数据比例
positive_count = df[df['Target'] == 1].shape[0]
negative_count = df[df['Target'] == 0].shape[0]
total_count = df.shape[0]

positive_ratio = positive_count / total_count
negative_ratio = negative_count / total_count

print("正样本比例:{:.2%}".format(positive_ratio))
print("负样本比例:{:.2%}".format(negative_ratio))

# 数据
labels = ['Positive sample', 'Negative sample']
sizes = [positive_count, negative_count]
colors = ['#ff9999', '#66b3ff']
explode = (0.1, 0)  # 突出显示正样本

# 绘制饼图
plt.pie(sizes, explode=explode, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True, startangle=140)
plt.axis('equal')  # 使饼图为正圆形
plt.title('positive and negative sample ratio')

# 显示图形
plt.show()

运行结果:

image11

image12

可以看出正负样本数据比例差距较大,所以这里使用下采样对数据进行平衡处理

首先,将数据框 df 中的特征和目标变量分别赋值给 X 和 y。

然后,使用 imblearn 库中的 RandomUnderSampler() 函数进行下采样,使得正负样本比例接近 1:1。这里使用了随机数种子(random_state=21)来确保每次采样的结果相同。

X = df.iloc[:, 0:len(df.columns.tolist()) - 1].values
y = df.iloc[:, len(df.columns.tolist()) - 1].values

# 下采样
under_sampler = RandomUnderSampler(random_state=21)
X, y = under_sampler.fit_resample(X, y)

7、数据转换

通过直方图的形式查看连续性数据的分布,只有类似于正态分布的数据分布才是符合现实规律的数据,并且这有利于模型的训练。

通过以下代码查看直方图:

# 划分类别特征, 数值特征
# cat_cols, float_cols = [], ['Target']
cat_cols, float_cols = [], []
for col in df.columns:
    if df[col].value_counts().count() < 50:
        cat_cols.append(col)
    else:
        float_cols.append(col)
print('离散特征:', cat_cols)
print('连续特征:', float_cols)

df[float_cols].hist(bins=50,figsize=(16,12))

运行结果:

image13

image14

既有符合正态分布的,也有比较不符合的,然后对不符合正态分布的特征数据进行数据转换:

# 针对不规则分布的变量进行非线性变换,一般进行log
log_col = ['Iron', 'Zinc', 'Turbidity', 'Copper', 'Manganese']
show_col = []
for col in log_col:
    df[col + '_log'] = np.log(df[col])
    show_col.append(col + '_log')
    
df[show_col].hist(bins=50,figsize=(16,12))

运行结果:

image15

到这里,基本的数据探索与处理结束。

三、模型训练

模型采用 XGBoost,并使用随机网格搜索(RandomizedSearchCV)进行优化。

1、数据切分

代码如下:

这里使用 train_test_split() 函数将 X 和 y 分割成训练集和测试集,其中测试集占总数据的 20%。同时,使用 StandardScaler() 函数对训练集和测试集进行标准化处理,使得每个特征的均值为 0,标准差为 1,以提高模型的性能。最后,输出训练集和测试集的形状。

X = df.drop( ['Target','Iron', 'Zinc', 'Turbidity', 'Copper', 'Manganese'], axis=1)
y = df['Target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=21)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print("Train Shape: {}".format(X_train_scaled.shape))
print("Test Shape: {}".format(X_test_scaled.shape))

X_train, X_test = X_train_scaled, X_test_scaled

image16

2、参数设置

网格搜索模型参数如下:

param_grid = {
    'max_depth': [10, 15, 20],
    "gamma": [0, 1, 2], 
    "subsample": [0.9, 1], 
    "colsample_bytree": [0.3, 0.5, 1], 
    'min_child_weight': [4, 6, 8], 
    "n_estimators": [10,50, 80, 100],
    "alpha": [3, 4, 5]
}

scorers = {
    'precision_score': make_scorer(precision_score),
    'recall_score': make_scorer(recall_score),
    'accuracy_score': make_scorer(accuracy_score),
    'f1_score': make_scorer(f1_score),
    'roc_auc_score': make_scorer(roc_auc_score),
}

其中网络参数包括:

  • 树的最大深度(max_depth),其取值范围是 10,15,20;
  • 评估器数量参数(n _estimators),可选取值为 10、50、80、100;
  • gamma 参数(min_split_loss),可选值为 0,1,2, 默认是 0,分裂节点时,损失函数减小值只有大于等于 gamma 节点才分裂,gamma 值越大,算法越保守,越不容易过拟合,但性能就不一定能保证,需要平衡。
  • colsample_bytree:可选值为 0.3, 0.5, 1,默认 = 1,列采样率,也就是特征采样率。范围为(0,1]
  • subsample:可选值为 0.9, 1,默认值 = 1,构建每棵树对样本的采样率,如果设置成 0.5,XGBoost 会随机选择一半的样本作为训练集。范围:(0,1]
  • min_child_weight:可选值为 4, 6, 8,默认值 = 1,如果新分裂的节点的样本权重和小于 min_child_weight 则停止分裂。这个可以用来减少过拟合,但是也不能太高,会导致欠拟合。范围:[0,∞]
  • alpha(reg_alpha):可选值为 3, 4, 5, 默认 = 0,权重的 L1 正则化项。增加此值将使模型更加保守。

3、训练模型

定义 XGBoost 分类器。

xgb = XGBClassifier(
    learning_rate=0.1,
    n_estimators=15,
    max_depth=12,
    min_child_weight=6,
    gamma=0,
    subsample=1,
    colsample_bytree=1,
    objective='binary:logistic', 
    nthread=4,
    alpha=4,
    scale_pos_weight=1,
    seed=27)

在网格搜索过程中,模型采用 f1_score 作为评价指标,基于 StratifiedKFold 将数据分为 3 份,尝试之前定义的参数列表,使用 fit 方法对模型进行训练。训练完成后,使用测试集(X_test)进行验证,并将结果输出,代码如下:

refit_score = "f1_score"

start_time = datetime.datetime.now()
print(start_time)
# rd_search = RandomizedSearchCV(xgb, param_grid, n_iter=10, cv=3, refit=refit_score, scoring=sklearn.metrics.make_scorer(f1_score), 
#                                verbose=10, return_train_score=True)
rd_search = RandomizedSearchCV(xgb, param_grid, n_iter=10, cv=3, refit=refit_score, 
                               scoring=scorers, verbose=10, return_train_score=True)
rd_search.fit(X_train, y_train)
print(rd_search.best_params_)
print(rd_search.best_score_)
print(rd_search.best_estimator_)
print(datetime.datetime.now() - start_time)

训练过程展示如下:

image17

image18

通过搜索之后得到的相关最优参数如下:

{
    'subsample': 0.9, 
    'n_estimators': 80, 
    'min_child_weight': 8, 
    'max_depth': 15, 
    'gamma': 1, 
    'colsample_bytree': 1, 
    'alpha': 5
}

然后进行测试,将测试集的预测结果与实际结果合起来,应用 confusion_matrix 构建混淆矩阵,并输出模型拟合时间,结果如下,最终输出模型的准确率、召回率、AUC 值、f1 分数等各项性能指标:

start = time.time()
    
y_pred = rd_search.best_estimator_.predict(X_test)
end = time.time()
print('模型拟合时间:{:.2f}'.format(end-start))

# confusion matrix on the test data.
print('\nConfusion matrix of Random Forest optimized for {} on the test data:'.format(refit_score))
print(pd.DataFrame(sklearn.metrics.confusion_matrix(y_test, y_pred),
                   columns=['pred_neg', 'pred_pos'], index=['neg', 'pos']))

# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print("准确率: {:.5f}".format(accuracy))

# 计算召回率
recall = recall_score(y_test, y_pred)
print("召回率: {:.5f}".format(recall))

# 计算AUC值
auc = roc_auc_score(y_test, y_pred)
print("AUC值: {:.5f}".format(auc))

# 计算F1分数
f1 = f1_score(y_test, y_pred)
print("F1分数: {:.5f}".format(f1))

可以看到,模型的准确性为 88%,召回率为 97%,AUC 值为 0.91,F1 值为 0.83

image19

4、结果分析与可视化

ROC 曲线是一个二元分类器系统在不同阈值下的性能表现的图形化表示,它通过绘制真正例率(TPR)与假正例率(FPR)在各种阈值设置下的表现来创建。

下面使用 Scikit-learn 库对测试集进行分层 K 折交叉验证。交叉验证将数据分成 5 个折叠,并在剩余的折叠上进行验证,同时在 4 个折叠上训练模型。使用的模型是随机搜索 CV 算法应用于机器学习模型的结果。 ROC 曲线分别为每个折叠绘制,使用不同的线型,使用 linetypes 变量。平均 ROC 曲线也以蓝色绘制,阴影区域表示不同折叠之间性能的变化。为每个折叠和平均曲线计算曲线下面积(AUC)。AUC 是一个衡量分类器总体性能的指标。

from sklearn.metrics import auc

params = {'legend.fontsize': 'x-large',
          'figure.figsize': (12, 9),
         'axes.labelsize': 'x-large',
         'axes.titlesize':'x-large',
         'xtick.labelsize':'x-large',
         'ytick.labelsize':'x-large'}
plt.rcParams.update(params)


tprs = []
aucs = []
mean_fpr = np.linspace(0, 1, 100)

skf = StratifiedKFold(n_splits=5)
linetypes = ['--',':','-.','-','-','O']

i = 0
cv_data =skf.split(X_test, y_test)

for train, test in cv_data:
    probas_ = rd_search.predict_proba(X_test[test])
    # Compute ROC curve and area the curve
    fpr, tpr, thresholds = roc_curve(y_test.iloc[test], probas_[:, 1])
    tprs.append(interp(mean_fpr, fpr, tpr))
    tprs[-1][0] = 0.0
    roc_auc_value = auc(fpr, tpr)
    aucs.append(roc_auc_value)
    plt.plot(fpr, tpr, lw=1.5,linestyle = linetypes[i], alpha=0.8,
             label='ROC fold %d (AUC = %0.2f)' % (i, roc_auc_value))

    i += 1
plt.plot([0, 1], [0, 1], linestyle='--', lw=1, color='r',
         label='Chance', alpha=.6)

mean_tpr = np.mean(tprs, axis=0)
mean_tpr[-1] = 1.0
mean_auc = auc(mean_fpr, mean_tpr)
std_auc = np.std(aucs)
plt.plot(mean_fpr, mean_tpr, color='b',
         label=r'Mean ROC (AUC = %0.2f $\pm$ %0.2f)' % (mean_auc, std_auc),
         lw=2, alpha=.8)

std_tpr = np.std(tprs, axis=0)
tprs_upper = np.minimum(mean_tpr + std_tpr, 1)
tprs_lower = np.maximum(mean_tpr - std_tpr, 0)
plt.fill_between(mean_fpr, tprs_lower, tprs_upper, color='grey', alpha=.2,
                 label=r'$\pm$ 1 std. dev.')

plt.xlim([-0.02, 1.02])
plt.ylim([-0.02, 1.02])
plt.xlabel('FPR',fontsize=20)
plt.ylabel('TPR',fontsize=20)
# plt.title('ROC')
plt.legend(loc="lower right")
plt.show()

image24

5、保存模型

import joblib

# 保存模型
joblib.dump(rd_search.best_estimator_, 'best_xgb_model.pkl')

四、推理测试

模型保存成功后,最后要用提供的专门测试集进行测试,得到的 F1 分数和推理时间作为主要评分依据。首先要将测试集的数据像训练集那样进行一些处理

1、查看数据集

# 读取测试数据集
test_df = pd.read_csv('./data/test_data.csv')

# 加载模型
model = joblib.load('best_xgb_model.pkl')

print("Data shape: {}\n".format(test_df.shape))
test_df.info()
display(test_df.head())

输出结果:

image20

image21

2、数据处理

1、将 Color、Source、Month 等英文字段进行因子化

factor = pd.factorize(test_df['Color'])
print(factor)
test_df.Color = factor[0]
factor = pd.factorize(test_df['Source'])
print(factor)
test_df.Source = factor[0]
factor = pd.factorize(test_df['Month'])
print(factor)
test_df.Month = factor[0]

2、删除相关性较差的特征

# 删除不相关的列
test_df = test_df.drop(columns=['Index', 'Day', 'Time of Day', 'Month', 'Water Temperature', 
                      'Source', 'Conductivity', 'Air Temperature'])

3、处理缺失值与重复值

test_df = test_df.fillna(test_df.interpolate())
test_df = test_df.drop_duplicates()

display(test_df.isna().sum())
missing = test_df.isna().sum().sum()
duplicates = test_df.duplicated().sum()
print("\n处理后的结果:")
print("共 {:,.0f} 缺失值 in the data.".format(missing))
print("共 {:,.0f} 重复值 in the data.".format(duplicates))

4、处理偏差值

test_df = test_df.drop('Lead', axis=1)

5、数据不平衡处理

X = test_df.iloc[:, 0:len(test_df.columns.tolist()) - 1].values
y = test_df.iloc[:, len(test_df.columns.tolist()) - 1].values

# 下采样
under_sampler = RandomUnderSampler(random_state=21)
X, y = under_sampler.fit_resample(X, y)

6、对不符合正态分布的特征数据进行数据转换

# 针对不规则分布的变量进行非线性变换,一般进行log
log_col = ['Iron', 'Zinc', 'Turbidity', 'Copper', 'Manganese']
show_col = []
for col in log_col:
    test_df[col + '_log'] = np.log(test_df[col])
    show_col.append(col + '_log')
    
test_df[show_col].hist(bins=50,figsize=(16,12))

image22

3、进行测试

X_test = test_df.drop(['Target','Iron', 'Zinc', 'Turbidity', 'Copper', 'Manganese'], axis=1)
scaler = StandardScaler()
X_test_scaled = scaler.fit_transform(X_test)

print("Test Shape: {}".format(X_test_scaled.shape))

X_test = X_test_scaled
# 进行推理
start_time = time.time()
y_pred = model.predict(X_test_scaled)
inference_time = time.time() - start_time
print("推理时间:", inference_time, "秒")

输出结果:

推理时间: 2.391632318496704 秒

结果可视化:

# 计算F1分数
f1 = f1_score(test_df['Target'], y_pred)
print("F1 Score:{:.5f}".format(f1))

# 计算AUC值
auc = roc_auc_score(test_df['Target'], y_pred)
print("AUC值:{:.5f}".format(auc))

# 计算召回率
recall = recall_score(test_df['Target'], y_pred)
print("召回率: {:.5f}".format(recall))

# 计算准确率
accuracy = accuracy_score(test_df['Target'], y_pred)
print("准确率: {:.5f}".format(accuracy))

# 计算ROC曲线相关指标
fpr, tpr, thresholds = roc_curve(test_df['Target'], y_pred)
roc_auc = roc_auc_score(test_df['Target'], y_pred)

# 可视化ROC曲线
plt.figure(figsize=(10, 6))
plt.plot(fpr, tpr, color='blue', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='red', linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC)')
plt.legend(loc="lower right")
plt.show()

输出结果:

F1 Score:0.82058
AUC值:0.90030
召回率: 0.97331
准确率: 0.87140

ROC 曲线展示:

image23

五、总结

XGBoost 虽然在训练阶段耗费不小的时间代价,但其在 oneAPI 提供的 daal4py 模型的加速下,其推理速度能得到更大的提升,随着数据量的增加,在保证训练机器足够的情况下,模型层面的准确率也会得到以进一步提升。

另外,我们的解决方案还有很大的提升空间,目前我们仅对少量的特征进行了分析以及交互处理,仍然有着很多潜在的与目标相关的信息等待着我们挖掘,相信在后续对本方案进行精细化探索后,仍然能够提升我们的模型性能。

最后,通过本次校企合作课程,我了解到了 intel oneAPI 在机器学习与数据挖掘领域的应用,通过作业实际体验到了 intel AI Analytics Toolkit 工具对于解决问题的效率提升。之前了解了 oneAPI 在深度学习中的应用,在本次作业中又体验到了 oneAPI 在机器学习中的应用。oneAPI 兼顾机器学习和深度学习,为开发者和应用者提供了极大的便利。

  • 26
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值