广告行业中那些趣事系列41:广告场景中NLP技术的业务应用及线上方案

111 阅读29分钟

导读:本文是“数据拾光者”专栏的第四十一篇文章,这个系列将介绍在广告行业中自然语言处理和推荐系统实践。本篇主要介绍了广告场景中NLP技术的业务应用和线上方案,对于想了解广告场景中NLP技术的小伙伴可能有所帮助。\

欢迎转载,转载请注明出处以及链接,更多关于自然语言处理、推荐系统优质内容请关注如下频道。

知乎专栏:数据拾光者

公众号:数据拾光者

摘要:本篇主要介绍了广告场景中NLP技术的业务应用和线上方案,主要介绍了三大类任务:第一类任务是文本分类任务,业务主要包括自然兴趣建模体系、搜索场景行业词包和在线分类以及商店/搜索/评论等舆情分析,同时介绍我们的线上方案以及在模型和样本上的优化实践;第二类任务是文本生成任务,介绍了头条巨量创意平台的妙笔以及我们自研的文案助手技术方案;第三类任务是相似文本召回任务,业务主要是广告算法词召回,线上主要使用基于对比学习simcse+faiss的相似文本召回方案。感兴趣的小伙伴可以多交流。

下面主要按照如下思维导图进行学习分享:\

b069091e39f71069c54bbc8b74a150f4.png\

01

背景介绍\

先介绍下本篇文章的背景,现在正值毕业季,应届生也陆续到公司上班,这是为应届生准备的一门课程,课程内容主要是介绍下广告场景中NLP的业务应用,刚好作为我在公司的一个工作总结吧。从NLP任务类型来看,主要涉及以下三大类任务:

  • 文本分类任务:这是NLP最常见的任务,也是我们实际工作中应用最多的任务,主要有自然兴趣建模体系中的数据源内容理解、搜索场景中的行业词包以及商店/搜索/评论舆情等;
  • 文本生成任务:文本生成任务应用到我们实际工作中主要是广告文案生成,根据一定的条件比如行业标签和关键词来生成广告文案,辅助广告主创建广告,一方面可以提升广告的创建效率,另一方面可以提升广告的转化效果;
  • 相似文本检索任务:相似文本检索任务主要是根据一条文本从搜索库中找到语义相似的其他文本,主要应用在我们的H5广告算法词召回、相似query召回买词服务以及天机谱相似关键词获取服务中。

下面的内容会重点介绍下我们广告场景中这三大类任务的业务应用以及线上技术方案。\

02

文本分类任务\

文本分类任务属于NLP最常见的任务之一,也是在我们实际工作中应用最广泛的任务。之前公众号里很多还在学校的小伙伴迷茫做NLP哪一方向可以更好的找到工作,那无疑是文本分类任务了。

**2.1 业务介绍
**

2.1.1 自然兴趣建模体系

我们团队有一个重点项目就是构建自然兴趣标签体系为广告主圈选人群。业务目标是为特定的广告主圈选特定的人群进行广告投放。首先根据用户操作终端行为日志数据来获取用户和数据源的关联,这里的数据源可以是手机应用app、用户搜索query、用户浏览资讯news、快应用、微信小程序等等,这里将数据源统一标记为item,那么就可以得到user-item关联;然后通过人工打标或者机器学习算法对这些数据源进行文本分类从而得到item-tag关联;最后根据上面两种关联进行join操作可以得到用户和标签的关联user-tag。\

通过这种方式我们就可以为用户打上兴趣标签了。当有一个广告主想找特定的人群来投放广告时,就可以选择单个或者多个标签组合的方式来圈选人群。比如现在有个传奇游戏标签的广告主想为app打广告,那么他会选择传奇游戏标签,也就是对传奇游戏感兴趣的人群进行广告投放,这样才会得到更好的广告转化效果。简单理解每个标签背后是一个特定的人群,下面是广告主通过标签来圈选人群示意图:

fd780b04d00511b3847ee58fc0d4e68e.png

图1 广告主通过标签来圈选人群示意图

