日期:2022年03月10日   

2016年年底,参加谷歌开发者大会,我站在会场最后一排,站着听完了tensorflow的讲座,觉得这技术很酷,因为2016年alphago战胜了李在石,所以对AI技术充满憧憬,虽然当时还听不懂,还是不明觉厉。

2017年年初,从创业公司退出来,和创业伙伴分道扬镳,站在一个人生的十字路口,就想着还是要过一个技术人生,选择一个最酷的技术学习和从事,想的很单纯,就很单纯地冲进去了。记得是3月份的时候,报了小象学院邹博的机器学习课,跟着啃了下来,大概3个月,虽然学完还是啥都不会,但是至少对机器学习有了概念,也能分清楚机器学习和深度学习的关系了,也努力开始把概率、高数、线代都捡了起来。随后,陪着家人看病,哩哩啦啦,一直到了年底。期间,去买了各类盗版课,疯狂的刷,似懂非懂,但是至少对AI的边边角角都有了概念。下半年,又开始学习深度学习,对CNN、LSTM等概念有了一定理解,也动手写了一些代码,写了一些典型的例子,也能跑通,同时努力理解它的原理。逐渐地,感觉自己已经入门了,但是,还是缺乏一个像样的项目的实践。

2018年,来到了一个互金公司,这里是它的一个子部门,恰好,部门技术老大想组建一个AI方向的团队,经朋友介绍,我获得了这个机会,我是非常珍惜这个机会,推掉了其他的offer。

刚来公司,技术老大就扔过来一个任务,我明白,这个就是一个试用期考察,是一个让我给别的团队提供验证码识别,对我一个从来没做过真实项目的人来说,是个不小的挑战,于是,我开始拼命的查找资料,github上clone,找例子尝试。最终,找到了一个比较简单的例子,很实用,我在此基础上做了改进,然后用我的笔记本,真的训练了出来,正确率还非常高,可以到90%+。其实,就是一个固定长度输出的CNN,现在看来非常简单,但是在当时,对自己来说还是一个不小的挑战,毕竟keras是第一次上手使用(之前主要是看tensorflow)。最终,2周,就把这东西训练出来,并且搞上线了,我自己都惊讶自己的高效,当然,这也是夜以继日不停的学习、思考、实践的结果。期间,还学习了docker,做成了容器发布,还完成了服务器上的部署等诸多细节。

老大对我的进度、能力非常满意,顺利转正。之后,就给我一些空间,让我探索,有什么可以落地的可能性,我也自信满满,自己对NLP、聊天机器学习人,非常感兴趣,于是,就把自己的方向尝试向这个方向努力,也和老大沟通了,他表示也同意。于是,我开始着手研究,经过调研,我找到了RASA,一个开源的chatbot引擎,从这里面,我看到了一个比较大的开源项目,如何使用LSTM、命令实体识别、意图识别等诸多细节,收获颇丰,我花了很长时间,一边补习这些深度的基础知识,一边阅读它的源码,运行它,尝试它的例子;然后,把这套东西,尝试用在公司的一个对外的业务问答上,做的过程中,才发现,把公司的业务知识梳理清楚,形成一个知识库很有必要,这个时候,就接触到了知识图谱,还报名参加了王昊奋老师的课,真心听不懂,不过硬是跟下来了。但是,真的去实践的时候,发现,根本没有一个成熟的知识图谱引擎,商业化的只有不带概念层的neo4j,而带着完备概念层的jena,根本就是个toy,自己也鼓捣了一下jena,根本不适用。而且,自己看到的唯一的可以run的是一个农业百科的问答系统,后来就越来越觉得这事难度太大,是自己一个人无法搞定的大工程。最最核心的是,如何把一个问答语句,转变成一个本体的查询语句sparql,是一个非常难的事,我根本没有思路。老大可没有耐心,在3个多月没有任何进展后,就让我必须把chatbot用起来,我于是,只好到处找场景,最终,和运维监控团队一起,尝试做一个业务监控报警机器人。最终,其实并没有用到rasa,只是很简单的一个固定模板,反倒是精力花在了基于微信的聊天机器人、QQ聊天机器人等诸多跟AI无关的技术细节上,偶尔用了用聚类做做问题的自动分类聚合等。就这样,哩哩啦啦、陆陆续续的忙到了年底。老大对我这块的进展非常不满意,甚至裁掉了我招的一个同事。

