

前言
“当你在凝视深渊的时候,深渊也在凝视着你。”当你在看 Hulu 的时候,Hulu 以及它背后的那些算法工程师们又在想些什么?不妨,就通过我加入 Hulu 以来的经历,一窥自然语言处理研发工程师在 Hulu 做的一点微小的工作。
本文共讲三件事,看似没什么内在联系,却是一个 NLP 研发工程师的切身体会和感悟。


“以史为鉴,可以知兴替”
从 NLP 简史出发,叩开 NLP 应用的大门。
时间、人类、未来,都有人写其简史,NLP 作为当下 AI 研究的热点之一,似乎鲜有人总结它的兴衰胜败。但毋庸置疑,NLP (Natural Language Processing, 自然语言处理) 涉及领域众多——语音识别、分词、词性标注、句法分析、文本分类、信息检索、自动摘要、QA、机器翻译、对话机器人、阅读理解,几乎所有跟自然语言沾边的话题都可以划分到 NLP 领域里。

在 2018 年 10 月底,Google 推出的论文 BERT 可谓一鸣惊人,在 NLP 界引起了轰动。BERT 之前,哪些工作和模型可以进入 NLP 名人堂尚未有定论,但从文章引用数和影响力的角度不难看出一些端倪,将以下三个工作列为近 20 年 NLP 的发展具有里程碑应该并不为过。
2003 年 Bengio 的 NNLM;
2013 年 Mikolov 的 Word2vec;
2017 年 Vaswani 的 Transformer;
在这三个模型之前,研究者针对 NLP 的不同任务,通常采用各不相同的模型架构去处理。比如命名实体识别任务用 HMM 隐马尔科夫模型或者 CRF 条件随机场;再比如文本分类任务应用词袋模型、主题模型提取特征,再用 LR 逻辑回归或者 SVM 支持向量机做分类。而这三个模型,都可谓时代的开创者,被记录在 NLP 的史册中。

1. NNLM (Yoshua Bengio, 2003):
上图可谓是上古时代的一张结构图,以现在的眼光来看,它其实就是一个非常简单的三层神经网络模型。沿袭语言模型(Language Model)的目标,即用前 n-1 个词来预测当前的词是什么,NNLM 只是把这个预测模型换成了神经网络。但在当时,由于这个模型最后一层是个结点到个结点的全连接层(为词向量维度,为词表大小),模型参数过多,而且当时计算力也并不算强,训练一个 NNLM 模型可能需要几个月的时间。而且,针对不同任务需要训练不同的 NNLM 模型,资源消耗极大。但无论如何,这篇论文都具有划时代的意义,因为它统一了 NLP 的特征形式——即 Embedding。在此之后,我们做各种 NLP 任务时,一般都用词向量(word embedding)的形式来表达一个词。

2. Word2vec (Mikolov, 2013):
从模型的角度看,Word2vec 比 NNLM 更简单,因为它其实就是一个线性模型。但正靠着模型的大幅度简化,以及 2013 年深度学习和其硬件的飞速发展,Word2vec 可以依赖大规模语料进行快速训练。从革新的角度,它不仅延续了 NNLM 的特征形式,而且不再需要针对特定任务从头训练模型,而是在一个大规模语料上先进行预训练,再利用类似迁移学习的思想,把预训练好的 embedding 应用到其他下游任务中。
回看当年的历史,计算机视觉之所以能蓬勃发展,很大程度上靠着 ImageNet 这样一个大规模、有标注的数据集。在自然语言处理领域,却并没有一个如此大规模的标注数据集。怎么办呢?从另一个角度出发,人们发现语言这个东西,在说出来或者写出来的时候就已经成为很有价值的数据了。Word2vec 正是利用了人类语言学高度抽象、高度概括的特点,在一个大规模语料中训练语言模型,再将语言模型里学到的信息(embedding)应用到下游不同的 NLP 任务中去。

