判别饮用水可饮用的多机器学习模型

2024-04-21 03:52

本文主要是介绍判别饮用水可饮用的多机器学习模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

注意:本文引用自专业人工智能社区Venus AI

更多AI知识请参考原站 ([www.aideeplearning.cn])

项目背景

饮用水是人类生存的基本需求之一,也是维护健康和有效保护健康政策的重要组成部分。因此,确保饮用水质量对于国家、地区和地方层面的健康和发展至关重要。在某些地区,已经证明投资于供水和卫生设施可以产生净经济效益,因为减少了不良健康效应和医疗成本,这些成本超过了实施干预措施的成本。

项目目标

本项目的主要目标是建立一个机器学习模型,通过水质指标来预测饮用水是否安全可饮用。我们将利用水质数据集中的各种指标来训练模型,以便快速、准确地判断水是否适合人类消费。这将有助于政府、水供应公司和公众监控和确保饮用水的质量,从而维护健康和提高生活质量。

项目应用

这个项目的应用潜力非常广泛。一些潜在的应用包括:

  1. 饮用水供应公司:可以使用该模型来定期检查饮用水质量,确保其符合标准,并采取必要的措施来解决潜在问题。
  2. 政府监管机构:可以使用该模型来监测和调查水质问题,确保公众的健康和安全。
  3. 智能家居设备:家用净水器或自动饮水机可以使用该模型来检测进入系统的水是否安全。
  4. 公众健康宣传:政府和非营利组织可以使用这一模型来提高公众对饮用水质量的意识,鼓励人们保持警惕。

数据集描述

我们将使用名为”water_potability.csv”的数据集,其中包含了3276个不同水体的水质指标。以下是数据集中的主要特征:

  1. pH值:评估水的酸碱平衡的重要参数。WHO建议的pH值范围为6.5到8.5。
  2. 硬度:主要由钙和镁盐引起。硬度可影响水的肥皂性能。
  3. 溶解固体总量 (TDS):反映水中的矿物质溶解度。高TDS值表示水中的矿物质含量高。
  4. 氯胺:主要用于处理饮用水的消毒剂。
  5. 硫酸盐:天然存在于土壤、岩石和水中的物质。
  6. 电导率:反映水中溶解物质的离子浓度。
  7. 有机碳:反映水中的有机物含量。
  8. 三卤甲烷:可能存在于用氯处理的水中。
  9. 浊度:反映水中固体物质的数量。
  10. 饮用水可饮性:1表示可饮,0表示不可饮。

模型选择与依赖库

为了预测饮用水的可饮性,我们将使用以下机器学习模型进行训练和比较:

  1. Logistic回归
  2. KNN分类器
  3. Gaussian朴素贝叶斯
  4. 决策树
  5. 随机森林分类器
  6. 梯度提升分类器
  7. AdaBoost分类器
  8. XGBoost分类器

在项目中,我们将使用以下Python库来进行数据预处理、可视化和模型训练:

数据预处理和探索性数据分析(Preprocessing & EDA):

  • pandas
  • seaborn
  • matplotlib

模型训练(Model Training):

  • sklearn
  • xgboost

通过这个项目,我们将能够快速而准确地评估水的质量,并为决策制定者、供水公司和公众提供有关饮用水是否安全的重要信息。这将有助于确保人们享有高质量的饮用水,从而维护和提高健康水平。

代码实现

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as pltfrom sklearn.model_selection import train_test_split, cross_val_score, cross_validate
from sklearn.metrics import confusion_matrix, classification_report, accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, roc_curve
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier
from sklearn.neural_network import MLPClassifier
from xgboost import XGBClassifier
def warn(*args, **kwargs):pass
import warnings
warnings.warn = warn
data = pd.read_csv('water_potability.csv') print("{} rows and {} columns".format(*data.shape)) data.head(10)
3276 rows and 10 columns
phHardnessSolidsChloraminesSulfateConductivityOrganic_carbonTrihalomethanesTurbidityPotability
0NaN204.89045520791.3189817.300212368.516441564.30865410.37978386.9909702.9631350
13.716080129.42292118630.0578586.635246NaN592.88535915.18001356.3290764.5006560
28.099124224.23625919909.5417329.275884NaN418.60621316.86863766.4200933.0559340
38.316766214.37339422018.4174418.059332356.886136363.26651618.436524100.3416744.6287710
49.092223181.10150917978.9863396.546600310.135738398.41081311.55827931.9979934.0750750
55.584087188.31332428748.6877397.544869326.678363280.4679168.39973554.9178622.5597080
610.223862248.07173528749.7165447.513408393.663396283.65163413.78969584.6035562.6729890
78.635849203.36152313672.0917644.563009303.309771474.60764512.36381762.7983094.4014250
8NaN118.98857914285.5838547.804174268.646941389.37556612.70604953.9288463.5950170
911.180284227.23146925484.5084919.077200404.041635563.88548117.92780671.9766014.3705620
data.duplicated().sum()
# There are no duplicated rows