转机出现在第二年春节后,其他团队的同事,找我帮着做银行流水的识别,是一个OCR需求,我非常高兴,详细和他沟通了需求,他们需要的是把客户拍摄的银行流水水单,把其中的工资项需要分裂出来,不需要客户再手工输入,或者,让客户输入后做交叉验证。所以,这个时候,就需要一个OCR引擎,可以把文字的位置和内容识别出来。他们也去寻找了其他的技术方案,找到了阿里提供这种通用文字识别方案,识别率还挺不错的,他们决定采用,但是,他们更希望,我这边提供自有的OCR识别方案,毕竟,把客户的银行流水图片,交给基于互联网的API,是有背风控原则的,这可是客户的私人资料,按理说不应该发给任何第三方的。我于是接受了这个挑战,我和他们两边同时进行,他们先用阿里的API开发,等我的OCR识别OK了,他们再切回来。

尽管我之前只有验证码和聊天机器人的实战经验,但是,我对这件事还不是那么有信心,不过后来安慰自己,既然别人能做出来,我也可以。于是,我展开了深入的学习和研究,感谢互联网,我逐渐了解到,OCR分为检测和识别,也逐渐了解到了各类检测核心算法和识别核心算法。最终,我选定了当时最为成熟的CTPN检测算法,和识别的CRNN算法。然后,认真的读了两篇论文,中文的读完了,再读英文的,基本上原理的各个细节都了解了,期间遇到各种自己不懂的问题,都一一研究全都搞清楚。最后,我还找到了github上star最多的两个项目,由于自己一直是在学习tensorflow和keras,所以,就直接过滤掉了pytorch的项目。接下来,就是,对代码一行行的啃,每行都搞清楚,搞不清楚的,就把代码拷贝出来,写个小例子,中间加入了无数的打印,图片输出,debug图像等,每个细节都力图清清楚楚。十分感谢这些开原作者的复现代码,当时的我,甚至现在的我,可能都很难复现每一个细节,而他们当时的每行代码的展示,都给我无穷的帮助。

代码搞清楚了,剩下的,就是要动手训练了,因为我有训练的经验,所以我明白样本的重要性。我先从CTPN入手,样本我不可能从头标注啊,那怎么办?恰好我的合作团队,他们正在调用阿里云的API,已经积累了大量的样本,对我来说,如获至宝,我管他们要来后,清洗,然后按照ctpn要求的样本格式进行训练,期间,修复了ctpn源码中的好几个bugs,最终,大约在一个半月左右,终于训练出来了我的检测模型。正确率和F1都可以到70%+。非常高兴和开心,自信心也大大增强。接下来,就是CRNN,CRNN的算法比CTPN要复杂,一如既往,我套路已熟,读论文、肯细节、推导也不放过,理论撸完撸代码,代码也是逐行读逐行理解,写注释,中间也遇到几个棘手的细节问题,都一一攻克了。样本,我使用了阿里切出来的大量的识别小图,但是,有一个问题,就是阿里的小图有很多错误,并且,覆盖的字符集太小(毕竟就是银行流水,涉及到的字数太少了)。怎么办?我的办法是,自己生成广泛字符集的样本,我使用6880的一级+二级字库,然后用图像生成的办法,均匀的生成所有的汉字小图,长度、大小、纹理、干扰等都完全随机。这样训练出一个60%正确率的模型,但是,仍然无法满足生产需求,我实在没办法了,只好像部门领导请求帮助,发动部门的研发兄弟,集体帮我打标,为此我还开发了一个小型的打标系统,然后使用阿里的真实小图,让同事们帮着校验正确与否,最终给我提供了宝贵的4万张,正确率非常高的样本,我再使用这些样本做增强,然后加入到我自己生成样本,一共大约900万张,终于在3-4天的训练后,正确率达到了85%+,基本上可以满足生产需求了。

这之后,我还遇到一些问题,如用户提交的图像的方向是不定的,歪的图像是无法做检测的,所以,我又自己设计了一个VGG做backbone+4方向判断的方向判断模型,并且,使用投影方差最大化,再做微调的方式,开发了一个正确率非常高的纠正方向的模型。

终于,我自己研发的OCR识别系统完成了,前后大概经历了3-4个月的时间,最终,我们把他部署到新采购的GPU服务器上,使用tensorflow serving的官方容器,来部署这些模型。对外,提供一个flask API容器,调用这个tensorflow serving的容器,完全替换了阿里的OCR服务。

经过2019年的一年,基本上,已经构建出一个新的产品方向,恰好这个时候,公司加盟了一位非常优秀的产品总监Z,Z对AI方向也非常感兴趣,也想通过AI来帮助公司开拓一些新方向,于是一拍即合。期间,我和她的产品团队,一起尝试过内部风控、风控评分卡等多种尝试,不过,在业务上都不太成功,最终,我们在OCR的进一步产品化方向上,达成一致,决心一起把OCR这个方向做突破。

