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

注意:本文引用自专业人工智能社区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 plt

from 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   float64
 1   Hardness         3276 non-null   float64
 2   Solids           3276 non-null   float64
 3   Chloramines      3276 non-null   float64
 4   Sulfate          2495 non-null   float64
 5   Conductivity     3276 non-null   float64
 6   Organic_carbon   3276 non-null   float64
 7   Trihalomethanes  3114 non-null   float64
 8   Turbidity        3276 non-null   float64
 9   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 StandardScaler

scl = 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 result
    

results={}
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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/560887.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3分钟看懂Microchip 32位MCU CAN模块的配置

文章目录 CAN模块系统框图Microchip MCC Harmony下CAN模块配置选项CAN模块工作模式CAN模块中断模式CAN工作速率Bit Timing Calculation配置CAN 接收的配置CAN 发送的配置CAN 过滤器工作流程说明CAN 过滤器的配置 CAN模块系统框图 CAN的英文全称&#xff1a;Control Area Networ…

通过linux工具iftop命令查看视频监控平台是否收到监控摄像头的视频流(视频监控平台接收和转发的视频流)

目录 一、需求描述 二、解决思路 &#xff08;一&#xff09;问题分析 &#xff08;二&#xff09;解决思路 1、通过抓包的方式 2、通过一些linux的网络监视工具 三、需求实现 &#xff08;一&#xff09;抓包工具 1、tcpdump 2、Wireshark 3、tcptrace &#xff0…

OpenHarmony 网络与连接—RPC连接

介绍 本示例使用ohos.rpc 相关接口&#xff0c;实现了一个前台选择商品和数目&#xff0c;后台计算总价的功能&#xff0c;使用rpc进行前台和后台的通信。 效果预览 使用说明&#xff1a; 点击商品种类的空白方框&#xff0c;弹出商品选择列表&#xff0c;选择点击对应的商品…

天软因子数据系列课堂回顾——“委托订单:流动性因子”

高频因子库4月更新&#xff0c;新增5张表单&#xff0c;51个因子。目前&#xff0c;高频因子数量扩容到628个&#xff0c;涵盖了从2000年开始的全A市场。本次“天软因子数据系列课堂”在线分享的即是最新发布因子列表之一的流动性因子&#xff0c;剖析微观角度下因子的底层逻辑…

什么是代理IP?如何正确使用代理IP?

代理IP&#xff08;Proxy IP&#xff09;是一种网络技术&#xff0c;它允许用户通过一个中介服务器&#xff08;即代理服务器&#xff09;来访问互联网。具体来说&#xff0c;代理IP隐藏了用户的真实IP地址&#xff0c;使用第三方的IP地址进行网络访问。当用户发起网络请求时&a…

Linux进阶篇:Centos7搭建smb服务

Centos7搭建smb服务 1 smb介绍 Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件&#xff0c;由服务器及客户端程序构成。SMB&#xff08;Server Messages Block&#xff0c;信息服务块&#xff09;是一种在局域网上共享文件和打印机的一种通信协议&#xff0c;它为局域…

数据结构-基于ArrayList的源码模拟

文章目录 继承关系 :1. 构造方法的模拟2. 扩容机制的分析3. 查找方法的模拟4. 获取,修改元素的方法模拟5. 添加元素的模拟6. 删除元素的模拟7. removeAll与retainAll的模拟总结: 边缘方法以及总代码 继承关系 : 1. 构造方法的模拟 源码中我们的ArrayList的构造方法给出了三种实…

基于SpringBoot+Vue的便利店管理系统 免费获取源码

项目源码获取方式放在文章末尾处 项目技术 数据库&#xff1a;Mysql5.7/8.0 数据表&#xff1a;11张 开发语言&#xff1a;Java(jdk1.8) 开发工具&#xff1a;idea 前端技术&#xff1a;vue 后端技术&#xff1a;SpringBoot 功能简介 (有文档) 项目获取关键字&#…

tcp-learner 数据包分析 20240420

输入输出&#xff1a; 数据包分析&#xff1a; learner和Adapter建立连接。 Learner让Adapter发送RST Adapter没有从SUT抓到任何回复&#xff0c;于是向learner发送timeout learner给adapter发送reset命令&#xff0c;让SUT重置。 这是第一次初始化&#xff0c;由于Adapter和…

