趋近智
将一个简单的机器学习 (machine learning)训练脚本容器化,为其构建一个Docker镜像,并在容器内执行训练过程。数据输入和模型输出使用绑定挂载进行管理。这种方法有助于巩固创建可复现训练环境的过程。
首先,我们来创建一个基本的Python脚本,用于在Iris数据集上训练一个Scikit-learn逻辑回归模型。我们会将其设计为通过命令行参数 (parameter)接收输入/输出目录路径和一个超参数 (hyperparameter)(正则化 (regularization)强度C)。
将以下代码保存为src/train.py:
# src/train.py
import argparse
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import joblib
import os
def train_model(input_dir, output_dir, C):
"""加载数据,训练模型,并保存模型。"""
print(f"Loading data from: {input_dir}")
# 假设 iris.csv 位于输入目录中
data_path = os.path.join(input_dir, 'iris.csv')
try:
iris_df = pd.read_csv(data_path)
except FileNotFoundError:
print(f"Error: Could not find {data_path}. Make sure iris.csv is mounted correctly.")
return
print("数据加载成功。")
X = iris_df[['sepal_length', 'sepal_width', 'petal_length', 'petal_width']]
y = iris_df['species']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"正在使用 C={C} 训练逻辑回归模型...")
model = LogisticRegression(C=C, max_iter=200, random_state=42)
model.fit(X_train, y_train)
# 评估
y_pred = model.predict(X_test)
acc = accuracy_score(y_test, y_pred)
print(f"模型在测试集上的准确率: {acc:.4f}")
# 保存模型
os.makedirs(output_dir, exist_ok=True) # 确保输出目录存在
model_path = os.path.join(output_dir, 'iris_model.joblib')
joblib.dump(model, model_path)
print(f"模型已保存到: {model_path}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="在Iris数据上训练一个逻辑回归模型。")
parser.add_argument('--input-dir', type=str, required=True, help='包含iris.csv的目录')
parser.add_argument('--output-dir', type=str, required=True, help='用于保存训练后模型的目录')
parser.add_argument('--C', type=float, default=1.0, help='正则化强度的倒数')
args = parser.parse_args()
train_model(args.input_dir, args.output_dir, args.C)
此脚本使用argparse处理命令行参数,使用pandas加载数据,使用Scikit-learn训练模型,并使用joblib保存训练后的模型。它明确要求提供输入数据和输出模型的路径。
您的项目文件应按以下方式组织:
ml-training-project/
├── Dockerfile
├── requirements.txt
├── src/
│ └── train.py
├── data/
│ └── iris.csv # 您需要下载/创建此文件
└── output/ # 此目录将被创建或用于模型输出
您可以在线轻松找到Iris数据集(例如,从Kaggle或UCI机器学习 (machine learning)库),或者创建一个示例iris.csv文件并将其放入data/目录。请确保它包含sepal_length、sepal_width、petal_length、petal_width和species等列。
requirements.txt)创建一个requirements.txt文件,列出所需的Python库:
pandas
scikit-learn==1.2.2 # 固定版本以确保可复现性
joblib
注意:固定版本(例如scikit-learn==1.2.2)是确保可复现性的一种良好做法。
现在,在项目根目录(ml-training-project/)中创建Dockerfile:
# 使用官方Python运行时作为基础镜像
FROM python:3.9-slim
# 设置容器内的工作目录
WORKDIR /app
# 先复制requirements文件以利用Docker缓存
COPY requirements.txt .
# 安装requirements.txt中指定的任何所需软件包
# 使用 --no-cache-dir 减少镜像大小
RUN pip install --no-cache-dir -r requirements.txt
# 将源代码复制到容器中
COPY src/ ./src/
# 定义容器的入口点
# 这使得容器像一个可执行文件一样运行
ENTRYPOINT ["python", "src/train.py"]
# 默认命令(可以在运行时覆盖)
# 这里,如果没有提供参数,我们设置默认的help标志
CMD ["--help"]
让我们分析此Dockerfile:
FROM python:3.9-slim: 使用轻量级的Python 3.9镜像作为起点。WORKDIR /app: 将容器内的默认目录设置为/app。随后的命令(COPY、RUN、CMD、ENTRYPOINT)将相对于此目录运行。COPY requirements.txt .: 仅复制requirements文件。RUN pip install ...: 安装依赖项。如果requirements.txt没有变化,此层通常会被缓存,从而加快后续构建的速度。COPY src/ ./src/: 将我们的训练脚本目录复制到镜像中的/app/src/下。ENTRYPOINT ["python", "src/train.py"]: 指定使用此镜像运行的容器默认会执行python src/train.py。在镜像名称之后提供给docker run的任何参数 (parameter)都将附加到此命令。CMD ["--help"]: 为ENTRYPOINT提供一个默认参数。如果您在不带参数的情况下运行容器,它将执行python src/train.py --help。在您的终端中导航到项目根目录(ml-training-project/)并运行构建命令:
docker build -t ml-training-app:latest .
-t ml-training-app:latest: 为镜像添加名为ml-training-app和标签latest的标记 (token)。.: 指定构建上下文 (context)(Docker查找Dockerfile和要复制文件的位置)是当前目录。Docker将执行您Dockerfile中的步骤,下载基础镜像,安装依赖项,并复制您的代码。
现在,我们将在容器内部运行训练脚本。我们需要做到:
data目录挂载到容器的/app/data路径,以便脚本可以读取iris.csv。output目录挂载到容器的/app/output路径,以便脚本可以将iris_model.joblib文件保存回我们的宿主机。--input-dir、--output-dir以及可选的--C)传递给容器,这些参数将附加到ENTRYPOINT。从项目根目录执行以下docker run命令:
docker run --rm \
-v "$(pwd)/data:/app/data" \
-v "$(pwd)/output:/app/output" \
ml-training-app:latest \
--input-dir /app/data \
--output-dir /app/output \
--C 0.5
让我们分析此命令:
docker run: 用于创建并启动新容器的命令。--rm: 容器退出时自动删除容器。这对于训练等一次性任务很有用。-v "$(pwd)/data:/app/data": 将宿主机的当前目录($(pwd))加上/data挂载到容器内的/app/data目录。在Windows PowerShell上使用${PWD}或在需要时将$(pwd)替换为完整路径。这使得iris.csv可供脚本使用。-v "$(pwd)/output:/app/output": 将宿主机的output目录(如果不存在,Docker将创建它)挂载到容器内的/app/output。这是脚本保存模型的位置。ml-training-app:latest: 容器要使用的镜像。--input-dir /app/data --output-dir /app/output --C 0.5: 这些是传递给ENTRYPOINT(python src/train.py)的参数。请注意,这里我们使用的是容器路径(/app/data、/app/output),而不是宿主机路径。我们还指定了一个超参数 (hyperparameter)C=0.5。您应该在终端中看到类似以下的输出:
从: /app/data 加载数据
数据加载成功。
正在使用 C=0.5 训练逻辑回归模型...
模型在测试集上的准确率: 1.0000
模型已保存到: /app/output/iris_model.joblib
容器运行结束后,检查您的本地output目录。您应该会发现iris_model.joblib文件,它是从容器内部成功保存的。
ls output/
iris_model.joblib
在本次实践练习中,您成功地:
Dockerfile来定义环境、安装依赖项并复制训练代码。docker run在隔离的容器中执行了训练过程。-v)管理了数据输入和模型输出,将宿主机目录与容器目录关联起来。此过程演示了机器学习 (machine learning)训练容器化的核心工作流程。通过将代码和依赖项打包在一起,您可以确保训练环境的一致性和可复现性,无论Docker镜像在哪里运行。使用卷允许与宿主机文件系统进行数据和结果的交互,弥合了隔离容器与外部环境之间的差异。
这部分内容有帮助吗?
© 2026 ApX Machine LearningAI伦理与透明度•