到了2020年,我们开始深入OCR的各个方向,团队也由我一人,变成了4个人,虽然其他3个人也都不是算法工程师出身,但是大家对这个方向都非常感兴趣,也非常努力学习,我们利用平时时间,一起研读各个机器学习算法,深度学习算法,一起读西瓜书、读花书,每周五中午,都要一起做分享,并且还拉了一些其他team对AI感兴趣的同事一起,搞了一个机器学习方向的技术论坛,让大家都对机器学习、深度学习有了更深入的学习和理解。我也利用这个机会,对GAN、DRL、图神经网络,都进行了深入的学习和实践。

2020年赶上非典,在家隔离了一段时间,期间,正好有业务部门找上我们,要我们帮助开发一个车牌识别系统,对我们来说,车牌其实就是文字识别的一种扩展,算法无非也是对车牌的定位,以及识别。我负责识别,另外一个同事负责识别检测,他选型后,选定了psenet,在当时是最好的检测算法之一,当时的 检测技术,已经从基于fast-rcnn的ctpn,发展成为了基于语义分割技术的模型,psenet就是其中优秀的算法之一。而对车牌识别而言,我其实就是使用传统的CNN,因为车牌长度也是固定的,所以相对难度不是那么大,主要难度体现在样本上,我们没有那么多样本,好在是,我找到了CCPD,一个开源的车牌数据集,大概有30万张+,我们使用他train完后,再用业务部门提供的几千张真实场景的图片,做增强训练,最终,使得正确率达到了非常高的97%+,完全可以满足业务的需求了。这里要提一句,我们几千张车牌的打标,使用的完全是免费的百度服务:我们写了一个爬虫,去调用百度的展示网页,完成了打标;我们同时也使用阿里的展示页进行打标,以及旷视的,最终我们再做交叉验证,很高效的得到了正确率非常高的样本。

接下来,我做了更多的尝试,使用Keras2.0复现了当时一篇很有名的识别算法TextScanner,期间,和论文作者取得联系,还从他那里得到了一些非常关键的演示代码,可惜的是,训练总是报显卡OOM,我们12G的显卡根本train不动,我最后也只是把这个模型使用CPU可以跑通,就放在那里了,但是通过这个项目,我对论文复现,对keras2.0都有了非常深刻的理解。然后,我还复现了AttentionOCR,完全自己实现了一个Seq2Seq的实现,这个倒是训练出来了,但是,正确率远远低于CRNN,果然如同OCR圈里大家所说,CRNN是一个很难超越的经典。Attention有注意力偏移(Attention Drift)的问题,为此,我还去读了FocusAttention算法,但是,有个细节一直没搞明白,联系了作者,也没有收到回复,就作罢了。通过大约半年的复现工作,我对tensorflow、keras、深度学习以及论文阅读和理解等,都提升大一截子,自己感觉已经完全是一个合格的算法工程师了,也对带领团队面对未来的挑战充满信心。

2020年下半年,我们就主动出击,在产品总监Z的带领下,去拜访各个业务线负责人,和他们座谈,推销我们的产品,通过我们的努力,果然就获得了一些内部机会:帮着车贷业务线尝试开发绿本(车辆产权证)的识别,帮着保险业务线开发国内各个保险公司保单的关键信息识别;纸质征信报告识别等诸多项目机会,但是,我们都没能把握住机会,原因是我们确实还欠缺很多,具体包括,表格识别能力,前端的布局分析能力,表单间的分割能力等等。痛定思痛,我们于是开始着手一一解决,首先,我们使用网上一个Unet代码样例,再其基础上,开发出一个表格识别,具体的做法是,使用UNet做表格线识别,识别出横线和竖线,然后我们自研了一个算法,去分割出行和列,然后做cell的合并,完成了表格的识别;然后,我们是使用语义分割算法,把典型的证件类,如身份证、行驶证、发票、绿本等,使用语义分割,将其从图片里剥离出来,当然,我们仍然使用阿里、百度、旷视、华为这些公司的demo网页作为我们打标的手段;期间,我们的一个同事,还使用Bert以及笔画库,开发了一个词语纠错和文字笔画纠错的模块,大大增加了我们识别的鲁棒性;我们还改进了CRNN,使用CenterLoss来区分形近字(这个受到阿里的一个分享中提及的方案的启发),并且,通过改进我们的造字程序,加大样本量等手段,是我们的正确率从我之前的85%提升到93%左右;最后,我们使用这些技术的基础和铺垫,研发出一套基于模板的自动对齐算法:我们首先在模板图像上标注关键字(其实是为了标识关键位置),然后,在识别过程中,使用语义分割出对应的证件区域和其类型,然后识别后,再根据关键字在做类型的二次校验,然后,根据之前标注的此类模板的关键位置,进行对齐,通过各种调整、透射、仿射,最终,把图像的关键区域“扣”出来,完成关键字段的识别,取得了非常好的效果;我们还开发了一系列和业务相关的校验器,如身份证、车证编号、地址等,大大提高了识别后的纠错能力。