0

data.describe()
phHardnessSolidsChloraminesSulfateConductivityOrganic_carbonTrihalomethanesTurbidityPotability
count2785.0000003276.0000003276.0000003276.0000002495.0000003276.0000003276.0000003114.0000003276.0000003276.000000
mean7.080795196.36949622014.0925267.122277333.775777426.20511114.28497066.3962933.9667860.390110
std1.59432032.8797618768.5708281.58308541.41684080.8240643.30816216.1750080.7803820.487849
min0.00000047.432000320.9426110.352000129.000000181.4837542.2000000.7380001.4500000.000000
25%6.093092176.85053815666.6902976.127421307.699498365.73441412.06580155.8445363.4397110.000000
50%7.036752196.96762720927.8336077.130299333.073546421.88496814.21833866.6224853.9550280.000000
75%8.062066216.66745627332.7621278.114887359.950170481.79230416.55765277.3374734.5003201.000000
max14.000000323.12400061227.19600813.127000481.030642753.34262028.300000124.0000006.7390001.000000
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3276 entries, 0 to 3275
Data columns (total 10 columns):#   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  0   ph               2785 non-null   float641   Hardness         3276 non-null   float642   Solids           3276 non-null   float643   Chloramines      3276 non-null   float644   Sulfate          2495 non-null   float645   Conductivity     3276 non-null   float646   Organic_carbon   3276 non-null   float647   Trihalomethanes  3114 non-null   float648   Turbidity        3276 non-null   float649   Potability       3276 non-null   int64  
dtypes: float64(9), int64(1)
memory usage: 256.1 KB
data.isna().sum()
ph                 491
Hardness             0
Solids               0
Chloramines          0
Sulfate            781
Conductivity         0
Organic_carbon       0
Trihalomethanes    162
Turbidity            0
Potability           0
dtype: int64
# 使用Python的matplotlib库和seaborn库创建一个热力图(heatmap),用于可视化数据集中缺失值的情况。
plt.rcParams['figure.figsize'] = (10, 6)missing_val_heatmap = sns.heatmap(data.notna(), cbar=False, cmap="Blues", cbar_kws={'label': 'Missing Values'})
missing_val_heatmap.set_title("Missing Val Heatmap")
missing_val_heatmap.set_xlabel("Features")
missing_val_heatmap.set_ylabel("Rows")
Text(95.72222222222221, 0.5, 'Rows')

数据集中存在多个缺失值

  • 酸碱度(ph)
  • 硫酸盐(sulfate)
  • 三卤甲烷(Trihalomethanes)

数据分析

data['Potability'].value_counts()
0    1998
1    1278
Name: Potability, dtype: int64

数据集相对均衡,负样本偏多。

# Pie cart for Potability
data['Potability'].value_counts().plot.pie(autopct='%1.1f%%', startangle=90, explode=(0.1, 0), figsize=(12, 6),labels=['Not Potable', 'Potable'],colors=['coral', 'lightblue'],)
<Axes: ylabel='Potability'>

f"{data['Potability'].value_counts()[0]/data.shape[0] * 100 :.1f}% 的水不可饮用"
'61.0% 的水不可饮用'
特征分布的可视化
fig, ax= plt.subplots(nrows=3,ncols=3,figsize=(15,15), constrained_layout=True)plt.suptitle('Feature distribution by Potability of Water', weight='bold', size=20)for i, feature in enumerate(data.columns[:-1]):plt.subplot(3,3,i+1)sns.kdeplot(data[feature])sns.kdeplot(data = data ,hue ='Potability',x=feature, palette=['coral', 'lightblue'])

fig, ax= plt.subplots(nrows=3,ncols=3,figsize=(15,15), constrained_layout=True)plt.suptitle('Feature distribution by Potability of Water', weight='bold', size=20)for i, feature in enumerate(data.columns[:-1]):plt.subplot(3,3,i+1)sns.boxplot(data = data ,x ='Potability',y=feature, palette=['coral', 'lightblue'])

从箱型图中,我们可以看到分布可能存在有异常值。

corr = data.corr()
f, ax = plt.subplots(figsize=(12, 10))
cmap = 'YlGnBu'sns.heatmap(corr, annot=True, cmap=cmap, ax=ax)
<Axes: >

我们可以看到,没有一个特征彼此之间具有很高的相关性。 这使得预测缺失值变得困难。

sns.pairplot(data = data, hue = 'Potability', palette=['coral', 'lightblue'])
<seaborn.axisgrid.PairGrid at 0x1bdb78773d0>

特征工程

特征分布
missing_values = data.isna().sum()*100/data.shape[0]
missing_values = missing_values[missing_values>0]
missing_values.sort_values(inplace=True,ascending=False)sns.barplot(x=missing_values.index,y=missing_values.values)
plt.title('Missing Values %')
plt.show()

