一、说明

欢迎来到我们每周的FiftyOne提示和技巧博客,我们回顾了最近在Slack,GitHub,Stack Overflow和Reddit上弹出的问题和答案。FiftyOne是一个开源机器学习工具集,使数据科学团队能够通过帮助他们策划高质量数据集、评估模型、查找错误、可视化嵌入。

二、什么是FifthOne?

FiftyOne是一个开源机器学习工具集,使数据科学团队能够通过帮助他们策划高质量数据集、评估模型、查找错误、可视化嵌入并更快地投入生产来提高其计算机视觉模型的性能。

  • 如果你喜欢在GitHub上看到的内容,给这个项目加一颗星。
  • 开始吧!我们使几分钟内启动和运行变得容易。
  • 加入 FiftyOneSlack 社区,我们总是很乐意提供帮助。

好的,让我们深入了解本周的提示和技巧!

三、省略检测实例很少的类

社区松弛成员西尔维娅施密特问道:

“当按特定字段中的值对样本进行分组时,我想省略具有数据集中很少出现的值的样本。怎么能做到这一点呢?

实现此目的的一种方法是使用来获取整个 or 对象中给定字段中每个唯一值的出现次数的计数,获取比所需截止值更频繁出现的值,并使用该方法获取包含这些值的样本。count_values()DatasetDatasetViewmatch()

例如,如果要从“野生家庭”数据集的测试拆分中获取值在数据集中出现十次以上的样本,则可以执行以下操作:name

import fiftyone as foimport fiftyone.zoo as fozfrom fiftyone import ViewField as F## load the datasetdataset = foz.load_zoo_dataset("fiw", split="test")counts = dataset.count_values("name")keep_names = [name for name, count in counts.items() if count > 10]## filter for samples with these namesview = dataset.match(F("name").is_in(keep_names))session = fo.launch_app(view)

名称在“野生家庭”数据集中出现十次以上的图像。

然后,您可以将此生成的视图传递到按字段中的值或所需的任何其他聚合进行分组。group_by()

在 FiftyOne 文档中了解有关 count_values()、is_in()和使用聚合的更多信息。

四、保存对示例字段所做的更改

社区松弛成员西尔维娅施密特问道:

“在添加示例字段以及稍后在视图中更改这些值时,是否必须通过调用‘数据集’对象来持久进行更改,或者如果数据集已经持久化,是否会保存这些更改?”save()

好问题,西尔维娅!通常,当对 or 中的单个样本进行更改时,需要通过调用样本而不是数据集来保存更改。即使数据集是持久性的,情况也是如此,即如果DatasetDatasetViewsave()

dataset.persistent = True

例如,可以更改快速入门数据集中第一个样本的首次检测的类标签,如下所示:

import fiftyone as foimport fiftyone.zoo as foz## load datasetdataset = foz.load_zoo_dataset("quickstart")## get samplesample = dataset.first()## change labelsample.ground_truth.detections[0].label = "bear"## save changes to datasetsample.save()