明确了项目目标接下来看我们的标签挖掘系统框架以及NLP在整体框架中的位置。我们标签挖掘系统框架主要从下到上分成四层:

  • 数据接入层,主要负责接入三大块内容:第一块内容是用户和数据源关联数据,主要通过埋点获取用户操作数据源行为日志数据,包括用户安装和使用app、浏览器搜索query、阅读资讯news、点击广告ad等;第二块是各数据源文本内容,对于各类数据源的理解主要是通过文本内容数据,比如理解app主要是app名、app描述等,浏览器搜索则主要是用户搜索query内容和点击页面的title数据,浏览资讯则主要是资讯title和资讯内容等,这里是为上游理解item数据作准备;第三块主要是接入非兴趣标签,比如用户的年龄、城市和性别等用户画像内容;
  • 文本理解层,核心就是通过NLP技术理解各数据源进行文本分类或者关键词抽取,从而给数据源打上兴趣标签。文本分类效果的好坏会直接影响下游用户兴趣打标效果。我们会根据广告主需求制定一个类目体系,目前是四层类目标签,根据类目体系使用textCNN、BERT等模型进行文本分类任务。除此之外,还需要挖掘关键词标签,之前也尝试过基于BERT+CRF构建关键词抽取模型;
  • 行为建模层,主要包括三块:第一块是构建用户和标签的关联,这里会分成自然兴趣建模和商业兴趣建模。自然兴趣建模主要根据用户行为使用统一兴趣建模流程构建user-tag关联。在自然兴趣标签的基础上,对重点标签使用更多的特征数据和更复杂的模型进行商业兴趣建模;第二块是根据种子人群进行人群扩量,也就是构建user-user的关联;第三块是投放广告;
  • 业务应用,也就是广告主圈选人群,主要有广告定向、排序特征以及天机谱等。

NLP技术主要应用在我们标签挖掘系统框架中文本理解层,下面是标签挖掘系统框架以及NLP在其中的位置介绍图:

3130403e3ad08ee75ea9d9986869de97.png

图2 标签挖掘系统框架以及NLP的位置

2.1.2 搜索场景行业词包和在线分类

搜索场景中的行业词包和在线分类主要使用的也是NLP中的文本分类技术。用户在浏览器搜索query会推荐对应的广告,中间会经过召回和排序两个流程,我们的主要工作是在召回流程提供一路分类召回。分类召回主要分成行业词包和在线分类两种方式。\

作为生产方我们会根据运营需求开发重点行业标签的分类器,需要实时对用户的query进行文本分类。而作为消费方的广告主会购买行业词包从而当用户搜索词命中行业标签的时候会曝光对应的广告。线上场景中需要实时对用户搜索query进行文本分类,如果使用textCNN这类轻量级模型可以很好的满足线上时延,但是文本分类的效果一般。要想提升文本分类的效果则需要考虑使用BERT这一类预训练模型,目前BERT模型也达到了文本分类任务的SOTA效果。如果直接使用BERT去构建在线分类任务,虽然能提升文本分类的效果,但是因为BERT参数量巨大导致很难满足在线时延的要求。\

要想既有好的文本分类效果,又同时满足线上时延,我们通过知识蒸馏技术,以BERT为老师来教textCNN知识,从而让textCNN具备媲美老师的分类效果,同时还可以满足线上时延。关于知识蒸馏的介绍小伙伴可以看下我之前写过的文章《广告行业中那些趣事系列21:从理论到实战BERT知识蒸馏》

为了进一步提升线上文本分类的速度,我们会离线构建文本分类器对高pv的搜索query进行文本分类,并且保存到内存数据库ES。当用户搜索query已经出现在ES中则直接返回离线文本分类的结果,否则进入在线文本分类任务。下面是用户搜索query推荐相应广告整体流程图:

03b2e0b51f7a216523c2b3f1cda03327.png

图3 用户搜索query推荐相应广告整体流程图

2.1.3 商店/搜索/评论等舆情

关于商店/搜索/评论等舆情这块的比较好理解,就是当用户搜索黄赌毒或者涉政相关的需要进行屏蔽,本质上是一个二分类任务。这块一笔带过。

2.2 线上文本分类方案介绍

上面介绍了我们广告场景中的文本分类任务具体的业务应用,下面则主要介绍下我们线上的文本分类方案,主要分成模型优化实践、样本优化实践以及小样本学习半监督流程介绍三个部分。

2.2.1 文本分类任务模型优化实践

先说下文本分类模型,之前进行算法调研的时候对比了一下传统的文本分类模型和BERT模型在我们线上业务的文本分类效果,下面是效果对比图:

