【intel校企合作课程】预测淡水质量

1.作业简介:预测淡水质量

1.1问题描述

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

1.2预期解决方案

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

1.3要求

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

1.4数据集

        https://filerepo.idzcn.com/hack2023/datasetab75fb3.zip

2.数据探索

2.1导入相应的包

        准备所需的库和工具,以便后续进行数据处理、模型训练和评估等任务。

import os
import time
import warnings
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.io as pio
import plotly.graph_objects as go
import xgboost
from xgboost import XGBClassifier
import sklearn
from sklearn.utils import resample
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV, RandomizedSearchCV
from sklearn.preprocessing import RobustScaler
from sklearn.metrics import roc_auc_score, roc_curve, auc, accuracy_score, f1_score
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import precision_recall_curve, average_precision_score
# !pip install modin dask
import modin.pandas as pd
os.environ["MODIN_ENGINE"] = "dask"
from modin.config import Engine
Engine.put("dask")

Modin是一个Python第三方库,可以通过并行来处理大数据集。其中语法与pandas相近,拥有出色的性能弥 补了pandas处理大型数据集的缺陷。

而Dask 是一个用于分析计算的灵活的并行计算库,实现大型多维数据集分析的更快执行以及加速和扩展数据科学制作流程或工作流程的强大工具。

2.2查看数据集

data = pandas.read_csv('./dataset.csv')
print('数据规模:{}\n'.format(data.shape))
display(data.head())

data=data.infer_objects()
data.info()

分析上图结果:

数据集大小:包含5,956,842条记录,占用大约1.1+ GB的内存。

数据类型:数据集包含24列,其中19列是浮点型(float64),2列是整型(int64),3列是对象型(object)。

2.3数据因子化操作

display(data.head())
factor = pd.factorize(data['Color'])
print(factor)
data.Color = factor[0]
factor = pd.factorize(data['Source'])
print(factor)
data.Source = factor[0]
factor = pd.factorize(data['Month'])
print(factor)
data.Month = factor[0]

经过这段代码处理后,data DataFrame中的Color、Source和Month列将不再包含原始的字符串值,而是被替换为整数编码。这种转换有助于简化后续的数据处理和机器学习建模,因为算法通常更容易处理数值型数据。

 2.4查看数据统计性描述

desc=data.describe()
skewness=data.skew()
kurtosis=data.kurtosis()
skewness_df = pd.DataFrame([skewness], index=['Skewness'], columns=data.columns)
desc=pd.concat([desc, skewness_df], axis=0)
kurtosis_df = pd.DataFrame([kurtosis], index=['Kurtosis'], columns=data.columns)
desc=pd.concat([desc, kurtosis_df], axis=0)
display(desc.style.format('{:,.3f}').background_gradient(subset=(desc.index[1:],desc.columns[:]),cmap='OrRd'))

这段代码的主要目的是计算并显示数据集中数值列的统计描述、偏度(Skewness)和峰度(Kurtosis),并通过颜色渐变的方式直观地展示这些统计量的数值大小。

2.5数据可视化

2.2.1饼状图

这段代码的主要目的是查看 Target 列中各个类别的出现次数,并将这些信息以饼图的形式进行可视化。

print(data.Target.value_counts())
target = data.Target.value_counts()
target.rename(index={1: 'Target 1', 0: 'Target 0'}, inplace=True)
plt.pie(target, [0, 0.05], target.index, autopct='%1.1f%%')
plt.show()

 2.2.2热力图

corr = plt.subplots(figsize = (30,20),dpi=128)
corr= sns.heatmap(data.corr(method='spearman'),annot=True,square=True)

这段代码的主要作用是创建一个热力图(heatmap)来展示data DataFrame中各个数值特征之间的Spearman相关性。这种可视化方式有助于快速识别哪些特征之间可能存在强相关性或潜在的多重共线性问题。

3.数据预处理

3.1相关性分析

bar = data.corr()['Target'].abs().sort_values(ascending=False)[1:]
 
plt.bar(bar.index, bar, width=0.5)
pos_list = np.arange(len(data.columns))
params = {
    'figure.figsize': '40, 10'
}
plt.rcParams.update(params)
plt.xticks(bar.index, bar.index, rotation=-60, fontsize=10)
plt.show()

这段代码的目的是为了快速识别data DataFrame中哪些特征与目标变量Target具有较强的Spearman相关性。通过条形图,可以直观地看到每个特征与目标变量之间的相关性大小。

data =data.drop(
    columns=['Index', 'Day', 'Time of Day', 'Water Temperature',
             'Conductivity', 'Air Temperature','Month','Source'],axis=1)

这段代码用于删除不相关的列。

3.2查看重复值和缺失值

display(data.isna().sum())
missing = data.isna().sum().sum()
duplicates = data.duplicated().sum()
print("\nThere are {:,.0f} missing values in the data.".format(missing))
print("There are {:,.0f} duplicate records in the data.".format(duplicates))

 这段代码的主要作用是对数据进行检查,以确定其中缺失值的数量和重复记录的数量,并打印这些信息。

3.3处理重复值和缺失值

data = data.fillna(0)
data = data.drop_duplicates()

这段代码继续对数据进行处理。首先,将所有缺失值(NaN)替换为数字 0。

