Skip to content

Commit

Permalink
Merge pull request #9 from MovisLi/main
Browse files Browse the repository at this point in the history
fix:wrong description
  • Loading branch information
ytzfhqs authored Feb 2, 2024
2 parents 233f5f8 + 9187868 commit ebebb53
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 45 deletions.
89 changes: 45 additions & 44 deletions docs/组织机器学习项目.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

是这样吗?

在开始之前,我们必须注意几件事。请记住,我们将在集成开发环境/文本编辑器中工作,而不是在 jupyter notebook中。你也可以在 jupyter notebook中工作,这完全取决于你。不过,我将只使用 jupyter notebook来探索数据、绘制图表和图形。我们将以这样一种方式构建分类框架,即插即用。您无需对代码做太多改动就能训练模型,而且当您改进模型时,还能使用 git 对其进行跟踪。
在开始之前,我们必须注意几件事。请记住,我们将在集成开发环境/文本编辑器中工作,而不是在 jupyter notebook 中。你也可以在 jupyter notebook 中工作,这完全取决于你。不过,我将只使用 jupyter notebook 来探索数据、绘制图表和图形。我们将以这样一种方式构建分类框架,即插即用。您无需对代码做太多改动就能训练模型,而且当您改进模型时,还能使用 git 对其进行跟踪。

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

Expand All @@ -31,17 +31,17 @@

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