3. Transformer (Vaswani, 2017):
Word2vec 在 NLP 届问世以后,大家通常采用 Word2vec 作为 embedding 的初始值,再利用 RNN、CNN、attention 等深度学习模型去训练下游任务。此时,文本分类的主流模型已经变成了 LSTM, charCNN 等,命名实体识别领域也大多被 LSTM+CRF 的框架所占据。人们不禁开始思考:统一了 embedding 这种数据特征形式和 pre-train 这种特征预训练方式,我们能不能用统一的模型来处理不同的 NLP 任务?2017 年 Transformer 应运而生,像无所不能的变形金刚一样,Transformer 放弃了 RNN、CNN 的结构,完全只用注意力(Attention)机制构建模型,处理多种 NLP 任务。

鉴于 Transformer 的模型结构较前两者复杂许多,而且又是最近一年 NLP 届的耀眼新星,我们不妨细看一番,以探其究竟。从结构上,Transformer 可以拆分为三个部分:1)Multi-Head Attention;2)Feed-Forward Network;3)Position encoding。
A. 多头注意力 Multi-Head Attention
如右上图所示,Multi-Head Attention 是由 Scaled Dot-Product Attention 单元堆叠而成的。Attention 机制想必已是耳熟能详,简单来说 Attention 就是 seq2seq 模型中 Decoder 在进行解码时,学习 Encoder 输入中各词的权重分配。Dot-product Attention 是 Attention 的一种形式,它把注意力表达成 Q(query), K(key), V(value)三元组。其中 Q 是待生成的序列,V 是输入的序列,K 为权重。例如机器翻译任务中从源语言翻译成目标语言,V 表示源语言序列,而 Q 就是待生成的目标语言序列;每产生 Q 中的一个翻译词时都需要计算与输入 V 中哪个词最有关系,这便是注意力权重 K;Attention 层之上,再经过一个 softmax 预测真实的翻译词。Scaled 则是指在 softmax 计算之前,进行尺度缩放,除以跟 Q 和 K 维度有关的一个量,用以防止点积时数值过大。如果其中 Q=K=V,我们一般又称其为 self-attention。
把很多 Scaled Dot-Product Attention 单元堆叠,如同卷积一样形成通道形式,然后将结果级联到一起,再经过一个线性映射,这便是 Multi-Head Attention 的过程。
B. Feed-Forward Network
通过 Multi-Head Attention 层后,再经过一个前向神经网络 Feed-Forward Network,用以增加网络的非线性。并且这个 FFN 添加了像 ResNet 一样的 shortcut 连接结构。
C. Position Encoding
因为在 attention 机制中每个词都会关注前后所有的词,导致所有词在位置信息上其实是等价的,所以 Transformer 中引入 Position Encoding 表达每个词在原始句子中的位置信息,来弥补这一缺陷。Position Encoding 既可以用一个固定的函数表达,也可以用一个可学习的函数表达。实验发现两者效果差不多,干脆就采取固定的,sin 族函数来表示。由于 sin 函数的特性,一定程度上还可以有效地表达句子中词的位置的周期性。

从整体上看,Transformer 结构的左边是 Encoder 部分,右边为 Decoder 部分。Encoder 堆叠了 6 个 Multi-Head Attention + Feed-Forward Network + shortcut 的结构。Decoder 同样堆叠 6 层这样的结构,然后与 Encoder 的 self-attention 结果共同送入 Multi-Head Attention,预测最终的输出。
那么,Transformer 结构为何能饱受青睐呢?首先,使用 Attention 机制后,每层的复杂度比 RNN 要小。再者,RNN 是一个递归的模型,t 时刻的计算需要依赖 t 时刻前的状态,很难进行并行计算。而 Attention 结构可以很容易地支持并行,因此可以用到更多的数据。另外,Attention 机制解决了一个 RNN 里一直以来很难处理的长距离依赖问题。RNN 中诸如 LSTM 模型,虽然添加了遗忘门等机制,但是依然不能很好的解决长距离依赖。Transformer 由于会关注输入的每一个位置,因此可以很好的解决这一问题。Transformer 也于是在之后几乎所有 NLP 相关的任务都展露了锋芒。


