NLP 实战 | 团队开发,一些本质的问题
Posted 幻灰龙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NLP 实战 | 团队开发,一些本质的问题相关的知识,希望对你有一定的参考价值。
目标和实践
经过连续的高质量迭代和团队协作,我们逐渐清晰了方向和目标:把海量内容用人工智能的手段内容分类, 质量分级。 促使各种内容 覆盖 IT 行业的各个领域。 充分挖掘 IT 领域知识点之间,内容,用户,社区的关系。利用这些关系清除低质量内容,鼓励高质量内容的生成,并把高质量内容在适当的时间呈现给用户,帮助用户学习,成长,成功。
在这个方向上,我们持续迭代,提供智能数据和服务,支持了两款创新应用,希望能解决技术人在一条线和一个面上学习领域知识的痛点问题:
- 每日一练:dailycode.csdn.net
- 领域技能树社区:python.csdn.net
学习是一件需要付出努力的事情,我们珍惜你的碎片时间,希望构建高质量的成体系的学习服务,让你的碎片时间获得成长而不只是消磨时间。
如何保证质量
对于数据,有一个名言是永远正确的:“垃圾数据进,垃圾数据出”,无论是什么算法,什么模型,什么服务,入口处的数据质量永远是重要的。这也是常说的:“数据清理第一步”。我们做文本数据处理,做“代码数据”处理,核心原则之一就是入口处的数据要宁缺毋滥。
对于文本数据的质量。实现一套涉及标题+内容的文本质量计算算法,从实用的角度衡量文本数据的内在质量是非常重要的。很多做过用户画像的都知道要利用用户的交互数据:点赞、评论、阅读量等等来做某种公式计算,获得交互数据的评分。而,我们对内容做质量计算的时候,则暂时不考虑这些数据,我们认为文本内在的结构、信息的密度、代码的密度、文/图的质量是不会造假的,因此应该尽量找到能衡量这些内在信息含量的算法和规则。
对于代码数据的质量。好的代码是需要经过设计的,反碎片化的代码。优秀的程序员,写代码的时候会重视结构化、模块化。因此,代码数据作为技能树的一个数据入口,代码数据则是经过仔细设计的。我们希望用户学习的过程中,第一时间看到的是结构良好的,充分考虑了工程实现的代码,以区别于碎片式的,只考虑“知识碎片”的代码。
如何匹配
匹配在多个层次的多个维度上做连结。
例如标签和标签之间,有远近之分,有强关联和弱关联之分。因此标签之间需要建立起包含/被包含/有关等不同关系,从而作为标签推理的基础。
例如内容和内容之间,有原创、重复和抄袭。需要做全文匹配,拆句子是一种朴素但是应该能解决问题的方式。很多真正解决问题的方式,背后的核心原理未必多复杂:不是越复杂越好,而是真正命中了目标问题本质的越好。
例如标题和文本之间的匹配,标题需要去跟文本的全文做匹配量太大,也没必要。标题只跟标签做匹配,相关性会没那么紧密。标题应该跟标题+摘要做匹配。
如果是一个序列如何匹配?例如一个层次结构的树:
- 节点A
- 子节点B
- 子节点C
- 子节点B
当要匹配数据到子节点C的时候,只用「子节点C」的文本是不够的,因为「子节点C」本身可能太通用,会导致「泛化」匹配的效果。而当「子节点C」的特征足够明显时,则可以获得比较好的匹配效果。怎么解决这个问题呢?数学里很常用一个思路是「滑动窗口」,让「子节点B+子节点C」组合起来给「子节点C」匹配数据,而当给「子节点B」匹配数据的时候,用「子节点A+子节点B」去匹配。实际上所谓的 “N-Gram” 也就是这个道理而已,所谓的卷积也就是这个道理而已。
如何给一个层次结构的序列做权重划分?例如:
- 节点A(权重1)
- 子节点B(权重2)
- 子节点C(权重4)
- 子节点B(权重2)
按照节点深度做权重划分,会导致一个问题,如果不同的层次结构深度不同,会导致深度不同的路径的权重之间绝对数值不平衡的问题。通过压缩变化率可以解决,例如加一个log函数,经过log(W)之后,深度绝对数值换算后的权重变化差异没那么大。实际上对于很多大的数字,我们都可以通过这种方式解决。这实际上就是把「两个带不同单位的数字换算到同一个单位」下的做法,例如1厘米和1000毫米,只看1和1000,比较是没意义的,但是换到同一个单位后,他们是相等的。
文本和文本之间,都一样的权重吗?明显不是,越是普通的、大众的文本、提供的信息含量越少。代码也是一样,「if」关键字在所有的语言里都有,「if」语句对于区分代码就没做出什么贡献。而衡量文本稀有程度的一个有效的算法就是看上去朴素的「TF-IDF」算法,实际上我们在很多地方都应该合理的利用上它。语义相似是一个很高级的需求,但是大部分人的直觉是你至少要在字面内容上是匹配的。因此,要从实用的角度出发去解决问题。
如何变化
对于文本和代码,提供智能的变换,在很多场景下能让数据产生「智能」。
一开始,我们可以基于初步的规则,做「初阶的等价替换」,经过替换后的文本或者代码,既然是符合文法的,能读的文本,能执行的代码。文本的变化可以支持多种不同的视图。代码的变化可以支持对代码理解的自动化答题,同时带有一定的内在难度在其中:不经过努力就获得的,也不会留下什么。而经过一定努力获得一定积累的,则是在帮助你真正学习。
一开始,简单的基于替换的规则可以支持初步的迭代。后续,则需要高阶的变种,例如对代码来说,就会需要高阶的解析能力,例如对代码经过解析后获得一定粒度对中间抽象语法树,进而获得高级变种能力。
解决问题的顺序
从算法、模型到服务,是一个简化的过程。这个过程要经过多次迭代。
例如初期算法和模型迭代解决的问题到了后期可能并不是很重要,但是初期就是要经过这个过程。
例如模型到服务,不走数据库的方式可以在初期快速迭代,但是到中期要提供高并发服务,以及让服务能水平伸缩,就需要让服务接入数据库。服务接口就需要做性能优化和缓存支持。我们不做过多的早期优化,但是必要的优化是需要的。
例如服务要支持海量数据的接入,就需要做读写分离。至少在服务机器上需要分离。那么就需要最小化模型数据,通过数据库让「动态」部分的数据解除耦合。
例如数据要挂载到不同的地方做好「预先准备」,有些挂载的地方对于数据层来说属于外部环境。整个处理过程有很多操作步骤,就需要做好全自动化,达到只需要准备数据,更新数据,之后执行一键操作即可。
例如算法和模型都是可能需要持续更新的,因此就需要支持快速 Rebuild 的机制,支持算法和模型更新后快速通过 Rebuild 达到最小成本最快迭代的目的。
很多年以前,看过早期造飞机的例子,能快速试错的周期和机制往往是复杂工程成功的关键因素。在工程上,我们经过实验阶段后,就需要在机制和周期上能实现变化,第一次消耗 N 的时间,第二次消耗 N/2,第三次消耗 N/4 … 这样的一个规律。
ML Ops: Machine Learning Operations
ML Ops: Machine Learning Operations 的意思是,做机器学习的应用不只是算法。真正解决问题需要经过一系列的过程:
- 实验算法和模型
- 服务化(提供接口)
- 接口文档化(交付应用)
- 如果接口依赖数据灌入才能有效发挥作用,则需要:
- 解决存量数据的灌入问题
- 解决增量数据的灌入问题
- 需要理解服务运行环境的搭建
- 需要理解服务的系统构架
- 需要知道服务治理的标准流程
我们充分理解应该尽可能不重复发明轮子,但是ML和普通数据库增删查相比,确实有算法、模型、计算、数据综合密集型的部分。底层框架和技术掌握在自己手里才能更好的在合适的地方解决问题。
良好的及时更新的文档是一个重要的手段:
SMAT
我们尽可能的让开发日的迭代高质量,因此我们每日晨会控制在30分钟内容解决。每周一个sprint,每个sprint有一个相对明确的issue列表。如果一个sprint没解决的issue,会移动到下一个sprint。我们希望每个issue会被解决并且有序经历「未开始」「开始中」「已解决」状态遍历。
如果发现某个issue定义不明确,以至于连续停留在「开始中」看板列表上,我们会直接拆分它,拆分到让issue符合 SMART 原则。
经过高质量的迭代,希望每个人获得足够质量的成长,从纯NLP工程师成长起来,能至少在一个重要的方向上做出足够价值的贡献。
–end–
以上是关于NLP 实战 | 团队开发,一些本质的问题的主要内容,如果未能解决你的问题,请参考以下文章