解决几乎任何机器学习问题 -- 学习笔记(组织机器学习项目)

news2024/11/17 15:26:17

书籍名:Approaching (Almost) Any Machine Learning Problem-解决几乎任何机器学习问题
此专栏记录学习过程,内容包含对这本书的翻译和理解过程

我们首先来看看文件的结构。对于你正在做的任何项目,都要创建一个新文件夹。在本例中,我
将项目命名为 “project” 。

项目文件夹内部应该如下所示。

  • input
    • train.csv
    • test.csv
  • src
    • create_folds.py
    • train.py
    • inference.py
    • models.py
    • config.py
    • model_dispatcher.py
  • models
    • model_rf.bin
    • model_et.bin
  • notebooks
    • exploration.ipynb
    • check_data.ipynb
  • README.md
  • LICENSE

让我们来看看这些文件夹和文件的内容。

**input/ **该文件夹包含机器学习项目的所有输入文件和数据。如果您正在开发 NLP 项目,您可以将 embeddings 放在这里。如果是图像项目,所有图像都放在该文件夹下的子文件夹中。
**scr/**我们将在这里保存与项目相关的所有 python 脚本。如果我说的是一个 python 脚本,即任何 *.py 文件,它都存储在 src 文件夹中。
** models/ **该文件夹保存所有训练过的模型。
**notebook/ **所有 jupyter notebook (即任何 *.ipynb 文件)都存储在笔记本 文件夹中。
**README.md **这是一个标记符文件,您可以在其中描述您的项目,并写明如何训练模型或在生产环境中使用。
**LICENSE **这是一个简单的文本文件,包含项目的许可证,如 MIT 、 Apache 等。关于许可证的详细介绍超出了本书的范围。

假设你正在建立一个模型来对 MNIST 数据集(几乎每本机器学习书籍都会用到的数据集)进行分类。如果你还记得,我们在交叉检验一章中也提到过 MNIST 数据集。网上有许多不同格式的 MNIST 数据集,但我们将使用 CSV 格式的数据集。

在这种格式的数据集中, CSV 的每一行都包含图像的标签和 784 个像素值,像素值范围从 0 到255 。数据集包含 60000 张这种格式的图像。

我们可以使用 pandas 轻松读取这种数据格式。

请注意,尽管图 1 显示所有像素值均为零,但事实并非如此。

在这里插入图片描述
图 1 : CSV 格式的 MNIST 数据集
在这里插入图片描述
我们不需要对这个数据集进行更多的探索。我们已经知道了我们所拥有的数据,没有必要再对不同的像素值进行绘图。从图 2 中可以清楚地看出,标签的分布相当均匀。因此,我们可以使用准确率 /F1 作为衡量标准。这就是处理机器学习问题的第一步:确定衡量标准!

现在,我们可以编写一些代码了。我们需要创建 src/ 文件夹和一些 python 脚本。

请注意,训练 CSV 文件位于 input/ 文件夹中,名为 mnist_train.csv 。

首先要创建的脚本是 create_folds.py 。

这将在 input/ 文件夹中创建一个名为 mnist_train_folds.csv 的新文件,与 mnist_train.csv 相同。唯一不同的是,这个 CSV 文件经过了随机排序,并新增了一列名为 kfold 的内容。一旦我们决定了要使用哪种评估指标并创建了折叠,就可以开始创建基本模型了。这可以在train.py 中完成。

import joblib
import pandas as pd
from sklearn import metrics
from sklearn import tree
def run(fold):
	# 读取数据文件
	df = pd.read_csv("../input/mnist_train_folds.csv")
	
	# 选取df中kfold列不等于fold
	df_train = df[df.kfold != fold].reset_index(drop=True)
	# 选取df中kfold列等于fold
	df_valid = df[df.kfold == fold].reset_index(drop=True)
	
	# 训练集输入,删除label列
	x_train = df_train.drop("label", axis=1).values
	# 训练集输出,取label列
	y_train = df_train.label.values
	
	# 验证集输入,删除label列
	x_valid = df_valid.drop("label", axis=1).values
	# 验证集输出,取label列
	y_valid = df_valid.label.values
	
	# 实例化决策树模型
	clf = tree.DecisionTreeClassifier()
	# 使用训练集训练模型
	clf.fit(x_train, y_train)
	
	# 使用验证集输入得到预测结果
	preds = clf.predict(x_valid)
	
	# 计算验证集准确率
	accuracy = metrics.accuracy_score(y_valid, preds)
	# 打印fold信息和准确率
	print(f"Fold={fold}, Accuracy={accuracy}")
	# 保存模型
	joblib.dump(clf, f"../models/dt_{fold}.bin")
if __name__ == "__main__":
	# 运行每个折叠
	run(fold=0)
	run(fold=1)
	run(fold=2)
	run(fold=3)
	run(fold=4)

您可以在控制台调用 python train.py 运行该脚本。

❯ python train.py
	Fold=0, Accuracy=0.8680833333333333
	Fold=1, Accuracy=0.8685
	Fold=2, Accuracy=0.8674166666666666
	Fold=3, Accuracy=0.8703333333333333
	Fold=4, Accuracy=0.8699166666666667

查看训练脚本时,您会发现还有一些内容是硬编码的,例如折叠数、训练文件和输出文件夹。

因此,我们可以创建一个包含所有这些信息的配置文件: config.py 。

TRAINING_FILE = "../input/mnist_train_folds.csv"
MODEL_OUTPUT = "../models/"

我们还对训练脚本进行了一些修改。训练文件现在使用配置文件。这样,更改数据或模型输出就更容易了。

import os
import config
import joblib
import pandas as pd
from sklearn import metrics
from sklearn import tree
def run(fold):
	# 使用config中的路径读取数据
	df = pd.read_csv(config.TRAINING_FILE)
	df_train = df[df.kfold != fold].reset_index(drop=True)
	df_valid = df[df.kfold == fold].reset_index(drop=True)
	x_train = df_train.drop("label", axis=1).values
	y_train = df_train.label.values
	x_valid = df_valid.drop("label", axis=1).values
	y_valid = df_valid.label.values
	clf = tree.DecisionTreeClassifier()
	clf.fit(x_train, y_train)
	preds = clf.predict(x_valid)
	accuracy = metrics.accuracy_score(y_valid, preds)
	print(f"Fold={fold}, Accuracy={accuracy}")
	joblib.dump(clf,os.path.join(config.MODEL_OUTPUT, f"dt_{fold}.bin") )
if __name__ == "__main__":
	# 运行每个折叠
	run(fold=0)
	run(fold=1)
	run(fold=2)
	run(fold=3)
	run(fold=4)

请注意,我并没有展示这个培训脚本与之前脚本的区别。请仔细阅读这两个脚本,自己找出不同之处。区别并不多。

与训练脚本相关的还有一点可以改进。正如你所看到的,我们为每个折叠多次调用运行函数。有时,在同一个脚本中运行多个折叠并不可取,因为内存消耗可能会不断增加,程序可能会崩溃。为了解决这个问题,我们可以向训练脚本传递参数。我喜欢使用 argparse 。

import argparse
if __name__ == "__main__":
	# 实例化参数环境
	parser = argparse.ArgumentParser()
	# fold参数
	parser.add_argument( "--fold", type=int)
	# 读取参数
	args = parser.parse_args()
	run(fold=args.fold)

现在,我们可以再次运行 python 脚本,但仅限于给定的折叠。

❯ python train.py --fold 0
	Fold=0, Accuracy=0.8656666666666667

仔细观察,我们的第 0 折得分与之前有些不同。这是因为模型中存在随机性。我们将在后面的章节中讨论如何处理随机性。

现在,如果你愿意,可以创建一个 shell 脚本,针对不同的折叠使用不同的命令,然后一起运行,如下图所示。

python train.py --fold 0
python train.py --fold 1
python train.py --fold 2
python train.py --fold 3
python train.py --fold 4

您可以通过以下命令运行它。

❯ sh run.sh
Fold=0, Accuracy=0.8675
Fold=1, Accuracy=0.8693333333333333
Fold=2, Accuracy=0.8683333333333333
Fold=3, Accuracy=0.8704166666666666
Fold=4, Accuracy=0.8685

我们现在已经取得了一些进展,但如果我们看一下我们的训练脚本,我们仍然受到一些东西的限制,例如模型。模型是硬编码在训练脚本中的,只有修改脚本才能改变它。因此,我们将创建一个新的 python 脚本,名为 model_dispatcher.py 。model_dispatcher.py ,顾名思义,将调度我们的模型到训练脚本中。

from sklearn import tree
models = {
	# 以gini系数度量的决策树
	"decision_tree_gini": tree.DecisionTreeClassifier(
		criterion="gini"
	),
	# 以entropy系数度量的决策树
	"decision_tree_entropy": tree.DecisionTreeClassifier(
		criterion="entropy"
	),
}

model_dispatcher.py从 scikit-learn 中导入了 tree ,并定义了一个字典,其中键是模型的名称,值是模型本身。在这里,我们定义了两种不同的决策树,一种使用基尼标准,另一种使用熵标准。要使用 py ,我们需要对训练脚本做一些修改。

import argparse
import os
import joblib
import pandas as pd
from sklearn import metrics
import config
import model_dispatcher
def run(fold, model):
	df = pd.read_csv(config.TRAINING_FILE)
	df_train = df[df.kfold != fold].reset_index(drop=True)
	df_valid = df[df.kfold == fold].reset_index(drop=True)
	x_train = df_train.drop("label", axis=1).values
	y_train = df_train.label.values
	x_valid = df_valid.drop("label", axis=1).values
	y_valid = df_valid.label.values
	
	# 根据model参数选择模型
	clf = model_dispatcher.models[model]
	clf.fit(x_train, y_train)
	preds = clf.predict(x_valid)
	accuracy = metrics.accuracy_score(y_valid, preds)
	print(f"Fold={fold}, Accuracy={accuracy}")
	joblib.dump( clf,os.path.join(config.MODEL_OUTPUT, f"dt_{fold}.bin"))
	
if __name__ == "__main__":
	parser = argparse.ArgumentParser()
	# fold参数
	parser.add_argument("--fold", type=int)
	# model参数
	parser.add_argument("--model", type=str)
	args = parser.parse_args()
	run(fold=args.fold, model=args.model)

train.py有几处重大改动:

  • 导入 model_dispatcher
  • 为 ArgumentParser 添加 --model 参数
  • 为 run() 函数添加 model 参数
  • 使用调度程序获取指定名称的模型

现在,我们可以使用以下命令运行脚本:

❯ python train.py --fold 0 --model decision_tree_gini
Fold=0, Accuracy=0.8665833333333334

或执行以下命令

❯ python train.py --fold 0 --model decision_tree_entropy
Fold=0, Accuracy=0.8705833333333334

现在,如果要添加新模型,只需修改 model_dispatcher.py 。让我们尝试添加随机森林,看看准
确率会有什么变化。

from sklearn import ensemble
from sklearn import tree
models = {
	"decision_tree_gini": tree.DecisionTreeClassifier(
		criterion="gini"
	),
	"decision_tree_entropy": tree.DecisionTreeClassifier(
		criterion="entropy"
	),
	# 随机森林模型
	"rf": ensemble.RandomForestClassifier(),
}

让我们运行这段代码。

❯ python train.py --fold 0 --model rf
Fold=0, Accuracy=0.9670833333333333

一个简单的改动就能让分数有如此大的提升!现在,让我们使用 run.sh 脚本运行 5 个折叠!

python train.py --fold 0 --model rf
python train.py --fold 1 --model rf
python train.py --fold 2 --model rf
python train.py --fold 3 --model rf
python train.py --fold 4 --model rf

得分情况如下

❯ sh run.sh
Fold=0, Accuracy=0.9674166666666667
Fold=1, Accuracy=0.9698333333333333
Fold=2, Accuracy=0.96575
Fold=3, Accuracy=0.9684166666666667
Fold=4, Accuracy=0.9666666666666667

示如何为你正在做的或计划在不久的将来做的几乎所有机器学习项目编写一个基本框架。有许多不同的方法可以改进这个 MNIST 模型和这个框架,我们将在以后的章节中看到。

我使用了一些脚本,如 model_dispatcher.py 和 config.py ,并将它们导入到我的训练脚本中。请注意,我没有导入 * ,你也不应该导入。如果我导入了 * ,你就永远不会知道模型字典是从哪里来的。编写优秀、易懂的代码是一个人必须具备的基本素质,但许多数据科学家却忽视了这一点。如果你所做的项目能让其他人理解并使用,而无需咨询你的意见,那么你就节省了他们的时间和自己的时间,可以将这些时间投入到改进你的项目或开发新项目中去。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Perplexity AI免费白嫖GPT4的使用次数((智能搜索工具)

一、Perplexity AI是什么 Perplexity AI是一款高质量的智能搜索工具,它可以为用户提供简洁清晰的搜索体验。Perplexity AI内置了基于GPT-4的Copilot搜索功能,用户可以在每四个小时使用五次(白嫖GPT-4)。此外,Perplexity AI有免费和付费&#…

Python是个什么鬼?朋友靠它拿了5个offer

闺蜜乐乐,外院科班出身,手持专八和CATTI证书,没想到找工作时却碰了钉子… 半夜12点,乐乐跟我开启了吐槽模式: 拿到offer的都是小公司的翻译活儿,只能糊个口。稍微好点的平台要求可就多了,不仅语…

以“防方视角”观文件上传功能

为方便您的阅读,可点击下方蓝色字体,进行跳转↓↓↓ 01 案例概述02 攻击路径03 防方思路 01 案例概述 这篇文章来自微信公众号“NearSec”,记录的某师傅接到一个hw项目,在充分授权的情况下,针对客户的系统进行渗透测试…

java计算下一个整10分钟时间点

最近工作上遇到需要固定在整10分钟一个周期调度某个任务,所以需要这样一个功能,记录下 package org.example;import com.google.gson.Gson; import org.apache.commons.lang3.time.DateUtils;import java.io.InputStream; import java.util.Calendar; i…

原型 原型对象 原型链

在面向开发对象开发过程中对每一个实例添加方法,会使每一个对象都存在该添加方法造成空间浪费 通过对原型添加公共的属性或方法,使所有实例对象都可访问 原型为了共享公共的成员 prototype 原型: JS为每个构造函数提供一个属性prototype(原型),它的值…

Redis与Mysql的数据强一致性方案

目的 Redis和Msql来保持数据同步,并且强一致,以此来提高对应接口的响应速度,刚开始考虑是用mybatis的二级缓存,发现坑不少,于是决定自己搞 要关注的问题点 操作数据必须是唯一索引 如果更新数据不是唯一索引&#…

原生小程序图表

原生小程序使用图表 话不多说直接进入正题 官方文档: https://www.ucharts.cn/v2/#/ 下载文件 首先去gitee上把文件下载到自己的项目中 https://gitee.com/uCharts/uCharts 找到微信小程序和里面的组件 把里面src下的文件全部下载下来放入自己项目中 项目文件 新建文件…

hdlbits系列verilog解答(Exams/m2014 q4h)-44

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 实现以下电路: 二、verilog源码 module top_module (input in,output out);assign out in;endmodule三、仿真结果 转载请注明出处!

java集合,ArrayList、LinkedList和Vector,多线程场景下如何使用 ArrayList

文章目录 Java集合1.2 流程图关系1.3 底层实现1.4 集合与数组的区别1.4.1 元素类型1.4.2 元素个数 1.5 集合的好处1.6 List集合我们以ArrayList集合为例1.7 迭代器的常用方法1.8 ArrayList、LinkedList和Vector的区别1.8.1 说出ArrayList,Vector, LinkedList的存储性能和特性1.…

【最新版】SolidWorks 2023 SP5.0 完整版安装包+安装教程

分享模式:免费/绿色,按教程安装 下载地址: https://pan.xunlei.com/s/VNL0-DD_ogcRFwy-xi0HUtlyA1?pwdfzqw# 提取码:fzqw SOLIDWORKS 2023新版本对电脑配置要求 更多详细说明请去官网查看。 安装使用方法: 一、卸…

还不会配置Nginx?刷完这篇就够了

Nginx是一个开源的高性能HTTP和反向代理服务器。它可以用于处理静态资源、负载均衡、反向代理和缓存等任务。Nginx被广泛用于构建高可用性、高性能的Web应用程序和网站。它具有低内存消耗、高并发能力和良好的稳定性,因此在互联网领域非常受欢迎。 为什么使用Nginx…

从 RBAC 到 NGAC ,企业如何实现自动化权限管理?

随着各领域加快向数字化、移动化、互联网化的发展,企业信息环境变得庞大复杂,身份和权限管理面临巨大的挑战。为了满足身份管理法规要求并管理风险,企业必须清点、分析和管理用户的访问权限。如今,越来越多的员工采用移动设备进行…

Python Web开发基础知识篇

一,基础知识篇 本片文章会简单地说一些python开发web中所必须的一些基础知识。主要包括HTML和css基础、JavaScript基础、网络编程基础、MySQL数据库基础、Web框架基础等知识。 1,Web简介 Web,全称为World Wide Web,也就是WWW,万…

入选数据结构与算法领域内容榜第26名

入选数据结构与算法领域内容榜第26名

【广州华锐互动】Web3D云展编辑器能为展览行业带来哪些便利?

在数字时代中,传统的展览方式正在被全新的技术和工具所颠覆。其中,最具有革新意义的就是Web3D云展编辑器。这种编辑器以其强大的功能和灵活的应用,正在为展览设计带来革命性的变化。 广州华锐互动开发的Web3D云展编辑器是一种专门用于创建、编…

【【linux C 编程记述 之 VIM的用法讲述】】

linux C 编程记述 之 VIM的用法讲述 我们所说的编写代码包括两部分:代码编写和编译,在Windows下可以使用Visual Studio来完成这两部,可以在 Visual Studio 下编写代码然后直接点击编译就可以了。但是在 Linux 下这两部分是分开的&#xff0c…

MySQL-04-InnoDB存储引擎锁和加锁分析

Latch一般称为闩锁(轻量级锁),因为其要求锁定的时间必须非常短。在InnoDB存储引擎中,latch又分为mutex(互斥量)和rwlock(读写锁)。 Lock的对象是事务,用来锁定的是…

分布式篇---第五篇

系列文章目录 文章目录 系列文章目录前言一、你知道哪些限流算法?二、说说什么是计数器(固定窗口)算法三、说说什么是滑动窗口算法前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去…

Dubbo配置注册中心设置application的name使用驼峰命名法可能存在的隐藏启动异常问题

原创/朱季谦 首先,先提一个建议,在SpringBootDubbo项目中,Dubbo配置注册中心设置的application命名name的值,最好使用xxx-xxx-xxx这样格式的,避免随便使用驼峰命名。因为使用驼峰命名法,在Spring的IOC容器…

数据资产确权的难点

数据是企业的重要资产之一,但是许多企业对于这项资产在管理上都面临着一些挑战,其中最关键就是数据确权的问题。接下来,将探讨数据资产确权的难点,并提出相应的解决方案,一起来看吧。 首先介绍一下数据资产入表的背景以…