华为云用户手册

  • 运行态-运行工作流 Workflow提供了可视化的工作流运行方式。使用者不需要了解工作流的内部细节,只需要关注一些简单的参数配置即可启动运行工作流。运行态的工作流来源主要为:通过开发态发布或者从gallery订阅。 运行态工作流的来源为:通过开发态发布,或者通过订阅。 运行态主要提供以下能力。 统一配置管理:管理工作流需要配置的参数及使用的资源等。 操作工作流:启动、停止、重试、复制、删除工作流。 查看运行记录:查看工作流历史运行的参数以及状态记录。
  • 检测规则 卡死检测主要是通过监控作业进程的状态和资源利用率来判定作业是否卡死,会启动一个协程来周期性地监控上述两个指标的变化情况。卡死检测有单实例和全实例两种检测规则,是同时生效的。 单实例检测 进程状态:只要训练作业单实例中的进程IO存在变化,就进入下一个检测周期。如果在多个检测周期内,所有进程IO都没有变化,则进入资源利用率检测阶段。 资源利用率:在作业单实例进程IO没有变化的情况下,采集一定时间段内的GPU利用率或NPU利用率,并根据这段时间内的GPU利用率或NPU利用率的方差和中位数来判断资源使用率是否有变化。如果没有变化,则判定作业卡死。 全实例检测 资源利用率:当作业在一段时间内所有实例的GPU利用率或者NPU利用率都没有变化,则判定作业卡死。 系统预置了卡死检测的环境变量“MA_HANG_DETECT_TIME=30”,表示检测到指标异常并持续30分钟则判定作业卡死。如果需要修改卡死检测时间,则可以修改环境变量“MA_HANG_DETECT_TIME”的值,具体操作指导请参见管理训练容器环境变量。 由于检测规则的局限性,当前卡死检测存在一定的误检率。如果是作业代码本身逻辑(如长时间sleep)导致的卡死,请忽略。 如果对于误检有疑问或者卡死问题无法自行解决,您可以前往ModelArts开发者论坛进行提问或者搜索问题。
  • 开启容错检查 用户可以在创建训练作业时通过设置自动重启的方式开启容错检查。 使用ModelArts Standard控制台的创建训练作业页面设置自动重启: 用户可以在控制台页面通过开关的方式开启自动重启。“自动重启”开关默认不开启,表示不做重新下发作业,也不会启用环境检测。打开开关后,允许设置重启次数为1~128次。 图5 自动重启设置 使用API接口设置容错检查: 用户可以通过API接口的方式开启自动重启。创建训练作业时,在“metadata”字段的“annotations”中传入“fault-tolerance/job-retry-num”字段。 添加“fault-tolerance/job-retry-num”字段,视为开启自动重启,value的范围可以设置为1~128的整数。value值表示最大允许重新下发作业的次数。如果不传入则默认为0,表示不做重新下发作业,也不会启用环境检测。 图6 设置API
  • 触发容错环境检测达到的效果 容错检查正常通过时,会打印检测项目的日志,表示具体涉及的检查项目成功。您可以通过在日志中搜索“item”关键字查看。当容错检查正常通过时,可以减少运行故障上报问题。 容错检查失败时,会打印检查失败的日志。您可以通过在日志中搜索“item”关键字查看失败信息。 如果作业重启次数没有达到设定的次数,则会自动做重新下发作业。您可以通过搜索“error,exiting”关键字查找作业重启失败结束的日志。
  • 异常处理 Clone仓库失败。可能是网络原因问题。可以在JupyterLab的Terminal中通过执行git clone https://github.com/jupyterlab/extension-examples.git测试网络连通情况。 图6 Clone仓库失败 如果克隆时遇到Notebook当前目录下已有该仓库,系统给出提示仓库名称重复,此时可以单击“覆盖”继续克隆仓库,也可以单击取消。
  • 上传本地超大文件(50GB以上)至JupyterLab 不支持在Notebook的JupyterLab中直接上传大小超过50GB的文件。 50GB以上的文件需要先从本地上传到OBS中,再在Notebook中调用ModelArts的Moxing接口或者SDK接口读写OBS中的文件。 图12 在Notebook中上传下载大文件 具体操作如下: 从本地上传文件至OBS。具体操作请参见上传文件至OBS桶。 将OBS中的文件下载到Notebook,可以通过在Notebook中运行代码的方式完成数据下载,具体方式有2种,ModelArts的SDK接口或者调用MoXing接口。 方法一:使用ModelArts SDK接口将OBS中的文件下载到Notebook后进行操作。 示例代码: 1 2 3 from modelarts.session import Session session = Session() session.obs.copy("obs://bucket-name/obs_file.txt","/home/ma-user/work/") 方法二:使用Moxing操作OBS文件将OBS中的文件同步到Notebook后进行操作。 import moxing as mox #下载一个OBS文件夹sub_dir_0,从OBS下载至Notebook mox.file.copy_parallel('obs://bucket_name/sub_dir_0', '/home/ma-user/work/sub_dir_0') #下载一个OBS文件obs_file.txt,从OBS下载至Notebook mox.file.copy('obs://bucket_name/obs_file.txt', '/home/ma-user/work/obs_file.txt') 如果下载到Notebook中的是zip文件,在Terminal中执行下列命令,解压压缩包。 unzip xxx.zip #在xxx.zip压缩包所在路径直接解压 代码执行完成后,参考图13打开Terminal后执行ls /home/ma-user/work命令查看下载到Notebook中的文件。或者在JupyterLab左侧导航中显示下载的文件,如果没有显示,请刷新后查看,如图14所示。 图13 打开Terminal 图14 查看下载到Notebook中的文件
  • 上传本地大文件(100MB~50GB)至JupyterLab 对于大小超过100MB不超过50GB的文件可以使用OBS中转,系统先将文件上传至OBS(对象桶或并行文件系统),然后从OBS下载到Notebook。下载完成后,ModelArts会将文件自动从OBS中删除。 例如,对于下面这种情况,可以通过“OBS中转”上传。 图5 通过OBS中转上传大文件 如果使用OBS中转需要提供一个OBS中转路径,可以通过以下三种方式提供: 图6 通过OBS中转路径上传 仅第一次单击“OBS中转”需要提供OBS中转路径,以后默认使用该路径直接上传,可以通过上传文件窗口左下角的设置按钮更新OBS中转路径。如图10所示。 方式一:在输入框中直接输入有效的OBS中转路径,然后单击“确定”完成。 图7 输入有效的OBS中转路径 方式二:打开OBS File Browser选择一个OBS中转路径,然后单击“确定”完成。 图8 打开OBS File Browser 方式三:单击“使用默认路径”完成。 图9 使用默认路径上传文件 图10 设置本地文件OBS中转路径 完成OBS中转路径设置后,开始上传文件。 图11 上传文件 解压缩文件包 将文件以压缩包形式上传至Notebook JupyterLab后, 可在Terminal中解压缩文件包。 unzip xxx.zip #在xxx.zip压缩包所在路径直接解压 解压命令的更多使用说明可以在主流搜索引擎中查找Linux解压命令操作。
  • 上传文件要求 对于大小不超过100MB的文件直接上传,并展示文件大小、上传进度及速度等详细信息。 对于大小超过100MB不超过50GB的文件可以使用OBS中转,系统先将文件上传OBS(对象桶或并行文件系统),然后从OBS下载到Notebook,上传完成后,会将文件从OBS中删除。 50GB以上的文件上传通过调用ModelArts SDK或者Moxing完成。 对于Notebook当前目录下已经有同文件名称的文件,可以覆盖继续上传,也可以取消。 支持10个文件同时上传,其余文件显示“等待上传”。不支持上传文件夹,可以将文件夹压缩成压缩包上传至Notebook后, 在Terminal中解压压缩包。 unzip xxx.zip #在xxx.zip压缩包所在路径直接解压 解压命令的更多使用说明可以在主流搜索引擎中查找Linux解压命令操作。 多个文件同时上传时,JupyterLab窗口最下面会显示上传文件总数和已上传文件数。
  • 动态扩容EVS有什么限制 Notebook实例的存储配置采用的是云硬盘EVS。 图1 创建Notebook实例时选择云硬盘EVS存储 单次最大可以扩容100GB,扩容后的总容量不超过4096GB。 云硬盘EVS存储容量最大支持4096GB,达到4096GB时,不允许再扩容。 实例停止后,扩容后的容量仍然有效。计费也是按照扩容后的云硬盘EVS容量进行计费。 云硬盘EVS只要使用就会计费,请在停止Notebook实例后,确认不使用就及时删除数据,释放资源,避免产生费用。
  • 修改标注信息 当数据完成标注后,您还可以进入已标注页签,对已标注的数据进行修改。 在数据标注详情页面,单击“已标注”页签,然后在图片列表中选中待修改的图片,单击图片跳转到标注页面,在右侧标签信息区域中单击此图片已添加的标注信息。 修改标签:“标注”区域中,单击编辑图标,在弹出框中输入正确的标签名或标签颜色,然后单击完成修改。也可以单击标签,在图片标注区域,调整标注框的位置和大小,完成调整后,单击其他标签即可保存修改。 修改图片标注信息:在图片展示区,显示物体边缘,可单击蓝色圆点,将标注框调整至物体边缘。 删除标签:在“标注”区域中,单击删除图标即可删除此图片中的标签。图片的标签全部删除后,该图片会重新回到“未标注”页签。 标注信息修改后,单击页面左上角的“返回数据标注预览”离开标注页面,在弹出对话框中单击“确定”保存修改。 图6 编辑标注信息
  • 删除数据 通过数据删除操作,可将需要丢弃的数据快速删除。 在“全部”、“未标注”或“已标注”页面中,依次选中需要删除的内容,或者选择“选择当前页”选中该页面所有内容,然后单击“删除”。在弹出的对话框中,根据实际情况选择是否勾选“同时删除OBS源文件”,确认信息无误后,单击“确定”完成删除操作。 图10 删除图片 其中,被选中的内容,其左上角将显示为勾选状态。如果当前页面无选中内容时,“删除”按钮为灰色,无法执行删除操作。 如果勾选了“同时删除OBS源文件”,删除图片操作将删除对应OBS目录下存储的图片,此操作可能会影响已使用此源文件的其他数据集或数据集版本,有可能导致展示异常或训练/推理异常。删除后,数据将无法恢复,请谨慎操作。
  • 筛选数据 在标注作业详情页面,默认展示作业中全部未标注的数据,您可以在“全部”、“未标注”或“已标注”页签下,在筛选条件区域,单击,添加筛选条件,快速过滤出您想要查看的数据。 支持的筛选条件如下所示,您可以设置一个或多个选项进行筛选。 难例集:难例或非难例。 标签:您可以选择全部标签,或者基于您指定的标签,选中其中一个或多个。 文件名或目录:根据文件名称或者文件存储目录筛选。 标注人:选择执行标注操作的账号名称。 样本属性:表示自动分组生成的属性。只有启用了自动分组任务后才可使用此筛选条件。 数据属性:筛选数据的来源,选择“全部”或“推理”。 图1 筛选条件
  • 修改标注 当数据完成标注后,您还可以进入已标注页签,对已标注的数据进行修改。 基于图片修改 在标注作业详情页面,单击“已标注”页签,然后在图片列表中选中待修改的图片(选择一个或多个)。在右侧标签信息区域中对图片信息进行修改。 修改标签:在“选中文件标签”区域中,单击操作列的编辑图标,然后在文本框中输入正确的标签名,然后单击确定图标完成修改。 删除标签:在“选中文件标签”区域中,单击操作列的删除图标删除该标签。此操作仅删除选中图片中的标签。 图2 编辑标签 基于标签修改 在标注作业详情页,单击右侧区域的“标签管理”,显示全部标签列表。 修改标签:单击操作列的“修改”,然后在弹出的对话框中输入修改后的标签名,然后单击“确定”完成修改。修改后,之前添加了此标签的图片,都将被标注为新的标签名称。 删除标签:单击操作列“删除”,之前添加了此标签的图片,都将删除此标签。 图3 标签管理 图4 全部标签的信息 单击标注作业操作列的“标签”,可跳转至标签管理页。 单击操作列的“修改”,即可完成标签的修改。 单击操作列的“删除”,即可删除该标签。 当数据完成标注后,您还可以进入已标注页签,对已标注的数据进行修改。 基于文本修改 在标注作业详情页,单击“已标注”页签,然后在文本列表中选中待修改的文本。 在文本列表中,单击文本,当文本背景变为蓝色时,表示已选择。当文本有多个标签时,可以单击文本标签上方的删除单个标签。 基于标签修改 在标注作业详情页,单击“已标注”页签,在图片列表右侧,显示全部标签的信息。 批量修改:在“全部标签”区域中,单击操作列的编辑图标,然后在文本框中修改标签名称,选择标签颜色,单击“确定”完成修改。 批量删除:在“全部标签”区域中,单击操作列的删除图标,在弹出对话框中,可选择“仅删除标签”或“删除标签及仅包含此标签的标注对象”,然后单击“确定”。 当数据完成标注后,您还可以进入“已标注”页签,对已标注的数据进行修改。 基于音频修改 在标注作业详情页面,单击“已标注”页签,然后在音频列表中选中待修改的音频(选择一个或多个)。在右侧标签信息区域中对标签进行修改。 修改标签:在“选中文件标签”区域中,单击操作列的编辑图标,然后在文本框中输入正确的标签名,然后单击确定图标完成修改。 删除标签:在“选中文件标签”区域中,单击操作列的删除图标删除该标签。 基于标签修改 在标注作业详情页面,单击“已标注”页签,在音频列表右侧,显示全部标签的信息。 图5 全部标签信息 修改标签:单击操作列的编辑图标,然后在弹出的对话框中输入修改后的标签名,然后单击“确定”完成修改。修改后,之前添加了此标签的音频,都将被标注为新的标签名称。 删除标签:单击操作列的删除图标,在弹出的对话框中,根据提示框选择需要删除的对象,然后单击“确定”完成删除。
  • 同步新数据 ModelArts会自动将数据集中新增的数据同步至标注作业,包含数据及当前标注作业支持的标注信息。 为了快速获取数据集中最新数据,可在标注作业详情页的“全部”、“未标注”或“已标注”页签中,单击“同步新数据”,快速将数据集中的数据添加到标注作业中。 问题现象: 将已标注好的数据上传至OBS,同步数据后,显示为未标注。 原因分析: 可能是OBS桶设置了自动加密导致此问题。 解决方法: 需要新建OBS桶重新上传数据,或者取消桶加密后,重新上传数据。
  • 本地构建镜像 以linux x86_x64架构的主机为例,您可以购买相同规格的E CS 或者应用本地已有的主机进行自定义镜像的制作。 购买ECS服务器的具体操作请参考购买并登录弹性云服务器。镜像选择公共镜像,推荐使用ubuntu18.04的镜像。 图1 创建ECS服务器-选择X86架构的公共镜像 登录主机后,安装Docker,可参考Docker官方文档。也可执行以下命令安装docker。 curl -fsSL get.docker.com -o get-docker.sh sh get-docker.sh 获取基础镜像。本示例以Ubuntu18.04为例。 docker pull ubuntu:18.04 新建文件夹“self-define-images”,在该文件夹下编写自定义镜像的“Dockerfile”文件和应用服务代码“test_app.py”。本样例代码中,应用服务代码采用了flask框架。 文件结构如下所示 self-define-images/ --Dockerfile --test_app.py “Dockerfile” From ubuntu:18.04 # 配置华为云的源,安装 python、python3-pip 和 Flask RUN cp -a /etc/apt/sources.list /etc/apt/sources.list.bak && \ sed -i "s@http://.*security.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list && \ sed -i "s@http://.*archive.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list && \ apt-get update && \ apt-get install -y python3 python3-pip && \ pip3 install --trusted-host https://repo.huaweicloud.com -i https://repo.huaweicloud.com/repository/pypi/simple Flask # 复制应用服务代码进镜像里面 COPY test_app.py /opt/test_app.py # 指定镜像的启动命令 CMD python3 /opt/test_app.py “test_app.py” from flask import Flask, request import json app = Flask(__name__) @app.route('/greet', methods=['POST']) def say_hello_func(): print("----------- in hello func ----------") data = json.loads(request.get_data(as_text=True)) print(data) username = data['name'] rsp_msg = 'Hello, {}!'.format(username) return json.dumps({"response":rsp_msg}, indent=4) @app.route('/goodbye', methods=['GET']) def say_goodbye_func(): print("----------- in goodbye func ----------") return '\nGoodbye!\n' @app.route('/', methods=['POST']) def default_func(): print("----------- in default func ----------") data = json.loads(request.get_data(as_text=True)) return '\n called default func !\n {} \n'.format(str(data)) # host must be "0.0.0.0", port must be 8080 if __name__ == '__main__': app.run(host="0.0.0.0", port=8080) 进入“self-define-images”文件夹,执行以下命令构建自定义镜像“test:v1”。 docker build -t test:v1 . 您可以使用“docker images”查看您构建的自定义镜像。
  • 将自定义镜像创建为模型 参考从容器镜像中选择元模型导入元模型,您需要特别关注以下参数: 元模型来源:选择“从容器镜像中选择” 容器镜像所在的路径:选择已制作好的自有镜像 图4 选择已制作好的自有镜像 容器调用接口:指定模型启动的协议和端口号。请确保协议和端口号与自定义镜像中提供的协议和端口号保持一致。 镜像复制:选填,选择是否将容器镜像中的模型镜像复制到ModelArts中。 健康检查:选填,用于指定模型的健康检查。仅当自定义镜像中配置了健康检查接口,才能配置“健康检查”,否则会导致模型创建失败。 apis定义:选填,用于编辑自定义镜像的apis定义。模型apis定义需要遵循ModelArts的填写规范,参见模型配置文件说明。 本样例的配置文件如下所示: [{ "url": "/", "method": "post", "request": { "Content-type": "application/json" }, "response": { "Content-type": "application/json" } }, { "url": "/greet", "method": "post", "request": { "Content-type": "application/json" }, "response": { "Content-type": "application/json" } }, { "url": "/goodbye", "method": "get", "request": { "Content-type": "application/json" }, "response": { "Content-type": "application/json" } } ]
  • 制作流程 场景一: 预置镜像的环境软件满足要求,只需要导入模型包,就能用于创建模型,通过镜像保存功能制作。具体案例参考在Notebook中通过镜像保存功能制作自定义镜像用于推理。 图1 模型的自定义镜像制作场景一 场景二: 预置镜像既不满足软件环境要求,同时需要放入模型包,在Notebook中通过Dockerfile制作。具体案例参考在Notebook中通过Dockerfile从0制作自定义镜像用于推理。 图2 模型的自定义镜像制作场景二 场景三:预置镜像既不满足软件环境要求,同时需要放入模型包,新的镜像超过35G,在服务器(如ECS)上制作。具体案例参考在ECS中通过Dockerfile从0制作自定义镜像用于推理。 图3 模型的自定义镜像制作场景三
  • 自定义镜像的配置规范 镜像对外接口 设置镜像的对外服务接口,推理接口需与config.json文件中apis定义的url一致,当镜像启动时可以直接访问。下面是mnist镜像的访问示例,该镜像内含mnist数据集训练的模型,可以识别手写数字。其中listen_ip为容器IP,您可以通过启动自定义镜像,在容器中获取容器IP。 请求示例 curl -X POST \ http://{listen_ip}:8080/ \ -F images=@seven.jpg 图4 listen_ip获取示例 返回示例 {"mnist_result": 7} (可选)健康检查接口 如果在滚动升级时要求不中断业务,那么必须在config.json文件中配置健康检查的接口,供ModelArts调用,在config.json文件中配置。当业务可提供正常服务时,健康检查接口返回健康状态,否则返回异常状态。 如果要实现无损滚动升级,必须配置健康检查接口。 自定义镜像如果需要在“在线服务”模块使用OBS外部存储挂载功能,需要新建一个OBS挂载专属目录如“/obs-mount/”,避免选择存量目录覆盖已有文件。OBS挂载仅开放对挂载目录文件新增、查看、修改功能,如果需要删除文件请到OBS并行文件系统中手动删除。 健康检查接口示例如下。 URI GET /health 请求示例curl -X GET \ http://{listen_ip}:8080/health 响应示例 {"health": "true"} 状态码 表1 状态码 状态码 编码 状态码说明 200 OK 请求成功 日志文件输出 为保证日志内容可以正常显示,日志信息需要打印到标准输出。 镜像启动入口 如果需要部署批量服务,镜像的启动入口文件需要为“/home/run.sh”,采用CMD设置默认启动路径,例如Dockerfile配置如下: CMD ["sh", "/home/run.sh"] 镜像依赖组件 如果需要部署批量服务,镜像内需要集成python、jre/jdk、zip等组件包。 (可选)保持Http长链接,无损滚动升级 如果需要支持滚动升级的过程中不中断业务,那么需要将服务的Http的“keep-alive”参数设置为200s。以gunicorn服务框架为例,gunicorn缺省情形下不支持keep-alive,需要同时安装gevent并配置启动参数“--keep-alive 200 -k gevent”。不同服务框架参数设置有区别,请以实际情况为准。 (可选)处理SIGTERM信号,容器优雅退出 如果需要支持滚动升级的过程中不中断业务,那么需要在容器中捕获SIGTERM信号,并且在收到SIGTERM信号之后等待60秒再优雅退出容器。提前优雅退出容器可能会导致在滚动升级的过程中业务概率中断。要保证容器优雅退出,从收到SIGTERM信号开始,业务需要将收到的请求全部处理完毕再结束,这个处理时长最多不超过90秒。例如run.sh如下所示: #!/bin/bash gunicorn_pid="" handle_sigterm() { echo "Received SIGTERM, send SIGTERM to $gunicorn_pid" if [ $gunicorn_pid != "" ]; then sleep 60 kill -15 $gunicorn_pid # 传递 SIGTERM 给gunicorn进程 wait $gunicorn_pid # 等待gunicorn进程完全终止 fi } trap handle_sigterm TERM
  • 设置告警规则 通过设置ModelArts在线服务和模型负载告警规则,用户可自定义监控目标与通知策略,及时了解ModelArts在线服务和模型负载状况,从而起到预警作用。 设置ModelArts服务和模型的告警规则包括设置告警规则名称、监控对象、监控指标、告警阈值、监控周期和是否发送通知等参数。本节介绍了设置ModelArts服务和模型告警规则的具体方法。 只有“运行中”的在线服务,支持对接 CES 监控。
  • ModelArts的自定义镜像使用场景 当用户对深度学习引擎、开发库有特殊需求场景的时候,预置镜像已经不能满足用户需求。ModelArts提供自定义镜像功能支持用户自定义运行引擎。 ModelArts底层采用容器技术,自定义镜像指的是用户自行制作容器镜像并在ModelArts上运行。自定义镜像功能支持自由文本形式的命令行参数和环境变量,灵活性比较高,便于支持任意计算引擎的作业启动需求。 在制作自定义镜像的时候,可以把ModelArts提供的预置镜像作为基础镜像,通过在Dockerfile中使用预置镜像的SWR地址来拉取预置镜像后进行改造。可在ModelArts预置镜像列表里获取镜像的SWR地址,参考ModelArts支持的预置镜像列表章节。 制作自定义镜像用于创建Notebook 当Notebook预置镜像不能满足需求时,用户可以制作自定义镜像。在镜像中自行安装与配置环境依赖软件及信息,并制作为自定义镜像,用于创建新的Notebook实例。同时也支持用户在Notebook中,基于已有镜像制作新的自定义镜像。 制作自定义镜像用于训练模型 如果您已经在本地完成模型开发或训练脚本的开发,且您使用的AI引擎是ModelArts不支持的框架。您可以制作自定义镜像,并上传至SWR服务。您可以在ModelArts使用此自定义镜像创建训练作业,使用ModelArts提供的资源训练模型。 制作自定义镜像用于推理 如果您使用了ModelArts不支持的AI引擎开发模型,可以通过制作自定义镜像,导入ModelArts创建为模型,并支持进行统一管理和部署为服务。 用户制作的自定义镜像,使用的场景不同,镜像规则也不同,具体如下: 通用规则:SWR镜像类型为“私有”时,才可以共享给他人,适用于开发环境、训练作业、模型。 开发环境:SWR镜像类型为“公开”时,其他用户才可以在ModelArts镜像管理页面注册使用。 训练作业:SWR镜像类型为“公开”时,在使用自定义镜像创建训练作业时,在“镜像”输入框内直接填写“组织名称/镜像名称:版本名称”即可。例如:公开镜像的SWR地址为“swr.cn-north-4.myhuaweicloud.com/test-image/tensorflow2_1_1:1.1.1”,则在创建训练作业的“镜像”输入框里内直接填“test-images/tensorflow2_1_1:1.1.1”。
  • ModelArts的预置镜像使用场景 ModelArts给用户提供了一组预置镜像,用户可以直接使用预置镜像创建Notebook实例,在实例中进行依赖安装与配置后,保存为自定义镜像,可直接用于ModelArts训练,而不需要做适配。同时也可以使用预置镜像直接提交训练作业、创建模型等。 ModelArts提供的预置镜像版本是依据用户反馈和版本稳定性决定的。当用户的功能开发基于ModelArts提供的版本能够满足的时候,比如用户开发基于MindSpore1.X,建议用户使用预置镜像,这些镜像经过充分的功能验证,并且已经预置了很多常用的安装包,用户无需花费过多的时间来配置环境即可使用。 ModelArts默认提供了一组预置镜像供开发使用,这些镜像有以下特点: 零配置,即开即用,面向特定的场景,将AI开发过程中常用的依赖环境进行固化,提供合适的软件、操作系统、网络等配置策略,通过在硬件上的充分测试,确保其兼容性和性能最合适。 方便自定义,预置镜像已经在SWR仓库中,通过对预置镜像的扩展完成自定义镜像注册。 安全可信,基于安全加固最佳实践,访问策略、用户权限划分、开发软件 漏洞扫描 、操作系统安全加固等方式,确保镜像使用的安全性。
  • 自定义镜像功能关联服务介绍 容器镜像服务 容器 镜像服务 (Software Repository for Container,SWR)是一种支持镜像全生命周期管理的服务, 提供简单易用、安全可靠的镜像管理功能,帮助您快速部署容器化服务。您可以通过界面、社区CLI和原生API上传、下载和管理容器镜像。 您制作的自定义镜像需要上传至SWR服务。ModelArts开发环境、训练和创建模型使用的自定义镜像需要从SWR服务管理列表获取。 图1 获取镜像列表 对象存储服务 对象存储服务(Object Storage Service,OBS)是一个基于对象的海量存储服务,为客户提供海量、安全、高可靠、低成本的数据存储能力。 在使用ModelArts时存在与OBS的数据交互,您需要使用的数据可以存储至OBS。 弹性云服务器 弹性云服务器(Elastic Cloud Server,ECS)是由CPU、内存、操作系统、云硬盘组成的基础的计算组件。弹性云服务器创建成功后,您就可以像使用自己的本地PC或物理服务器一样,使用弹性云服务器。 在制作自定义镜像时,您可以在本地环境或者ECS上完成自定义镜像制作。
  • 利用MoXing使h5py.File支持OBS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import os import h5py import numpy as np import moxing as mox h5py_File_class = h5py.File class OBSFile(h5py_File_class): def __init__(self, name, *args, **kwargs): self._tmp_name = None self._target_name = name if name.startswith('obs://'): self._tmp_name = name.replace('/', '_') if mox.file.exists(name): mox.file.copy(name, os.path.join('cache', 'h5py_tmp', self._tmp_name)) name = self._tmp_name super(OBSFile, self).__init__(name, *args, **kwargs) def close(self): if self._tmp_name: mox.file.copy(self._tmp_name, self._target_name) super(OBSFile, self).close() setattr(h5py, 'File', OBSFile) arr = np.random.randn(1000) with h5py.File('obs://bucket/random.hdf5', 'r') as f: f.create_dataset("default", data=arr) with h5py.File('obs://bucket/random.hdf5', 'r') as f: print(f.require_dataset("default", dtype=np.float32, shape=(1000,)))
  • 利用文件对象读取图片 使用opencv打开一张图片时,无法传入一个OBS路径,需要利用文件对象读取,考虑以下代码是无法读取到该图片的。 1 2 import cv2 cv2.imread('obs://bucket_name/xxx.jpg', cv2.IMREAD_COLOR) 修改为如下代码: 1 2 3 4 import cv2 import numpy as np import moxing as mox img = cv2.imdecode(np.fromstring(mox.file.read('obs://bucket_name/xxx.jpg', binary=True), np.uint8), cv2.IMREAD_COLOR)
  • 将一个不支持OBS路径的API改造成支持OBS路径的API pandas中对h5的文件读写to_hdf和read_hdf既不支持OBS路径,也不支持输入一个文件对象,考虑以下代码会出现错误。 1 2 3 4 import pandas as pd df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, index=['a', 'b', 'c']) df.to_hdf('obs://wolfros-net/hdftest.h5', key='df', mode='w') pd.read_hdf('obs://wolfros-net/hdftest.h5') 通过重写pandas源码API的方式,将该API改造成支持OBS路径的形式。 写h5到OBS = 写h5到本地缓存 + 上传本地缓存到OBS + 删除本地缓存 从OBS读h5 = 下载h5到本地缓存 + 读取本地缓存 + 删除本地缓存 即将以下代码写在运行脚本的最前面,就能使运行过程中的to_hdf和read_hdf支持OBS路径。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import os import moxing as mox import pandas as pd from pandas.io import pytables from pandas.core.generic import NDFrame to_hdf_origin = getattr(NDFrame, 'to_hdf') read_hdf_origin = getattr(pytables, 'read_hdf') def to_hdf_override(self, path_or_buf, key, **kwargs): tmp_dir = '/cache/hdf_tmp' file_name = os.path.basename(path_or_buf) mox.file.make_dirs(tmp_dir) local_file = os.path.join(tmp_dir, file_name) to_hdf_origin(self, local_file, key, **kwargs) mox.file.copy(local_file, path_or_buf) mox.file.remove(local_file) def read_hdf_override(path_or_buf, key=None, mode='r', **kwargs): tmp_dir = '/cache/hdf_tmp' file_name = os.path.basename(path_or_buf) mox.file.make_dirs(tmp_dir) local_file = os.path.join(tmp_dir, file_name) mox.file.copy(path_or_buf, local_file) result = read_hdf_origin(local_file, key, mode, **kwargs) mox.file.remove(local_file) return result setattr(NDFrame, 'to_hdf', to_hdf_override) setattr(pytables, 'read_hdf', read_hdf_override) setattr(pd, 'read_hdf', read_hdf_override)
  • 利用pandas读或写一个OBS文件 利用pandas读一个OBS文件。 1 2 3 4 import pandas as pd import moxing as mox with mox.file.File("obs://bucket_name/b.txt", "r") as f: csv = pd.read_csv(f) 利用pandas写一个OBS文件。 1 2 3 4 5 import pandas as pd import moxing as mox df = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]}) with mox.file.File("obs://bucket_name/b.txt", "w") as f: df.to_csv(f)
  • 读取完毕后将文件关闭 当读取OBS文件时,实际调用的是HTTP连接读取网络流,注意要记得在读取完毕后将文件关闭。为了防止忘记文件关闭操作,推荐使用with语句,在with语句退出时会自动调用mox.file.File对象的close()方法: 1 2 3 import moxing as mox with mox.file.File('obs://bucket_name/obs_file.txt', 'r') as f: data = f.readlines()
  • 删除操作 删除一个OBS文件。 例如删除“obs://bucket_name/obs_file.txt”。 1 2 import moxing as mox mox.file.remove('obs://bucket_name/obs_file.txt') 删除一个OBS目录,并且递归的删除这个目录下的所有内容。如果这个目录不存在,则会报错。 例如删除“obs://bucket_name/sub_dir_0”下的所有内容。 1 2 import moxing as mox mox.file.remove('obs://bucket_name/sub_dir_0', recursive=True)
  • 移动和复制操作 移动一个OBS文件或文件夹。移动操作本身是用“复制+删除”来实现的。 一个OBS文件移动到另一个OBS文件,例如将“obs://bucket_name/obs_file.txt”移动到“obs://bucket_name/obs_file_2.txt”。 1 2 import moxing as mox mox.file.rename('obs://bucket_name/obs_file.txt', 'obs://bucket_name/obs_file_2.txt') 移动和复制操作不可以跨桶,必须在同一个桶内操作。 从OBS移动到本地,例如将“obs://bucket_name/obs_file.txt”移动到“/tmp/obs_file.txt”。 1 2 import moxing as mox mox.file.rename('obs://bucket_name/obs_file.txt', '/tmp/obs_file.txt') 从本地移动到OBS,例如将“/tmp/obs_file.txt”移动到“obs://bucket_name/obs_file.txt”。 1 2 import moxing as mox mox.file.rename('/tmp/obs_file.txt', 'obs://bucket_name/obs_file.txt') 从本地移动到本地,例如将“/tmp/obs_file.txt”移动到“/tmp/obs_file_2.txt”,该操作相当于os.rename。 1 2 import moxing as mox mox.file.rename('/tmp/obs_file.txt', '/tmp/obs_file_2.txt') 所有的移动操作均可以操作文件夹,如果操作的是文件夹,那么则会递归移动文件夹下所有的内容。 复制一个文件。mox.file.copy仅支持对文件操作,如果要对文件夹进行操作,请使用mox.file.copy_parallel。 从OBS复制到OBS,例如将“obs://bucket_name/obs_file.txt”复制到“obs://bucket_name/obs_file_2.txt”。 1 2 import moxing as mox mox.file.copy('obs://bucket_name/obs_file.txt', 'obs://bucket_name/obs_file_2.txt') 将OBS文件复制到本地,也就是下载一个OBS文件。例如下载“obs://bucket_name/obs_file.txt”到本地“/tmp/obs_file.txt”。 1 2 import moxing as mox mox.file.copy('obs://bucket_name/obs_file.txt', '/tmp/obs_file.txt') 将本地文件复制到OBS,也就是上传一个OBS文件,例如上传“/tmp/obs_file.txt”到“obs://bucket_name/obs_file.txt”。 1 2 import moxing as mox mox.file.copy('/tmp/obs_file.txt', 'obs://bucket_name/obs_file.txt') 将本地文件复制到本地,操作等价于shutil.copyfile,例如将“/tmp/obs_file.txt”复制到“/tmp/obs_file_2.txt”。 1 2 import moxing as mox mox.file.copy('/tmp/obs_file.txt', '/tmp/obs_file_2.txt') 复制一个文件夹。mox.file.copy_parallel仅支持对文件夹操作,如果要对文件进行操作,请使用mox.file.copy。 从OBS复制到OBS,例如将obs://bucket_name/sub_dir_0复制到obs://bucket_name/sub_dir_1 1 2 import moxing as mox mox.file.copy_parallel('obs://bucket_name/sub_dir_0', 'obs://bucket_name/sub_dir_1') 将OBS文件夹复制到本地,也就是下载一个OBS文件夹。例如下载“obs://bucket_name/sub_dir_0”到本地“/tmp/sub_dir_0”。 1 2 import moxing as mox mox.file.copy_parallel('obs://bucket_name/sub_dir_0', '/tmp/sub_dir_0') 将本地文件夹复制到OBS,也就是上传一个OBS文件夹,例如上传“/tmp/sub_dir_0”到“obs://bucket_name/sub_dir_0”。 1 2 import moxing as mox mox.file.copy_parallel('/tmp/sub_dir_0', 'obs://bucket_name/sub_dir_0') 将本地文件夹复制到本地,操作等价于shutil.copytree,例如将“/tmp/sub_dir_0”复制到“/tmp/sub_dir_1”。 1 2 import moxing as mox mox.file.copy_parallel('/tmp/sub_dir_0', '/tmp/sub_dir_1')
  • 列举操作 列举一个OBS目录,只返回顶层结果(相对路径),不做递归列举。 例如列举“obs://bucket_name/object_dir”,返回该目录下所有的文件和文件夹,不会递归查询。 假设“obs://bucket_name/object_dir”中有如下结构 1 2 3 4 5 bucket_name |- object_dir |- dir0 |- file00 |- file1 调用如下代码: 1 2 import moxing as mox mox.file.list_directory('obs://bucket_name/object_dir') 返回一个list: ['dir0', 'file1'] 递归列举一个OBS目录,返回目录中所有的文件和文件夹(相对路径),并且会做递归查询。 假设obs://bucket_name/object_dir中有如下结构。 1 2 3 4 5 bucket_name |- object_dir |- dir0 |- file00 |- file1 调用如下代码: 1 2 import moxing as mox mox.file.list_directory('obs://bucket_name/object_dir', recursive=True) 返回一个list: ['dir0', 'dir0/file00', 'file1']
共100000条
提示

您即将访问非华为云网站,请注意账号财产安全