仅在编辑数据集级元数据(如 .save()dataset.info

但是,在某些情况下,无需显式运行即可将更改传播回数据集。其中包括方法(该方法接收值列表并将这些值写入视图中示例的字段)以及将标记添加到视图中所有示例的方法。sample.save()view.set_values(field_name, field_vals)field_valsfield_nameview.tag_samples(tags)tags

如果您知道需要循环访问 or 并对每个示例进行更改,而不是调用每个示例,则传递 to 对操作进行批处理会更有效。例如,要为数据集中的每个样本设置一个带有随机数的字段,我们可以运行:DatasetDatasetViewsave()autosave=Trueiter_samples()random

import randomimport fiftyone as foimport fiftyone.zoo as foz## load datasetdataset = foz.load_zoo_dataset("quickstart")## Automatically saves sample edits in efficient batchesfor sample in dataset.select_fields().iter_samples(autosave=True):sample["random"] = random.random()

在 FiftyOne 文档中了解有关set_values()和标记示例的更多信息。

五、预测齐次图像中的类标签

社区松弛成员乔治·皮尔斯问道:

“处理对象的标签与示例中其他对象的标签紧密交织的应用程序的最佳方法是什么?例如,我可能有一些图像,通常是所有猫的人群,或者所有狗的人群,但不是同时包含猫和狗的人群。

好问题,乔治!有很多方法可以处理这样的数据。一种方法是积累大量这样的示例,并根据这些数据训练模型。给定足够高质量的示例,模型应该(理论上)能够学习这些关系。

作为仅使用现有数据的替代方法,您可以根据模型预测的输出对样本中的标签执行后处理。例如,如果模型的预测存储在样本的字段中,则可以创建新的标签字段,并根据该样本的内容填充此新字段的内容。model_rawmodel_processedmodel_raw

对于每个样本,检查是否有三个或更多具有相同类标签的对象。为了简单起见,我们假设就是这个类。如果有,则对于未标记为 s in 的所有对象,如果其类置信度分数低于某个阈值,则将其类标签设置为 in 。dogdogmodel_rawdogmodel_processed

这可能是这样的:

import numpy as npimport fiftyone as foimport fiftyone.zoo as fozfrom fiftyone import ViewField as F## create or load your datasetdataset = fo.Dataset(..)## clone predictions into new fielddataset.clone_sample_field("model_raw", "model_processed")## set a class confidence thresholdconf_thresh = 0.3## iterate through samples in datasetfor sample in dataset.iter_samples(autosave=True):dets = sample.model_processed.detectionslabels = [det.label for det in dets]unique_labels, label_counts = np.unique(labels, return_counts=True)## find samples with at least 3 labels of same classif max(label_counts) > 2:crowd_label = unique_labels[np.argmax(label_counts)]for det in dets:if (det.label != crowd_label) and(det.confidence < conf_thresh): det.label = crowd_label det.confidence = None## tag samples to look at latersample.tags.append("possible homogeneous crowd")

然后,您可以比较这些已处理模型预测与原始预测不同的标记样本,并在FiftyOne 应用程序中对其进行检查。

在 FiftyOne 文档中了解有关保存、保留和克隆示例字段的更多信息。

六、匹配分类结果

社区松弛成员纳达夫问道:

“我有一个有两种分类的数据集。在代码或应用中创建仅包含两个分类一致的示例的视图的最佳方法是什么?

在代码中执行此操作的一种方法是使用 FiftyOne 的内置筛选和匹配功能。该方法将返回一个视图,其中包含条件为 true 的所有样本。dataset.match(my_condition)my_condition

在您的情况下,您可以使用ViewField在两个分类之间创建协议条件。下面是它的外观:

import fiftyone as foimport fiftyone.zoo as fozfrom fiftyone import ViewField as F# create or load your dataset with# classifications in field1 and field2dataset = fo.Dataset(...)view = dataset.match(F("field1.label") == F("field2.label"))session = fo.launch_app(view)

如果您想要一个包含两个分类不对齐的所有样本的视图,则可以将相等运算符替换为等式运算符。==!=

在 FiftyOne 文档中了解有关筛选的更多信息。

七、关闭会话

社区松弛成员斯科特问道:“如何断开启动的会话?”

在 FiftyOne 中,会话是连接到特定或 的FiftyOne 应用程序的实例。您可以使用以下方法启动特定数据集或视图的会话:DatasetDatasetViewlaunch_app()

import fiftyone as foimport fiftyone.zoo as foz## load datasetdataset = foz.load_zoo_dataset("quickstart")## launch one sessionsession1 = fo.launch_app(dataset)## create a viewview = dataset.take(20)## launch another sessionsession2 = fo.launch_app(view)

您还可以通过以下方式查看所有已注册的会话:fo.core.session.session._subscribed_sessions

defaultdict(set,{5151: {Dataset:quickstartMedia type: imageNum samples:20Selected samples: 0Selected labels:0Session URL:http://localhost:5151/View stages:1. Take(size=20, seed=None),Dataset:quickstartMedia type: imageNum samples:20Selected samples: 0Selected labels:0Session URL:http://localhost:5151/View stages:1. Take(size=20, seed=None)}})

当您终止运行 FiftyOne 的 Python 进程时,所有会话都将关闭,因此通常不需要显式关闭会话。

但是,如果您想随时终止会话,则可以使用私有方法执行此操作:_unregister_session()

from fiftyone.core.session.session import _unregister_session_unregister_session(session1)

在 FiftyOne 文档中了解有关会话的更多信息,包括如何在远程计算机上启动多个应用程序实例。

八、加入五十一社区!

加入已经使用FiftyOne解决当今计算机视觉中一些最具挑战性问题的数千名工程师和数据科学家的行列!

  • 1,350+FiftyOne Slackmembers
  • 2,550+ stars onGitHub
  • 3,200+Meetup members
  • Used by246+ repositories
  • 56+contributors

九、下一步是什么?

  • 如果你喜欢在GitHub上看到的内容,给这个项目加一颗星。
  • 开始吧!我们使几分钟内启动和运行变得容易。
  • 加入 FiftyOneSlack 社区,我们总是很乐意提供帮助。

    雅各布·马克斯