4. Bert:
至此,我们既统一模型架构,也统一特征形式,下一个问题也自然而然——能不能在大规模数据集上训练一个 Transformer,然后再用到其他各式各样的下游任务中?其实,包括 AllenAI 的 ELMo,OpenAI 的 GPT,Google 的 Bert 等,都在做这样的尝试。其中 Bert 从 2018 年 10 月提出便一骑绝尘,引起 NLP 届广泛关注,凭借的是其惊人的效果。用论文中原话来说,Bert 是一个理论上非常简单,但是非常有效的模型,它在 11 个自然语言处理的任务场景中取得了当前最好结果,并且把 GLUE benchmark 提高了 7.6%,在 SQuAD 数据集上已经超过人类表现。

上图是 GLUE(General Language Understanding Evaluation)的榜单,GLUE 将一些 NLP 任务集中在一起,可以评价一个模型在不同任务上的通用性。这个表是 2018 年 11 月份的统计,可以看出 Bert 当时技压群雄,比每个数据集之前最好的结果还要好。

简单来说,Bert 采用了 Transformer 中 encoder 的双向结构。在输入端除了有 token embedding,position embedding 之外,还加上了 segment embedding。这主要是为了处理双句任务,比如判断两个句子之间的关系,以及 Question Answering 等,通过 segment embedding 来区分前后句子。

Bert 的预训练包含以下两种操作,一是把句子里的一些词随机掩盖,然后让模型去预测这些词。另一个是用前一个句子来预测下一个句子。 通过优化这两个目标,Bert 就可以在大规模的语料中进行训练了。

继承 Transformer 的优点,Bert 自然也可以应用到多种不同的 NLP 任务中。文章提出了上图的四种架构,对应 Bert 四种不同的应用场景,既可以做分类任务又可以做标注任务、既能处理单个句子也能胜任双句任务,因此 NLP 很多问题都可以用以上模型来套用。

5. NLP 展望
在此也不妨分享一下我在 10 月底参加 EMNLP 会议时对 NLP 发展方向的一点思考。
A. 在学术上大家还是一直在追求纯粹的、优雅的、通用的模型。
B. 从现象上来看,会议中已经很少能见到非深度学习的论文,深度学习现在基本占领 CV、NLP 领域。
C. NLP 在社会应用和工业届应用受到大家更多的关注。会议上有多个 session 讨论这个问题,而且参与人数众多,可以发现人们越来越关注自己的研究领域在生活中或者在产品中的应用。 这也引出我们下一部分要讨论的问题:学术研究和产品开发有什么区别和联系?这对很多刚毕业不久或还没毕业的同学来说,更容易引发共鸣和思考。

“当学术研究遇到产品开发”
从一个算法研究工程师的角度,讲述从学校到公司的心路历程。
以下将从 5 个方面介绍学术研究和产品开发之间的对比和利弊权衡:1. 问题的定义; 2.数据的处理;3. 模型的选择;4. 评价指标;5. 开发流程标准化。
1. 问题的定义:
在学校时我们往往知道问题的输入是什么,只需要用一个合适的模型不断优化,来找到一个更好的解,提升模型的效果。但在公司场景中,更多时候你可能需要先定义问题是什么。

A. top-down 和 bottom-up:从问题产生背景上讲,问题主要分为两种方式定义:top-down 和 bottom-up。理想情况下 bottom-up 的问题一般是:你有一个创新点,然后去做一些实验进行验证,之后设计成一个小 demo 形式给产品经理查看,产品经理认为效果不错,再去做一些 UX 上的优化,最终成为一个产品特征。而 top-down 通常是:产品经理有一个需求,然后去找公司里哪个团队有这样的能力去做,他发现你有能力完成这个需求,找到你后针对这个项目去做 POC (proof of concept),在此基础上针对真实用户进行 A/B 测试,如果效果不错,最终就可以转化为产品特征。

B. Vagueness:但很多时候产品经理提出的需求是并不一定十分清晰,而是相对模糊,所以作为算法工程师,对问题,对通过技术能解决、善于解决什么问题要有自己的判断和见解,以此给出问题正确的定义。

C. Division:对问题要有划分,并且有策略。定义问题时需要分清哪些是重点,哪些是眼前亟待解决的问题,哪些是需要长远去看的问题。

D. Goal:先定一个小目标。在公司做产品,如果目标不同,对于问题的定义也不同。比如要分清是做一个 PoC 还是一个简单调研,甚至目标是做一个产品特征,这些都决定了定义问题时侧重点不一样。比如需要做一个 demo,在模型的选择和实验上,就不必过分关注细节,更重要的是强调一个新的概念,新的设计或者功能。

