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

2024-03-20 14:30

本文主要是介绍【Intel校企合作课程实践】淡水质量预测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、项目简介
    • 1、问题描述
    • 2、预期解决方案
    • 3、数据集
    • 4、相关技术
      • 4.1、Intel oneAPI
      • 4.2、Modin
      • 4.3、daal4py
      • 4.4、sklearnex
  • 二、数据探索与处理
    • 1、环境配置
    • 2、数据读取与分析
    • 3、特征相关性分析
    • 4、缺失值与重复值处理
    • 5、偏差值处理
    • 6、数据不平衡处理
    • 7、数据转换
  • 三、模型训练
    • 1、数据切分
    • 2、参数设置
    • 3、训练模型
    • 4、结果分析与可视化
    • 5、保存模型
  • 四、推理测试
    • 1、查看数据集
    • 2、数据处理
    • 3、进行测试
  • 五、总结

一、项目简介

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 = dfvar = 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.columnsfor 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_countprint("正样本比例:{:.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 aucparams = {'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 curvefpr, tpr, thresholds = roc_curve(y_test.iloc[test], probas_[:, 1])tprs.append(interp(mean_fpr, fpr, tpr))tprs[-1][0] = 0.0roc_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 兼顾机器学习和深度学习,为开发者和应用者提供了极大的便利。

这篇关于【Intel校企合作课程实践】淡水质量预测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/829757

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

Prometheus与Grafana在DevOps中的应用与最佳实践

Prometheus 与 Grafana 在 DevOps 中的应用与最佳实践 随着 DevOps 文化和实践的普及,监控和可视化工具已成为 DevOps 工具链中不可或缺的部分。Prometheus 和 Grafana 是其中最受欢迎的开源监控解决方案之一,它们的结合能够为系统和应用程序提供全面的监控、告警和可视化展示。本篇文章将详细探讨 Prometheus 和 Grafana 在 DevO

springboot整合swagger2之最佳实践

来源:https://blog.lqdev.cn/2018/07/21/springboot/chapter-ten/ Swagger是一款RESTful接口的文档在线自动生成、功能测试功能框架。 一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务,加上swagger-ui,可以有很好的呈现。 SpringBoot集成 pom <!--swagge

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

【HarmonyOS】-TaskPool和Worker的对比实践

ArkTS提供了TaskPool与Worker两种多线程并发方案,下面我们将从其工作原理、使用效果对比两种方案的差异,进而选择适用于ArkTS图片编辑场景的并发方案。 TaskPool与Worker工作原理 TaskPool与Worker两种多线程并发能力均是基于 Actor并发模型实现的。Worker主、子线程通过收发消息进行通信;TaskPool基于Worker做了更多场景化的功能封装,例

《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》P98

更改为 差分的数学表达式从泰勒级数展开式可得: 后悔没听廖老师的。 禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》 禹晶、肖创柏、廖庆敏《数字图像处理》资源二维码

vue2实践:第一个非正规的自定义组件-动态表单对话框

前言 vue一个很重要的概念就是组件,作为一个没有经历过前几代前端开发的我来说,不太能理解它所带来的“进步”,但是,将它与后端c++、java类比,我感觉,组件就像是这些语言中的类和对象的概念,通过封装好的组件(类),可以通过挂载的方式,非常方便的调用其提供的功能,而不必重新写一遍实现逻辑。 我们常用的element UI就是由饿了么所提供的组件库,但是在项目开发中,我们可能还需要额外地定义一

《C++中的移动构造函数与移动赋值运算符:解锁高效编程的最佳实践》

在 C++的编程世界中,移动构造函数和移动赋值运算符是提升程序性能和效率的重要工具。理解并正确运用它们,可以让我们的代码更加高效、简洁和优雅。 一、引言 随着现代软件系统的日益复杂和对性能要求的不断提高,C++程序员需要不断探索新的技术和方法来优化代码。移动构造函数和移动赋值运算符的出现,为解决资源管理和性能优化问题提供了有力的手段。它们允许我们在不进行不必要的复制操作的情况下,高效地转移资源

Vue3+elementplus实现图片上传下载(最强实践)

图片上传子组件: 实现照片的上传,预览,以及转成以逗号隔开的图片地址,即时监听,并发送消息到父组件。 <!-- ImageUploader.vue --> <template><div><el-upload class="avatar-uploader" :http-request="customUpload" :before-upload="beforeUpload":show-fil