终于,在2021年,我们迎来了真正的项目机会,我们连续给业务部门提供了多个服务,包括,给车贷线的绿本12页识别,34页识别(12页和34页模式完全不同,需要不同的特殊的处理),我们还定制性的研发了车牌和二维码在一起的混合识别;我们研发的身份证、行驶本、驾照业务识别也同步上线;这些都在真实的业务场景下,每月为业务线提供了数万计的调用,有力的支撑了业务的发展。我们团队的同事,也得到了极大的成就感,成为全公司唯一的一条支撑OCR识别的内部AI团队。

到了下半年,风云突变,公司相关的业务线由于战略调整,逐渐开始裁撤,我们目测的业务量呈直线下降,而和我配合的产品总监Z,也由于个人原因离开团队,团队内部也出现了问题,其中的两位同事,分别在年中和年末离开了团队,加入了更有前途的外企和互联网大厂,虽然深深的祝福她们,但是,也是感觉到团队的没落和危机。

于是,2021年8月份开始,我尝试开发研发人脸识别系统。我首先把焦点聚焦在人脸识别上,通过大量的论文学习和阅读,我逐渐理解了,人脸识别才是人脸系统的核心。而人脸检测其实就是目标检测的一个应用而已。回到识别上,本质上,人脸识别就是人脸的比对,如何判断一张脸和另外一张脸就是同一张脸,而和另外一张脸不是同一张呢?这本质上,就是一个相似性、或者叫两张脸的距离问题,在使用backbone做了人脸的特征抽取后,然后使用各类衡量特征距离的方法,来衡量人脸的距离,最终,梳理了整个人脸比对的算法发展脉络后,我选定了arcface,一个把特征映射到到球面上,计算弧度距离的算法上。这次,我使用的是pytorch,借这个项目,我把pytorch认真学习了一遍,真心感觉keras就是抄的pytorch,pytorch的代码确实简洁很多,也很直白,下次做项目,我可能还会选择pytorch。为了实现arcface,我还开发了基于arcface的MNIST识别,降维到2维,可视化体验了arcface如何分开不同人脸的。最终,我train出了人脸比对,虽然正确率达不到生产要求,但是基本上已经实现了算法的诉求。接下来,我又着手人脸检测,这次要简单的多了,我选择了比较成熟的RetineFace,其实就是一个目标检测,使用FPN做特征抽取后,除了人脸的位置回归,还加入了人脸的关键点lanmark的loss,最终训练来了检测模型。

话说,已经到了11月底,我发现,即使我train出来人脸识别,也无法改变团队的命运了,一方面是缺乏产品端的支持,另一方面公司的人脸识别场景也不是特别明确,看来,我train出来的这个人脸模型,注定无法给业务带来支撑的机会了。于是,我决心,在最后的阶段,全力把经历转变到量化投资上吧,一个为自己的投资积累一些经验,另一个也算是再尝试一个可能跟公司业务相关的一个方向把。

从12月初开始,我开始学习量化投资,我了解到,量化投资适合我们做的,只有CTA和多因子这两个方向,CTA不是很难,而多因子则复杂很多,而且是机构常用的方法。于是,我还是选择了多因子方向。多因子模型是从fama-frech的三因子模型逐渐发展而来,于是,我又去研读了一遍投资学的教材,学习了从CAMP到多因子模型到FF三因子模型,最后找到了石川老师的《多因子实证》的书研读,发现,这个领域其实也是非常深。经过学习和探索,我逐渐形成了一套,基于tushare、alphalens、jads、backtrader的开发脚手架,分别覆盖数据源、单因子分析、多因子合成和回测的所有内容,完成后,我开始着手寻找别人实现的因子,以及准备开始复现各个金工研报的因子和策略,这些都在稳步的进行。我也尝试认识了量化投资圈的很多朋友,包括一些有经验的朋友,跟他们学习和请教,逐渐认识到这个领域的博大精深,以及对市场的敬畏。我还尝试联系了公司内部的量化部门,但是反馈是,确实没有什么机会了,好吧,最终,这个可能成为我将来个人的一个学习和研究方向吧。

目前,即将离开这个公司了,工作已经基本上告一段落了,回想四年的工作,还是收获满满,还是非常感谢当初部门的老大给我这个机会,可以让我在人工智能这个领域可以有四年的学习和实践。也经历了从白纸一张,到学习理解,到最终实践交付的整个过程,期间认识了非常优秀的同事们,带领他们一起为公司的业务发展也贡献了力量,也帮助她们收获了职业的发展,心里还是非常高兴和满足的。

天下没有不散的宴席,我自己也要开启一段新的旅程了,我还是持续关注人工智能发展,关注数学的应用,关注计算机行业的最新发展,关注量化投资、NLP等具体的领域,希望未来有机会再经历这样的有意义的四年。