Docker在机器学习中的应用

在机器学习领域,Docker容器化技术的应用越来越广泛。本文将介绍如何使用Docker来处理机器学习中的一些常见问题,特别是大型模型的处理。将以自然语言处理(NLP)任务为例,探讨如何使用PyTorch和Transformers库来构建和部署模型。

Docker容器与大型模型

在处理相对较小的模型时,Docker的使用相对简单。模型可以作为代码的一部分,在构建容器时添加进去。然而,随着模型体积的增大,这种方法变得复杂。大型模型往往需要数百兆甚至更大的存储空间,这会增加镜像的大小和构建时间。此外,如果在水平扩展的集群中运行代码,这种额外的负担会随着运行容器的数量而增加。

通常,不应该在镜像中包含任何可以轻松在容器实例之间共享的内容。在开发过程中,可以通过将本地文件夹映射到容器卷来处理共享文件。在生产环境中,这可能并不可行,尤其是当计划在云中运行容器时。

在这种情况下,更优的解决方案是依赖于Docker卷。这种方法也有一些缺点。在容器之间持久化和共享任何内容都会引入额外的依赖。同一个容器可能会根据持久卷中已经存储的内容而表现出不同的行为。此外,在构建过程中,不能在卷中存储任何内容(只能在容器运行时)。

构建Dockerfile

Hugging Face的Transformers是一个非常流行的处理自然语言处理任务的库。它支持许多现代NLP模型架构和机器学习框架,包括TensorFlow和PyTorch。已经多次使用TensorFlow,这次让尝试使用PyTorch版本。

Dockerfile相当简单: FROM pytorch/pytorch:1.6.0-cuda10.1-cudnn7-runtime ENV DEBIAN_FRONTEND=noninteractive ARG USERNAME=mluser ARG USERID=1000 RUN useradd --system --create-home --shell /bin/bash --uid $USERID $USERNAME \ && mkdir /home/$USERNAME/.cache && chown -R $USERNAME /home/$USERNAME/.cache COPY requirements.txt /tmp/requirements.txt RUN pip install -r /tmp/requirements.txt \ && rm /tmp/requirements.txt USER $USERNAME COPY --chown=$USERNAME ./app /home/$USERNAME/app WORKDIR /home/$USERNAME/app ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 ENTRYPOINT ["python", "nlp.py"] 除了基础镜像,这与之前的文章没有太大的不同。官方的PyTorch基础镜像为提供了所需的一切,并且仍然比TensorFlow-GPU镜像小。

这次,不需要任何额外的系统依赖项,因此可以避免使用apt-get命令。注意第一个RUN语句中的mkdir /home/$USERNAME/.cache命令。在容器执行期间,将挂载一个Docker卷到这个路径,用于下载的PyTorch模型。

明确创建这个文件夹,以便在构建镜像时设置访问权限。这些权限将在容器执行期间挂载的卷中传递。

requirements.txt文件非常紧凑。它只包含一行: transformers==4.3.2

解决方案中最复杂的部分存储在nlp.py脚本中。它被设置为容器的入口点,并且在代码下载存档中可用。

组合容器

为了简化卷的创建和挂载,这次将使用docker-compose来构建和运行容器。如果使用的是Docker桌面版,应该已经安装了它。在Linux上的Docker服务器上,可能需要安装它。

请注意,在最近的Docker版本中,可以使用docker compose命令而不是docker-compose。然而,令惊讶的是,注意到这两个命令的结果并不总是相同的。因此,将在本系列文章中坚持使用docker-compose。

现在,让在与Dockerfile相同的目录中创建一个简短的docker-compose.yml文件: version: '3.7' volumes: mluser_cache: name: mluser_cache services: mld07_transformers: build: context: '.' dockerfile: 'Dockerfile' image: 'mld07_transformers' volumes: - mluser_cache:/home/mluser/.cache' 在这里指示docker-compose做两件事:创建mluser_cache卷,并在容器运行时将其挂载到/home/mluser/.cache路径。除此之外,该文件定义了镜像名称和构建上下文。

构建容器

使用docker-compose构建容器的命令与之前的文章略有不同: $ docker-compose build --build-arg USERID=$(id -u) 由于所有基本参数都包含在docker-compose.yml配置中,在这里只需要传递USERID值。由于这次不会将本地文件夹作为容器卷挂载,--build-arg USERID属性可以安全地忽略。实际上,当在Windows上运行时,总是可以忽略它。在这里保留它只是为了确保后续文章的一致权限。

运行容器

现在容器已经构建好了,让检查它是否有效。将从一个问答任务开始: $ docker-compose run --user $(id -u) mld07_transformers \ --task="qa" \ --document="We have considered many names for my dog, such as: Small, Black or Buster. Finally we have called him Ratchet. It is quite an unusual name, but the dog's owner named Michael picked it." \ --question="What is the name of my dog?" 在这里故意耍了点花招:在文档中抛出了多个“名字”;然而,模型处理得很好:

模型第一次执行时,相关的模型被下载并存储在映射到mluser_cache卷的.cache文件夹中。

要检查卷的大小,可以使用以下命令: $ docker system df -v 本地卷空间使用情况应该显示:

为了确保模型数据被持久化,可以运行与之前相同的docker-compose run命令,但结果略有不同:

这次模型已经在.cache文件夹中,所以它没有被再次下载。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485