2d27a18dff0b047a60cedbb4a697ab7c.png

图4 文本分类任务算法调研效果图

从上图中可以看到我们主要调研了传统的文本分类算法比如textcnn、fasttext和目前主流的BERT模型,结论是BERT模型效果优于传统文本分类算法。传统文本分类算法效果虽然不如BERT,但是优点在于模型预测速度较快,可以应用到一些实时性要求较高但效果略微降低的场景中。传统的文本分类算法需要对中文文本进行分词操作,北大的pkuseg效果优于jieba分词。最终我们使用BERT来构建分类器。基于BERT构建分类器大概是如下流程:

d45c1c3261a2f8a08d03b43e5308ec19.png

图5 基于BERT构建分类器流程

模型输入一条文本“一刀传奇好玩么?”,最后需要输出分类结果,中间需要经过三个阶段:第一个阶段是使用BERT等预训练模型进行编码,第二个阶段是获取句向量表示,第三个阶段就是构建分类层。从模型层面的优化也是基于上面这三个阶段分别进行优化的。

第一个阶段Encoder编码器优化。Encoder优化主要是为了获取文本更好的向量表示,所以这里主要是对BERT这一类预训练模型进行优化。我们预训练模型的优化流程大约是下面的线路:

6e2707ecc06d05cf99a02acd92f168f3.png

图6 预训练模型优化线路

预训练模型的优化经过三个阶段,从最开始使用谷歌原生中文版BERT模型,再到使用ALBERT,最后到目前线上使用的RoBERTa-wwm-ext预训练模型。关于这三个预训练模型演进之路详细介绍可以看下我之前写过的文章《广告行业中那些趣事系列37:广告场景中的超详细的文本分类项目实践汇总》。

第二个阶段是句向量表示优化。对于文本分类任务来说,BERT论文建议直接取CLS向量作为句向量表示,因为作者认为CLS已经可以作为语句向量的表示。下面是句向量表示图:

8f37439d4973b6d630eae7efe84eafc4.png

图7 句向量表示

关于句向量表示优化,我们尝试了最后一层Transformer的首字符句向量(CLS)、每个字对应的Embedding取均值AVG、取和SUM,最后使用了第一层Transformer和最后一层Transformer得到的字向量累加之后再取均值操作。这么做的原因是对文本进行tokenembedding词编码之后第一层Transformer得到的embedding向量包含更多的词向量信息,最后一层Transformer之后的embedding向量包含更多语句向量信息,将两者累加之后可以最大程度上保留词和语句的向量信息。

第三个阶段是分类层优化。通过句向量表示我们可以得到一个768维的向量,接下来就是分类层优化。最简单的分类层就是直接添加一个softmax全连接层进行分类。对于二分类任务来说,通常会使用sigmoid函数,但是通过实验对比发现softmax函数效果会优于sigmoid函数。之前在知乎上看到这个问题的回答,里面的结论是从理论角度来说二分类问题两者是没有区别的,但是因为Pytorch、TensorFlow等框架计算矩阵方式的问题,导致两者在反向传播的过程中还是有区别的。对于NLP而言使用softmax的处理方式会优于sigmoid,而CV则相反,使用sigmoid会优于softmax。我们在NLP实验中也证明使用softmax的效果是优于sigmoid。

除了最后一层分类层使用softmax之外,还可以根据训练集规模大小以及任务的难度来决定是否使用更多的分类层。实验中对比了1-3层全连接层对模型效果的影响,1层就是直接最后添加一层softmax全连接层,2层则是先将768转化为256维度之后再接softmax,3层则是将768转换为256再转换为128最后再接softmax。最后实验结果是使用两层全连接层效果是最好的。

2.2.2 文本分类任务样本优化实践

文本分类任务样本优化实践主要是解决三个问题:如何又快又好的获取人工标注数据集?如何解决样本不均衡问题?如何获取更多的训练样本?为了又快又好的获取人工标注数据集,我们通过主动学习流程提升标注效率。关于样本不均衡则主要通过损失函数优化,线上使用focal loss和GHM loss来解决。为了获取更多的训练样本,我们构建了一套半监督自训练项目,将主动学习、半监督和自训练相结合,仅使用少量的样本就可以获得一个效果很好的分类器模型。下面会重点介绍下半监督和自训练流程,半监督和自训练项目的基本流程图如下所示:

ac1cf7872808b1513721a17b5010847f.png

图8 半监督和自训练流程项目基本流程图

整体来看半监督和自训练流程项目基本流程如下:

  • S1使用少量带标签数据集D1和有效enlarged样本集D2合并得到训练集来训练一个初始分类器f0,这里需要注意的是第一轮训练时D2为空。训练完分类器之后记录模型效果;
  • S2使用enlarge&clean策略扩展伪标签样本并纠正错误样本。这是半监督项目的核心,通过各种enlarge策略来增加伪标签样本。线上使用的enlarge策略有利用simbert模型基于语义相似度来检索相似文本从而给无标签数据集D0打上伪标签。还可以使用初始分类器f0预测D0来打上伪标签。还可以通过对比学习模型SimCSE打上伪标签。这里enlarge策略非常丰富,可以说enlarge策略的好坏直接影响半监督流程的效果。因为标注的样本中可能存在误标的情况,所以需要对错误样本进行修正,也就是clean策略,实际工作中主要使用置信学习等方式来修正错误样本。这里enlarge&clean策略还会选择置信度较低的样本提交给标注人员标注,标注完成之后会添加到D1中;
  • S3将D1、D2和经过enlarge策略打上伪标签的候选enlarged样本集D3合并作为训练集用于训练新的分类器fi并评估模型效果。评估完成之后将fi和f0进行对比,如果没有提升则说明enlarge策略得到的D3数据集无效,直接结束半监督流程。如果有提升则说明D3有效,将D3加入到D2中,并进入后续流程;
  • S4使用新的分类器fi去预测D0数据集,这里进入了小循环自训练流程;
  • S5将S4得到的伪标签数据集使用PseudoLabel筛选策略得到Pseudo Label样本集D4。目前线上使用的筛选策略是根据模型预测得分选择伪标签样本,第一轮自训练流程会选择大于0.95分的正样本。这里得到D4有不同的策略,可以只选正样本,也可以正负样本都选。这里Pseudo label筛选策略会使用主动学习流程选择标注价值高的样本进行标注;
  • S6将D1、D2、D3和D4合并得到最新的训练数据集,然后训练新的分类器f(i+1)并进行评估。和之前的分类器进行对比,如果有提升,则说明D4有效,接下来进入到S4流程。如果没有提升则在第二轮自训练流程降低阈值选择得分大于0.9分的作为D4,继续训练新的分类器并评估。如果连续N次选出的D4都无效则退出当前的小循环并进入到S1开启下一次大循环流程。这里N的次数可以进行设置。

整个半监督流程重点是大循环和小循环的进入条件。当enlarge策略得到的D2无效时退出半监督流程,否则进入小循环。当连续N次D4无效时则退出小循环。明确了大循环和小循环的进入条件理解整个流程就变得容易了。半监督流程通过少量人工标注数据集提供的信息去获取更多的训练样本数据集,从而得到好的分类器。整个半监督流程可以应用到更广泛的分类任务中,包括NLP场景、CV场景等等,我们将模型训练、评估和预测流程通过脚本进行定制化,对于使用方来说仅仅需要关注数据流转过程即可。当前我们已经使用半监督流程优化线上文本分类器并取得不错的效果,正在向更简单易用的方向努力,后续可能会做到开源。\

还需要说明的是,半监督流程不仅仅是从样本层面对分类任务进行优化,模型训练、评估和预测流程中会将之前积累的模型层面的优化添加进来,对于样本不均衡问题也使用了Focal loss和GHM loss等。关于文本分类任务样本层面的优化汇总小伙伴可以看下之前写过的文章《广告行业中那些趣事系列40:广告场景文本分类任务样本优化实践汇总》。

03

文本生成任务\

文本生成任务也是NLP场景中比较常用的一个方向,应用领域主要有三个方面:第一个方面是创作,比如写诗词、小说之类的,还可以生成广告文案或者营销标题等;第二个方面是信息抽取,比如自动摘要任务,从一篇文章中根据内容自动生成核心摘要内容;第三个方面是对话系统,比如现在很常见的天猫精灵、我们的小bu助手以及小米的小爱等等语音对话机器人,据说现在很多稀奇古怪的社交app(比如Tantan)里就有很多语音机器人陪大家聊天。\