E. Cost Control:注意产品的成本控制,包括对时间、金钱、人力成本等的控制。在定义一个问题时也要考虑是不是对公司或者对问题解决的领域有长远影响?比如做一个机器学习任务,可能很多时候缺少标注数据。那我们在定义问题的时候就要计划清楚数据应该从哪来?是外包,还是自己上阵,亦或找一些实习生去做,都是成本控制所要考虑的问题。

2. 数据的处理:
A. 有哪些数据可以用?
Hulu 有自己的视频,也包括携带的音频、字幕等,同时还有内容提供商给的一些演员、导演、类型、描述、标签等辅助信息。当然,我们还站在巨人的肩膀上,因为有很多其他组的同事、前人留下的各种各样的模型和数据供我们使用。
B. 应该使用那些数据?
数据显然不是越多越好,因为不同的数据有不同的处理难度。
C. 怎么用?
无论中英文,真实的数据中往往是比较脏的数据,显然从这些数据中训练好的模型是不可能的。在公司场景下,数据预处理是一个非常重要的环节,在 NLP 中包括对关联符号,标点,数字,人名等的处理,经过预处理的数据才能进入下一步,被模型所使用。

3. 模型的选择:
A. 无论做什么任务,都需要有前期调研工作,吸取前人之经验,看看在这个问题上成熟的、主流的方法有哪些。
B. 如果不知道哪个模型适合产品目标,可以先选一个最通用的模型。比如 seq2seq 问题就用我们刚才讲过的 Transformer 结构,序列标注任务用 LSTM+CRF,分类任务选用 TextCNN、fastText 等模型。当然了,现在你都可以使用 Bert。
C. 选择比较高效的模型。在公司往往要选更高效率的模型,先做出一个基准结果,评价此方法是否可行。比如公司产品开发周期为 2-3 个月,倘若你花很长时间调试出的模型最后效果一般无法使用,很容易就会陷入进退两难的尴尬境地。
D. 模型微调(fine-tuning)。对于模型 fine-tuning 分为两个部分,1) 对模型结构上的 fine-tuning,比如说保留一个大模型的前面若干层,对最后的 1-2 层进行 fine-tuning。2) 在模型的基础上加入一些人工规则。诚然,我们都在追求通用的模型架构,并且这也是 AI 前进的一个方向,但是现阶段的很多场景中如果不引入人工干预,单靠机器学习或者深度学习其实很难支撑产品级别的应用,所以 fine-tuning 有时需要一些针对用户、针对数据、针对结果的规则过滤。

4. 评价指标
A. 在学届,我们可能更多关注 Accuracy、Recall、ROC 等指标。但在公司,我们要更关注和用户行为相关的评价方式,比如展示位点击转化率 CTR、用户的总观看时间等指标。
B. 采用多个版本的控制,将用户的反馈传递到模型中。比如要做在线 A/B 测试,但其反馈到模型的周期往往很长,这时就需要用多个版本来控制线上运行和线下实验的模型。
C. 警惕 metrics trap。在学术界常用的评价指标在实际产品中往往并不适用。比如在机器翻译中多使用 BLEU 作为评价指标,但是此评价指标会忽略语法上的准确性。比如我们把翻译结果里的词序进行颠倒,可能 BLEU 评价很高,但实际却表达出截然不同的语义,这将对真实的用户体验造成极大的影响。

5. 流程标准化:
在产品开发中,流程的标准化对项目管理、开发效率、后期维护等都有着深远影响,我们将在下一部分中详细介绍。

6. 总结
总结学术研究和产品开发的区别如下:
A.从问题定义上讲:在学术研究时是明确的、没有歧义;在产品开发时是模糊的、开放的问题。
B.从数据角度上讲:学术研究时数据是干净的、规范的;在产品开发时可能会遇到脏数据。
C.从模型角度上讲:学术研究追求优雅的、创新的模型;在真实的用户场景中可能需要制定相关的人工规则。
D.从评价指标上讲:学术研究采用比较固定的评价指标;在公司场景中,则会采用一些产品导向的评价指标。
E.从工程的角度上讲:学术研究可能写一次代码,调整参数得到理想的结果就满意了;在公司,要不断进行产品迭代,观察具体数据和结果,对产品进行细致维护。
接下来,不妨从两个我最近在做的项目出发,一探在 Hulu 做 NLP 开发的真实情景:
1. News Personalization:


