Help
RSS
API
Feed
Maltego
Contact
Domain > liucaiquan.site
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2024-09-15
151.101.229.147
(
ClassC
)
Port 80
HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 129941Server: GitHub.comContent-Type: text/html; charsetutf-8Last-Modified: Sat, 09 Nov 2019 12:29:54 GMTAccess-Control-Allow-Origin: *ETag: 5dc6b142-1fb95expires: Thu, 12 Sep 2024 21:52:54 GMTCache-Control: max-age600x-proxy-cache: MISSX-GitHub-Request-Id: BA72:30D39A:16FF8A0:17ABB15:66E3605DAccept-Ranges: bytesAge: 0Date: Sun, 15 Sep 2024 05:21:46 GMTVia: 1.1 varnishX-Served-By: cache-hnd18722-HNDX-Cache: HITX-Cache-Hits: 0X-Timer: S1726377706.281440,VS0,VE243Vary: Accept-EncodingX-Fastly-Request-ID: 1b9577ca06f355a557e94786a248afbb135e44fc !doctype html> html classtheme-next mist use-motion langzh-Hans>head> meta charsetUTF-8/>meta http-equivX-UA-Compatible contentIEedge />meta nameviewport contentwidthdevice-width, initial-scale1, maximum-scale1/>meta http-equivCache-Control contentno-transform />meta http-equivCache-Control contentno-siteapp /> link href/lib/fancybox/source/jquery.fancybox.css?v2.1.5 relstylesheet typetext/css /> link href//fonts.googleapis.com/css?familyLato:300,300italic,400,400italic,700,700italic&subsetlatin,latin-ext relstylesheet typetext/css> link href/lib/font-awesome/css/font-awesome.min.css?v4.6.2 relstylesheet typetext/css />link href/css/main.css?v5.1.0 relstylesheet typetext/css /> meta namekeywords contentHexo, NexT /> link relshortcut icon typeimage/x-icon href/favicon.ico?v5.1.0 />meta propertyog:type contentwebsite>meta propertyog:title content才权的博客>meta propertyog:url contenthttp://yoursite.com/index.html>meta propertyog:site_name content才权的博客>meta propertyog:locale contentzh-Hans>meta nametwitter:card contentsummary>meta nametwitter:title content才权的博客>script typetext/javascript idhexo.configurations> var NexT window.NexT || {}; var CONFIG { root: /, scheme: Mist, sidebar: {position:left,display:post,offset:12,offset_float:0,b2t:false,scrollpercent:false}, fancybox: true, motion: true, duoshuo: { userId: 0, author: 博主 }, algolia: { applicationID: , apiKey: , indexName: , hits: {per_page:10}, labels: {input_placeholder:Search for Posts,hits_empty:We didnt find any results for the search: ${query},hits_stats:${hits} results found in ${time} ms} } };/script> link relcanonical hrefhttp://yoursite.com//> title> 才权的博客 /title>/head>body itemscope itemtypehttp://schema.org/WebPage langzh-Hans> script typetext/javascript> var _hmt _hmt || ; (function() { var hm document.createElement(script); hm.src https://hm.baidu.com/hm.js?4e94c4c1ded5d320541370545af638ea; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(hm, s); })(); /script> div classcontainer sidebar-position-left page-home > div classheadband>/div> header idheader classheader itemscope itemtypehttp://schema.org/WPHeader> div classheader-inner>div classsite-brand-wrapper> div classsite-meta > div classcustom-logo-site-title> a href/ classbrand relstart> span classlogo-line-before>i>/i>/span> span classsite-title>才权的博客/span> span classlogo-line-after>i>/i>/span> /a> /div> p classsite-subtitle>/p> /div> div classsite-nav-toggle> button> span classbtn-bar>/span> span classbtn-bar>/span> span classbtn-bar>/span> /button> /div>/div>nav classsite-nav> ul idmenu classmenu> li classmenu-item menu-item-home> a href/ relsection> i classmenu-item-icon fa fa-fw fa-home>/i> br /> 首页 /a> /li> li classmenu-item menu-item-archives> a href/archives relsection> i classmenu-item-icon fa fa-fw fa-archive>/i> br /> 归档 /a> /li> li classmenu-item menu-item-tags> a href/tags relsection> i classmenu-item-icon fa fa-fw fa-tags>/i> br /> 标签 /a> /li> li classmenu-item menu-item-about> a href/about relsection> i classmenu-item-icon fa fa-fw fa-user>/i> br /> 关于 /a> /li> /ul> /nav> /div> /header> main idmain classmain> div classmain-inner> div classcontent-wrap> div idcontent classcontent> section idposts classposts-expand> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/11/09/《从零开始学习自然语言处理-NLP-》-BERT推理加速实践(6)/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/11/09/《从零开始学习自然语言处理-NLP-》-BERT推理加速实践(6)/ itempropurl> 《从零开始学习自然语言处理(NLP)》-BERT推理加速实践(6) /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-11-09T20:22:05+08:00> 2019-11-09 /time> /span> /div> /header> div classpost-body itemproparticleBody> p>BERT推理加速的理论可以参考之前的博客《从零开始学习自然语言处理(NLP)》-BERT模型推理加速总结(5)。这里主要介绍基于Nvidia开源的Fast Transformer,并结合半精度模型量化加速,进行实践,并解决了TensorFlow Estimator预测阶段重复加载模型的问题。主要包括:/p>ul>li>p>环境搭建/p>/li>li>p>Pre-train模型获取/p>/li>li>p>结合自身业务Fine-tuning/p>/li>li>p>模型单精度(FP32)转半精度(FP16)/p>/li>li>p>Fast-transformer编译/p>/li>li>p>Fast-transformer集成/p>/li>li>p>TensorFlow estimator线上推理/p>/li>/ul>p>下面逐个进行介绍。/p>h1 id环境搭建>a href#环境搭建 classheaderlink title环境搭建>/a>环境搭建/h1>p>BERT的Fine-tuning需要GPU环境(CPU训练估计要慢到天长地久),而GPU的环境配置又相对麻烦。除了显卡驱动外,还需要对应版本的安装CUDA、CUDNN、Python、TensorFlow-GPU。版本不匹配很容易出问题。简单的环境搭建,推荐直接使用Nvidia的NGC镜像。针对BERTFine-tuning(Pre-train同样适用),本文中使用Docker镜像:nvcr.io/nvidia/tensorflow:19.10-py3(镜像说明:a hrefhttps://ngc.nvidia.com/catalog/containers/nvidia:tensorflow)。 target_blank relexternal>https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow)。/a>/p>p>镜像主要包括:/p>ul>li>Python 3.6.8/li>li>Tensorflow-estimator 1.14.0/li>li>Tensorflow-gpu 1.14.0+nv/li>li>TensorRT 6.0.1(Fast transformer基于TensorRT实现,需要依赖TensorRT)/li>/ul>h1 idPre-train模型获取>a href#Pre-train模型获取 classheaderlink titlePre-train模型获取>/a>Pre-train模型获取/h1>p>中文的BERT预训练模型直接从google-research/bert获得即可,具体地址:a hrefhttps://github.com/google-research/bert target_blank relexternal>https://github.com/google-research/bert/a>br>img srchttps://pic2.zhimg.com/80/v2-880d0627c03b8afb4e5c4e2da345ba19_hd.jpg alt中文BERT模型>/p>h1 id结合自身业务Fine-tuning>a href#结合自身业务Fine-tuning classheaderlink title结合自身业务Fine-tuning>/a>结合自身业务Fine-tuning/h1>p>Fine-tuning主要是根据自己的使用场景,修改训练的数据读取逻辑,这里以文本分类(多分类、单标签)为例进行展开。文本分类的入口是run_classifier.py文件,主要增加一个自定义的数据获取类,比如,br>img srchttps://pic3.zhimg.com/80/v2-c4bbbeca55f3c1805a9d82eec525f30e_hd.jpg alt自定义数据读取类>br>其中,br>img srchttps://pic4.zhimg.com/80/v2-be3888cb481a03859f9bc5be160ddb07_hd.jpg alt自定义数据读取类>br>img srchttps://pic4.zhimg.com/80/v2-da7fbc75ab97d2ac848278d9b5d1ff37_hd.jpg alt自定义数据读取类>br>需要注意的是,如果训练样本提前没有进行shuffle操作,可以将代码中的shuffle值修改的大一些,否则,训练结果会很差,比如,br>img srchttps://pic4.zhimg.com/80/v2-b1cc5f52e143944064717a363f04959b_hd.jpg altshuffle修改>br>Fine-tuning的代码可以使用Google官方的代码(代码地址:a hrefhttps://github.com/google-research/bert),也可以使用Nvidia提供的BERT代码(代码地址:https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT)。 target_blank relexternal>https://github.com/google-research/bert),也可以使用Nvidia提供的BERT代码(代码地址:https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT)。/a>br>Nvidia代码的优点是方便配置,比如:br>strong>混合精度/strong>:加快训练速度br>strong>XLA优化/strong>:后面使用Fast Transformer加速,不建议打开这个选项,担心XLA的网络优化,会导致Fast Transformer参数初始化失败。(没有通过实验验证,不确定真实的结果)。br>Fine-tuning后的模型会发现变大很多,比如BERT的中文预训练模型大小为393M,Fine-tuning后居然变成了1.2G。这么大的变化,主要由于训练过程中的checkpoints由于包含了每个权重变量对应的Adam momentum和variance变量。具体可以参考《BERT-TensorFlow版微调后模型过大解决方案》。/p>h1 id模型单精度(FP32)转半精度(FP16)>a href#模型单精度(FP32)转半精度(FP16) classheaderlink title模型单精度(FP32)转半精度(FP16)>/a>模型单精度(FP32)转半精度(FP16)/h1>p>Fine-tuning后的模型默认是FP32保存的,在服务上线进行推理阶段,要先转换成半精度(FP16),从而加快推理速度。br>TensorFlow提供了半精度转换的API,具体参考《TensorFlow 模型优化工具 — float16 量化将模型体积减半》。br>这里没有使用TensorFlow的API,而是,使用了Nvidia Fast transformer提供的方法(ckpt_type_convert.py):br>img srchttps://pic3.zhimg.com/80/v2-e0911803cb0a4d4327e891538a24d992_hd.jpg altckpt_type_convert.py>br>解释地址:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/blob/master/FasterTransformer/sample/tensorflow_bert/sample.md target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/blob/master/FasterTransformer/sample/tensorflow_bert/sample.md/a>br>ckpt_type_convert.py地址:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer/sample/tensorflow_bert target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer/sample/tensorflow_bert/a>/p>h1 idFast-transformer编译>a href#Fast-transformer编译 classheaderlink titleFast-transformer编译>/a>Fast-transformer编译/h1>p>Fast-transformer由C++编写实现,使用前需要先进行编译。br>编译环境之间使用当前的Docker环境即可,需要注意的是要先下载TensorRT的压缩包。虽然环境中已经有了TensorRT,但为了方便起见,还是直接下载一个(直接编译会出错)。注意对齐环境中的TensorRT版本(环境中使用的是TenorRT6.0版本)。br>TensorRT下载地址:a hrefhttps://developer.nvidia.com/tensorrt target_blank relexternal>https://developer.nvidia.com/tensorrt/a>br>编译命令:br>img srchttps://pic2.zhimg.com/80/v2-a81c95d2575a9bb8a6a2bb4b088c8071_hd.jpg alt编译命令>br>命令地址:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer/a>br>要正常使用Fast transformer还需要gemm_config.in文件,这个文件通过命令生成:br>img srchttps://pic3.zhimg.com/80/v2-5c0af33a5d7a27237621894bb6c65206_hd.jpg altgemm_config.in文件生成>br>命令地址:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer/a>/p>h1 idFast-transformer集成>a href#Fast-transformer集成 classheaderlink titleFast-transformer集成>/a>Fast-transformer集成/h1>p>Fast transformer的集成相对简单,直接将DeepLearningExamples/FasterTransformer/sample/tensorflow_bert/目录中的内容,拷贝到BERT源码目录即可。这里需要注意的是拷贝到google-research/bert的官方源码目录,而不是NVIDIA/DeepLearningExamples的BERT源码目录。br>拷贝到后者中,会运行出错(Fast transformer Demo应该是基于Google官方BERT源码实践的)。br>同时,需要注意的是上一个步骤中生成的C++层Fast transformer动态链接库,以及gemm_config.in文件的位置。br>C++层Fast transformer动态链接库引用:br>img srchttps://pic3.zhimg.com/80/v2-51393a54039124f572e2540cc8f043da_hd.jpg alt动态链接库引用>br>gemm_config.in文件放在源码目录下即可(执行命令的根目录)。br>最后,设置/p>pre>code>FLAGS.floatx 'float16'/code>/pre>p>从而开启半精能力。br>总结下Fast transformer集成需要的注意点:/p>ul>li>1 Fast transformer example代码拷贝到Google的BERT官方源码中;/li>li>2 包含libtf_fastertransformer.so的build文件放置在正确位置;/li>li>3 a hrefhttp://gemm_config.in文件放置在执行命令的目录; target_blank relexternal>http://gemm_config.in文件放置在执行命令的目录;/a>/li>li>4 设置FLAGS.floatx ‘float16’,开启半精推理能力;/li>/ul>h1 idTensorFlow-estimator线上推理>a href#TensorFlow-estimator线上推理 classheaderlink titleTensorFlow estimator线上推理>/a>TensorFlow estimator线上推理/h1>p>Google官方的BERT是基于Estimator实现的,但Estimator的模型训练、评估、预测,每次都要重新加载模型。这对于实时的线上预测任务是不能接受的。需要将Estimator的预测部分进行修改,每次推理预测时不重新加载模型。具体的实现可以参考《TensorFlow关于怎样解决Estimater.predict总是重新加载模型的问题》。实际上,这篇博客的实现主要是参考了一个很棒的gitlab开源项目hanxiao/bert-as-service。br>基于Fast transformer推理速度:br>img srchttps://pic3.zhimg.com/80/v2-b2b7fd0091a596383ccb94495e64650a_hd.jpg alt推理速度对比>br>数据来源:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/blob/master/FasterTransformer/sample/tensorflow_bert/sample.md target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/blob/master/FasterTransformer/sample/tensorflow_bert/sample.md/a>/p>h1 id小结>a href#小结 classheaderlink title小结>/a>小结/h1>p>本文基于Nvidia的Fast transformer,详细介绍了BERT推理加速优化的完整步骤,包括环境搭建、Pre-train模型获取、结合自身业务Fine-tuning、模型单精度(FP32)转半精度(FP16)、Fast-transformer编译、Fast-transformer集成、TensorFlow estimator线上推理等步骤,以及其中需要注意的问题,为BERT推理服务上线提供参考。/p>h1 id参考资料>a href#参考资料 classheaderlink title参考资料>/a>参考资料/h1>p>《BERT-TensorFlow版微调后模型过大解决方案》:a hrefhttps://blog.csdn.net/ljp1919/article/details/100652794 target_blank relexternal>https://blog.csdn.net/ljp1919/article/details/100652794/a>br>《TensorFlow 模型优化工具 — float16 量化将模型体积减半》:a hrefhttps://mp.weixin.qq.com/s?__bizMzU1OTMyNDcxMQ&mid2247486633&idx1&sn18d8541781f48d4d845c93473cd27bcb&chksmfc1847e1cb6fcef7617832b538751ed7731755d2bcb052f0005c8736c866b2153c87484a680d&scene0&xtrack1&key6ccb298b02eeb1eb594dec195455c03b8590cecdfa74d520f2ac3ffa3045a6a68fecf770f1ffe514191634410c0b511057cf428acc0d07c8686e77b626052a5a076801f3e0dbed26e3c7f9ed9fc270f1&ascene1&uinMTU2Nzk1MDIyMA%3D%3D&devicetypeWindows+10&version62070152&langzh_CN&pass_ticket%2BEHBIFHwjhPmTTiowh%2FkWmCf9eVl%2BAYiX2jsbCe13wDg%2FyRzwrFbvFs7zf4i3icO target_blank relexternal>https://mp.weixin.qq.com/s?__bizMzU1OTMyNDcxMQ&mid2247486633&idx1&sn18d8541781f48d4d845c93473cd27bcb&chksmfc1847e1cb6fcef7617832b538751ed7731755d2bcb052f0005c8736c866b2153c87484a680d&scene0&xtrack1&key6ccb298b02eeb1eb594dec195455c03b8590cecdfa74d520f2ac3ffa3045a6a68fecf770f1ffe514191634410c0b511057cf428acc0d07c8686e77b626052a5a076801f3e0dbed26e3c7f9ed9fc270f1&ascene1&uinMTU2Nzk1MDIyMA%3D%3D&devicetypeWindows+10&version62070152&langzh_CN&pass_ticket%2BEHBIFHwjhPmTTiowh%2FkWmCf9eVl%2BAYiX2jsbCe13wDg%2FyRzwrFbvFs7zf4i3icO/a>br>《TensorFlow关于怎样解决Estimater.predict总是重新加载模型的问题》:a hrefhttps://blog.csdn.net/hezhefly/article/details/98877796 target_blank relexternal>https://blog.csdn.net/hezhefly/article/details/98877796/a>/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/11/01/《从零开始学习自然语言处理-NLP-》-BERT模型推理加速总结(5)/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/11/01/《从零开始学习自然语言处理-NLP-》-BERT模型推理加速总结(5)/ itempropurl> 《从零开始学习自然语言处理(NLP)》-BERT模型推理加速总结(5) /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-11-01T21:06:23+08:00> 2019-11-01 /time> /span> /div> /header> div classpost-body itemproparticleBody> h2 id1-BERT模型介绍>a href#1-BERT模型介绍 classheaderlink title1 BERT模型介绍>/a>1 BERT模型介绍/h2>p>BERT是NLP任务的集大成者。 发布时,在GLUE 上的效果排名第一。br>strong>在语义表征方面/strong>br>将基于浅层语义表征的词向量,加强为深层语义特征向量。同时,引入上下文特征,解决了词向量一词多义的问题。br>strong>在知识迁移方面/strong>br>能够在海量的无监督文本训练语料中,有效的抽取语义特征。Pre-Train+Fine-Turning的模式下,非常实用。br>strong>在计算效率方面/strong>br>BERT基于Transformer实现,采用self-attention机制,采用并行的矩阵运算,替代RNN的串行执行,有效提升模型计算效率。br>strong>在任务设计方面/strong>br>BERT提供了分类、相似度计算(也是一种分类)、序列标注等NLP任务模板,基本覆盖了NLP任务的大多数模型应用场景。br>具体的BERT介绍可以参考Google的论文:《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》br>在学习BERT之前,建议先熟悉Transformer,具体可以参考Google论文:《Attention Is All You Need》br>直接看论文可能不好理解,建议先参考网上的Blog:br>图解Transformer:《The Illustrated Transformer》br>图解BERT:《The Illustrated BERT, ELMo, and co. (How NLP Cracked Transfer Learning)》br>很多国内的博客都是上面两篇博客的翻译或者引用。br>BERT在NLP预训练领域确实有里程碑的意义,这篇博客做了不错的总结:《从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史》/p>h2 id2-BERT模型的困境>a href#2-BERT模型的困境 classheaderlink title2 BERT模型的困境>/a>2 BERT模型的困境/h2>p>虽然BERT有各种优点,在项目落地上却存在缺陷:计算复杂度过高。通过BERT模型的参数量,感受下:br>img srchttps://pic1.zhimg.com/80/v2-b49abd72fe4e5aa04c8f102bcbfc1d10_hd.jpg altBERT参数量>br>数据来源:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/a>br>针对BERT模型,我们从预训练(Pre-train)、Fine-tuning、推理三个维度来看模型的计算耗时。br>strong>模型训练(Pre-train)时间:/strong>br>img srchttps://pic3.zhimg.com/80/v2-0b13b8f55e34ef76907cf51a6d8f8822_hd.jpg altPre-train时间>br>数据来源:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/a>br>strong>Fine-tuning时间:/strong>br>img srchttps://pic1.zhimg.com/80/v2-9ba0e98a1ecd826554bb1b0cd89190f0_hd.jpg altFine-tuning时间>br>数据来源:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/a>br>strong>模型推理时间:/strong>br>img srchttps://pic3.zhimg.com/80/v2-67b1d044bd7305133bf32f28dc30217a_hd.jpg alt模型推理时间>br>img srchttps://pic3.zhimg.com/80/v2-fd3a4a3a757235bd81db0d0f92223cb6_hd.jpg alt模型推理时间>br>数据来源:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/a>br>从上面的数据来看,预训练(Pre-train)要求的计算资源最大,耗时最长。自己做预训练相对较难。还好Google提供预训练模型(包括中文的预训练模型),git地址:a hrefhttps://github.com/google-research/bert target_blank relexternal>https://github.com/google-research/bert/a>br>如果,计算资源充裕,可以使用自己的语料进行预训练,从实际的项目经验反馈来看,用自己的业务相关语料进行预训练,对模型的最终效果,相对于使用Google通用的预训练模型,有小幅提升。br>Fine-tuning的计算在实际项目应用中基本可以接受,这里不做特别的深入。br>最后需要关注的就是模型推理,而这也是服务上线最需要关注的。后面我们的分析重点,也集中在如何提升BERT模型的推理效率。/p>h2 id3-BERT模型推理加速方案汇总>a href#3-BERT模型推理加速方案汇总 classheaderlink title3 BERT模型推理加速方案汇总>/a>3 BERT模型推理加速方案汇总/h2>p>BERT的模型优化方案,大概有下面几个方面:/p>h3 id3-1-编译优化>a href#3-1-编译优化 classheaderlink title3.1 编译优化>/a>3.1 编译优化/h3>p>这里的编译优化主要指计算框架自身的编译优化,以TensorFlow的XLA为例,br>img srchttps://pic4.zhimg.com/80/v2-3fb25dba91373640286cd746d2cc0d07_hd.jpg altxla编译优化>br>数据来源:a hrefhttps://www.tensorflow.org/xla target_blank relexternal>https://www.tensorflow.org/xla/a>br>从实际的数据来看,TensorFlow的XLA优化能力有限,>1.15倍。/p>h3 id3-2-知识蒸馏>a href#3-2-知识蒸馏 classheaderlink title3.2 知识蒸馏>/a>3.2 知识蒸馏/h3>p>知识蒸馏是一个不错的模型压缩方案,通过小模型(student)来学习大模型(teacher)的能力。但一般来说,通过蒸馏获得小模型,相对于原来的小模型有算法效果提升,但不能保证能完全达到大模型(teacher)的效果。br>TinyBERT就是使用了这种思路,具体可以参考paper《TinyBERT: Distilling BERT for Natural Language Understanding》/p>h3 id3-3-混合精度(Nvidia-TensorCore)>a href#3-3-混合精度(Nvidia-TensorCore) classheaderlink title3.3 混合精度(Nvidia-TensorCore)>/a>3.3 混合精度(Nvidia-TensorCore)/h3>p>一般模型的参数使用FP32(单精度)进行保存和计算。特定的计算平台,比如英伟达的P100,可以使用单个的FP32寄存器,缓存两个FP16(半精度)变量,并进行并行计算,参考《Nvidia GPU的浮点计算能力》。/p>p>同时,英伟达的瓦特架构(Tesla V100)和图灵架构(Tesla T4)有TensorCore计算单元,可以同时完成混合精度矩阵的乘加运算。具体可以参考《Video Series: Mixed-Precision Training Techniques Using Tensor Cores for Deep Learning》。/p>p>将模型中的FP32变量替换成FP16,可以有效的压缩模型大小,同时,可以提升模型的训练及推理速度。但对模型效果会不会有影响呢?答案,肯定是不会的。具体原因可以参考这篇paper《Mixed Precision Training》。br>文章主要提了三个方法:br>strong>1 FP32 MASTER COPY OF WEIGHTS/strong>br>img srchttps://pic3.zhimg.com/80/v2-069c19888f2154b37f801469bdaa8a9e_hd.jpg altFP32 MASTER COPY OF WEIGHTS>br>简单的说就是把FP32的变量先拷贝一份,然后把所有的变量都量化成FP16。在前向和反向计算时都使用FP16,只是在最后更新参数时转化为FP32。br>这样做也很好理解,更新参数时,一方面,会进行整个batch参数相加(然后取均值),转化成FP32避免向上溢出;另一方面,非常小的梯度会乘以学习率(一般<1),转化成FP32避免向下溢出。br>strong>2 LOSS SCALING/strong>br>就是计算梯度时,梯度一般都会非常小,这里将梯度先乘以一个较大的系数进行放大,避免反向传播发生下溢出,最终再除以一个相同系数进行缩小,恢复正常值,从而在FP16精度的情况下,完成计算。br>strong>3 ARITHMETIC PRECISION/strong>br>这里其实就是介绍了下英伟达的专用硬件模块TensorCore,可以同时完成混合精度的矩阵乘加运算。br>ps:这篇paper的作者来自百度和英伟达。br>在Nvidia平台上,使用混合精度也非常方便,TensorFlow直接集成了Nvidia的混合精度特性,具体操作如下:br>img srchttps://pic2.zhimg.com/80/v2-7e539f13af0ec75625a7111704a2a091_hd.jpg alt混精操作>br>参考《Automatic Mixed Precision for Deep Learning》/p>h3 id3-4-Nvidia-编译优化(TensorRT)>a href#3-4-Nvidia-编译优化(TensorRT) classheaderlink title3.4 Nvidia-编译优化(TensorRT)>/a>3.4 Nvidia-编译优化(TensorRT)/h3>p>除了TensorFlow自己的XLA优化编译之外,Nvidia推出了自己的模型编译优化方案TensorRT。XLA完成的是通用平台的模型压缩和剪枝优化编译,TensorRT更侧重跟自家平台的结合。br>在Nvidia的GPU平台上TensorRT应该比XLA有更好的优化效果。TensorRT其实是一个较大的工具体系,混合精度、模型优化编译、自定义Plugin、TensorRT Serving都是它的组成部分。所以,不要单纯的理解TensorRT只是用来做编译优化的。/p>h3 id3-5-Nvidia-Batch合并(TensorRT-Inference-Serving)>a href#3-5-Nvidia-Batch合并(TensorRT-Inference-Serving) classheaderlink title3.5 Nvidia-Batch合并(TensorRT Inference Serving)>/a>3.5 Nvidia-Batch合并(TensorRT Inference Serving)/h3>p>Batch合并操作充分利用了计算平台并行计算的能力。假设有8个请求,一种方式是每个请求顺序发给模型,然后,串行获取结果;另一种是8个请求合并成一个batch请求模型,然后,并行获取结果。在GPU这样的并行计算平台,后者的计算效率更高。br>TensorRT Inference Serving就是利用这个特点,在可容忍的时间相应时间内,尽量合并请求,进行batch处理,从而,提升服务的吞吐量。这是BERT模型在TensorRT Inference Serving的表现:br>img srchttps://pic1.zhimg.com/80/v2-bd4fd2a6273989bce2094bd4c6560760_hd.jpg altInference Serving的表现>br>数据来源:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/a>br>使用TensorRT Inference Serving后,服务的吞吐量有明显的提升。/p>h3 id3-6-Nvidia-自定义Plugin(TensorRT)>a href#3-6-Nvidia-自定义Plugin(TensorRT) classheaderlink title3.6 Nvidia-自定义Plugin(TensorRT)>/a>3.6 Nvidia-自定义Plugin(TensorRT)/h3>p>Plugin的意思是指模型中的特定计算操作。可以是重写TensorFlow中的算子(如softmax操作),也可以是自定义的矩阵乘加运算。TensorRT提供了C++和Python层的接口,可以进行自定义Plugin的编写。br>这些自定义的操作,一方面,可以充分利用Nvidia GPU的计算特性;另一方面,在网络编译优化阶段也会有更好的效果。TensorRT的具体使用可以参考《TensorRT Developer Guide》。br>这部分会是BERT性能优化最大的地方,后面的内容会围绕这一点重点展开。/p>h2 id4-BERT模型推理加速优化实践>a href#4-BERT模型推理加速优化实践 classheaderlink title4 BERT模型推理加速优化实践>/a>4 BERT模型推理加速优化实践/h2>p>Nvidia对BERT加速做了专门的工作,也获得不不错的效果,先看结果感受下:br>img srchttps://pic4.zhimg.com/80/v2-382269ae01b54d4270dc84c3462c5bdb_hd.jpg altBERT模型推理加速优化实践>br>数据来源:a hrefhttps://devblogs.nvidia.com/nlu-with-tensorrt-bert/ target_blank relexternal>https://devblogs.nvidia.com/nlu-with-tensorrt-bert//a>/p>h3 id4-1-基于TensorRT-API实现>a href#4-1-基于TensorRT-API实现 classheaderlink title4.1 基于TensorRT API实现>/a>4.1 基于TensorRT API实现/h3>p>在阅读理解任务上的响应时间压缩到了2.2ms,可见优化效果是非常明显的。英伟达开源了整个实验的数据和代码,具体可以参考《Real-Time Natural Language Understanding with BERT Using TensorRT》br>基本思路是:br>1 Fine-tuning获得的TensorFlow的ckpt模型(如果需要开启混合精度能力,需要在Fine-tuning步骤完成,建议直接使用英伟达修改过的BERT模型,参考《DeepLearningExamples/TensorFlow/LanguageModeling/BERT》)br>2 使用TensorRT重新实现BERT,主要是Transformer部分(可以理解自定义了很多Plugin),同时,也包含任务相关的部分代码(如分类任务和阅读理解任务的实现是不同的)br>3 使用TensorRT接口加载ckpt模型文件并获取参数br>4 将参数输入给重新实现的BERT网络br>5 优化编译并输出优化后的模型文件(TensorRT-engine文件)br>6 加载TensorRT-engine文件,并进行推理br>文中的示例只提供了阅读理解的实现,如果是分类问题,需要自己使用TensorRT API编写Transformer输出后,任务相关的代码,并对其参数。这里需要熟悉TensorRT的API,操作起来比较麻烦。/p>h3 id4-2-基于Fast-Transformer实现>a href#4-2-基于Fast-Transformer实现 classheaderlink title4.2 基于Fast Transformer实现>/a>4.2 基于Fast Transformer实现/h3>p>如果先看了《Real-Time Natural Language Understanding with BERT Using TensorRT》这篇文章,并尝试文中的方法进行分类分类任务。再看到基于Fast Transformer的方案,肯定觉得自己走了弯路(PS,我就是这样,汗~)。br>BERT的核心是Transformer,Nvidia很贴心的把Transformer(主要是Encoder)以组件的形式进行了加速优化,并作为单独的开源项目发布(实现原理和上面一致)。项目参考《Faster Transformer》br>简单来说,就是编写推理服务时,还是继续使用TensorFlow,只是其中的Google默认实现的Transformer被Nvidia换成了自己的定制实现模块。Transformer之外的部分原封不动。这样就既实现了BERT的计算加速,又保证了使用的灵活性。效果还是蛮不错的:br>img srchttps://pic4.zhimg.com/80/v2-44bf23e1ad85a509c3dc585103aee94b_hd.jpg altfast-transformer优化效果>br>数据来源:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/blob/master/FasterTransformer/sample/tensorflow_bert/sample.md target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/blob/master/FasterTransformer/sample/tensorflow_bert/sample.md/a>br>这里多说一句,后面Nvidia会开源Fast Transformer 2.0,核心就是实现了Transformer的Decoder。br>另外,TensorRT和Fast Transformer Nvidia有专门的在线研讨会(虽然过期了,但可以回看),这里推荐两个,《利用 TensorRT 自由搭建高性能推理模型》,《Faster Transformer 介绍》/p>h2 id总结>a href#总结 classheaderlink title总结>/a>总结/h2>p>本文介绍了BERT的基本情况,面临的上线问题,以及加速优化的各种方案及原理。最后提出了基于Fast Transformer的通用加速方案。/p>h2 id资料参考>a href#资料参考 classheaderlink title资料参考>/a>资料参考/h2>p>《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》:a hrefhttps://arxiv.org/abs/1810.04805 target_blank relexternal>https://arxiv.org/abs/1810.04805/a>/p>p>《Attention Is All You Need》:a hrefhttps://arxiv.org/abs/1706.03762 target_blank relexternal>https://arxiv.org/abs/1706.03762/a>/p>p>《The Illustrated Transformer》:a hrefhttps://jalammar.github.io/illustrated-transformer/ target_blank relexternal>https://jalammar.github.io/illustrated-transformer//a>/p>p>《The Illustrated BERT, ELMo, and co. (How NLP Cracked Transfer Learning)》:a hrefhttps://jalammar.github.io/illustrated-bert/ target_blank relexternal>https://jalammar.github.io/illustrated-bert//a>/p>p>《从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史》:a hrefhttps://zhuanlan.zhihu.com/p/49271699 target_blank relexternal>https://zhuanlan.zhihu.com/p/49271699/a>/p>p>《TinyBERT: Distilling BERT for Natural Language Understanding》:a hrefhttps://arxiv.org/abs/1909.10351 target_blank relexternal>https://arxiv.org/abs/1909.10351/a>/p>p>《Nvidia GPU的浮点计算能力》:a hrefhttps://weibo.com/ttarticle/p/show?id2309403987017473113077 target_blank relexternal>https://weibo.com/ttarticle/p/show?id2309403987017473113077/a>/p>p>《Video Series: Mixed-Precision Training Techniques Using Tensor Cores for Deep Learning》:a hrefhttps://devblogs.nvidia.com/video-mixed-precision-techniques-tensor-cores-deep-learning/?ncidso-twi-dplgdrd3-73821 target_blank relexternal>https://devblogs.nvidia.com/video-mixed-precision-techniques-tensor-cores-deep-learning/?ncidso-twi-dplgdrd3-73821/a>/p>p>《Mixed Precision Training》:a hrefhttps://arxiv.org/abs/1710.03740 target_blank relexternal>https://arxiv.org/abs/1710.03740/a>/p>p>《Automatic Mixed Precision for Deep Learning》:a hrefhttps://developer.nvidia.com/automatic-mixed-precision target_blank relexternal>https://developer.nvidia.com/automatic-mixed-precision/a>/p>p>《TensorRT Developer Guide》:a hrefhttps://docs.nvidia.com/deeplearning/sdk/tensorrt-developer-guide/index.html#extending target_blank relexternal>https://docs.nvidia.com/deeplearning/sdk/tensorrt-developer-guide/index.html#extending/a>/p>p>《NVIDIA/tensorrt-inference-server》:a hrefhttps://github.com/NVIDIA/tensorrt-inference-server target_blank relexternal>https://github.com/NVIDIA/tensorrt-inference-server/a>/p>p>《Real-Time Natural Language Understanding with BERT Using TensorRT》:a hrefhttps://devblogs.nvidia.com/nlu-with-tensorrt-bert/ target_blank relexternal>https://devblogs.nvidia.com/nlu-with-tensorrt-bert//a>/p>p>《Faster Transformer》:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer/a>/p>p>《利用 TensorRT 自由搭建高性能推理模型》:a hrefhttps://info.nvidia.com/223020-ondemand.html target_blank relexternal>https://info.nvidia.com/223020-ondemand.html/a>/p>p>《Faster Transformer 介绍》:a hrefhttps://mudu.tv/watch/3737641?key502dfd75f66e66a8d5e4621c0887f617&expire600 target_blank relexternal>https://mudu.tv/watch/3737641?key502dfd75f66e66a8d5e4621c0887f617&expire600/a>/p>p>《DeepLearningExamples/TensorFlow/LanguageModeling/BERT》:a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT target_blank relexternal>https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/a>/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/10/13/混合精度对模型训练和推理的影响/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/10/13/混合精度对模型训练和推理的影响/ itempropurl> 混合精度对模型训练和推理的影响 /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-10-13T11:36:42+08:00> 2019-10-13 /time> /span> /div> /header> div classpost-body itemproparticleBody> h2 id单精度-双精度-半精度-混合精度>a href#单精度-双精度-半精度-混合精度 classheaderlink title单精度/双精度/半精度/混合精度>/a>单精度/双精度/半精度/混合精度/h2>p>计算机使用0/1来标识信息,每个0或每个1代表一个bit。信息一般会以下面的三种形式表示:/p>p>strong>1 字符串/strong>/p>p>字符串的最小单元是char,每个char占8个bit,也就是1个byte。比如字符串“abc”这三个字符组成的串占用的存储空间:/p>pre>code>存储空间1x33(bytes)24(bits)/code>/pre>p>strong>2 整数/strong>/p>p>整数包括INT4、INT8、INT16、INT32、INT64,INT后面的数值表示该整数类型占用的byte个数。/p>p>strong>3 浮点数/strong>/p>p>浮点数包括Float16、Float32、Float64,同样,Float后面的数字表示该浮点型占用byte的个数。而这三种浮点数又有个不同的名字:/p>ul>li>半精度浮点数:Float16/li>li>单精度浮点数:Float32/li>li>双精度浮点数:Float64/li>/ul>p>有了上面单精度、双精度、混合精度三种形式的解释,混合精度就很好理解了。就是计算中存在不同精度的浮点数,比如:/p>pre>code>Float16+Float32/code>/pre>h2 id混合精度的优点>a href#混合精度的优点 classheaderlink title混合精度的优点>/a>混合精度的优点/h2>p>先说结论:/p>p>strong>压缩模型大小/strong>/p>p>我们一般模型训练使用的是Float32,那换成混合精度有什么好处呢?为了更好理解,我们将Float32的模型参数都换成Float16. 在参数数目不变的情况下,将Float32的参数都更换成Float16后,模型占用的内存就变成了之前的一半。所以,混合精度最直观的优点就是能够压缩模型的大小。/p>p>前面为了好理解,将Float32全都转成了Float16,但在实际的模型训练中,Float16因为能表示的精度有限,会导致数据溢出(超出能表示的范围),所以,只能部分操作用Float16,部分操作用Float32.最终导致混合精度的提出。/p>p>混合精度比较经典的论文是这篇:/p>p>a hrefhttps://arxiv.org/abs/1710.03740 target_blank relexternal>《Mixed Precision Training》/a>/p>p>论文介绍了混合精度在模型训练中的方法,并在多个训练场景中证实,混合精度相对于完全Float32的模型的参数训练,最终的算法效果影响不大。/p>h2 id混合精度对模型训练和推理速度的影响>a href#混合精度对模型训练和推理速度的影响 classheaderlink title混合精度对模型训练和推理速度的影响>/a>混合精度对模型训练和推理速度的影响/h2>p>先说结论:/p>p>strong>理论上没有提升,反而会下降。但在结合计算平台特性,训练和推理速度会有提升/strong>/p>p>理论上混合精度只能压缩模型的大小,在训练阶段和推理阶段,都能能大大缓解CPU内存或GPU显存限制对模型训练压力。/p>p>因为模型结构和参数数量没有发生显著的变化(忽略混合精度对模型训练,参数更新的影响),理论上训练和推理速度应该不会有大的改变。而且,因为不同的精度需要进行对齐再运算(计算时,先将不同的精度转变成统一的精度后,再进行计算),返回导致计算效率降低,从而会导致训练和推理的速度降低。/p>p>但实际上计算平台对这种特殊的计算场景一般都有专门的硬件计算加速,比如:/p>p>strong>1 具备专用的半精度计算单元/strong>/p>p>GPU针对Float16、Float32运算,都有专门的计算单元。/p>p>strong>2 单精度支持两个半精度计算同时进行/strong>/p>p>比如,英伟达的GPU Tesla P100支持在一个Float32里同时进行2次Float16的半精度浮点计算,所以对于半精度的理论峰值可以达到单精度浮点数计算能力的两倍。/p>p>strong>3 TensorCore/strong>/p>p>英伟达的瓦特(如Tesla V100)和图灵架构(如Tesla T4)都具备TensorCore单元,能完成单指令的混合精度矩阵乘加运算。/p>h2 id混合精度的实际表现>a href#混合精度的实际表现 classheaderlink title混合精度的实际表现>/a>混合精度的实际表现/h2>p>我们以英伟达开源的BERT评测对比下:/p>p>模型训练:br>img srchttps://pic3.zhimg.com/80/v2-e3691b971598d9cc0df3904508b0938a_hd.jpg altBERT模型训练>/p>p>模型推理:br>img srchttps://pic3.zhimg.com/80/v2-7981642c61dba53d1f29731995b69242_hd.jpg altBERT模型推理>/p>h2 id总结>a href#总结 classheaderlink title总结>/a>总结/h2>p>混合精度可以明显的对模型的大小进行压缩(内存占用),同时,针对优化的计算平台,在模型训练和推理的速度方面也都有提升。/p>p>参考文档:/p>p>a hrefhttps://weibo.com/ttarticle/p/show?id2309403987017473113077 target_blank relexternal>《Nvidia GPU的浮点计算能力》/a>/p>p>a hrefhttps://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT target_blank relexternal>《Nvidia BERT评测》/a>/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/03/29/TensorFlow-GPU开发环境搭建/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/03/29/TensorFlow-GPU开发环境搭建/ itempropurl> TensorFlow GPU开发环境搭建 /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-03-29T23:27:14+08:00> 2019-03-29 /time> /span> /div> /header> div classpost-body itemproparticleBody> p>由于图片外链被禁止了,图片不能显示,完整文章看这里吧:a hrefhttps://zhuanlan.zhihu.com/p/60924644 target_blank relexternal>https://zhuanlan.zhihu.com/p/60924644/a>/p>p>TensorFlow有CPU版本和GPU版本之分,CPU版本安装相对简单,按着TensorFlow的官方文档进行安装即可。但CPU版本只能使用CPU进行计算,计算效率低。对于简单的模型计算可以使用CPU模式,但对于复杂的模型训练就需要GPU的支持了。/p>h2 idGPU版本安装方式>a href#GPU版本安装方式 classheaderlink titleGPU版本安装方式>/a>GPU版本安装方式/h2>p>TensorFlow的GPU版本有两种安装方式:br>strong>源码编译安装/strong>br>这种方式灵活性最强,但这种方式不但会涉及TensorFlow GPU版本计算框架的依赖,还会牵扯到源码编译的工具依赖和库依赖。如果不是有特别的需要,不建议采用这种安装方式。br>strong>二进制安装包安装/strong>br>针对大多数的使用场景,直接使用编译好的二进制安装包进行安装即可,操作相对简单,依赖也比较少。本文主要针对二进制安装包的方式进行安装。/p>h2 id二进制安装包安装方式选择>a href#二进制安装包安装方式选择 classheaderlink title二进制安装包安装方式选择>/a>二进制安装包安装方式选择/h2>p>strong>参考TensorFlow官方文档/strong>br>TensorFlow官方文档提供了基于命令方式的安装模式。但实际上,文档提供的安装命令更多是一种参考,而不是针对所有显卡和硬件环境都可以适用的,傻瓜式解决方案。或者说,直接按照TensorFlow的官网提供命令进行安装,多半会出现问题。br>strong>自定义安装/strong>br>TensorFlow CPU版本和GPU版本最大的不同在于它们依赖的硬件平台,CPU版本的硬件依赖比较低,甚至可以粗糙的认为对硬件没有特别的要求(桌面或工作站处理器,大多是基于X86计算架构的)。GPU则不同,即便大家目前使用的GPU卡大多是Nvidia的,但Nvidia不同的显卡系列的计算能力和对TensorFlow的支持也是不一样的。所以有必要针对自己实际的GPU显卡,配置与之相对应的运行环境,最终满足TensorFlow GPU版本的运行要求。/p>h2 idTensorFlow-GPU版本的运行依赖>a href#TensorFlow-GPU版本的运行依赖 classheaderlink titleTensorFlow GPU版本的运行依赖>/a>TensorFlow GPU版本的运行依赖/h2>p>GPU版本的TensorFlow运行依赖并不复杂,从底层到上层,依赖关系如下图所示:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-e64598fdad6c2325.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt运行依赖>/p>p>strong>显卡/strong>br>目前深度学习使用的主流GPU大多是Nvidia的显卡。而大家常用的是GeForce系列和Tesla系列。从Nvidia的角度,GeForce系列定位在游戏市场,Tesla系列定位在数据中心。但实际上从经济考虑,很多公司都使用GeForce做模型训练,然后使用Tesla做线上服务(Nvidia禁止公司使用Tesla系列之外的显卡作为数据中心)。br>strong>驱动/strong>br>驱动运行在系统的内核态,是操作系统的一部分,直接跟显卡硬件打交道,是应用层和硬件打交道的门户。不同的显卡需要不同的驱动。br>strong>CUDA/strong>br>CUDA运行在系统的应用层,对通用GPU计算操作做了封装,方便其他组件调用。br>strong>cuDNN/strong>br>cuDNN依赖CUDA库,封装了常用的深度学习方法,供更上层的组件调用。br>strong>TensorFlow GPU版本要求/strong>br>不同版本的TensorFlow,对运行环境是有不同的要求。驱动版本的选择,主要依赖于显卡型号。而CUDA、cuDNN、Python版本的选择,则需要依赖TensorFlow GPU版本的选择:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-726584ec5bee3647.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt依赖版本>br>参考:a hrefhttps://www.tensorflow.org/install/source target_blank relexternal>https://www.tensorflow.org/install/source/a>/p>p>在有了显卡之后,后面需要做的,就是从下到上,安装对应版本的驱动、CUDA库、cuDNN库、Python和TensorFlow了。/p>h2 id具体环境搭建步骤>a href#具体环境搭建步骤 classheaderlink title具体环境搭建步骤>/a>具体环境搭建步骤/h2>p>下面我们以超微的GPU工作站为例,逐步搭建TensorFlow GPU开发环境。br>strong>系统环境/strong>/p>ul>li>GTX 1080TI 四卡/li>li>Ubuntu 16.04/li>li>目标:TensorFlow GPU 1.10.0版本/li>/ul>p>strong>(一)驱动安装/strong>br>驱动选择地址:a hrefhttps://www.nvidia.com/Download/index.aspx?langen-us target_blank relexternal>https://www.nvidia.com/Download/index.aspx?langen-us/a>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-7d32ed5c819f8dc7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt驱动选择>br>最终,会下载得到xxx.run的安装文件,直接使用shell安装,/p>pre>code># sudo sh xxx.run/code>/pre>p>strong>(二)CUDA安装/strong>br>下载地址:a hrefhttps://developer.nvidia.com/cuda-zone target_blank relexternal>https://developer.nvidia.com/cuda-zone/a>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-4af061cba4cfd665.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt最新CUDA>br>我们需要安装的TensorFlow GPU版本为1.10.0,所以CUDA的版本是9。但直接打开是最新版本的CUDA。可以选择上面的“Legacy Releases”,然后,选择需要的版本,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-1dcf34269d5c370f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt对应版本CUDA>br>最终,会下载得到xxx.run的安装文件,直接使用shell命令进行安装,/p>pre>code># sudo sh xxx.run/code>/pre>p>strong>(三)CUDNN安装/strong>br>下载地址(需要注册):a hrefhttps://developer.nvidia.com/cudnn target_blank relexternal>https://developer.nvidia.com/cudnn/a>br>cuDNN主要和CUDA版本对齐,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-b0030c20943724b2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altcuDNN>br>cuDNN主要下载两个文件,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-6933e5f4e092925b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt两个文件>br>下载的两个xxx.deb文件,通过dpkg -i命令进行安装,/p>pre>code># dpkg -i xxx.deb/code>/pre>p>strong>(四)Python安装/strong>br>Python可以采用Anaconda环境,具体的安装步骤就不详细展开了,工作中选择了Python3.6版本。只提两点:br>strong>全局环境变量设置/strong>br>Anaconda默认会将环境变量设置到~/.bashrc文件中。如果想全局可见,可以手动在/etc/profile文件中添加环境变量。br>strong>使用清华的下载链接/strong>br>Anaconda的官方下载,国内下载速度很慢,可以直接使用清华的源。br>地址:a hrefhttps://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ target_blank relexternal>https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive//a>br>strong>(五)TensorFlow GPU安装/strong>br>TensorFlow安装先对简单,直接使用pip命令进行安装即可,但低于1.13.0版本的TensorFlow GPU版本,不能直接使用“pip install tensorflow-gupxxx”来安装。需要手动下载安装文件,然后进行安装。br>TensorFlow GPU历史版本下载地址:a hrefhttps://pypi.org/project/tensorflow-gpu/ target_blank relexternal>https://pypi.org/project/tensorflow-gpu//a>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-8e91236a94f8f8a5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt历史版本>br>TensorFlow GPU也可以使用清华的源,但源更新的可能不够及时:br>清华TensorFlow GPU地址:a hrefhttps://mirrors.tuna.tsinghua.edu.cn/help/tensorflow/ target_blank relexternal>https://mirrors.tuna.tsinghua.edu.cn/help/tensorflow//a>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-8d5ccc9b25aba2f3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt清华地址>/p>h2 id小结>a href#小结 classheaderlink title小结>/a>小结/h2>p>TensorFlow的GPU版本安装,本身并不复杂。关键是要梳理清楚不同组件的依赖关系。不同组件之间没有特别的强依赖,如果发现其中的某个组件有问题,单独卸载和重装即可。/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/03/02/《从零开始学习自然语言处理-NLP-》-DeepPavlov框架解析(4)/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/03/02/《从零开始学习自然语言处理-NLP-》-DeepPavlov框架解析(4)/ itempropurl> 《从零开始学习自然语言处理(NLP)》-DeepPavlov框架解析(4) /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-03-02T19:49:19+08:00> 2019-03-02 /time> /span> /div> /header> div classpost-body itemproparticleBody> p>由于图片外链被禁止了,图片不能显示,完整文章看这里吧:a hrefhttps://zhuanlan.zhihu.com/p/58133705 target_blank relexternal>https://zhuanlan.zhihu.com/p/58133705/a>/p>h2 id写在最前面>a href#写在最前面 classheaderlink title写在最前面>/a>写在最前面/h2>p>在这个日新月异的信息时代,海量数据的积累,计算能力的不断提升,机器学习尤其是深度学习的蓬勃发展,使得人工智能技术在不同领域焕发出蓬勃的活力。自己经历了嵌入式开发,移动互联网开发,目前从事自然语言处理算法开发工作。从工程软件开发到自然语言处理算法开发,希望通过这个系列的文章,能够由浅入深,通俗易懂的介绍自然语言处理的领域知识,分享自己的成长,同大家一起进步。/p>h2 id问题描述>a href#问题描述 classheaderlink title问题描述>/a>问题描述/h2>p>在上一篇《从零开始学习自然语言处理(NLP)-NLP Framework开源方案梳理(3)》中梳理了目前流行的NLP开源框架,这里重点介绍下DeepPavlov框架。DeepPavlov框架的模型实用性很强,对实际的生产开发有很大的借鉴意义。/p>h2 id框架组成>a href#框架组成 classheaderlink title框架组成>/a>框架组成/h2>p>DeepPavlov是一个基于TensorFlow和Keras的,专门针对对话系统研究和实验部署的自然语言处理框架。br>项目地址:a hrefhttp://docs.deeppavlov.ai/en/master/# target_blank relexternal>http://docs.deeppavlov.ai/en/master/#/a>br>框架主要包括:br>strong>常用的NLP模型(包括Pre-train模型)/strong>br>如词向量训练、分类、命名实体识别(NER)、相似度计算等;br>strong>针对对话系统实现和评测的实验框架(Framework)/strong>br>基于Json文件进行开发流程和数据流pipeline配置;br>strong>提供同第三方应用进行集成的工具/strong>br>如与Amazon Alexa和Microsoft Bot Framework的集成;br>strong>为对话模型的评测提供Benchmark环境/strong>br>DeepPavlov的默认Pre-train模型和测评数据集主要基于英文和俄文,对于中文场景需要做适当的调整。/p>h2 id框架使用对象>a href#框架使用对象 classheaderlink title框架使用对象>/a>框架使用对象/h2>p>strong>新模型开发者/strong>br>方便同已有Benchmark模型进行对比评测br>strong>普通NLP任务处理者/strong>br>如针对内容审核任务,敏感信息增加掩码等任务,可以直接使用框架提供的分类和序列标注模型,完成业务服务的快速开发和测评;br>strong>对话系统开发者/strong>br>DeepPavlov是为对话系统场景量身定制的。对话系统开发者,可以直接参考使用;br>strong>对话系统应用开发者/strong>br>DeepPavlov框架为应用集成提供了专门的工具,可以直接与Amazon Alexa,Microsoft Bot Framework等平台进行对接。/p>h2 id框架使用>a href#框架使用 classheaderlink title框架使用>/a>框架使用/h2>p>strong>规范开发流程/strong>br>框架将数据模型服务的开发和验证流程(如数据清洗、模型设计、模型训练、模型选优、模型评测),使用Json配置文件串联成pipeline。能够很好的规范开发流程;br>strong>新模型对比评测/strong>br>为对话模型的评测提供Benchmark环境,方便新模型的对比评测。但环境主要基于英文和俄文,对于中文任务,需要重新训练对比;br>strong>常用NLP模型使用/strong>br>框架内置了很多常用模型(以分类为例,就包含了cnn_model,bilstm_model,bilstm_attention_model,transformer_model等12种模型实现),在项目中可以直接使用;br>同时框架提供了Pre-train模型,但主要是基于英文和俄文的,对于中文场景需要自己进行重新训练;br>strong>对话系统开发/strong>br>DeepPavlov是为对话系统场景量身定制的,对话系统开发者,可以直接参考使用;/p>h2 idDeepPavlov框架层次>a href#DeepPavlov框架层次 classheaderlink titleDeepPavlov框架层次>/a>DeepPavlov框架层次/h2>p>DeepPavlov从整体到局部,可分为如下三个层次:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-f4c0014e182c870b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altDeepPavlov框架层次>br>下面我们从外层到内层,逐层介绍DeepPavlov的框架设计。/p>h2 idDeepPavlov顶层框架>a href#DeepPavlov顶层框架 classheaderlink titleDeepPavlov顶层框架>/a>DeepPavlov顶层框架/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-c0f6ca8cbb1f27c8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altDeepPavlov框架>br>strong>Agent/strong>br>同用户直接交互的代理,直接接收用户输入的纯文本信息(raw text)br>strong>Skill/strong>br>领域技能,如基于意图-词槽的任务型技能,基于Seq2Seq的闲聊技能,基于知识图谱的知识问答技能;br>strong>Skill Manager/strong>br>确定用户query,选择使用哪些skill,并确定将哪一个skill的召回结果作为最终的回复;br>strong>Component/strong>br>Skill实现的组成部分,如针对任务型技能,包括数据预处理component、意图识别component、slotfilling component等;br>strong>Chainer/strong>br>Chainer以Json配置文件的形式,将某个skill相关的所有component串联起来;br>strong>Data Storage/strong>br>框架本身包含的Pre-train模型和Benchmark评测数据集/p>h2 idSkill框架>a href#Skill框架 classheaderlink titleSkill框架>/a>Skill框架/h2>p>DeepPavlov内置的skill主要包括:br>strong>任务型skill(Goal-Oriented Dialogue Bot)/strong>br>基于意图/词槽/对话管理等component实现的问答skill。br>img srchttps://upload-images.jianshu.io/upload_images/4905018-aa3877cb08461905.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt任务型skill>br>strong>阅读理解skill(Open-Domain Question Answering)/strong>br>基于阅读理解实现问答skill。相对于阅读理解component(Context Question Answering),skill还包含在多个召回结果中进行排序的能力。br>strong>规则型skill(Pattern Matching)/strong>br>基于自定义规则实现问答skill。br>strong>Seq2Seq skill(Sequence-To-Sequence Dialogue Bot)/strong>br>基于Seq2Seq实现问答skill。br>img srchttps://upload-images.jianshu.io/upload_images/4905018-20ec116fa7907873.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altSeq2Seq skill>br>strong>常见问题问答skill(Frequently Asked Questions Answering)/strong>br>先将句子嵌入为向量(使用词向量叠加),然后做分类处理(给每一个answer一个打分),选取打分最高的answer作为最终回复的skill。br>strong>商品查询skill(eCommerce Bot)/strong>br>商品查询回复skill,支持多轮(添加过滤条件)。下面是场景示例,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-99c0ebb7de6cc02f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt商品查询skill>/p>h2 id基本能力框架>a href#基本能力框架 classheaderlink title基本能力框架>/a>基本能力框架/h2>p>DeepPavlov内置的基本能力主要包括:br>strong>数据预处理component(Data processors)/strong>br>主要提供包括分词、嵌入向量化等预处理能力(主要基于俄文和英文)。br>strong>阅读理解component(Context Question Answering)/strong>br>相对于阅读理解skill(Open-Domain Question Answering),component不包含对多个召回结果进行排序(rank)的能力。具体的处理场景示例如下,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-b5316fe0884017ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt阅读理解component>br>strong>分类component(Classification)/strong>br>分类组件,可以用来做场景和意图的分类。br>strong>Morphological Tagger component/strong>br>一种特殊的POS?br>strong>命名实体识别component(Named Entity Recognition)/strong>br>NER能力组件。br>strong>相似度计算component(Neural Ranking)/strong>br>通过基于孪生网络完成相似度计算,实现在标准问答库中标准答复的查找。br>strong>词槽填充component(Slot filling)/strong>br>在NER的基础上,增加了词表限制。br>strong>*拼写纠错component(Spelling Correction)/strong>br>提供了两种纠错方法:/p>ul>li>levenshtein_corrector :基于编辑距离/li>li>brillmoore:基于统计模型/li>/ul>p>strong>TF-IDF排序component(TF-IDF Ranking)/strong>br>基于TF-IDF的文档召回排序。br>strong>流行度排序component(Popularity Ranking)/strong>br>将TF-IDF打分和流行度打分作为特征,通过逻辑回归计算流行度,最终实现排序。/p>h2 idJson配置文件解析>a href#Json配置文件解析 classheaderlink titleJson配置文件解析>/a>Json配置文件解析/h2>p>DeepPavlov通过Json配置文件实现开发流程控制和数据流pipeline的控制。br>上面提到DeepPavlov主要分为Agent、Skill和Component三个层次。而Json配置文件主要应用在Skill和Component这两个层面。而对Agent的控制,框架通过直接的代码来实现,例如,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-35bbd3ed436a7545.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altagent>br>其中,br>strong>skills/strong>br>Agent支持的所有skill列表;br>strong>skills_filter/strong>br>针对用户query,确定Agent使用哪些skill;br>strong>skills_filter/strong>br>通过召回的不同skill结果,确定最后的回复内容给用户;br>下面我们具体的介绍下Json配置文件的具体结构。/p>h2 idJson配置文件结构>a href#Json配置文件结构 classheaderlink titleJson配置文件结构>/a>Json配置文件结构/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-6f83f4dcefee7713.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altJson配置文件结构>br>如上图所示,Json配置文件主要由如下五个部分组成(参考分类component):br>strong>dataset_reader/strong>br>主要负责数据的读取。br>img srchttps://upload-images.jianshu.io/upload_images/4905018-ba0d381b6d858e97.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altdataset_reader>br>strong>dataset_iterator/strong>br>数据迭代器,从dataset_reader中获得数据,然后按batch抽取数据,供后面的模型训练使用。br>img srchttps://upload-images.jianshu.io/upload_images/4905018-0e61711decf24e69.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altdataset_iterator>br>strong>chainer/strong>br>配置文件的核心,将数据预处理、模型选优和模型预测输出,通过pipeline(”pipe”字段内进行约束)的形式串联起来。/p>pre>code>"chainer": {"in": "x","in_y": "y","pipe": { "id": "classes_vocab", "class_name": "simple_vocab", "fit_on": "y" , "save_path": "{MODELS_PATH}/classifiers/{PROJECT_NAME}_{MODEL_NAME}/classes.dict", "load_path": "{MODELS_PATH}/classifiers/{PROJECT_NAME}_{MODEL_NAME}/classes.dict", "in": "y", "out": "y_ids" }, { "in": "x", "out": "x_tok", "id": "my_tokenizer", "class_name": "char_tokenizer", "tokenizer": "char_tokenizer" }, { "in": "x_tok", "out": "x_ids", "id": "seq_to_emb_ids", "class_name": "seq_to_emb_ids", "emb_file_path":"{EMBED_PATH}", "text_size":250 }, { "in": "y_ids", "out": "y_onehot", "class_name": "one_hotter", "id": "my_one_hotter", "single_vector": true, "depth": "#classes_vocab.len" }, { "in": "x_ids" , "fit_on_batch_preprocess": "x_ids", "y_onehot" , "out": "y_pred_probas" , "main": true, "class_name": "keras_classifier_model", "graph_metrics": "multilabel_f1", "save_path": "{MODELS_PATH}/classifiers/{PROJECT_NAME}_{MODEL_NAME}/model", "load_path": "{MODELS_PATH}/classifiers/{PROJECT_NAME}_{MODEL_NAME}/model", "n_classes": "#classes_vocab.len", "train_emb": false, "kernel_sizes_cnn": 1, 2, 3, 4, 5 , "filters_cnn": 512, "optimizer": "Adam", "learning_rate": 0.001, "learning_rate_decay": 0.9, "loss": "categorical_crossentropy", "embedding_matrix": "#seq_to_emb_ids.matrix", "text_size": 250, "last_layer_activation": "softmax", "coef_reg_cnn": 0.0, "coef_reg_den": 0.0, "dropout_rate": 0.5, "dense_size": 30, "model_name": "cnn_model" }, { "in": "y_pred_probas", "out": "y_pred_ids", "class_name": "proba2labels", "max_proba": true }, { "in": "y_pred_ids", "out": "y_pred_onehot", "ref": "my_one_hotter" }, { "in": "y_pred_ids", "out": "y_pred_labels", "ref": "classes_vocab" },"out": "y_pred_ids", "y_pred_onehot", "y_pred_labels", "y_pred_probas"},/code>/pre>p>官方文档中,将“pipe”字段内的每一对花括号({})中的内容成为一个component(注意这里的component和上面提到的框架component是不同的。为了方便区分,我们将”pipe”中的component标识为pipe-component)。br>strong>train/strong>br>模型训练、模型选优和评测配置。/p>pre>code>"train": {"epochs": 10,"batch_size": 256,"metrics": { "name": "cal_confusion_matrix", "inputs": "y", "y_pred_labels" }, { "name": "f1_micro", "inputs": "y", "y_pred_labels" }, { "name": "recall_micro", "inputs": "y_ids", "y_pred_ids" }, { "name": "precision_micro", "inputs": "y_onehot", "y_pred_onehot" }, { "name": "f1_macro", "inputs": "y_onehot", "y_pred_onehot" }, { "name": "precision_macro", "inputs": "y", "y_pred_labels" }, { "name": "recall_macro", "inputs": "y_ids", "y_pred_ids" }, { "name": "recall_group", "inputs": "y_onehot", "y_pred_onehot" }, { "name": "precision_group", "inputs": "y", "y_pred_labels" }, { "name": "f1_group", "inputs": "y_ids", "y_pred_ids" },"validation_patience": 5,"val_every_n_epochs": 1,"log_every_n_epochs": 1,"show_examples": true,"validate_best": true,"test_best": true,"report_path": "{MODELS_PATH}/classifiers/{PROJECT_NAME}_{MODEL_NAME}/report.xlsx"},/code>/pre>p>其中,br>“metric”字段中排在最前面的指标,作为模型选优的标准。br>strong>metadata/strong>br>相关相关的常量配置。br>img srchttps://upload-images.jianshu.io/upload_images/4905018-4b3fafd2b9128a17.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altmetadata>br>其中,”imports”是DeepPavlov框架之外自定义实现。/p>h2 idDeepPavlov存在的问题>a href#DeepPavlov存在的问题 classheaderlink titleDeepPavlov存在的问题>/a>DeepPavlov存在的问题/h2>p>strong>环境依赖/strong>br>DeepPavlov是基于TensorFlow和Keras实现的,不能继承其他计算框架的模型实现(如PyTorch)。br>strong>语言支持/strong>br>Pre-train模型和评测数据集主要基于英文和俄文,不支持中文。br>strong>生产环境部署/strong>br>DeepPavlov在运行时需要依赖整个框架源码,开发环境对框架修改后,生产环境需要更新整个框架。同时,也不能直接将功能Component作为服务独立导出,不适合在生产环境的部署和发布。/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/02/24/《TensorFlow内核剖析》笔记/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/02/24/《TensorFlow内核剖析》笔记/ itempropurl> 《TensorFlow内核剖析》笔记 /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-02-24T19:40:33+08:00> 2019-02-24 /time> /span> /div> /header> div classpost-body itemproparticleBody> p>由于图片外链被禁止了,图片不能显示,完整文章看这里吧:a hrefhttps://zhuanlan.zhihu.com/p/57559407 target_blank relexternal>https://zhuanlan.zhihu.com/p/57559407/a>/p>p>市面上对TensorFlow使用介绍的书非常之多,但剖析原理的却很少。如果对TensorFlow的底层实现感兴趣,刘光聪的《TensorFlow内核剖析》是一个不错的选择。同时,这是一本开源技术书,可以免费获得。/p>h2 idDistBelife框架>a href#DistBelife框架 classheaderlink titleDistBelife框架>/a>DistBelife框架/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-4353758491c42988.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altDistBelife框架>/p>h2 idDistBelief缺点>a href#DistBelief缺点 classheaderlink titleDistBelief缺点>/a>DistBelief缺点/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-8e7217b17816c5f1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altDistBelief缺点>/p>h2 idTensorFlow设计原则>a href#TensorFlow设计原则 classheaderlink titleTensorFlow设计原则>/a>TensorFlow设计原则/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-61167f0c483ebef2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altTensorFlow设计原则>/p>h2 idTensorFlow优势>a href#TensorFlow优势 classheaderlink titleTensorFlow优势>/a>TensorFlow优势/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-b5274b1e0a620542.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altTensorFlow优势>/p>h2 idTensorFlow里程碑>a href#TensorFlow里程碑 classheaderlink titleTensorFlow里程碑>/a>TensorFlow里程碑/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-5a1f4453b8c12fbf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altTensorFlow里程碑>/p>h2 idTensorFlow技术栈>a href#TensorFlow技术栈 classheaderlink titleTensorFlow技术栈>/a>TensorFlow技术栈/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-fc46239d6f9e5447.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altTensorFlow技术栈>/p>h2 idTensorFlow系统架构>a href#TensorFlow系统架构 classheaderlink titleTensorFlow系统架构>/a>TensorFlow系统架构/h2>p>strong>TensorFlow系统架构/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-64be0bebce3b0fea.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altTensorFlow系统架构>br>strong>说明/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-b9adaaea3bf849d0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt说明>br>strong>Client/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-9edbf4350c1eb435.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altClient>br>strong>Master/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-3a4a8f95f10fbdd8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altMaster>br>strong>Worker/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-a9d3670a01be4c17.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altWorker>br>strong>Kernel/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-0d571744e78612d5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altKernel>/p>h2 id集群组建>a href#集群组建 classheaderlink title集群组建>/a>集群组建/h2>p>img srchttps://upload-images.jianshu.io/upload_images/4905018-fc9adc70dba88bf6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt集群组建>/p>h2 id本地模式>a href#本地模式 classheaderlink title本地模式>/a>本地模式/h2>p>strong>本地模式/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-7fbc67ed7ad2c16e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt本地模式>br>strong>本地模式:图操作/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-19beefd44fa712ac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt本地模式:图操作>/p>h2 id分布式模式>a href#分布式模式 classheaderlink title分布式模式>/a>分布式模式/h2>p>strong>分布式模式/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-8421bbe8a067bf2f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt分布式模式>br>strong>分布式模式-图操作/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-078e3463fda1933b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt分布式模式-图操作>br>strong>PS与Worker/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-30a2d980b9f325ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altPS与Worker>br>strong>服务互联/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-889d5c03ed5237d7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt服务互联>br>strong>单Client接入集群/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-1cb2f9c97633ede4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt单Client接入集群>br>strong>多Client接入集群/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-2361f428ce897631.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt多Client接入集群>br>strong>会话协同/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-533b782f7bbf85fa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt会话协同>br>strong>会话控制领域模型/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-7a2cfa2712dc4900.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt会话控制领域模型>br>strong>获取远端设备集/strong>br>img srchttps://upload-images.jianshu.io/upload_images/4905018-550f9faaa2881cdb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt获取远端设备集>/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/02/01/《从零开始学习自然语言处理-NLP-》-NLP-Framework开源方案梳理-3/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/02/01/《从零开始学习自然语言处理-NLP-》-NLP-Framework开源方案梳理-3/ itempropurl> 《从零开始学习自然语言处理(NLP)》-NLP Framework开源方案梳理(3) /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-02-01T21:20:16+08:00> 2019-02-01 /time> /span> /div> /header> div classpost-body itemproparticleBody> p>由于图片外链被禁止了,图片不能显示,完整文章看这里吧:a hrefhttps://zhuanlan.zhihu.com/p/56159591 target_blank relexternal>https://zhuanlan.zhihu.com/p/56159591/a>/p>h2 id写在最前面>a href#写在最前面 classheaderlink title写在最前面>/a>写在最前面/h2>p>在这个日新月异的信息时代,海量数据的积累,计算能力的不断提升,机器学习尤其是深度学习的蓬勃发展,使得人工智能技术在不同领域焕发出蓬勃的活力。自己经历了嵌入式开发,移动互联网开发,目前从事自然语言处理算法开发工作。从工程软件开发到自然语言处理算法开发,希望通过这个系列的文章,能够由浅入深,通俗易懂的介绍自然语言处理的领域知识,分享自己的成长,同大家一起进步。/p>h2 id问题描述>a href#问题描述 classheaderlink title问题描述>/a>问题描述/h2>p>新的项目开启时,一般会经历如下的流程:/p>ul>li>业务需求梳理/li>li>算法方案选择/li>li>模型实现:选择开源方案,或自己实现/li>li>模型训练:数据清洗、模型训练(使用训练集)/li>li>最优模型选择:依据验证集结果,选择最优模型/li>li>模型评测:依据测试集结果,对模型进行评测/li>li>模型优化:本模型调优,或选择新的模型/li>li>模型服务上线/li>/ul>p>而在实际的项目开发中,存在如下的问题:br>strong>1模型实现问题/strong>br>模型实现一般会选择开源方案,或自己编码实现。自己编码实现开发和调试成本高。直接选择开源方案,会面临开发环境不统一,编译问题,代码结果和可靠性难以保证等问题;br>strong>2模型训练和评测问题/strong>br>该阶段会设计到数据清洗,输入读入,数据迭代器设计,数据预处理,词向量训练与准备,分词,文本转索引,br>标签ont-hot表示,训练集/验证集/测试集划分,训练过程最优模型选择,模型评测(准确度A、精确度P、召回率R、F1值等),数据分析(结果分析,混淆矩阵分析,ROC/AUC分析),Tensorboard结果查看等。由于该部分设计的流程和步骤较多,自己编码开发和调试工作量大,而开源方案很多步骤和组件并不全面。br>strong>3 模型优化问题/strong>br>除了在现有模型的基础上进行局部优化外,还会选择新的模型。如果选择新的模型,则会重新自己编码实现或选择开源方案,会再次经历前面提到的问题1(模型实现问题)和问题2(模型训练和评测问题)。br>strong>4 模型服务上线问题/strong>br>模型服务上线,同模型的训练和预测和类似,但又不完全相同。模型上线需要和模型训练一样的预处理,词向量,分词,文本转索引等步骤,但不需要模型的测评。同时,模型上线要求只能包含模型的训练文件,br>而不能包括模型的代码。通常需要编写专门的代码用于模型服务上线。br>一般来说,针对上面的问题,公司都会有一个统一的NLP算法框架,br>strong>一方面,统一模型的实现、评测和上线流程/strong>br>strong>另一方面,框架自身包含很多现成的模型,便于业务在算法落地方面的快速验证/strong>br>大多数公司并不开源自己的NLP算法框架,但开源社区NLP开源框架还是蛮多的,这里做一个统一的梳理。/p>h2 id针对对话系统的Framework>a href#针对对话系统的Framework classheaderlink title针对对话系统的Framework>/a>针对对话系统的Framework/h2>h3 id1-DeepPavlov>a href#1-DeepPavlov classheaderlink title1 DeepPavlov>/a>1 DeepPavlov/h3>p>运行依赖:TensorFlow/Kerasbr>支持功能:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-ffa015c3e2212104.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt支持功能>br>项目地址:br>a hrefhttps://github.com/deepmipt/DeepPavlov target_blank relexternal>https://github.com/deepmipt/DeepPavlov/a>/p>h3 id2-ParlAI>a href#2-ParlAI classheaderlink title2 ParlAI>/a>2 ParlAI/h3>p>运行依赖:Pytorchbr>支持功能:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-31a1018b9a6dc7bf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt支持功能>br>项目地址:a hrefhttps://github.com/facebookresearch/ParlAI target_blank relexternal>https://github.com/facebookresearch/ParlAI/a>/p>h3 id3-Rasa>a href#3-Rasa classheaderlink title3 Rasa>/a>3 Rasa/h3>p>运行依赖:Pythonbr>支持功能:纯任务型对话br>项目地址:a hrefhttps://www.rasa.com/ target_blank relexternal>https://www.rasa.com//a>/p>h3 id4-OpenDial>a href#4-OpenDial classheaderlink title4 OpenDial>/a>4 OpenDial/h3>p>运行依赖:Javabr>支持功能:对话系统br>描述:主要基于传统方法,深度网络较少涉及。br>项目地址:a hrefhttps://github.com/plison/opendial target_blank relexternal>https://github.com/plison/opendial/a>/p>h2 id通用NLP-Framework>a href#通用NLP-Framework classheaderlink title通用NLP Framework>/a>通用NLP Framework/h2>h3 id1-Intel-NLP-Architect>a href#1-Intel-NLP-Architect classheaderlink title1 Intel NLP-Architect>/a>1 Intel NLP-Architect/h3>p>运行依赖:TensorFlowbr>支持功能:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-3869c6d90607bcf2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt支持功能>br>项目地址:a hrefhttp://nlp_architect.nervanasys.com/ target_blank relexternal>http://nlp_architect.nervanasys.com//a>/p>h3 id2-AllenNLP>a href#2-AllenNLP classheaderlink title2 AllenNLP>/a>2 AllenNLP/h3>p>运行依赖:Pytorchbr>支持功能:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-19871ec0e38c2f3a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt支持功能>br>项目地址:br>a hrefhttps://allennlp.org/ target_blank relexternal>https://allennlp.org//a>/p>h3 id3-PyText>a href#3-PyText classheaderlink title3 PyText>/a>3 PyText/h3>p>运行依赖:Pytorchbr>支持功能:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-658f4db3cb09b08d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt支持功能>br>项目地址:br>a hrefhttps://pytext-pytext.readthedocs-hosted.com/en/latest/ target_blank relexternal>https://pytext-pytext.readthedocs-hosted.com/en/latest/#/a>/p>h2 idNLP基础依赖组件项目(提供pre-train模型)>a href#NLP基础依赖组件项目(提供pre-train模型) classheaderlink titleNLP基础依赖组件项目(提供pre-train模型)>/a>NLP基础依赖组件项目(提供pre-train模型)/h2>h3 id1-Stanford-CoreNLP>a href#1-Stanford-CoreNLP classheaderlink title1 Stanford CoreNLP>/a>1 Stanford CoreNLP/h3>p>运行依赖:Javabr>支持功能:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-e62c769d3804da3e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt支持功能>br>项目地址:br>a hrefhttps://stanfordnlp.github.io/CoreNLP/index.html target_blank relexternal>https://stanfordnlp.github.io/CoreNLP/index.html/a>/p>h3 id2-Stanford-NLP>a href#2-Stanford-NLP classheaderlink title2 Stanford NLP>/a>2 Stanford NLP/h3>p>运行依赖:Pytorchbr>支持功能:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-84ece0293bf62370.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt支持功能>br>项目地址:br>a hrefhttps://stanfordnlp.github.io/stanfordnlp/tokenize.html target_blank relexternal>https://stanfordnlp.github.io/stanfordnlp/tokenize.html/a>/p>h3 id3-spaCy>a href#3-spaCy classheaderlink title3 spaCy>/a>3 spaCy/h3>p>运行依赖:Pythonbr>支持功能:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-b05fe1a8edb066c2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt支持功能>br>项目地址:br>a hrefhttps://spacy.io/ target_blank relexternal>https://spacy.io//a>/p>h2 id小结>a href#小结 classheaderlink title小结>/a>小结/h2>p>本文梳理了实际的业务算法落地开发过程,并提出了其中存在的问题,和解决方案。对当前开源的NLP框架做了整理,可以依据自身的需要开发自己的NLP算法框架,规范开发流程,提升业务落地效率。同时,也可以直接从开源方案中获取自己需求的算法实现模块。后续有新的开源框架方案,会持续整理进来。/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/02/01/深度学习的高阶数学/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/02/01/深度学习的高阶数学/ itempropurl> 深度学习的高阶数学 /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-02-01T21:18:03+08:00> 2019-02-01 /time> /span> /div> /header> div classpost-body itemproparticleBody> p>由于图片外链被禁止了,图片不能显示,完整文章看这里吧:a hrefhttps://zhuanlan.zhihu.com/p/56159815 target_blank relexternal>https://zhuanlan.zhihu.com/p/56159815/a>/p>p>有了基础的《概率/统计》、《线性代数》、《微积分》知识,就可以上手深度学习的算法和实践了。但经过一段时间的工程实践,慢慢觉得大多数时间都用在选模型,调超参,或者是网络结构的排列组合上。深度学习的黑盒特性越来越明显。难道深度学习工程师就当真是数据“炼丹师”吗?br>如果,你有了这样的感觉,下面的视频不妨抽时间看看(都需要翻墙):/p>h2 id李宏毅《Machine-Learning-and-having-it-deep-and-structured》>a href#李宏毅《Machine-Learning-and-having-it-deep-and-structured》 classheaderlink title李宏毅《Machine Learning and having it deep and structured》>/a>李宏毅《Machine Learning and having it deep and structured》/h2>p>不多说,直接看目录吧。br>课程地址:a hrefhttp://speech.ee.ntu.edu.tw/~tlkagk/courses_MLDS18.html target_blank relexternal>http://speech.ee.ntu.edu.tw/~tlkagk/courses_MLDS18.html/a>br>strong>《Theory 1 - Why Deep Structure》/strong>br> a hrefhttps://www.youtube.com/watch?vKKT2VkTdFyc&featureyoutu.be target_blank relexternal>Can shallow network fit any function/a>br> a hrefhttps://www.youtube.com/watch?vFN8jclCrqY0&featureyoutu.be target_blank relexternal>Potential of Deep/a>br> a hrefhttps://www.youtube.com/watch?vqpuLxXrHQB4&featureyoutu.be target_blank relexternal>Is Deep better than Shallow/a>br>strong>《Theory 2 - Optimization》/strong>br> a hrefhttps://www.youtube.com/watch?vXSdkBG6Vvr0&featureyoutu.be target_blank relexternal>When Gradient is Zero/a>br> a hrefhttps://www.youtube.com/watch?v0O6nYRC7GeY&featureyoutu.be target_blank relexternal>Deep Linear Network/a>br> a hrefhttps://www.youtube.com/watch?vNmelPQkUark&featureyoutu.be target_blank relexternal>Does Deep Network have Local Minima/a>br> a hrefhttps://www.youtube.com/watch?v_VuWvQUMQVk&featureyoutu.be target_blank relexternal>Geometry of Loss Surfaces (Conjecture)/a>br> a hrefhttps://www.youtube.com/watch?vXysGHdNOTbg&featureyoutu.be target_blank relexternal>Geometry of Loss Surfaces (Empirical)/a>br>strong>《Theory 3 - Generalization 》/strong>br> a hrefhttps://www.youtube.com/watch?v9dtxv4HLq_8&featureyoutu.be target_blank relexternal>Capability of Generalization/a>br> a hrefhttps://www.youtube.com/watch?vpivB5jEBOQw&featureyoutu.be target_blank relexternal>Indicator of Generalization/a>/p>h2 idSanjeev-Arora《The-mathematics-of-machine-learning-and-deep-learning》>a href#Sanjeev-Arora《The-mathematics-of-machine-learning-and-deep-learning》 classheaderlink titleSanjeev Arora《The mathematics of machine learning and deep learning》>/a>Sanjeev Arora《The mathematics of machine learning and deep learning》/h2>p>视频地址:a hrefhttps://www.youtube.com/watch?vr07Sofj_puQ target_blank relexternal>https://www.youtube.com/watch?vr07Sofj_puQ/a>br>这是ICM2018的主题演讲,虽然Sanjeev Arora作为普林斯顿计算机科学的教授,但演讲内容深入浅出,并没有涉及大量的数学公式和推导,这里贴一下提纲:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-7d5ed8e29ad63030.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt内容提纲>/p>h2 id小结>a href#小结 classheaderlink title小结>/a>小结/h2>p>这两部分的内容是相互呼应的,可以先看李宏毅老师的课程,然后在看Sanjeev Arora教授的分享总结。/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/01/27/《从零开始学习自然语言处理-NLP-》-TF-IDF算法-2/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/01/27/《从零开始学习自然语言处理-NLP-》-TF-IDF算法-2/ itempropurl> 《从零开始学习自然语言处理(NLP)》-TF-IDF算法(2) /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-01-27T21:16:59+08:00> 2019-01-27 /time> /span> /div> /header> div classpost-body itemproparticleBody> p>由于图片外链被禁止了,图片不能显示,完整文章看这里吧:a hrefhttps://zhuanlan.zhihu.com/p/55843621 target_blank relexternal>https://zhuanlan.zhihu.com/p/55843621/a>/p>h1 id写在最前面>a href#写在最前面 classheaderlink title写在最前面>/a>写在最前面/h1>p>在这个日新月异的信息时代,海量数据的积累,计算能力的不断提升,机器学习尤其是深度学习的蓬勃发展,使得人工智能技术在不同领域焕发出蓬勃的活力。自己经历了嵌入式开发,移动互联网开发,目前从事自然语言处理算法开发工作。从工程软件开发到自然语言处理算法开发,希望通过这个系列的文章,能够由浅入深,通俗易懂的介绍自然语言处理的领域知识,分享自己的成长,同大家一起进步。/p>h1 id问题描述>a href#问题描述 classheaderlink title问题描述>/a>问题描述/h1>p>在上一篇文章中(a hrefhttps://zhuanlan.zhihu.com/p/55296265 target_blank relexternal>《《从零开始学习自然语言处理(NLP)》-倒排索引(1)》/a>)描述了基于关键词搜索的基本原理,以及通过倒排索引来提升和关键词相关网页的查询。本文在上文的基础上提出一个新的问题:br>如果通过倒排索引查找到的网页都包含strong>全部的/strong>查询关键字,而且,召回(符合查找条件)的网页数目又很多,这就需要将网页与查询Query的相关度进行排序了。相关度高的网页排在查询结果的前面,相关度低的网页排在后面。那问题来了,如何依据网页与查询关键词的相关性对召回的网页做排序呢?/p>h1 id基于TF(Term-Frequency,词频)进行排序>a href#基于TF(Term-Frequency,词频)进行排序 classheaderlink title基于TF(Term Frequency,词频)进行排序>/a>基于TF(Term Frequency,词频)进行排序/h1>p>最容易想到的便是基于词频打分进行排序,具体来说,对于查询Query:“林俊杰/2019/演唱会/行程”,下面的哪个网页跟查询Query的相关度更高呢?br>strong>网页a/strong>/p>pre>code>林俊杰/2019/全球/演唱会/行程/发布/,/这是/林俊杰/的/第/20/场/全球/巡演/。/code>/pre>table>thead>tr>th>关键字/th>th>出现频次/th>/tr>/thead>tbody>tr>td>林俊杰/td>td>2/td>/tr>tr>td>2019/td>td>1/td>/tr>tr>td>演唱会/td>td>1/td>/tr>tr>td>行程/td>td>1/td>/tr>/tbody>/table>p>strong>网页b/strong>/p>pre>code>在 林俊杰/2019/全球/演唱会/行程/发布/之后/,/田馥甄/也/发布/了/今年/的/巡演/计划/,/她的/第一站/是/台北/。/code>/pre>table>thead>tr>th>关键字/th>th>出现频次/th>/tr>/thead>tbody>tr>td>林俊杰/td>td>1/td>/tr>tr>td>2019/td>td>1/td>/tr>tr>td>演唱会/td>td>1/td>/tr>tr>td>行程/td>td>1/td>/tr>/tbody>/table>p>显然网页a和Query的相关度更高。当然对于计算机就没有这么“显然”了,它需要依靠规则和具体算法来计算判断。基于词频的排序用公式表示就是,br> img srchttps://upload-images.jianshu.io/upload_images/4905018-2166358dc8c2fbae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt相关性计算>br>其中,br>k:Query中查询关键词序号br>img srchttps://upload-images.jianshu.io/upload_images/4905018-8c341c80a496862e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt参数说明>/p>p>为了方便计算,我们假设每个网页包含的词的总数为100,通过上面的公式,br>strong>网页a/strong>/p>pre>code>网页a相关度2/100+1/100+1/100+1/1000.05/code>/pre>p>strong>网页b/strong>/p>pre>code>网页b相关度1/100+1/100+1/100+1/1000.04/code>/pre>p>通过上面的公式,计算机也能“显然”的判断,网页a与查询Query的相关度更高了。/p>h1 id基于TF排序的问题>a href#基于TF排序的问题 classheaderlink title基于TF排序的问题>/a>基于TF排序的问题/h1>p>假设现在有新的召回网页,br>strong>网页c/strong>/p>pre>code>在 林俊杰/2019/全球/演唱会/行程/发布/之后/,/众多/明星/也/都/发布/了/自己/2019年/的/巡演/计划/,/行程/安排/如下/,/code>/pre>table>thead>tr>th>关键字/th>th>出现频次/th>/tr>/thead>tbody>tr>td>林俊杰/td>td>1/td>/tr>tr>td>2019/td>td>2/td>/tr>tr>td>演唱会/td>td>1/td>/tr>tr>td>行程/td>td>2/td>/tr>/tbody>/table>pre>code>网页c相关度1/100+2/100+1/100+2/1000.06/code>/pre>p>显然基于词频的相关性计算公式,网页c(相关度0.06)大于网页a(相关度0.05),但真实情况是,网页c和查询Query的相关度,并没有网页a大。/p>h1 idIDF(Inverse-DocumentFrequency,逆文件词频)>a href#IDF(Inverse-DocumentFrequency,逆文件词频) classheaderlink titleIDF(Inverse DocumentFrequency,逆文件词频)>/a>IDF(Inverse DocumentFrequency,逆文件词频)/h1>p>上面的问题关键在于用户的查询Query主要关注的是”strong>林俊杰/strong>“,至于”strong>2019/strong>“,”strong>行程/strong>“等信息也是在strong>林俊杰/strong>的基础上展开的。所以,现在要解决的问题便是,排序算法如何能够凸显出”strong>林俊杰/strong>“这个关键的查询信息。在这里便引入了IDF(Inverse DocumentFrequency,逆文件词频)。br>我们先看下它的定义:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-7e6f8bbd74473dc1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altIDF定义>br>其中,br>分母的+1操作,是为了避免当所有文档都不包含该关键词时,分母出现为0的情况。br>IDF的分子是固定的,所以,IDF的特性主要体现在分母上。br>从IDF的定义可以看出,br>strong>1 越是能代表特定内容的关键词,包含该关键词的网页越少,IDF值越高,如“林俊杰”/strong>br>strong>2 越是和内容主旨不相关的关键词,包含该关键词的网页越多,IDF值越低,如“2019”,“行程”/strong>br>所以,IDF值就能很好的体现出查询Query关键字,与需要查询内容的相关性。/p>h1 id基于TF-IDF进行排序>a href#基于TF-IDF进行排序 classheaderlink title基于TF-IDF进行排序>/a>基于TF-IDF进行排序/h1>p>结合TF和IDF的特定,便有了TF-IDF,定义也非常直观,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-ad1332e689276ef9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 altTF-IDF>br>具体来说就是,一个网页与查询Query的相关性体现在:br>strong>1 网页中包含查询关键词的频度/strong>br>strong>2 查询关键词对查询内容的反映程度/strong>br>基于TF-IDF,网页与查询Query的相关性,改写为,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-de1a33712251872a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt相关性定义>br>其中,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-db90ca37a0c4ec6a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt参数说明>br>在实际工程中,TF和IDF值,以及TF-IDF值针对于具体网页是提前计算好的,当搜索系统接收到用户的查询Query后,能够实时计算查询关键词与网页的相关度。/p>h1 id小结>a href#小结 classheaderlink title小结>/a>小结/h1>p>本文沿用了a hrefhttps://zhuanlan.zhihu.com/p/55296265 target_blank relexternal>《《从零开始学习自然语言处理(NLP)》-倒排索引(1)》/a>中搜索的例子,提出了在网页包含所有查询关键词的情况下,如何对网页与查询Query的相关性进行排序。文中提出了基于TF的相关性排序方法,同时,也指出了该方法存在的问题。最终,引出TF-IDF算法:结合查询关键词在网页中的出现频率和该关键词反映查询内容程度两个特征,对召回网页进行排序。/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> article classpost post-type-normal itemscope itemtypehttp://schema.org/Article> link itempropmainEntityOfPage hrefhttp://yoursite.com/2019/01/20/《从零开始学习自然语言处理-NLP-》-倒排索引-1/> span hidden itempropauthor itemscope itemtypehttp://schema.org/Person> meta itempropname contentLiu Caiquan> meta itempropdescription content> meta itempropimage content/images/avatar.gif> /span> span hidden itemproppublisher itemscope itemtypehttp://schema.org/Organization> meta itempropname content才权的博客> /span> header classpost-header> h1 classpost-title itempropname headline> a classpost-title-link href/2019/01/20/《从零开始学习自然语言处理-NLP-》-倒排索引-1/ itempropurl> 《从零开始学习自然语言处理(NLP)》-倒排索引(1) /a> /h1> div classpost-meta> span classpost-time> span classpost-meta-item-icon> i classfa fa-calendar-o>/i> /span> span classpost-meta-item-text>发表于/span> time title创建于 itempropdateCreated datePublished datetime2019-01-20T11:09:47+08:00> 2019-01-20 /time> /span> /div> /header> div classpost-body itemproparticleBody> p>由于图片外链被禁止了,图片不能显示,完整文章看这里吧:a hrefhttps://zhuanlan.zhihu.com/p/55296265 target_blank relexternal>https://zhuanlan.zhihu.com/p/55296265/a>/p>h1 id写在最前面>a href#写在最前面 classheaderlink title写在最前面>/a>写在最前面/h1>p>在这个日新月异的信息时代,海量数据的积累,计算能力的不断提升,机器学习尤其是深度学习的蓬勃发展,使得人工智能技术在不同领域焕发出蓬勃的活力。自己经历了嵌入式开发,移动互联网开发,目前从事自然语言处理算法开发工作。从工程软件开发到自然语言处理算法开发,希望通过这个系列的文章,能够由浅入深,通俗易懂的介绍自然语言处理的领域知识,分享自己的成长,同大家一起进步。/p>h1 id问题描述>a href#问题描述 classheaderlink title问题描述>/a>问题描述/h1>p>倒排索引是搜索引擎的基础算法,在本文中我们以一个简单的例子来详细介绍倒排索引的思想和实现。br>假设用户有个搜索query:“林俊杰2019演唱会行程”。百度的搜索结果如下:br>img srchttps://upload-images.jianshu.io/upload_images/4905018-25e46b27de0ebfdd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt百度搜索结果>br>如果要求你来设计一个搜索引擎,来解决这个问题,你会如何着手呢?/p>h1 id问题简化>a href#问题简化 classheaderlink title问题简化>/a>问题简化/h1>p>现在我们把这个问题具体化。我们除了有要查询的query:“林俊杰2019演唱会行程”。还有被查询的网页数据库。这里我们做个简化,假设我们的网页数据库内容只有如下4条:br>strong>网页1:/strong>/p>pre>code>2019年,JJ林俊杰全球演唱会在北京首场演出,行程如下xxxxxxx;/code>/pre>p>strong>网页2:/strong>/p>pre>code>林俊杰,吴亦凡终于同框合影 ,惹粉丝们尖叫连连,xxxxx;/code>/pre>p>strong>网页3:/strong>/p>pre>code>蔡依林2019世界演唱会行程全曝光,xxxxx;/code>/pre>p>strong>网页4:/strong>/p>pre>code>告别2018,迎接崭新的2019,xxxxxx;/code>/pre>p>简单来说,就是从网页1~4中选取最理想的查询结果。你会怎么做呢?/p>h1 id关键词匹配>a href#关键词匹配 classheaderlink title关键词匹配>/a>关键词匹配/h1>p>最容易想到的方法就是关键词匹配了,简单的来说,就是网页中包含查询的关键词越多,网页和查询query的相关度也就越大。br>在做关键词查询前,一般文本会先进行预处理。这里的预处理主要包括去停用词和分词。br>strong>去停用词/strong>br>去除和查询不相关的内容,比如本例子中的标点符号。在其他场景中,除了标点符号也会去除一些特别的字或词。br>strong>分词/strong>br>分词主要目的是将句子切长短语或关键字,这样才利于查询匹配。比如“林俊杰2019演唱会行程”可以分词成,/p>pre>code>林俊杰/2019/演唱会/行程/code>/pre>p>当然网页也需要这样进行分词:br>strong>网页1:/strong>/p>pre>code>2019/年/JJ/林俊杰/全球/演唱会/在/北京/首场/演出/行程/如下/xxxxxxx/code>/pre>p>strong>网页2:/strong>/p>pre>code>林俊杰/吴亦凡/终于/同框/合影 /惹/粉丝们/尖叫/连连/xxxxx/code>/pre>p>strong>网页3:/strong>/p>pre>code>蔡依林/2019/世界/演唱会/行程/全曝光/xxxxx/code>/pre>p>strong>网页4:/strong>/p>pre>code>告别/2018/迎接/崭新/的/2019/xxxxxx;/code>/pre>p>分词是一项专门的技术,在实际工程中可以至今借助工具来完成,比如a hrefhttps://github.com/fxsjy/jieba target_blank relexternal>jieba分词/a>。br>分词处理后,我们用查询query中的关键词在网页数据库中进行关键词匹配,并统计匹配数目:/p>table>thead>tr>th>网页序号/th>th>匹配关键词/th>th>匹配个数/th>/tr>/thead>tbody>tr>td>网页1/td>td>2019,林俊杰,演唱会,行程/td>td>4/td>/tr>tr>td>网页2/td>td>林俊杰/td>td>1/td>/tr>tr>td>网页3/td>td>2019,演唱会,行程/td>td>3/td>/tr>tr>td>网页4/td>td>2019/td>td>1/td>/tr>/tbody>/table>p>从“匹配个数”中很容易确定,网页1就是和查询query最匹配的网页。/p>h1 id倒排索引>a href#倒排索引 classheaderlink title倒排索引>/a>倒排索引/h1>p>讲到这里大家可能会疑问,这和倒排索引有什么关系?实际上,如果仔细考虑上面的关键词查询过程,会发现这种方法有个很大的效率问题:我们的例子中只有4个待查询的网页,而实际的互联网世界的网页数目是非常巨大的。假设互联网世界的网页数据为N,那么使用关键词查询的时间复杂度就是O(N),显然,这样的时间复杂度还是太大了,而倒排索引就很好的优化了这个问题。br>从倒排索引这个名字很容易联想出它的实现,关键就是“倒排”的“索引”。在前面的讲解中,我们的索引(key)是网页,内容(value)是关键字。倒排索引就是反过来:内容关键字作为索引(key),所在网页作为内容(value)。前面的表格就可以改写成,/p>table>thead>tr>th>关键词/th>th>包含关键词的网页/th>/tr>/thead>tbody>tr>td>林俊杰/td>td>网页1,网页2/td>/tr>tr>td>2019/td>td>网页1,网页3,网页4/td>/tr>tr>td>演唱会/td>td>网页1,网页3,/td>/tr>tr>td>行程/td>td>网页1,网页3/td>/tr>/tbody>/table>p>通过上面的表格,很明显网页1是包含最多关键词的网页,也是和查询query相关度最高的网页。采用倒排索引的方法,搜索的时间复杂度得到了明显的降低。/p>h1 id搜索引擎框架>a href#搜索引擎框架 classheaderlink title搜索引擎框架>/a>搜索引擎框架/h1>p>有了倒排索引的知识,我们就可以搭建简单的搜索引擎了,br>img srchttps://upload-images.jianshu.io/upload_images/4905018-0cc45397fced1b35.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 alt搜索引擎框架>br>具体步骤包括:br>strong>网页抓取/strong>br>主要是借助网络爬虫,来抓取网络世界的所有网页,并进行存储。网络爬虫是一项专门的技术,目前工程上也有很多现成的开源工具。br>strong>倒排索引生成/strong>br>将抓取后的网页经过预处理后,整理生成倒排索引。br>strong>用户在线查询/strong>br>借助倒排索引,搜索引擎能够满足用户的实时在线查询。br>前两个步骤是不用考虑实时性的,可以离线进行,而用户的在线查询则需要保证实时性。/p>h1 id小结>a href#小结 classheaderlink title小结>/a>小结/h1>p>本文通过一个搜索查询的例子,引出关键词查询的方案,及遇到的问题。进而介绍了倒排索引的原理,和搜索引擎的整体框架。现代搜索引擎是一个非常庞大和复杂的系统工程,这里的例子只是为了方便大家理解做了特别的简化。文中提到的分词和网络爬虫也是专门的文本处理技术,在后续的文章后,会根据需要专门展开。/p> /div> div> /div> div> /div> div> /div> footer classpost-footer> div classpost-eof>/div> /footer> /article> /section> nav classpagination> span classpage-number current>1/span>a classpage-number href/page/2/>2/a>span classspace>…/span>a classpage-number href/page/8/>8/a>a classextend next relnext href/page/2/>i classfa fa-angle-right>/i>/a> /nav> /div> /div> div classsidebar-toggle> div classsidebar-toggle-line-wrap> span classsidebar-toggle-line sidebar-toggle-line-first>/span> span classsidebar-toggle-line sidebar-toggle-line-middle>/span> span classsidebar-toggle-line sidebar-toggle-line-last>/span> /div> /div> aside idsidebar classsidebar> div classsidebar-inner> section classsite-overview sidebar-panel sidebar-panel-active> div classsite-author motion-element itempropauthor itemscope itemtypehttp://schema.org/Person> img classsite-author-image itempropimage src/images/avatar.gif altLiu Caiquan /> p classsite-author-name itempropname>Liu Caiquan/p> p classsite-description motion-element itempropdescription>/p> /div> nav classsite-state motion-element> div classsite-state-item site-state-posts> a href/archives> span classsite-state-item-count>71/span> span classsite-state-item-name>日志/span> /a> /div> div classsite-state-item site-state-tags> a href/tags/index.html> span classsite-state-item-count>11/span> span classsite-state-item-name>标签/span> /a> /div> /nav> div classlinks-of-author motion-element> /div> /section> /div> /aside> /div> /main> footer idfooter classfooter> div classfooter-inner> div classcopyright > © span itempropcopyrightYear>2019/span> span classwith-love> i classfa fa-heart>/i> /span> span classauthor itempropcopyrightHolder>Liu Caiquan/span>/div>div classpowered-by> 由 a classtheme-link hrefhttps://hexo.io>Hexo/a> 强力驱动/div>div classtheme-info> 主题 - a classtheme-link hrefhttps://github.com/iissnan/hexo-theme-next> NexT.Mist /a>/div>div>script async src//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js>/script>span idbusuanzi_container_site_pv>本站总访问量span idbusuanzi_value_site_pv>/span>次/span>/div> /div> /footer> div classback-to-top> i classfa fa-arrow-up>/i> /div> /div> script typetext/javascript> if (Object.prototype.toString.call(window.Promise) ! object Function) { window.Promise null; }/script> script typetext/javascript src/lib/jquery/index.js?v2.1.3>/script> script typetext/javascript src/lib/fastclick/lib/fastclick.min.js?v1.0.6>/script> script typetext/javascript src/lib/jquery_lazyload/jquery.lazyload.js?v1.9.7>/script> script typetext/javascript src/lib/velocity/velocity.min.js?v1.2.1>/script> script typetext/javascript src/lib/velocity/velocity.ui.min.js?v1.2.1>/script> script typetext/javascript src/lib/fancybox/source/jquery.fancybox.pack.js?v2.1.5>/script> script typetext/javascript src/js/src/utils.js?v5.1.0>/script> script typetext/javascript src/js/src/motion.js?v5.1.0>/script> script typetext/javascript src/js/src/bootstrap.js?v5.1.0>/script> /body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]