*input/*:该文件夹包含机器学习项目的所有输入文件和数据。如果您正在开发 NLP 项目,您可以将embeddings放在这里。如果是图像项目,所有图像都放在该文件夹下的子文件夹中。
_input/_:该文件夹包含机器学习项目的所有输入文件和数据。如果您正在开发 NLP 项目,您可以将 embeddings 放在这里。如果是图像项目,所有图像都放在该文件夹下的子文件夹中。

*src/*:我们将在这里保存与项目相关的所有 python 脚本。如果我说的是一个 python 脚本,即任何 *.py 文件,它都存储在 src 文件夹中。
_src/_:我们将在这里保存与项目相关的所有 python 脚本。如果我说的是一个 python 脚本,即任何 \*.py 文件,它都存储在 src 文件夹中。

*models/*:该文件夹保存所有训练过的模型。
_models/_:该文件夹保存所有训练过的模型。

*notebook/*:所有 jupyter notebook(即任何 *.ipynb 文件)都存储在笔记本 文件夹中。
_notebook/_:所有 jupyter notebook(即任何 \*.ipynb 文件)都存储在笔记本 文件夹中。

*README.md*:这是一个标记符文件,您可以在其中描述您的项目,并写明如何训练模型或在生产环境中使用。
_README.md_:这是一个标记符文件,您可以在其中描述您的项目,并写明如何训练模型或在生产环境中使用。

*LICENSE*:这是一个简单的文本文件,包含项目的许可证,如 MIT、Apache 等。关于许可证的详细介绍超出了本书的范围。
_LICENSE_:这是一个简单的文本文件,包含项目的许可证,如 MIT、Apache 等。关于许可证的详细介绍超出了本书的范围。

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

Expand All @@ -63,36 +63,36 @@

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

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

请注意,训练 CSV 文件位于 *input/* 文件夹中,名为 *mnist_train.csv*
请注意,训练 CSV 文件位于 _input/_ 文件夹中,名为 _mnist_train.csv_

对于这样一个项目,这些文件应该是什么样的呢?

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

这将在 *input/* 文件夹中创建一个名为 *mnist_train_folds.csv* 的新文件,与 *mnist_train.csv* 相同。唯一不同的是,这个 CSV 文件经过了随机排序,并新增了一列名为 *kfold* 的内容。
这将在 _input/_ 文件夹中创建一个名为 _mnist_train_folds.csv_ 的新文件,与 _mnist_train.csv_ 相同。唯一不同的是,这个 CSV 文件经过了随机排序,并新增了一列名为 _kfold_ 的内容。

一旦我们决定了要使用哪种评估指标并创建了折叠,就可以开始创建基本模型了。这可以在 train.py 中完成。

```python
import joblib
import pandas as pd
from sklearn import metrics
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_train = df[df.kfold != fold].reset_index(drop=True)
# 选取df中kfold列等于fold
df_valid = df[df.kfold == fold].reset_index(drop=True)
df_valid = df[df.kfold == fold].reset_index(drop=True)
# 训练集输入,删除label列
x_train = df_train.drop("label", axis=1).values
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
x_valid = df_valid.drop("label", axis=1).values
# 验证集输出,取label列
y_valid = df_valid.label.values
# 实例化决策树模型
Expand All @@ -102,11 +102,11 @@ def run(fold):
# 使用验证集输入得到预测结果
preds = clf.predict(x_valid)
# 计算验证集准确率
accuracy = metrics.accuracy_score(y_valid, preds)
accuracy = metrics.accuracy_score(y_valid, preds)
# 打印fold信息和准确率
print(f"Fold={fold}, Accuracy={accuracy}")
# 保存模型
joblib.dump(clf, f"../models/dt_{fold}.bin")
joblib.dump(clf, f"../models/dt_{fold}.bin")

if __name__ == "__main__":
# 运行每个折叠
Expand All @@ -133,7 +133,7 @@ Fold=4, Accuracy=0.8699166666666667
因此,我们可以创建一个包含所有这些信息的配置文件:**config.py**

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

Expand All @@ -144,21 +144,21 @@ import os
import config
import joblib
import pandas as pd
from sklearn import metrics
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
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
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)
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__":
Expand Down Expand Up @@ -223,13 +223,13 @@ Fold=4, Accuracy=0.8685
from sklearn import tree
models = {
# 以gini系数度量的决策树
"decision_tree_gini": tree.DecisionTreeClassifier(
"decision_tree_gini": tree.DecisionTreeClassifier(
criterion="gini"
),
# 以entropy系数度量的决策树
"decision_tree_entropy": tree.DecisionTreeClassifier(
"decision_tree_entropy": tree.DecisionTreeClassifier(
criterion="entropy"
),
),
}
```

Expand All @@ -240,39 +240,40 @@ import argparse
import os
import joblib
import pandas as pd
from sklearn import metrics
from sklearn import metrics
import config
import model_dispatcher
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
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
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)
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()
parser = argparse.ArgumentParser()
# fold参数
parser.add_argument("--fold", type=int)
# model参数
parser.add_argument("--model", type=str)
args = parser.parse_args()
args = parser.parse_args()
run(fold=args.fold, model=args.model)
```

train.py 有几处重大改动:

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

现在,我们可以使用以下命令运行脚本:
Expand All @@ -289,20 +290,20 @@ Fold=0, Accuracy=0.8665833333333334
Fold=0, Accuracy=0.8705833333333334
```

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

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

Expand All @@ -313,7 +314,7 @@ models = {
Fold=0, Accuracy=0.9670833333333333
```

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

```python
python train.py --fold 0 --model rf
Expand All @@ -336,4 +337,4 @@ Fold=4, Accuracy=0.9666666666666667

MNIST 几乎是每本书和每篇博客都会讨论的问题。但我试图将这个问题转换得更有趣,并向你展示如何为你正在做的或计划在不久的将来做的几乎所有机器学习项目编写一个基本框架。有许多不同的方法可以改进这个 MNIST 模型和这个框架,我们将在以后的章节中看到。

我使用了一些脚本,如 *model_dispatcher.py**config.py*,并将它们导入到我的训练脚本中。请注意,我没有导入 *,你也不应该导入。如果我导入了 *,你就永远不会知道模型字典是从哪里来的。编写优秀、易懂的代码是一个人必须具备的基本素质,但许多数据科学家却忽视了这一点。如果你所做的项目能让其他人理解并使用,而无需咨询你的意见,那么你就节省了他们的时间和自己的时间,可以将这些时间投入到改进你的项目或开发新项目中去。
我使用了一些脚本,如 _model_dispatcher.py__config.py_,并将它们导入到我的训练脚本中。请注意,我没有使用 `import *` 语法,你也不应该使用。如果我使用了 `import *`,你就永远不会知道模型字典是从哪里来的。编写优秀、易懂的代码是一个人必须具备的基本素质,但许多数据科学家却忽视了这一点。如果你所做的项目能让其他人理解并使用,而无需咨询你的意见,那么你就节省了他们的时间和自己的时间,可以将这些时间投入到改进你的项目或开发新项目中去。
2 changes: 1 addition & 1 deletion docs/评估指标.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ $$

你猜怎么着,你可以使用 ROC 曲线来选择这个阈值!ROC 曲线会告诉您阈值对假阳性率和真阳性率的影响,进而影响假阳性和真阳性。您应该选择最适合您的问题和数据集的阈值。

例如,如果您不希望有太多的误报,那么阈值就应该高一些。不过,这也会带来更多的误报。注意权衡利弊,选择最佳阈值。让我们看看这些阈值如何影响真阳性和假阳性值。
例如,如果您不希望有太多的误报,那么阈值就应该高一些。不过,这也会带来更多的漏报。注意权衡利弊,选择最佳阈值。让我们看看这些阈值如何影响真阳性和假阳性值。

```python
# 真阳性样本数列表
Expand Down

0 comments on commit ebebb53

Please sign in to comment.