MLOps - 烹饪书,第一章

MLOps - 烹饪书,第一章

大家好! 我是 CROC 的简历开发人员。 我们在 CV 领域实施项目已有 3 年了。 这段时间我们做了很多事情,比如:对司机进行监控,让他们开车时不喝酒、不抽烟、不打电话、看路、不看梦、不看云。 ; 我们记录了在专用车道上行驶并占用多个停车位的人; 确保工人佩戴头盔、手套等; 确定一名想要进入该设施的员工; 我们尽可能地计算了一切。

我做这一切是为了什么?

在实施项目的过程中,我们遇到了坎坷,很多坎坷,有些问题要么是你熟悉的,要么是以后会熟悉的。

模拟情况

假设我们在一家年轻公司“N”找到了一份工作,该公司的活动与机器学习相关。 我们从事一个 ML(DL、CV)项目,然后由于某种原因我们切换到另一份工作,通常会休息一下,然后返回到我们自己或其他人的神经元。

  1. 关键时刻到来了,您需要以某种方式记住您停止的位置、您尝试过的超参数,以及最重要的是它们导致的结果。 对于谁存储所有启动的信息可以有很多选择:在头中、配置中、记事本中、在云中的工作环境中。 当超参数作为注释行存储在代码中时,我碰巧看到了一个选项,一般来说,这是一种幻想。 现在想象一下,您返回的不是您的项目,而是一个离开公司的人的项目,并且您继承了一个代码和一个名为 model_1.pb 的模型。 为了完成图片并传达所有痛苦,让我们假设您也是一名初学者专家。
  2. 前进。 为了运行代码,我们和每个使用它的人都需要创建一个环境。 经常发生的情况是,由于某种原因,他们没有把他作为我们的遗产留给我们。 这也可能成为一项不平凡的任务。 您不想在这一步上浪费时间,是吗?
  3. 我们训练一个模型(例如,汽车检测器)。 我们已经到了非常好的地步——是时候保存结果了。 我们将其命名为 car_detection_v1.pb。 然后我们训练另一个 - car_detection_v2.pb。 一段时间后,我们的同事或我们自己使用不同的架构教授越来越多的内容。 结果,形成了一堆工件,必须煞费苦心地收集有关这些工件的信息(但我们稍后会这样做,因为现在我们有更多优先事项)。
  4. 好吧,现在一切都结束了! 我们有一个模型! 我们可以开始训练下一个模型,开发一个架构来解决新问题,或者我们可以去喝杯茶吗? 谁将部署?

发现问题

开发一个项目或产品是很多人的工作。 随着时间的推移,人们离开又到来,项目越来越多,项目本身也变得更加复杂。 无论如何,上述循环中的情况(并且不仅如此)在某些组合中将在迭代之间发生。 所有这些都会导致时间浪费、混乱、紧张,甚至可能引起客户不满,并最终造成金钱损失。 尽管我们通常都遵循同样的老套路,但我相信没有人愿意一遍又一遍地重温这些时刻。

MLOps - 烹饪书,第一章

所以,我们经历了一个开发周期,我们看到有一些问题需要解决。 为此,您需要:

  • 方便存储工作结果;
  • 使新员工参与的过程变得简单;
  • 简化部署开发环境的过程;
  • 配置模型版本控制流程;
  • 有一种方便的方法来验证模型;
  • 找到一个模型状态管理工具;
  • 找到一种将模型交付生产的方法。

显然有必要想出一个工作流程来让您轻松方便地管理这个生命周期? 这种做法称为 MLOps

MLOps(即机器学习的 DevOps)允许数据科学和 IT 团队通过监视、验证和治理机器学习模型来协作并加快模型开发和部署的步伐。

可以 荣誉谷歌的人对这一切有何看法? 从文章中可以清楚地看出 MLOps 是一个相当庞大的东西。

MLOps - 烹饪书,第一章