A. 问题定义:
News personalization 项目的任务是给用户推荐个性化的新闻。这是一个源自产品经理的 top-down 的需求。它分为两个场景:一个是在用户登录时推荐,一个是用户看完新闻后推荐下一个相关的新闻。这个问题的定义比较明确,就是推荐算法。在 Hulu 有很多成熟的推荐算法,比如协同滤波推荐、基于 DNN 的推荐等。但是 Hulu 新闻的场景属于短视频推荐,其特点是有很多的视频数量,但是有较少的观看数量,这就决定了不太适合用基于协同滤波的推荐算法。并且新闻具有时效性,我们不能给用户推荐几年前的事情,而是需要推荐近期、甚至当天的新闻。再者,一些用户虽然在当天或者近段时间内观看比较少,但用户历史上偏好某一类新闻,这也是我们可以利用的特征。于是最后,我们将任务定义为:给新闻做分组,然后让用户去观看他喜欢的分组中最新的新闻。

B. 数据与模型:
在此 NLP 任务中可用的 feature 包括有视频标题、关键词,简短描述、字幕(由语音转文本的模型生成)等。NLP 中有很多的方法来处理这个问题,比如文本分类、聚类、主题模型等。其中 Dynamic Topic Mapping 就是假设我们已经有一些新闻主题,再将提取出的视频主题对应到到新闻 topic 上。
对于文本分类任务存在的问题是其类别是固定的,而现实中新闻的类别会随着时间的推移而变化。聚类也会存在这一问题,一些动态的聚类方法又非常复杂。于是我们设计了了 Dynamic Topic Mapping 方式。这主要因为我们有第三方提供的近期发生的新闻事件,一方面可以对我们对新闻提出的动态主题进行验证和监督,另一方面也可以把它们作为 trending topic 的信息。最后,只需要将新闻提取的新闻关键词与 trending topic 进行匹配即可。


C. 整体架构:
上图为系统的整体架构:首先对 data 去做一些数据预处理,比如:去停用词、命名实体,句法分析等。再去做词频分析,有监督分类出关键词或者无监督地提取关键词。然后将这些关键词和 trending topics 的关键词进行 mapping,最后计算相似打分。
从目标出发,这个项目是一个 PoC,我们更多的注意力是先把这个项目实现。当然之后有很多事情需要进一步迭代,比如:classification 应用更复杂,更准确的模型,topic mapping 里引入层次结构,优化相似性评价指标等。一旦有一定的用户实验反馈,就可以很轻松地进行下一步持续的优化。

2. Content Embedding:
A. 问题定义:
利用每部视频的事实和描述性的标签,对视频进行 embedding 向量化表示。这是介于 top-down 和 bottom-up 之间的需求。从 top-down 角度讲:推荐系统经常会面临冷启动的问题,在用户还没有很多点击的时候,经常会推荐不出去。这时我们会将库中内容和用户看过的内容做相似度匹配,然后推荐给用户。从 bottom-up 角度讲:很多场景如电影、电视剧推荐,很难显式计算两个视频之间的相似度。这时丰富的标签信息可以帮助我们对 show 进行 embedding 便于相似度计算。Content Embedding 的优势有一下几个方面:1) 它是对视频标签、元数据 metadata 的一个高度抽象表示;2) 它适合用于 DNN 等各种机器学习、深度学习算法中;3)作为向量表示,它很容易集成到现有系统中;4) 可以通过直接计算两个实体在向量空间中的距离来计算它们的相似度。



