在项目的下一阶段,需要从Roboflow下载标注好的数据,然后在CometML中创建一个数据工件以追踪数据的来源。可能会想,“嘿,如果数据已经在Roboflow中了,为什么还需要在Comet中也有呢?”这是个好问题。
在开始使用Roboflow或Comet之前,图像数据一团糟。有来自手机的图像文件夹,相机的图像文件夹,互联网的图像文件夹,创建了额外的文件夹来保存还没有标注的数据,数据到处都是。
在夏天把项目搁置了几个月,当重新捡起来时,完全不知道上次使用了哪些数据,不得不在文件夹中大量挖掘以弄清楚哪个文件夹有正确的数据。有了Comet中的数据来源,总是知道最后使用的是什么数据,将拥有所有的代码、数据、依赖项、训练运行等,都在一个地方。所以即使没有把数据弄得一团糟,把所有的数据放在一个地方仍然很有价值,这样将来需要时就能找到,或者如果正在与他人共享Comet工作簿。
最初,发现Roboflow是因为在寻找一些数据增强。最终使用的数据显示没有增强,因为安全摄像头将始终在同一个地方,它将始终看着家外面的同一个场景。没有必要添加它在野外永远不会看到的图像变异。
Roboflow的UI使得上传数据,进行标注,进行增强(还是尝试了),然后下载需要的任何文件格式的文件变得容易,用于构建模型。它还为设置了训练和验证集。Roboflow是一个端到端的解决方案,但已经计划尝试YOLOv5库,所以使用了Roboflow Python库来访问数据。
<video controls>
<source src="annotating-school-buses-in-roboflow.mp4" type="video/mp4">
浏览器不支持视频标签。
</video>
要从Roboflow中导出图像,首先点击“导出”按钮。将看到已经选择了Yolov5 PyTorch格式,这是这个项目需要的。选择“显示下载代码”,这样就可以将其添加到仓库中。这也将创建一个“data.yaml”,列出了数据工件中测试/训练/验证图像集的位置。
脚本将使用Roboflow API将图像数据下载到一个暂存目录。可以继续在Roboflow中进行项目,因为他们为计算机视觉项目的各个阶段提供了工具。然而,在这个版本的项目中,正在寻找新的CometML与YOLOv5的集成。
一旦在本地机器上的目录中有了图像数据,就创建了一个Comet实验,加载了data.yml文件,指向数据目录以访问图像,然后上传它们以创建一个数据工件。这也将创建一个comet_artifact.yaml。这个.yaml也在版本控制中,如果想看,它。
# 下载从Roboflow导出的数据集,并使用文件创建Comet数据工件。
from roboflow import Roboflow
from glob import glob
from comet_ml import Artifact, Experiment
import yaml
import os
import shutil
# 这些是在运行此脚本之前需要设置的所有“配置参数”
roboflow_workspace = "kristen-kehrer"
roboflow_project = "schoolbus-images"
roboflow_version = 4
staging_directory = f"Schoolbus-Images-{roboflow_version}"
roboflow_api_key_file = '.roboflow_api_key'
def create_artifact():
# 如果暂存目录已经存在,则删除它
if os.path.exists(staging_directory):
shutil.rmtree(staging_directory)
if not os.path.exists(roboflow_api_key_file):
raise f'Missing configuration file: {roboflow_api_key_file}'
# 从保存的凭证文件中加载api密钥,并去除两端的空白字符
roboflow_api_key = open(roboflow_api_key_file).read().strip()
# 使用Roboflow python SDK下载所需的数据集。
# 在 `.download("yolov5")` 完成后,完整的数据工件将
# 在本地文件系统中的 `staging_directory` 上
rf = Roboflow(api_key=roboflow_api_key)
project = rf.workspace(roboflow_workspace).project(roboflow_project)
dataset = project.version(roboflow_version).download("yolov5")
# 开始一个comet实验(项目名称/ api密钥已经在 `.comet.config` 中设置)
experiment = Experiment()
# 从Roboflow工件中加载 `data.yaml` 文件(这是数据需要为YOLOv5格式化的方式)
metadata = yaml.load(open(os.path.join(staging_directory, 'data.yaml')), Loader=yaml.Loader)
# 将元数据中的 `names` 字段从字符串列表转换为整数键字典
# 的字符串(`['bus', 'car']` 需要被转换为 `{ '0': 'bus', '1': 'car'}` 以适应comet元数据
# 创建了一个PR将其添加到yolov5库中,一旦它被合并,将移除这个。
names_dict = {}
for i in range(len(metadata['names'])):
names_dict[str(i)] = metadata['names'][i]
metadata['names'] = names_dict
# 创建comet Artifact对象
artifact = Artifact(name="schoolbus-yolov5-take2", artifact_type="dataset", metadata=metadata)
# 遍历 `staging_directory` 中的所有文件,并将文件添加到工件中
for file in glob(f'{staging_directory}/**/*.*', recursive=True):
artifact.add(file, logical_path=file.replace('', '/'))
# 记录工件并结束实验
experiment.log_artifact(artifact)
experiment.end()
def write_yolov5_data_file():
with open('comet_artifact.yaml', 'w') as file:
file.write(f'path: "comet://kristenkehrer/schoolbus-yolov5-take2:latest"n')
# 当运行此脚本时,运行这两个函数:
create_artifact()
write_yolov5_data_file()
下图显示了项目部分的数据版本。实际上,当准备公开项目时,创建了一个新的工件,但认为下面较旧的图像更好地说明了要说的内容。
上传的最后一个工件总是被Comet自动标记为“latest”,这样就总是可以使用最新的工件进行训练。在这个视图中,还可以看到创建的工件的早期版本,而构建项目时。可以看到有多个版本的数据,所以如果需要回去,可以,但也总是能够识别出哪个数据源是最新的。
在计算机上拥有未组织好的文件有点痛苦,尤其是在把这个项目搁置了一两个月之后,然后试图重新捡起来。
下面可以看到能够看到哪个模型是用哪些数据训练的。“hilarious_reptile”只是模型运行之一的名称。
现在数据都设置好了,准备开始模型。
现在有了数据,是时候考虑计算了。选择在自己的GPU上运行这个模型。为了确保可以访问GPU,确保遵循了pytorch(由yolov5使用)的“”文档。这提供了安装pytorch的具体pip指令,然后将其添加到requirements.txt文件中。
现在设置好了训练YOLOv5模型。对于训练,遵循了yolov5项目的“”指令。创建了一个简单的脚本,train.ps1,它调用了yolov5存储库中的yolov5 train.py脚本。包括了通往comet artifact.yaml的路径,这将被下载并用作yolov5的训练数据源,这要感谢新的yolov5 comet ml集成。
模型运行比较和跟踪的工作簿。不会声称自己是计算机视觉专家,使用了提供的权重,并且稍微玩了玩默认值,但这里没有发生什么魔法。一旦开始在超过一千张图像的集合上训练,所有的训练运行都做得很好。
CometML中的训练运行图表
好吧,在这一点上,可能已经启动了一个训练运行,正在等待模型训练。在本文中,使用Roboflow来标注图像,并使用Roboflow Python SDK将标注图像数据从Roboflow移动到一个暂存目录,然后将图像数据作为工件上传到Comet。然后使用数据来训练模型。