对应到我们的实际业务需求主要就是创作任务,也就是根据一定的条件来生成广告文案,也就是文案助手。文案助手的作用主要有两个,第一个是帮助广告主更有效率的创建广告,节约人工撰写广告文案的时间和人力成本;另一个是提升广告的转化效果,好的广告文案可以吸引人的眼球,从而提升广告转化效果。很多因为广告文案一鸣惊人的产品,比如脑白金等等。

3.1 头条巨量创意平台的妙笔

调研了其他大厂的文案助手,比较有代表性的就是头条的巨量创意平台中的妙笔,下面是妙笔文案助手生成广告文案效果图:

8e913e261ebb86b67ca34a957c68e886.png

图9 妙笔文案助手生成广告文案效果图

从上图中可以看出,用户只需要输入行业和关键词(非必须)即可得到对应的广告文案,从效果来看生成的广告文案语言通顺,并且内容也是和行业、关键词契合的,基本上妙笔工具就是我们广告文案助手的模板工具了。

3.2 自研的文案助手技术方案介绍

整体来说广告文案生成任务模型的输入和输出都是文本序列,并且输入和输出的长度可能不同,所以是Seq2seq任务。Seq2seq模型架构如下图所示:

654fbda4e2bb38ca03362cfb3f86820e.png

图10 Seq2seq模型架构

从上图中可以看出,Seq2seq模型架构中输入是w1、w2、…wn,输出是y1、y2、…yn,主要分成编码器和解码器两部分。编码器把输入序列转化成一个固定大小的向量hn,然后解码器根据向量hn单向递归的生成输出序列。重点注意下输出序列的流程,解码器第一轮解码会根据hn向量和开始符号S先输出y1,然后第二轮再根据hn向量和已经生成的词y1来输出y2,不断循环,每轮解码只能利用已经生成的序列,而后面的序列是不可见的,直到遇见结束符号E完成模型整个输出。

在NLP领域中编码器和解码器结构可以选择的很多,主要有LSTM、CNN或者当前超火的Transformer模型。实际项目中主要使用BERT来构建Seq2Seq任务。通常来说广告文案生成任务属于NLG(自然语言生成任务),这类任务一般会使用单向语言模型比如GPT来完成。\

而BERT这一类双向语言模型更适合NLU(自然语言理解任务),比如文本分类、句子对关系识别等任务。这里没有使用GPT模型的主要原因是当时没有中文开源的GPT模型,并且GPT模型太大导致很难使用下游业务相关的数据进行微调。如果直接使用BERT也存在问题,Seq2Seq模型结构的解码器是利用编码器得到的固定向量hn去单向递归的生成输出序列,而BERT是基于Transformer的双向循环结构,模型训练过程中对于每个词来说其他所有词都是可见的,所以需要对BERT进行改造才能适配Seq2Seq模型。\

将BERT用于完成Seq2Seq任务主要是使用微软的UNILM模型,具体做法是对Attention矩阵进行改造从而可以仅需使用一个BERT模型来同时完成编码器和解码器的工作,需要提前说明下,下图中蓝色小框代表是可见的,绿色小框代表是不可见的。下面分别是双向可见、单向可见和前缀双向可见的注意力机制掩码操作:

ea4522f9d0b4efece9857774379d1ce6.png

图11 三种不同的注意力掩码机制

从上图中可以看出,第一种双向可见的Attention机制是BERT原始的编码机制,对于每个词来说所有词都是可见的;第二种单向可见的Attention机制是Seq2Seq模型中解码器的结构,对于每个词来说只能看到它之前的词,而之后的词都是不可见的。比如对于第三个字“吃”来说,之前的“我”和“想”是可见的,而之后的“苹“和”果”是不可见的。如果用单向可见的Attention机制,那么需要使用两个BERT模型,第一个BERT用于作为编码器,第二个BERT改造成单向可见的Attention即可完成,这也是BERT和Seq2Seq模型相结合的一个工作,是微软的MASS。但是整体来看不够优雅;第三种是前缀双向可见的Attention机制,也就是微软的UNILM。这个模型巧妙之处在于仅使用单个BERT模型就可以完成Seq2Seq任务,不需要区分编码器和解码器。\