B. 数据与模型:
电影、电视剧推荐场景中可以使用的 NLP 特征主要:影片发布时间,评级,演员和工作人员,影片描述等;从第三方获得的外部信息,如关键字,标签,奖项,票房收入等。这些 NLP 特征又可以分为文本类型和标签类型。文本类型可以通过一些 seq2seq 模型提取高层语义特征,得到 featrue representation。
对于标签类型,如果考虑实体之间的关系,可以把它看成知识图谱问题。但如果淡化实体之间关系,只考虑每个 content 和它共现的信息,就可以当做为 network embedding 的过程。在我们的场景中,要去计算两个 content 之间的距离,显然可以剥离掉它们之间的实体关系,于是可以采用一些网络学习的方法。最后我们选择了基于 node2vec 的解决方案,从理论上这是一个比较简单的模型,它的思路和 Word2vec 完全一致,只是需要先对图中的边进行路径采样,再将每个路径当做 Word2vec 中的一个句子,每个节点当做 Word2vec 中的一个单词,之后在这些采样路径上去学习 embedding。这其中根据元数据和标签的特性又做了很多结构和优化目标上的细节调整,这里就不一一展开叙述了。

C. 评价指标:
Content Embedding 的评价有很多种方法:1) 每一部 show 在观看的时候有一个相关内容列表,可以用这一列表中内容的点击率作为评价标准;2) 通过人工编辑团队判断内容之间的相关性;3) 基于 Content Embedding,利用用户的行为对线上的其他服务进行 fine-tuning,以获得更好的线上指标;4) 用 Content Embedding 为特征,进行内容点击率预估等。

D. 整体架构:
上图为 content embedding 集成到推荐系统的一个架构图。对于 user,可以利用用户标签、用户上下文信息等特征得到 user vector 。对于 show,可以利用前文介绍的方式获得 show embedding。将两者作为输入,通过一个深度神经网络来建模它们的交互信息,以此为用户进行更精准的推荐。


“你不是一个人在战斗”
平台、架构对于 Hulu Research 研发效率的长远影响
关于开发效率可以分为两类,一类是团队的效率,另一类是个人开发效率。

1. 团队效率:
Hulu 有五个研究团队,团队间更多时候是相对独立的,各自都在做各自的项目。但事实上,团队之间有很多数据、特征、模型其实是可以复用的。在此基础上,为了避免大家做重复性的工作,我们构建了 AI Platform 架构,可以为开发团队减轻重复造轮子的压力,也让研究团队能将更多精力关注于模型优化上。

AI Platform 分为三层,第一层为基础架构层,第二层为机器学习数据层,第三层为 AI 服务层。基础架构包括对原始数据的存储、分布式的计算资源 GPU 的调度,分配不同节点进行机器学习、深度学习的任务等。ML 数据层存放加工之后的机器学习原材料,比如 Content Embedding 就会存放在这里,以便日后各个 team 的使用和模型的迭代优化、版本控制。第三层服务层的构建是为了让模型更好地服务于线上产品,使团队能更好的管理、发布和监控模型线上的运行情况。

在 Hulu 的整个机器学习任务周期中,一般流程为:建立数据流 pipeline,自动化将数据取出放入特征仓库,然后训练模型、进行评估,将稳定的模型版本存放在在模型仓库中,之后部署到线上通过 AI 服务层进行预测和监控等。

2.个人开发效率:
在公司中个人的工程实践能力也非常重要。个人工程化能力的提升是一个日积月累的过程:
A. 代码效率:在开发过程中我们需要考虑编写的代码是否高效,比如在 python 中选择哪个库?用哪种形式、哪种写法的函数会使程序效率更高。
B. 算法优化:从算法角度提高代码效率,类似 Word2vec 相对 NNLM 采用的 Hierarchical Softmax 等方式对算法进行优化,极大提高了训练效率。
C. 并行化:在公司进行项目开发,要灵活地运用大数据基础架构等底层服务对代码进行并行化,比如数据读写、训练模型时都需要考虑能否以及如何进行并行化,这样可以大幅度缩短项目的开发和迭代周期。

最后提一下《百面机器学习》,从这本书里你会看到机器学习领域有着许多值得玩味、值得思考的方面,这也是“百面”真正的寓意,供大家参考。
作者介绍:

李凡丁,毕业于北京大学信息科学技术学院。2016 年 6 月加入 Hulu 内容理解团队,从事 CV 和 NLP 相关的研究和软件开发工作。
本文来自李凡丁在 DataFun 社区的演讲,由 DataFun 编辑整理。
评论