7. DAX 时间函数-- DATE 日期--TOTALMTD、TOTALQTD、TOTALYTD

函数名目的语法返回值TOTALMTD计算当前上下文中该月份至今的表达式的值 。TOTALMTD ( <表达式>, <日期列>, [<筛选器>] )标量 表示表达式的标量值&#xff0c;在“日期”中给定日期&#xff0c;计算当前月份至今的日期 。TOTALQTD计算当前上下文中该季度至今…

452. 用最少数量的箭引爆气球[排序+贪心]

https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/description/?envTypestudy-plan-v2&envIdtop-interview-150 题目描述 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xst…

C++ 内存分区管理

一、栈区&#xff08;Stack&#xff09; 栈区用来存储函数的参数值、局部变量的值等数据。栈区是自动分配和释放的&#xff0c;函数执行时会在栈区分配空间&#xff0c;函数执行结束时会自动释放这些空间。栈区的数据是连续分配的&#xff0c;由系统自动管理。 注意事项&…

大话设计模式-依赖倒转原则

依赖倒转原则 在大话设计模式这本书中&#xff0c;作者通过电话修电脑这个例子引入了面向对象设计的基本原则之一&#xff1a;依赖倒转原则。 概念 依赖倒转原则是面向对象设计的基本原则之一&#xff0c;它用于减少类之间的耦合&#xff0c;提高系统的灵活性和可维护性。在…

明道云HAP合作伙伴计划全解析:开辟业务增长新路径

什么是明道云HAP合作伙伴计划&#xff1f; 明道云采纳的是增值伙伴商业模式。在这个模式下&#xff0c;合作伙伴通过平台型产品为终端客户提供定制应用、行业解决方案、赋能培训等增值活动&#xff0c;从而在大幅降低交付成本的同时获得多来源的收入&#xff0c;提高经营绩效水…

PLC中连接外部现场设备和CPU的桥梁——输入/输出(I/O)模块

输入&#xff08;Input&#xff09;模块和输出&#xff08;Output&#xff09;模块简称为I/O模块&#xff0c;数字量&#xff08;Digital&#xff0c;又称为开关量&#xff09;输入模块和数字量输出模块简称为DI模块和DQ模块&#xff0c;模拟量&#xff08;Analog&#xff09;输…

RK3568 android11 修改关机弹窗界面

需要修改关机弹窗界面&#xff0c;当前界面我已经按照客户需求去掉emergency 但是客户需要按其他区域可以实现返回&#xff0c;也就是点击黑色背景取消dialog 嗑代码发现黑色布局为&#xff1a; <node index"0" text"" resource-id"com.android.…

【Redis】string数据类型

文章目录 常用命令setsetnx & NXXXsetex & EXpsetex & PX msetget & mgetincr & decrincrby & decrbyincrbyfloatappendgetrangesetrangestrlen 内部编码 字符串类型是 Redis 最基础的数据类型。 在redis中所有的键都是 string 类型&#xff0c;其他的…

oracle操作系统OS认证和密码文件认证

1 说明 1.1 常见认证方式 Oracle登录认证方式主要涉及到如何验证用户身份以访问数据库。Oracle数据库提供了多种认证机制来确保数据的安全性和访问控制&#xff0c;每种方式都有其特定的使用场景和安全性考虑。以下是Oracle中常见的登录认证方式&#xff1a; 1、基于操作系统…

Vue-鼠标悬浮在缩略图图片上,弹出原图

使用Popover 弹出框实现 <template><div><el-popoverplacement"right"width"400"trigger"hover"><img src"https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x36…

三维天地低代码平台实现客户需求的快速交付与灵活定制

— 款合格的低代码平台应具备架构稳定、 产品质量高、 交付速度快、 运维简便的特点, 能快速实现业务需求到系统功能落地。 二十余年来, 北京三维天地科技股份有限公司一直专注于实验室信息化管理 领域, 旗下 SW- LIMS 已在化工、 环保、 食品、 科研等二十余个行业广泛应用,服…