然后,删除 DataFrame 中的所有重复行。

 3.4数据清洗-偏差值处理

from scipy.stats import pearsonr

variables = data.columns
df = data
 
var = df.var()
numeric = df.columns
df = df.fillna(0)
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))

删除相关性较弱的数据,保留相关性较强的数据

3.5数据平衡,标准化处理

from imblearn.under_sampling import RandomUnderSampler

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)
 
X = df.drop('Target', 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

这段代码的主要目的是对一个数据框进行处理,解决类别不平衡问题,并对数据进行标准化处理,使其更适合机器学习模型的训练。

4.模型训练

4.1模型参数设置

from sklearn.metrics import make_scorer, precision_score, recall_score, accuracy_score,f1_score, roc_auc_score
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),
}

1.定义了一个参数网格(param_grid):这个网格包含了多个超参数和它们各自的可能值。这些超参数是用于配置机器学习模型(特别是像XGBoost这样的树模型)的。在参数调优过程中,网格搜索(如GridSearchCV)会遍历这个网格中的所有参数组合,以找出最佳的参数组合。

2.定义了一个评分器字典(scorers):这个字典包含了多个评分函数,每个评分函数都通过make_scorer函数从sklearn.metrics中转换而来。在机器学习模型评估时,这些评分函数可以用于评估模型的性能。

4.2配置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)

这段代码创建了一个配置好的XGBoost分类器对象,该对象准备好用于训练数据,并根据提供的参数进行模型训练。

4.3模型训练

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=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)

这段代码使用随机搜索(Randomized Search)来优化XGBoost分类器的超参数,并输出最佳参数、最佳得分、最佳估计器以及运行时间。

5.推理评估

5.1使用划分的测试集进行推理

from datetime import datetime
inference_start_time = datetime.now()
 
y_pred = rd_search.best_estimator_.predict(X_test)

inference_time = datetime.now() - inference_start_time
print("模型推理时间:", inference_time)
f1 = f1_score(y_test, y_pred)
print("模型在测试集上的f1分数:", f1)

 

5.2使用统一的数据集进行推理

test_df = pd.read_csv('./test_data.csv')
 
factor = pd.factorize(test_df['Color'])
test_df.Color = factor[0]
factor = pd.factorize(test_df['Source'])
test_df.Source = factor[0]
factor = pd.factorize(test_df['Month'])
test_df.Month = factor[0]
 
test_df
 
test_df = test_df.drop(
    columns=['Index', 'Day', 'Time of Day', 'Month', 'Water Temperature', 'Source', 'Conductivity', 'Air Temperature'])
 
test_df = test_df.fillna(0)
test_df = df.drop_duplicates()
 
from imblearn.under_sampling import RandomUnderSampler
import datetime
 
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)
 
X = df.drop('Target', 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)
 
X_train, X_test = X_train_scaled, X_test_scaled

import pandas as pd
from datetime import datetime

inference_start_time = datetime.now()
y_pred = rd_search.best_estimator_.predict(X_test)

inference_time = datetime.now() - inference_start_time
print("模型推理时间:", inference_time)
 
f1 = f1_score(y_test, y_pred)
print("模型在测试集上的f1分数:", f1)

模型推理时间:

时间为0:00:00.413491,这表示模型进行单次推理(可能是单个样本或多个样本的预测)所花费的时间大约是0.41秒。这个推理时间相对较快,表明模型可以在短时间内完成预测,对于需要实时响应或高频次调用的应用场景,这样的速度是可以接受的。

模型在测试集上的F1分数:

F1分数为0.831418,这是一个相对较高的分数。F1分数是精确率和召回率的调和平均值,通常用于评估分类模型的性能,特别是在类别不平衡的情况下。F1分数越高,表示模型在精确率和召回率之间取得了较好的平衡,模型的整体性能越好。

具体来说,F1分数在0.8到0.9之间通常被认为是优秀的性能,这表明模型在大多数情况下能够正确分类样本,并且对于正类和负类的识别能力都比较强。综合以上分析,可以得出以下结论:

1.模型在推理速度方面表现良好,可以在短时间内完成预测。

2.模型在测试集上的F1分数较高,表明其分类性能优秀,能够较好地处理分类任务。

这些结果表明,该模型在实际应用中可能具有较好的性能,但仍需结合具体的应用场景和业务需求来进一步评估模型的适用性和可靠性。此外,为了持续提高模型的性能,还可以考虑使用更多的数据、更复杂的模型结构或更先进的训练技术来进一步优化模型。

 5.3结果可视化

from scipy import interp
 
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])
    fpr, tpr, thresholds = roc_curve(y_test[test], probas_[:, 1])
    tprs.append(interp(mean_fpr, fpr, tpr))
    tprs[-1][0] = 0.0
    roc_auc = auc(fpr, tpr)
    aucs.append(roc_auc)
    plt.plot(fpr, tpr, lw=1.5,linestyle = linetypes[i], alpha=0.8,
             label='ROC fold %d (AUC = %0.2f)' % (i, roc_auc))
 
    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()

 这段代码主要用于绘制ROC曲线,并计算其AUCArea Under the Curve,曲线下面积)值,以评估分类模型的性能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值