具体通过举例说明,假如我们现在输入序列是“我”、“想”、“吃”,输出序列是“苹“、”果”。通过UNILM模型,对于输入序列中的每个字都是互相可见的,而对于输出序列则之前的序列是可见,之后的序列是不可见的,很好的满足了Seq2Seq的模型结构,可以说是非常巧妙的设计。通过这种方式,可以将BERT很好的应用到NLG自然语言生成任务中去。经过实践,模型的生成效果也是很不错的。关于文案生成模型的详细介绍可以看下我之前写过的文章《广告行业中那些趣事系列29:文案生成之路-基于BERT构建文案生成模型》。

04

相似文本召回任务

相似文本召回任务其实就是根据语义来找到相似的文本,对应到我们线上主要有广告算法词召回、相似query召回买词服务以及天机谱相似关键词。\

4.1广告算法词召回任务

广告算法词召回任务就是根据用户搜索query来推荐相应的广告。比如用户输入了“什么传奇游戏好玩”,我们会推荐传奇游戏标签的app,其中一种召回的原理就是根据语音相似度,最简单的就是将用户搜索query文本和app名文本计算语义相似度,从而返回相似度高的app实现相似文本召回。下面是根据用户输入query召回相似广告示意图:

d36ef212bfc8fe1b408055c2410939d9.png

图12 用户输入query召回相似广告示意图

4.2 基于对比学习的相似文本召回方案

从任务复杂度来说,相似文本召回任务比较简单,主要有两步,第一步是获取文本语义向量embedding,第二步根据向量从海量文本库中找到相似文本。

第一步获取文本语义向量embedding。这一步重点是如何获取高质量的语义向量表示,这里涉及两个方面:文本的丰富度和更好的语义向量表示。文本的丰富度方面,如果直接将用户搜索query和app名进行语义匹配,会发现召回的文本数量比较少,表现在线上就是曝光量少消耗低,主要原因是提供的信息有效,从广告角度来说能召回的query太少。为了提升召回的数量,我们会提供更加丰富的文本信息,app侧会将app名、app标签、app内容的关键词等更丰富的信息进行拼接作为app的文本信息。Query侧也会将搜索query、query分类等信息拼接作为query的文本信息。通过这种方式可以大大提升文本的丰富度,从而匹配的结果也会大大增加。\

文本丰富度的问题解决之后就是如何获取更好的语义向量表示。如果直接用google原生BERT获取语义向量,会发现任意两个句子的向量相似度比较高,也就是说文本之间的区分度很差,相似文本召回的效果也会很差,主要原因是向量分布的非线性和奇异性使得BERT句向量并没有均匀的分布在向量空间中,对应的信息熵比较低。\

针对这个问题BERT-flow通过normalizing flow把语义向量映射到规整的高斯分布中,从而语义向量可以分布在相对均匀的空间中。还可以使用BERT-whitening对语义向量分布进行PCA降维操作去除冗余信息,也可以把语义向量映射到更均匀的向量空间中从而提升相似文本召回效果。除此之外,我们还可以使用NLP场景中的对比学习模型SimCSE获取分布更均匀的语义向量。关于对比学习模型SimCSE的详细介绍小伙伴可以参考我之前写的一篇文章:《广告行业中那些趣事系列35:NLP场景中的对比学习模型SimCSE》。线上我们使用的就是基于对比学习模型SimCSE获取文本的语义向量表示embedding;

第二步是根据向量从海量文本库中找到相似文本。为了提升检索的效率,我们主要使用基于faiss进行海量高维数据集检索,关于faiss的介绍可以参考之前写过的文章《广告行业中那些趣事系列38:广告搜索业务中海量高维数据集检索利器Faiss》。

05

总结及反思\

本篇主要介绍了广告场景中NLP技术的业务应用和线上方案,主要介绍了三大类任务:第一类任务是文本分类任务,业务主要包括自然兴趣建模体系、搜索场景行业词包和在线分类以及商店/搜索/评论等舆情分析,同时介绍我们的线上方案以及在模型和样本上的优化实践;第二类任务是文本生成任务,介绍了头条巨量创意平台的妙笔以及我们自研的文案助手技术方案;第三类任务是相似文本召回任务,业务主要是广告算法词召回,线上主要使用基于对比学习simcse+faiss的相似文本召回方案。感兴趣的小伙伴可以多交流。\

最新最全的文章请关注我的微信公众号或者知乎专栏:数据拾光者。\

548083a14f7b4ebf3052b02fa6e3c161.png

码字不易,欢迎小伙伴们点赞和分享。\