# Sulfate
upper_sul = data['Sulfate'].mean() + 3*data['Sulfate'].std()
lower_sul = data['Sulfate'].mean() - 3*data['Sulfate'].std()
sulfate_mean = data[(data['Sulfate']>=lower_sul) &(data['Sulfate']<=upper_sul)]['Sulfate'].mean()
# Replacing with mean
data['Sulfate'].fillna(sulfate_mean,inplace=True)
# PH
upper_ph = data['ph'].mean() + 3*data['ph'].std()
lower_ph = data['ph'].mean() - 3*data['ph'].std()
ph_mean = data[(data['ph']>=lower_ph) &(data['ph']<=upper_ph)]['ph'].mean()
# Replacing with mean
data['ph'].fillna(ph_mean,inplace=True)
# Trihalomethanes
upper_tri = data['Trihalomethanes'].mean() + 3*data['Trihalomethanes'].std()
lower_tri = data['Trihalomethanes'].mean() - 3*data['Trihalomethanes'].std()
trihalomethanes_mean = data[(data['Trihalomethanes']>=lower_tri) &(data['Trihalomethanes']<=upper_tri)]['Trihalomethanes'].mean()
# Replacing with mean
data['Trihalomethanes'].fillna(trihalomethanes_mean,inplace=True)
data.isna().sum()
ph                 0
Hardness           0
Solids             0
Chloramines        0
Sulfate            0
Conductivity       0
Organic_carbon     0
Trihalomethanes    0
Turbidity          0
Potability         0
dtype: int64
处理异常值

首先计算每个水质指标(除最后一个之外)的均值和标准差,然后使用均值减去三倍标准差和加上三倍标准差作为阈值,移除那些超出这个范围的异常值。最后,它打印出原始数据和经过清理后数据的行数,以及被移除的行数,并将清理后的数据集赋值给原始数据变量。

data_new = data.copy()
# for col in data_new.columns[:-1]:
#     mean = data_new[data_new[col].notna()][col].mean()
#     std = data_new[data_new[col].notna()][col].std()
#     low = mean - 3*std
#     high = mean + 3*std
#     data_new = data_new[(data_new[col] > low) & (data_new[col] < high)]# old_rows = data.shape[0]
# new_rows = data_new.shape[0]# print(f"Old rows: {old_rows}, New rows: {new_rows}, Removed rows: {old_rows - new_rows}")# data = data_new.copy()# This step is making the model perform worse

根据阈值设置的异常值删除后模型的性能反而下降,因此这里以结果为导向对异常值不进行处理

数据预处理


X = data_new.drop('Potability', axis=1).values
y = data_new['Potability'].values
划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)X_train.shape, X_test.shape, y_train.shape, y_test.shape
((2620, 9), (656, 9), (2620,), (656,))
标准化
from sklearn.preprocessing import StandardScalerscl = StandardScaler()
X_train = scl.fit_transform(X_train)
X_test = scl.transform(X_test)

创建模型

models = {'Logistic Regression': LogisticRegression(),'Knn': KNeighborsClassifier(),'Gaussian Naive Bayes': GaussianNB(),'Decision Tree': DecisionTreeClassifier(),'Random Forest': RandomForestClassifier(),'Adaboost': AdaBoostClassifier(),'Gradient Boosting': GradientBoostingClassifier(),'XGgboost': XGBClassifier(),'MLP': MLPClassifier(),
}
scoring = ['accuracy', 'precision', 'recall', 'f1', 'roc_auc']def get_model_result(model, X_train, y_train, X_test, y_test):scores = cross_validate(model, X_train, y_train, scoring=scoring, return_train_score=False, cv=5)result = {k.split('_')[1].title(): v.mean() for k, v in scores.items() if k not in ['fit_time', 'score_time']}return resultresults={}
for name,model in models.items():results[name] = get_model_result(model, X_train, y_train, X_test, y_test)results = pd.DataFrame(results).T
results = results.sort_values('Roc', ascending=False)
results
AccuracyPrecisionRecallF1Roc
MLP0.6763360.6342940.4293470.5108190.694688
Random Forest0.6637400.6328100.3568310.4550710.662103
XGgboost0.6335880.5442570.4439190.4884120.646361
Gradient Boosting0.6339690.5892470.2514380.3513970.632178
Knn0.6267180.5373780.3897710.4515480.625058
Gaussian Naive Bayes0.6209920.5500200.2398250.3326750.585986
Adaboost0.5919850.4684170.2059990.2851220.569846
Decision Tree0.5656490.4492550.4448760.4468260.544640
Logistic Regression0.6053440.3000000.0028990.0057150.501686

我们可以看到没有模型能够提供良好的精度。 这是可能因为特征之间的相关性非常低。

结论

  • 没有模型能够提供良好的精度,最大值约为 0.6。
  • 神经网络是该数据集的最佳模型。

代码和数据集下载

详情请见 判别饮用水可饮用的多机器学习模型-VenusAI (aideeplearning.cn)

这篇关于判别饮用水可饮用的多机器学习模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss