数据科学家们试图使用监督学习技术解决问题时,通常需要在着手建模之前整理出高质量的标记数据集。这可是个辛苦活。好在Amazon SageMaker Ground Truth的出现让每个人都能针对多种不同的任务(例如文本分类与对象检测),轻松地获得自己需要的数据集。
Ground Truth还能帮助大家为用户自定义的任务构建自定义数据集,对其中的任意内容做出标注。为了实现这项功能,Ground Truth充分发挥以下亚马逊云科技 (Amazon Web Services)服务的强大能力:
- 自定义Amazon Lambda函数,用于在各标记步骤之间触发特定操作。据此,我们可以在标记之前执行自定义逻辑,例如过滤示例或者通过其他服务(Amazon Translate或Amazon Rekognition)添加元数据;也可以在完成标记之后执行用于标签合并或质量控制的逻辑。
- 自定义Web模板,允许我们使用HTML、JavaScript自定义用户界面,并与Ground Truth工作流完美集成。这些模板可通过Crowd HTML Elements轻松构建(Crowd HTML Elements是一组用于文本、视频以及音频标记作业的通用UI元素,我们可以像在自定义模板中调整版块那样对其任意排列)。
- 如果需要特定领域专家团队的具体参与,则可以在Amazon Marketplace及Amazon Mechanical Turk中联系到众多熟练且专业的从业人员。Amazon Marketplace中的认证合作伙伴精通多种语言,能够根据多种行业的实际需求(例如医疗保健行业)对视频及图像内容做出有针对性的注解。
然而对于复杂的标记任务,例如困难的分类标准设定、极端多样的分类或者自动驾驶标记任务,大家可能需要为标记工作人员构建起更庞大的前端应用程序。在这类情况下,Angular等前端框架可以发挥作用,通过多种非常实用的设计模式(例如模型 - 视图 - 控制器,简称MVC)显著改善面向设计人员与开发人员庞大团队的用户体验/用户界面效果,同时保证整体代码库更健壮、更具可维护性。
本文将引导大家逐步使用Angular与Angular Elements创建起可完全自定义的解决方案,并将该方案与Ground Truth完美匹配。本演练要求大家能够熟练使用Ground Truth与Crowd HTML Elements运行自定义标记作业。关于更多详细信息,请参阅使用Amazon SageMaker Ground Truth构建自定义数据标记工作流。
本文中描述的方法还可与Amazon Augmented AI(Amazon A2I)配合使用,这将进一步降低构建需要人工审查的机器学习预测工作流的难度。这样的便利性,归功于Amazon A2I使用Crowd HTML Elements创建自定义工作模板。关于更多详细信息,请参阅创建自定义工作模板。
为复杂的分类方案构建一套自定义UI
如果我们在管理一套大规模供应链,并且需要与全球各地的餐厅或汽车制造商等不同类型的供应链开展互动,那么一定会收到多种格式不同、语言各异的发票。为了跟踪运营状况并提高财务效率,大家需要在对发票及收据与产品大类对应起来,并按照层级分类法将其收归组织。
下图所示,为计算机组件的层级分类法架构:
下图所示,为食物类型的层级分类法架构:
层级分类法的叶层级可以包含多至数各千个分类。实际用例则包括Web目录(Yahho! Directory或Open Directory Project)、图书馆分类法(Dewey Decimal或者美国国会图书馆)、自然科学、法律以及医学领域中应用的多种分类方案。
如果自然语言处理(NLP)模型能够帮助我们将每张发票自动标记至正确的类别,结果会如何?如果文本标记工具可以直接从发票中提取内容并加以分类,又会如何?
对大批量相关度较高的素材进行准确分类比较困难,我们需要以最优的成本效益来构建起高质量数据集。
使用Angular Elements创建分类标签
在以下用例中,假定我们是全球最大快餐连锁品牌兼材料采购方之一。要为NLP模型构建训练数据集,我们需要开发一套基于用户体验研究的单页Web应用程序,该应用可帮助员工阅读发票信息并在分类法中快速选择相应的类别。具体请参见以下截屏。
这套实现方案使用Angular Materials选项卡外加筛选器框以简化分类导航。其中还将显示发票说明的英文翻译,以便工作人员能够标记来自世界各地的发票。此外,由于页面由Angular框架构建而成,因此我们可以添加更多元素对其做出改进,例如使用更高级别的分类下拉列表,或者引入来自第三方API的动态内容(如图片或视频)。
关于此应用程序的更多详细信息,请参阅GitHub repo。
这款应用程序使用Angular Elements构建而成,其中还用到打包为自定义元素(也称Web组件)形式的多个Angular组件 —— 一种用于定义新HTML元素且框架中立的Web标准。大家后续可以基于此将该应用程序与Crowd HTML Elements无缝集成。
Angular Elements输入与输出
在本用例中,我们的Angular组件需要两项输入:发票说明与发票翻译。这两项输入通过<ng-home>(指定应用程序根元素的指令)中的标记属性进行传递,而后通过src/app/home.ts中由Angular Controller定义的@Input()注解捕捉输入中的各值。详见以下代码:
<ng-home source='10牛ステーキ-20パッケージ-ブランドX' translation='10 beef steak - 20 packages - brand X' id="home">loading</ng-home>
export class Home implements OnInit {
@Input() invoice = '';
@Input() translation = '';
...
在src/app/home.html中的Angular View当中,由双向绑定的占位符{{source}}与{{translation}}实现数值呈现,具体请参见以下代码:
<!-- Invoice Description -->
<div class="card" >
<div class="card-header">
<h3>Invoice Description</h3>
</div>
<div>
<p id="step1">
<span>Invoice Description: <br />
<b>{{ invoice }}</b></span>
</p>
<p style='font-weight: small; color: gray;' id="step2">
<span>English Translation: <br /> {{ translation }}</span>
</p>
</div>
</div>
以下截屏所示,为Food Categories页面中的Meats选项卡。
当我们选中一个类别并点击Submit时,Angular组件向其父DOM元素广播一个包含类别ID的JavaScript事件。整个过程在src/app/home.ts中通过Angular Controller的@Output()实现,详见以下代码:
<button mat-button color="primary" (click)="onSubmit()" id="submitButton">Submit</button>
<table>
...
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
(click)="selectRow(row)" [ngClass]="{ 'highlight': row === selectedRow }">
</tr>
</table>
@Output('rowselected') rowselected = new EventEmitter<any>();
#called when user click on a row in the table ("selecting" a category)
selectRow(row) {
this.selectedRow = row;
}
#called when user click on Submit button
onSubmit(){
this.rowselected.emit(this.selectedRow);
}
Angular与Crowd HTML Elements相集成
Angular Elements与Crowd HTML Elements之间的通信机制如上一节所述。
按照使用Amazon SageMaker Ground Truth构建自定义数据标记工作流中描述的步骤,大家可以调整文本向注解的具体传递方式,并了解如何从Angular Elements中捕捉广播事件以创建自定义模板。
以下代码所示,为作业创建当中使用的完整Liquid HTML模板。此文件也是我们Angluar应用中src/文件夹下的根文件index.html。(请确保使用的是dist文件夹下的index.html文件,且该文件中已经插入压缩后的.js文件,并带有正确的Amazon Simple Storage Service(Amazon S3)路径来托管我们的应用程序)。
<!doctype html>
<html lang="en">
<html>
<head>
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>
</head>
<body>
<crowd-form style="display: none;">
<input name="annotations" id="annotations" type="hidden">
<input name="timeElapsed" id="timeElapsed" type="hidden">
<!-- Prevent crowd-form from creating its own button -->
<crowd-button form-action="submit" style="display: none;"></crowd-button>
</crowd-form>
<div class="mat-app-background basic-container">
<!-- Dev Mode to test the Angular Element -->
<!-- <ng-home source='10牛ステーキ-20パッケージ-ブランドX' translation='10 beef steak - 20 packages - brand X' id="home">loading</ng-home> -->
<ng-home source='{{ task.input.source }}' translation='{{ task.input.translatedDesc }}'>loading</ng-home>
</div>
<script src="<your-s3-bucket-angular-app>/runtime-es2015.js" type="module"></script>
<script src="<your-s3-bucket-angular-app>/runtime-es5.js" nomodule defer></script>
<script src="<your-s3-bucket-angular-app>/polyfills-es5.js" nomodule defer></script>
<script src="<your-s3-bucket-angular-app>/polyfills-es2015.js" type="module"></script>
<script src="<your-s3-bucket-angular-app>/styles-es2015.js" type="module"></script>
<script src="<your-s3-bucket-angular-app>/styles-es5.js" nomodule defer></script>
<script src="<your-s3-bucket-angular-app>/vendor-es2015.js" type="module"></script>
<script src="<your-s3-bucket-angular-app>/vendor-es5.js" nomodule defer></script>
<script src="<your-s3-bucket-angular-app>/main-es2015.js" type="module"></script>
<script src="<your-s3-bucket-angular-app>/main-es5.js" nomodule defer></script>
</body>
</html>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
// Counter
var enterDate = new Date();
function secondsSinceEnter()
{
return (new Date() - enterDate) / 1000;
}
// GT Form Submitting
const component = document.querySelector('ng-home').addEventListener('rowselected', (event) => {
// alert(event.detail.CODE);
document.getElementById('annotations').value = event.detail.CODE;
document.getElementById('timeElapsed').value = secondsSinceEnter();
document.querySelector('crowd-form').submit();
});
});
</script>
<style>
.body {
background-color: #fafafa;
}
.header {
background: #673ab7;
color: #fff;
padding: 0 16px;
margin: 20px 20px 0px 20px;
padding: 20px;
}
.cards {
display: grid;
grid-template-columns: 30% auto;
grid-auto-rows: auto;
grid-gap: 1rem;
margin: 20px 20px 0px 20px;
}
.card {
box-shadow: 0 2px 1px -1px rgba(0,0,0,.2), 0 1px 1px 0 rgba(0,0,0,.14), 0 1px 3px 0 rgba(0,0,0,.12);
transition: box-shadow 280ms cubic-bezier(.4,0,.2,1);
display: block;
position: relative;
padding: 16px;
border-radius: 4px;
/* margin: 20px 0px 0px 20px; */
border: 2px solid #e7e7e7;
border-radius: 4px;
}
.highlight-step {
background-color: #2515424a;
margin: 0px -15px 0px -15px;
padding: 15px;
}
</style>
创建模板
要创建上述模板,请完成以下操作步骤:
- 在模板之上添加crowd-html-element.js脚本,以便可以使用Crowd HTML Elements:
<script src="https://assets.crowd.aws/crowd-html-elements.js"></script>
- 直接在根元素<ng-home>中使用Liquid模板语言,将需要注释的文本及来自预处理Lambda函数的相关元数据注入至用户界面:
<ng-home source='{{ task.input.source }}' translation='{{ task.input.translated }}' id="home">loading</ng-home>
- 使用<crowd-form />元素,由其将注解提交至Ground Truth。由于提交发生在后台,因此该元素处于隐藏状态。具体请参见以下代码:
<crowd-form style="display: none;">
<input name="annotations" id="annotations" type="hidden">
<input name="timeElapsed" id="timeElapsed" type="hidden">
<!-- Prevent crowd-form from creating its own button -->
<crowd-button form-action="submit" style="display: none;"></crowd-button>
</crowd-form>
不要使用Crowd HTML Elements提交注释;相反,请使用一个脚本将Angular Element与<crowd-form />集成起来:
document.addEventListener("DOMContentLoaded", function(event) {
var enterDate = new Date();
function secondsSinceEnter()
{
return (new Date() - enterDate) / 1000;
}
const component = document.querySelector('ng-home').addEventListener('rowselected', (event) =>
document.getElementById('annotations').value = event.detail.CODE;
document.getElementById('timeElapsed').value = secondsSinceEnter();
document.querySelector('crowd-form').submit();
});
});
在本用例中,我们还要设计一个计时器,用于监控工作人员完成注解所耗费的时间。
下图所示,为各元素之间的数据流:
总结
本文展示了如何使用Angular与Ground Truth构建自定义的数据标注UI界面。该解决方案能够在标记作业创建过程中,处理各自定义模板中不同范围之间的通信活动。充分使用Angular等自定义前端框架的功能,帮助大家轻松创建现代Web应用程序,从而在公共、内部或者来自供应商的标记工作人员的配合下切实满足您的数据标注需求。
关于在Ground Truth中使用层级分类法的更多详细信息,请参阅使用Amazon SageMaker Ground Truth创建层级标记分类。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。