在我的文章中,我将仅描述该过程的一部分。 为了实现,我将使用 MLflow 工具,因为...... 这是一个开源项目,需要少量代码即可连接,并且与流行的机器学习框架集成。 您可以在互联网上搜索其他工具,例如 Kubeflow、SageMaker、Trains 等,也许会找到更适合您需求的工具。

使用 MLFlow 工具的示例“构建”MLOps

MLFlow 是一个用于机器学习模型生命周期管理的开源平台(https://mlflow.org/).

MLflow 包括四个组件:

  • MLflow Tracking - 涵盖记录结果和导致此结果的参数的问题;
  • MLflow Project - 允许您打包代码并在任何平台上重现它;
  • MLflow Models - 负责将模型部署到生产中;
  • MLflow 注册表 - 允许您在集中存储库中存储模型并管理其状态。

MLflow 在两个实体上运行:

  • 启动是我们想要注册的训练、参数和指标的完整周期;
  • 实验是一个共同运行的“主题”。

示例的所有步骤均在Ubuntu 18.04操作系统上实现。

1.部署服务器

为了使我们能够轻松管理我们的项目并接收所有必要的信息,我们将部署一台服务器。 MLflow 跟踪服务器有两个主要组件:

  • 后端存储 - 负责存储有关已注册模型的信息(支持 4 个 DBMS:mysql、mssql、sqlite 和 postgresql);
  • 工件存储 - 负责存储工件(支持 7 种存储选项:Amazon S3、Azure Blob 存储、Google 云存储、FTP 服务器、SFTP 服务器、NFS、HDFS)。

由于 文物商店 为了简单起见,我们以 sftp 服务器为例。

  • 创建一个组
    $ sudo groupadd sftpg
  • 添加一个用户并为其设置密码
    $ sudo useradd -g sftpg mlflowsftp
    $ sudo passwd mlflowsftp 
  • 调整一些访问设置
    $ sudo mkdir -p /data/mlflowsftp/upload
    $ sudo chown -R root.sftpg /data/mlflowsftp
    $ sudo chown -R mlflowsftp.sftpg /data/mlflowsftp/upload
  • 添加几行到 /etc/ssh/sshd_config
    Match Group sftpg
     ChrootDirectory /data/%u
     ForceCommand internal-sftp
  • 重新启动服务
    $ sudo systemctl restart sshd

由于 后端商店 让我们以 postgresql 为例。

$ sudo apt update
$ sudo apt-get install -y postgresql postgresql-contrib postgresql-server-dev-all
$ sudo apt install gcc
$ pip install psycopg2
$ sudo -u postgres -i
# Create new user: mlflow_user
[postgres@user_name~]$ createuser --interactive -P
Enter name of role to add: mlflow_user
Enter password for new role: mlflow
Enter it again: mlflow
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
# Create database mlflow_bd owned by mlflow_user
$ createdb -O mlflow_user mlflow_db

要启动服务器,您需要安装以下python包(我建议创建一个单独的虚拟环境):

pip install mlflow
pip install pysftp

让我们启动我们的服务器

$ mlflow server  
                 --backend-store-uri postgresql://mlflow_user:mlflow@localhost/mlflow_db 
                 --default-artifact-root sftp://mlflowsftp:mlflow@sftp_host/upload  
                --host server_host 
                --port server_port

2.添加追踪

为了让我们训练的成果不丢失,让后代的开发者了解发生了什么,也为了让老同志和你们能够冷静地分析学习过程,我们需要添加跟踪。 跟踪意味着在服务器上保存参数、指标、工件和有关训练开始的任何其他信息。

例如,我创建了一个小 github上的项目 在 Keras 上分割所有内容 COCO数据集。 为了添加跟踪,我创建了一个文件 mlflow_training.py。

以下是最有趣的事情发生的几行:

def run(self, epochs, lr, experiment_name):
        # getting the id of the experiment, creating an experiment in its absence
        remote_experiment_id = self.remote_server.get_experiment_id(name=experiment_name)
        # creating a "run" and getting its id
        remote_run_id = self.remote_server.get_run_id(remote_experiment_id)

        # indicate that we want to save the results on a remote server
        mlflow.set_tracking_uri(self.tracking_uri)
        mlflow.set_experiment(experiment_name)

        with mlflow.start_run(run_id=remote_run_id, nested=False):
            mlflow.keras.autolog()
            self.train_pipeline.train(lr=lr, epochs=epochs)

        try:
            self.log_tags_and_params(remote_run_id)
        except mlflow.exceptions.RestException as e:
            print(e)

这里 self.remote_server 是 mlflow.tracking 方法的一个小包装。 MlflowClient(我为了方便而创建它),在它的帮助下我创建了一个实验并在服务器上运行它。 接下来,我指示应在何处合并启动结果 (mlflow.set_tracking_uri(self.tracking_uri))。 我启用自动日志记录 mlflow.keras.autolog()。 目前 MLflow Tracking 支持 TensorFlow、Keras、Gluon XGBoost、LightGBM、Spark 的自动日志记录。 如果您还没有找到您的框架或库,那么您始终可以显式记录。 我们正在开始训练。 在远程服务器上注册标签并输入参数。

只需几行代码,您就可以像其他人一样访问有关所有发布的信息。 凉爽的?

3.我们制定项目

现在让我们轻松启动该项目。 为此,请将 MLproject 和 conda.yaml 文件添加到项目根目录。
机器学习项目

name: flow_segmentation
conda_env: conda.yaml

entry_points:
  main:
    parameters:
        categories: {help: 'list of categories from coco dataset'}
        epochs: {type: int, help: 'number of epochs in training'}

        lr: {type: float, default: 0.001, help: 'learning rate'}
        batch_size: {type: int, default: 8}
        model_name: {type: str, default: 'Unet', help: 'Unet, PSPNet, Linknet, FPN'}
        backbone_name: {type: str, default: 'resnet18', help: 'exampe resnet18, resnet50, mobilenetv2 ...'}

        tracking_uri: {type: str, help: 'the server address'}
        experiment_name: {type: str, default: 'My_experiment', help: 'remote and local experiment name'}
    command: "python mlflow_training.py 
            --epochs={epochs}
            --categories={categories}
            --lr={lr}
            --tracking_uri={tracking_uri}
            --model_name={model_name}
            --backbone_name={backbone_name}
            --batch_size={batch_size}
            --experiment_name={experiment_name}"

MLflow 项目有几个属性:

  • 名称 - 您的项目名称;
  • 环境 - 在我的例子中,conda_env表示使用Anaconda来运行,依赖描述在conda.yaml文件中;
  • 入口点 - 指示我们可以运行哪些文件和参数(开始训练时会自动记录所有参数)

conda.yaml

name: flow_segmentation
channels:
  - defaults
  - anaconda
dependencies:
  - python==3.7
  - pip:
    - mlflow==1.8.0
    - pysftp==0.2.9
    - Cython==0.29.19
    - numpy==1.18.4
    - pycocotools==2.0.0
    - requests==2.23.0
    - matplotlib==3.2.1
    - segmentation-models==1.0.1
    - Keras==2.3.1
    - imgaug==0.4.0
    - tqdm==4.46.0
    - tensorflow-gpu==1.14.0

您可以使用docker作为运行环境,更多详细信息请参考 文件资料.

4. 让我们开始训练吧

我们克隆项目并进入项目目录:

git clone https://github.com/simbakot/mlflow_example.git
cd mlflow_example/

要运行您需要安装库

pip install mlflow
pip install pysftp

因为在我使用 conda_env 的示例中,您的计算机上必须安装 Anaconda(但您可以通过自己安装所有必要的软件包并使用启动参数来解决这个问题)。

所有的准备步骤都完成了,我们可以开始启动培训了。 从项目根目录:

$ mlflow run -P epochs=10 -P categories=cat,dog -P tracking_uri=http://server_host:server_port .

输入命令后,会自动创建conda环境并开始训练。
在上面的例子中,我传递了训练的纪元数,我们想要分割的类别(你可以看到完整的列表 这里)和我们的远程服务器的地址。
可以在 MLproject 文件中找到可能参数的完整列表。

5. 评估学习成果

完成训练后,我们可以在浏览器中访问我们服务器的地址 http://server_host:server_port

MLOps - 烹饪书,第一章

在这里,我们看到所有实验的列表(左上)以及运行信息(中)。 我们可以查看每次启动的更详细信息(参数、指标、工件和一些附加信息)。

MLOps - 烹饪书,第一章

对于每个指标,我们可以观察变化的历史记录

MLOps - 烹饪书,第一章

那些。 目前我们可以以“手动”模式分析结果,您也可以使用 MLflow API 设置自动验证。

6. 注册模型

在我们分析了我们的模型并确定它已准备好战斗后,我们继续注册它,为此我们选择我们需要的发射(如上一段所示)并继续下去。

MLOps - 烹饪书,第一章

当我们给模型命名后,它就有了一个版本。 如果您保存了同名的另一个模型,版本将自动升级。

MLOps - 烹饪书,第一章

对于每个模型,我们可以添加描述并选择三种状态之一(暂存、生产、存档);随后,使用 API,我们可以访问这些状态,这与版本控制一起提供了额外的灵活性。

MLOps - 烹饪书,第一章

我们还可以轻松访问所有型号

MLOps - 烹饪书,第一章

以及他们的版本

MLOps - 烹饪书,第一章

与上一段一样,所有操作都可以使用 API 完成。

7. 部署模型

在这个阶段,我们已经有了一个经过训练的(keras)模型。 如何使用它的示例:

class SegmentationModel:
    def __init__(self, tracking_uri, model_name):

        self.registry = RemoteRegistry(tracking_uri=tracking_uri)
        self.model_name = model_name
        self.model = self.build_model(model_name)

    def get_latest_model(self, model_name):
        registered_models = self.registry.get_registered_model(model_name)
        last_model = self.registry.get_last_model(registered_models)
        local_path = self.registry.download_artifact(last_model.run_id, 'model', './')
        return local_path

    def build_model(self, model_name):
        local_path = self.get_latest_model(model_name)

        return mlflow.keras.load_model(local_path)

    def predict(self, image):
        image = self.preprocess(image)
        result = self.model.predict(image)
        return self.postprocess(result)

    def preprocess(self, image):
        image = cv2.resize(image, (256, 256))
        image = image / 255.
        image = np.expand_dims(image, 0)
        return image

    def postprocess(self, result):
        return result

为了方便起见,这里 self.registry 再次是 mlflow.tracking.MlflowClient 的一个小包装。 关键是我访问远程服务器并在那里查找具有指定名称和最新生产版本的模型。 接下来,我将工件本地下载到 ./model 文件夹,并从此目录 mlflow.keras.load_model(local_path) 构建模型。 现在我们可以使用我们的模型了。 CV(ML)开发人员可以轻松改进模型并发布新版本。

总之

我提出了一个系统,它允许:

  • 集中存储有关机器学习模型、训练进度和结果的信息;
  • 快速部署开发环境;
  • 监控和分析模型工作的进展;
  • 方便模型的版本管理和状态管理;
  • 部署生成的模型很容易。

这个例子是一个玩具,可以作为构建您自己的系统的起点,其中可能包括结果评估和模型注册的自动化(分别为第 5 点和第 6 点),或者您将添加数据集的版本控制,或者可能是其他东西? 我想要表达的观点是,你需要 MLOps 作为一个整体,MLflow 只是达到目的的一种手段。

写下你遇到了什么我没有显示的问题?
您会向系统添加什么内容以满足您的需求?
您使用什么工具和方法来解决全部或部分问题?

PS我会留下几个链接:
github项目- https://github.com/simbakot/mlflow_example
ML流- https://mlflow.org/
我的工作电子邮件用于提问 - [电子邮件保护]

我们公司定期为IT专家举办各种活动,例如:莫斯科时间8月19日00:XNUMX将举办在线简历见面会,如果您有兴趣,可以参加,报名 这里 .

来源: habr.com

添加评论