将一个简单的机器学习训练脚本容器化,为其构建一个Docker镜像,并在容器内执行训练过程。数据输入和模型输出使用绑定挂载进行管理。这种方法有助于巩固创建可复现训练环境的过程。前提条件Docker已安装并在您的系统上运行。本地已安装Python 3(用于准备示例)。一个文本编辑器或IDE。训练脚本(示例:train.py)首先,我们来创建一个基本的Python脚本,用于在Iris数据集上训练一个Scikit-learn逻辑回归模型。我们会将其设计为通过命令行参数接收输入/输出目录路径和一个超参数(正则化强度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机器学习库),或者创建一个示例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)是确保可复现性的一种良好做法。创建Dockerfile现在,在项目根目录(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的任何参数都将附加到此命令。CMD ["--help"]: 为ENTRYPOINT提供一个默认参数。如果您在不带参数的情况下运行容器,它将执行python src/train.py --help。构建Docker镜像在您的终端中导航到项目根目录(ml-training-project/)并运行构建命令:docker build -t ml-training-app:latest .-t ml-training-app:latest: 为镜像添加名为ml-training-app和标签latest的标记。.: 指定构建上下文(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),而不是宿主机路径。我们还指定了一个超参数C=0.5。您应该在终端中看到类似以下的输出:从: /app/data 加载数据 数据加载成功。 正在使用 C=0.5 训练逻辑回归模型... 模型在测试集上的准确率: 1.0000 模型已保存到: /app/output/iris_model.joblib验证输出容器运行结束后,检查您的本地output目录。您应该会发现iris_model.joblib文件,它是从容器内部成功保存的。ls output/iris_model.joblib总结在本次实践练习中,您成功地:创建了一个Python训练脚本,通过接受输入/输出路径,使其设计为在容器化环境中工作。编写了一个Dockerfile来定义环境、安装依赖项并复制训练代码。构建了一个包含训练脚本及其环境的Docker镜像。使用docker run在隔离的容器中执行了训练过程。使用绑定挂载(-v)管理了数据输入和模型输出,将宿主机目录与容器目录关联起来。通过命令行参数向脚本传递了配置(超参数)。此过程演示了机器学习训练容器化的核心工作流程。通过将代码和依赖项打包在一起,您可以确保训练环境的一致性和可复现性,无论Docker镜像在哪里运行。使用卷允许与宿主机文件系统进行数据和结果的交互,弥合了隔离容器与外部环境之间的差异。