|
本周早些时候,我们发布了 Android 9 Pie,这是 Android 的最新版本,它使用机器学习让您的手机更易于使用。Android 9 中的一项功能是Smart Linkify,这是一种新 API,当在文本中检测到某些类型的实体时,它会添加可点击的链接。例如,当您在消息应用中收到朋友的地址并想在地图上查找时,此功能非常有用。使用 Smart Linkify 注释的文本,一切都变得容易得多!
Smart Linkify 是现有 Android Linkify API 的新版本。它由一个小型前馈神经网络(每种语言 500kB)提供支持,具有低延迟(在 Google Pixel 手机上不到 20 毫秒)和小型推理代码(250kB),并且使用与智能文本选择(作为 Android Oreo 的一部分发布)基本相同的机器学习技术,现在也可以创建链接。Smart
Linkify 可作为 Android 中的开源TextClassifier API使用(作为 generateLinks 方法)。这些模型使用TensorFlow进行训练,并导出到由TensorFlow Lite和FlatBuffers支持的自定义推理库。这些模型的 C++ 推理库可作为 Android 开源框架的一部分在此处使用,并在每个文本选择和 Smart Linkify API 调用上运行。
查找实体
在文本中查找电话号码和邮政地址是一个难题。人们不仅在书写方式上存在许多差异,而且对于所表示的实体类型也常常存在歧义(例如,“确认号码:857-555-3556 ”虽然形式与电话号码相似,但并不是电话号码)。为了解决这个问题,我们设计了一种以两个小型前馈神经网络为核心的推理算法。这种算法足够通用,可以执行除地址和电话号码之外的所有类型的实体分块。
总体而言,系统架构如下:首先将给定的输入文本拆分为单词(基于空格分隔),然后生成所有可能的单词子序列,这些子序列的最大长度一定(在我们的例子中为 15 个单词),并且对于每个候选词,评分神经网络根据其是否表示有效实体分配一个值(介于 0 和 1 之间):
对于给定的文本字符串,第一个网络为非实体分配低分,为正确选择整个电话号码的候选者分配高分。
接下来,删除重叠的生成实体,优先选择得分较高的实体,而不是得分较低的冲突实体。现在,我们有了一组实体,但仍然不知道它们的类型。因此,现在使用第二个神经网络对实体的类型进行分类,可以是电话号码、地址,在某些情况下也可以是非实体。
在我们的示例中,唯一不冲突的实体是“明天拨打857 555 3556 。 ”(“ 857 555 3556 ”被归类为电话号码)和“明天拨打 857 555 3556。”(“明天拨打 857 555 3556 ”被归类为非实体)。
现在我们有了仅有的非冲突实体“并明天拨打857 555 3556 。 ”(其中“ 857 555 3556 ”被归类为电话号码)和“并明天拨打 857 555 3556。”(其中“并”被归类为非实体),我们能够轻松地在屏幕上显示的文本中为它们加下划线,并在单击时运行正确的应用程序。
文本特征
到目前为止,我们已经对 Smart Linkify 定位和分类文本字符串中的实体的方式进行了一般性描述。在这里,我们将更详细地介绍如何处理文本并将其输入到网络。
给定输入文本中的实体候选,网络的任务是确定该实体是否有效,然后对其进行分类。为此,网络需要知道实体周围的上下文(除了实体本身的文本字符串之外)。在机器学习中,这是通过将这些部分表示为单独的特征来实现的。实际上,输入文本被分成几个部分,分别输入到网络:
特征提取以单词为操作对象,我们使用字符 n-gram 和大写特征将各个单词表示为适合作为神经网络输入的真实向量:
字符 N-gram。我们使用散列字符图嵌入,而不是使用标准词嵌入技术来表示单词,因为标准词嵌入技术会为模型中的每个单词保留一个单独的向量,因此对于存储空间大的移动设备来说不可行。此技术将单词表示为一定长度的所有字符子序列的集合。我们使用的长度为 1 到 5。这些字符串经过额外散列并映射到固定数量的存储桶(有关该技术的更多详细信息,请参阅此处)。因此,最终模型仅存储每个哈希存储桶的向量,而不是每个单词/字符子序列,并且可以保持较小。我们使用的散列字符图嵌入矩阵有 20,000 个存储桶和 12 个维度。
二进制特征,表示单词是否以大写字母开头。这对于网络来说很重要,因为邮政地址中的大写字母非常明显,有助于网络进行区分。
训练数据集
对于这项任务,我们没有明显的数据集可以轻易地训练网络,因此我们想出了一个训练算法,该算法从现实片段中生成合成示例。具体来说,我们从 Web 上收集了地址、电话号码和命名实体(如产品、地点和企业名称)以及其他随机单词的列表(使用Schema.org注释),并使用它们来合成神经网络的训练数据。我们按原样获取实体,并围绕它们生成随机文本上下文(来自 Web 上的随机单词列表)。此外,我们将“确认号码: ”或“ ID: ”等短语添加到电话号码的负面训练数据中,以教会网络在这些上下文中抑制电话号码匹配。
使其发挥作用
我们必须使用许多其他技术来训练网络并进行实际的移动部署:
将嵌入矩阵量化为 8 位。我们发现,通过将嵌入矩阵值量化为 8 位整数,我们可以将模型大小缩小近 4 倍,而不会影响性能。
在选择网络和分类网络之间共享嵌入矩阵。这几乎不会带来任何损失,并且使模型体积缩小 2 倍。
改变实体之前/之后上下文的大小。在移动设备屏幕上,文本通常很短,上下文不足,因此网络在训练期间也需要了解这一点。
为分类网络从正例中创建人工反例。例如,对于正例:“今天给我打电话857 555-3556 ”,标签为“电话”,我们生成“今天给我打电话857 555-3556 ”作为反例,标签为“其他”。这教会分类网络更精确地了解实体跨度。如果不这样做,网络将只是一个检测器,无论跨度如何,它都会检测输入中是否有电话号码。
国际化很重要
我们使用的自动数据提取使训练特定于语言的模型变得更加容易。但是,让它们适用于所有语言是一项挑战,需要专家仔细检查语言细微差别,并拥有可接受的训练数据量。我们发现,为所有拉丁字母语言(例如捷克语、波兰语、德语、英语)建立一个模型效果很好,而为中文、日语、韩语、泰语、阿拉伯语和俄语分别建立单独的模型。虽然 Smark Linkify 目前支持 16 种语言,但我们正在试验支持更多语言的模型,这尤其具有挑战性,因为移动模型大小有限制,而且对于不使用空格拆分单词的语言来说,这很棘手。
后续步骤
虽然本文中描述的技术能够快速准确地注释文本中的电话号码和邮政地址,但航班号、日期和时间或 IBAN 的识别目前是使用标准正则表达式这种更传统的技术实现的。然而,我们也在研究创建日期和时间的 ML 模型,特别是用于识别消息传递环境中普遍存在的非正式相对日期/时间规范,例如“下周四”或“三周后”。
小模型和二进制大小以及低延迟对于移动部署非常重要。我们开发的模型和代码作为 Android 框架的一部分开源。我们相信该架构可以扩展到其他设备上的文本注释问题,我们期待看到来自开发者社区的新用例!
|
|