-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.json
1 lines (1 loc) · 494 KB
/
content.json
1
{"meta":{"title":"mantch的博客","subtitle":"","description":"","author":"mantch","url":"http://reverent-montalcini-17e4bf.netlify.com","root":"/"},"pages":[{"title":"404 Not Found","date":"2019-12-24T12:13:00.541Z","updated":"2019-12-24T12:13:00.541Z","comments":true,"path":"404.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/404.html","excerpt":"","text":"404 Not Found **很抱歉,您访问的页面不存在** 可能是输入地址有误或该地址已被删除"},{"title":"Linner Regression","date":"2019-12-24T09:51:34.000Z","updated":"2019-12-24T09:51:34.035Z","comments":true,"path":"Linner-Regression/index.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/Linner-Regression/index.html","excerpt":"","text":""},{"title":"sdf","date":"2019-12-24T09:42:14.000Z","updated":"2019-12-24T09:43:07.620Z","comments":true,"path":"ML/me.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/ML/me.html","excerpt":"","text":"s地方sd飞阿斯蒂芬"},{"title":"","date":"2019-12-24T12:06:10.333Z","updated":"2019-12-24T12:06:10.333Z","comments":true,"path":"archives/index.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/archives/index.html","excerpt":"","text":""},{"title":"所有分类","date":"2019-12-24T12:02:05.757Z","updated":"2019-12-24T12:02:05.757Z","comments":true,"path":"categories/index.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/index.html","excerpt":"","text":""},{"title":"404 Not Found","date":"2019-12-25T02:50:58.781Z","updated":"2019-12-25T02:50:58.781Z","comments":true,"path":"friends/index.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/friends/index.html","excerpt":"","text":"404 Not Found **很抱歉,您访问的页面不存在** 可能是输入地址有误或该地址已被删除"},{"title":"所有标签","date":"2019-12-24T12:04:36.394Z","updated":"2019-12-24T12:04:36.394Z","comments":true,"path":"tags/index.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/tags/index.html","excerpt":"","text":""},{"title":"关于我的小站","date":"2019-07-28T02:22:12.000Z","updated":"2019-12-24T11:50:20.779Z","comments":true,"path":"about/mantch/index.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/about/mantch/index.html","excerpt":"","text":"博主:mantch 公众号:AI-Area 分享自个儿在AI、机器学习、深度学习、NLP、推荐系统等领域的所见、所闻、所思、所想。 公众号的文章都会在我的个人博客里发布,欢迎关注!好货等着你。"},{"title":"汇总&资源","date":"2019-07-28T04:30:00.000Z","updated":"2019-12-25T09:57:06.666Z","comments":true,"path":"projects/mantch/index.html","permalink":"http://reverent-montalcini-17e4bf.netlify.com/projects/mantch/index.html","excerpt":"","text":"一:项目 ML-NLP 此项目是机器学习(Machine Learning)、深度学习(Deep Learning)、NLP面试中常考到的知识点和代码实现,也是作为一个算法工程师必会的理论基础知识。 CodingInterviews2-ByPython 此项目是《剑指offer》第二版里算法面试题的Python3实现版本,作为一本经典书籍,可以时常拿出来看一看、翻一翻、记一记。同时也是为了Python程序员能够更好的通过公司的技术面试,拿到心仪的offer。 二:总结汇总机器学习 线性回归 逻辑回归 决策树 3.1 随机森林 3.2 GBDT 3.3 XGBoost 3.4 LightGBM 支持向量机(SVM) 概率图模型 5.1 贝叶斯网络 5.2 马尔可夫模型 5.3 主题模型 EM算法 聚类算法 ML特征工程和优化方法 KNN 深度学习 神经网络 卷积神经网络CNN 循环神经网络RNN 12.1 门控循环单元GRU 12.2 长短期记忆LSTM 迁移学习 强化学习 深度学习优化方法 自然语言处理 自然语言处理 16.1 词嵌入(Embedding) 16.2 fastText 16.3 GloVe 16.4 textRNN & textCNN 16.5 seq2seq 16.6 注意力机制(Attention) 16.7 Transformer模型 16.8 BERT 16.9 XLNet 16.10 智能客服 推荐系统 推荐系统 二:资源2.1 书籍 《白面机器学习》:https://www.lanzous.com/i56i24f 《剑指offer》:https://www.lanzous.com/i4ya3wd 《数学之美》第二版:https://www.lanzous.com/i3ousch 《推荐系统实战》:https://www.lanzous.com/i6362bi 《自然语言处理综论》第二版:https://www.jianguoyun.com/p/DZIKYLwQj4G5BxiZjboC 2.2 GitHub 《动手学深度学习》TF2.0版:https://github.com/TrickyGo/Dive-into-DL-TensorFlow2.0 数据竞赛top解决方案开源整理:https://github.com/Smilexuhc/Data-Competition-TopSolution 吴恩达老师的课程笔记:https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes"}],"posts":[{"title":"【NLP】智能客服","slug":"NLP/Intelligent Customer Service","date":"2019-09-29T16:00:00.000Z","updated":"2019-12-25T06:15:36.057Z","comments":true,"path":"2019/09/30/NLP/Intelligent Customer Service/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/09/30/NLP/Intelligent%20Customer%20Service/","excerpt":"我们就会产生一个想法:能不能有一个机器人来回答这些重复的问题,它能 24 小时的工作不用休息,降低客户成本,还能挖掘聊天记录里面的一些有价值的知识点。这就是智能客服产生的背景。","text":"我们就会产生一个想法:能不能有一个机器人来回答这些重复的问题,它能 24 小时的工作不用休息,降低客户成本,还能挖掘聊天记录里面的一些有价值的知识点。这就是智能客服产生的背景。 1. 智能客服系统智能客服产生的背景:为什么要有智能客服这样的一个产品,或者说研究方向呢?主要有以下这几个原因: 我们日常生活中会遇到大量的客服问题,比如说你打电话给联通、移动等,或者说在淘宝上买东西,这些问题大部分都是一些重复的问题,而且频率也特别高,非常的耗人工; 对于一个客服密集型的企业来说,大量的人工客服,造成了企业的客服成本非常的高; 人工客服是没有办法做到 24 小时全天候的服务; 在客户和客服的对话的过程中产生了大量的有价值的数据,这些数据也没有被很好的利用起来。 基于以上的这些原因,我们就会产生一个想法:能不能有一个机器人来回答这些重复的问题,它能 24 小时的工作不用休息,降低客户成本,还能挖掘聊天记录里面的一些有价值的知识点。这就是智能客服产生的背景。 1.1 智能客服的目标如果说要做一个智能客服,那做智能客服的一个基本的目标,或者说它的技术目标是要做到什么样的程度呢?它是要完全的替代人工,还是要部分的替代人工呢? 一般情况下,一个智能客服的目标就是下面这张图里描述的这些:一个客服的机器人负责回答客户的一些高频简单问题,将疑难问题交给人工客服团队来回答。那这个一定比例是多大比例呢?我这边写了一个百分之 X,也就是说这个比例不太确定,它是根据不同的场景以及不同的技术条件,不同厂商的技术能力而不同的,有的厂商是 80%,有的是 90%,有的甚至 95%,这都是不确定的。 总之智能客服做的一个技术目标就是:一定比例的解决客服的简单的高频问题,将疑难问题仍然交给人工客服团队。这是目前智能客服一个基本的技术目标,是一个比较现实的目标。那么想让客服的机器人来完全取代人工客服,这个目标到目前为止,在绝大部分场景下还是没有办法实现的。 1.2 细分领域整个智能客服系统的发展非常快,应用也划分了很多的细分领域。 第一大类是对话操作系统级别的系统。那么这一类系统比较有代表性的有亚马逊的 Alexa,这些系统都希望做操作系统级别的人机对话,就是把人机对话直接做成一个操作系统,那在这个系统上开发各种各样不同的智能硬件、软件等等这些应用。 第二大类,就是智能客服,智能客服里面又细分成两类:一类是企业内部的智能客服,为了企业自身的业务发展需要研发的智能客户系统;还有一类是对外服务的智能客服,并且以 SaaS 的方式对外服务。 第三大类就是个人助理类,最有名的就是苹果的 Siri,还有微软的 Cortana 等。智能家居现在做得比较火热的就是一些智能音箱,比如说亚马逊 Echo 等。还有些公司是做一些智能交互的服务,这些智能交互服务主要是自然语言处理和意图识别方面的服务,其他的厂商可以基于这些智能交互服务做一些自己的应用。 第四类是开放平台,这个开放平台也可以叫 Bot Factory,比较有代表性的,有 Google 的 API.AI、Facebook 的 Wit.AI、还有微软的 Luis.AI 等等。这些开放平台主要是做任务对话方面的一些定制。 1.3 智能客服常见功能智能客服系统最常见的功能有哪些?目前最常见的形式是在人工客服系统基础上,扩展出智能客服的功能,最常见的功能有 单轮问答、多轮对话和人机协作。 单轮问答:一问一答,但是没有记录上下文,每一次问答和下一次问答都没有任何的关系; 多轮对话:是带着上下文来问答,每个问答可能跟它的上文是有一定关系,或者是它记录了上文的一些信息; 人机协作:人机协作是一种比较有效的一种智能客服功能,现有的方式主要有两大类:一类是机器人加人工进行问答,另外一大类是机器人推荐答案,人工选择回答 。我们这里举几个例子:比如说上班的时候人工来回答,下班的时候机器人来回答;普通的客户机器人来回答,VIP 客户人工来回答;或者是说分渠道来选择,比如说微信渠道来的机器人回答,手机渠道来的人工回答;还有就是机器人优先,机器人答不出来,转给人工回答。 2. 智能客服的工作原理刚才我们是给智能客服做了一个概述。接下来,我们介绍一下智能客服的工作原理。一个常见的智能客服,就包括以下这些模块并且按照一个类似的流程进行工作。 识别模块:首先可能会有一个 ASR(语音识别)模块,也可能没有,这取决于具体厂商的一个选择,这个语音识别模块会把语音转换成文字。如果没有语音识别模块,直接就是文字。 意图识别:对这个文字做一个问句的理解,或者说做一个查询的理解,理解完以后,再对意图做一个识别; 机器回答:最后,我们把这个问句的理解和意图识别的结果带到对话管理系统里边,对话管理系统会决定到底是给哪一种机器人发过去,这些机器人最后给出答案,将答案返回。 对话管理系统可以选择一个机器人将问题发过去,也可以同时将问题发给所有的机器人,当它们都回复答案时,进行答案选择再返回,使用哪种方式取决于厂商自己的一个选择。上图中这四种机器人分别对应了四种不同的模块: 第一种是任务管理类的模块,比如说订机票,它属于一个特定的任务,这种机器人就类似苹果的 Siri,是任务处理类; 第二种是知识库问答,也就是咨询问答类的,只是做一些咨询类的工作,一般情况下,它并不处理实际的一些任务; 第三类是知识图谱问答,知识图谱是知识库常见的是提供一个问答对结构和一个树型结构,知识图谱提供一个图结构,可以认为是一个广义上的知识库问答。 第四类是聊天机器人的技术,聊天并不是客服的首要功能,客服主要是解决问题的,不是来聊天的,为什么在一个智能客服系统里面会有聊天这么一个功能呢?原因在于,一是在用户没有输入知识库内容的时候,这个聊天机器人会被客户当成是测试厂商机器人技术能力的评测对象;二是在某些场景下,会让整个客服对话没那么单调。 2.1 自然语言理解自然语言理解主要做一些什么事情呢?比如说用户的问题如果是多句话,那么我们做一个“分句”,对每一句话来寻找答案,最后呢,将答案组合起来,发给用户;“分词”很常见,分词后才能理解,才能进行标注,进行实体识别,这是常规的一些处理,然后就是句法分析、指代消解,再有就是词权重、语义相似度等等,做这些分析都是为后面的算法做准备,这是第一部分的预处理工作,就是自然语言理解或者自然语言处理的内容。 2.2 意图识别第二部分的预处理工作就是意图识别。意图识别主要是用户的这句话暴露了用户什么样的意图,比如说我们这个例子里:“今天天气怎么样”,这个意图实际上就是用户要问天气。那么如果用户说“帮我定一张去上海的机票”,这个意思就是用户要订机票。 那么意图识别一般是怎么实现的?就是有模板和分类器两种方式。 模板的方式,比如说:“北京今天天气怎么样?”我们会建一个叫“city”的词典,这里面会有北京、上海、天津等城市;我们会把今天、明天、后天等等也做一个词典,词典名字叫做“date”。这样如果满足刚开始有一个“city”,中间有任意字符串,然后再有一个“date”,然后再有“天气”这个词,就满足了一个模板,那么我们基本上可以认为它是一个询问天气怎么样的意图,这是模板的方法。 分类器的方法很容易理解,我们在某一个特定领域里面收集大量语料,人工去标注这些语料是属于哪种意图的,用分类器模型来做一些二分类或者多分类的分类器,用来判断意图。但是分类器方法需要大量人工标注的数据,以及如何去收集多个领域里面的语料的问题。 基于知识库的问答可以使用检索或者分类模型来实现。检索式回答的流程是:首先对用户的输入问题做处理,如分词、抽取关键词、同义词扩展、计算句子向量等;然后基于处理结果在知识库中做检索匹配,例如利用BM25、TF-IDF或者向量相似度等匹配出一个问题集合,这类似推荐系统中的召回过程; 由于我们是一个问答系统,最终是直接返回给用户一个答案,因此需要从问题集合中挑出最相似的那个问题,这里会对问题集合做重排序,例如利用规则、机器学习或者深度学习模型做排序,每个问题会被打上一个分值,最终挑选出top1,将这个问题对应的答案返回给用户,这就完成了一次对话流程。在实际应用中,我们还会设置阈值来保证回答的准确性,若最终每个问题的得分低于阈值,会将头部的几个问题以列表的形式返回给用户,最终用户可以选择他想问的问题,进而得到具体的答案。 2.3 知识库知识库问答的技术本质也是用一些跟搜索引擎相似的技术,分为两个阶段:第一个阶段是侯选集召回,第二个阶段是重排序。 首先是侯选集,侯选集召回有很多种方式,和搜索引擎相比,相对简单,原因是搜索引擎要召回的量特别的大,但是知识库,因为是人工导入的,它的召回的就没有那么复杂。 第二是重排序,其实我们可以用文本相似度、检索相关度,如果有足够数据的话,还可以用神经网络的语义相似度等,来做重排序工作。这些工作也可以用多模型融合的方式来做,将多个模型的结果综合考虑得到最终结果。这些都跟搜索引擎的技术没有特别本质的区别,也会有些微小的差别,这是知识库这块的工作。 2.4 知识图谱知识图谱(Knowledge Graph),在图书情报界称为知识域可视化或知识领域映射地图,是显示知识发展进程与结构关系的一系列各种不同的图形,用可视化技术描述知识资源及其载体,挖掘、分析、构建、绘制和显示知识及它们之间的相互联系。 知识图谱问答最难的一点在于数据的整理,其次是工具方面。有很多开源的工具,例如:Neo4j、OrientDB、Titan。 假设我们解决了数据来源和更新的问题,同时也有了工具,接下来要做的事情就是查询转换的工作。因为一般的知识图谱工具都会有一些自己的查询语言,那么我们所要做的工作实际上就是把自然语言通过某种方式转换成知识图谱的工具所支持的查询语言。 查询转换也有常见的两种方式,一种是可以用模板,做一些查询转换的工作。 2.5 对话技术对话技术就是我们前面所说的任务对话等等,比较典型的有三大类: 第一大类是一种用状态机,或者和状态机类似的填槽方式。这种方式的主要特点是将整个的对话过程抽象成一个有限状态机,每一轮对话,或者每几轮作为一种状态,随着对话状态的进行,这个状态机在不断的迁移,最终对话结束,状态机也结束。这里面的所有状态,以及所要执行的动作都是事先约定好的,所以状态机它比较适合一些场景简单的对话,对于场景复杂的对话,状态机这种方式就已经不太适应了。 第二大类就是马可夫决策过程(Markov Decision Process, MDP)的方式,它和状态机的区别在于它里面增加了动作,状态机里面的动作是我们事先约定好的,是固定的动作,已经事先知道对话到了那时候,于是就固定的采取这样的动作,但是 MDP 这种方式,状态不确定,动作也不确定,所以说我的状态和动作是需要根据我的上一个状态和将要采用的动作做了以后的回馈(Reward)来进行决策的,所以说这个决策过程在特定领域里有足够的语料的时候可以做出很好的效果,但是我们得想办法去找到合适的领域,以及找到足够的语料才能做这样的事情。 最后一类是端到端的模型。端到端的模型主要出发点是:我有一个问题,把问题输入到一个模型里面之后,这个模型是帮我解决了我们之前整个对话过程所有流程的所有问题,而这个模型是需要从数据里面去学习,包括自然语言处理、意图识别,包括整个系统里面方方面面的各种东西都要学习到。这个模型对于我们来说它是个黑盒,我给它一个问题,它也能给我答案,我并不需要仔细的去研究里面是怎么做得,我只需要设计训练这么一个模型就行了。 那么这三种方式是现在的比较常见的三类对话技术,第一大类,像状态机和填槽这一类是商用系统的主流;第二大类是学术界的主流,但是工业界也在积极的尝试,有的也已经落地,或者接近落地;端到端这种模型,主要还是停留在学术界的研究阶段,我并没有看到哪一个商业系统已经做到了端到端的模型的产品化,还没有成为商用主流的技术。 2.6 聊天机器人在智能客服系统里面通常都会有聊天机器人的模块。这个模块主要有三种做法: 第一种就是检索式,比如答案是事先编辑好的,并不会随便生成,在检索式里面又会分为两大类:第一类是用大量的语料和模型来训练,收集大量的语料,把问题和答案给一个神经网络的模型,用这个模型帮我去找到问题和答案之间的相关度,这样的话,就能够用大量的语料训练出聊天机器人模型,这是最常见的一种方式; 第二种方式是基于规则来做,使用类似于之前介绍过的 Alice 机器人所用到的 AIML 标记语言,写大量的 pattern,以及在这个 pattern 下所需要的答案,写大量这样的人工规则就可以做一个检索式的机器人,但是这仅限于少量的小规模应用,如果需要编辑大量的规则,规则之间可能会有冲突等问题,所以主流的这种聊天机器人的方式是我们说到的第一种,用统计模型和大量的语料来训练聊天机器人。 第三种是生成式的聊天机器人,我需要把我的答案直接生成出来,这种方式是需要限定在一定的领域里面。开放领域里直接生成式的聊天机器人会有一些敏感词的问题,因为语料一般是网上收集的,想做到所有语料都人工审核成本是巨大的。所以说生成式需要把它限定在一个特定的领域里面,生成式分为两种:一种是纯粹的生成,一种是基于一些模板来生成。 3. 整体架构整体技术架构如下图所示,包括基础服务层、应用服务层、编辑运营层、接入层以及在线客服系统。基础服务层提供对话系统的基础技术能力,系统需要对用户输入的一段语句进行理解,这里需要自然语言理解模块,对语句进行分词、词性标注、实体识别、关键词抽取和句法分析等;同时需要识别用户的意图,包括通用意图和业务意图,通用意图是指用户是来做业务咨询还是闲聊,业务意图是指若用户是做业务咨询,具体咨询什么业务,这里会使用文本分类的技术去识别用户意图。 基础服务之上是应用服务层,这一层具体实现了KB-Bot基于问答知识库的机器人、Task-Bot任务对话型机器和Chat-Bot闲聊类型机器人,这是智能客服系统的三种核心能力。编辑运营层是指有一个编辑团队支撑算法策略迭代,主要完成数据标注、问答运营、数据分析和效果评估的工作,这些工作输出会作用到基础服务层和应用服务层。基于应用服务层,对外提供通用的接口服务以便于业务方接入。此外,机器不是万能的,用户有很多复杂的问题仍需要人工解决,这里有一套在线客服系统提供了人工在线客服的能力,应用服务层会和这套在线客服系统做无缝对接。 4. 评价体系智能客服系统需要有一个完备的评价体系去评价它的好坏,在我们的评价体系中有基于人工标注的评价和基于用户反馈的评价两种方式: 基于人工标注的评价 系统的回答能力受限于知识库的丰富程度,因此并非能回答用户的所有问题,系统最佳的状态是将能回答的全部回答准确,不能回答的全部拒识,即拒绝回答。因此这里的评价指标包括有结果率、拒识率、召回率和准确率等,我们的目标是让系统的有结果率无限接近数据的真实有结果率,召回率和准确率尽量高。这里我们是通过标注标准评测集来计算系统的各项指标,我们会从每日的全量数据集中抽样出一个小数据集,保证小数据集的数据分布尽量符合全量数据集,然后由标注团队对数据集做标注,标注出每个问题的实际答案,一般标注完成后还有质检的环节,以保证标注结果尽量准确,这样便生成了每日数据的标准评测集。基于该标准评测集我们会去评价系统的好坏,并且每次做新模型迭代时都会使用标准评测集去评价新模型,只有新模型的效果好了才允许上线。 基于用户反馈的评价 人工评价能够评价智能客服系统的准确率,但是答案是否合理,能否为用户解决问题,需要用户去反馈评价,整个智能客服系统的最终目标是帮助用户解决问题。我们会在产品上设计智能客服和在线客服的评价功能,例如会让用户评价智能客服的每个答案或者某次会话,在和人工客服聊天完毕会发送评价卡片给用户去评价满意度。最终我们会统计参评比例、满意度等指标,这些指标能够真正反应智能客服系统的好坏。实际中往往用户参评比例低,我们会使用各种方法去刺激用户评价。 5. 参考文献15年研发经验博士手把手教学:从零开始搭建智能客服 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】XLNet","slug":"NLP/XLNet","date":"2019-09-29T16:00:00.000Z","updated":"2019-12-25T06:10:58.806Z","comments":true,"path":"2019/09/30/NLP/XLNet/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/09/30/NLP/XLNet/","excerpt":"XLNet 是一个类似 BERT 的模型,而不是完全不同的模型。总之,XLNET是一种通用的自回归预训练方法。它是CMU和Google Brain团队在2019年6月份发布的模型,最终,XLNet 在 20 个任务上超过了 BERT 的表现,并在 18 个任务上取得了当前最佳效果(state-of…","text":"XLNet 是一个类似 BERT 的模型,而不是完全不同的模型。总之,XLNET是一种通用的自回归预训练方法。它是CMU和Google Brain团队在2019年6月份发布的模型,最终,XLNet 在 20 个任务上超过了 BERT 的表现,并在 18 个任务上取得了当前最佳效果(state-of… 1. 什么是XLNetXLNet 是一个类似 BERT 的模型,而不是完全不同的模型。总之,XLNet是一种通用的自回归预训练方法。它是CMU和Google Brain团队在2019年6月份发布的模型,最终,XLNet 在 20 个任务上超过了 BERT 的表现,并在 18 个任务上取得了当前最佳效果(state-of-the-art),包括机器问答、自然语言推断、情感分析和文档排序。 作者表示,BERT 这样基于去噪自编码器的预训练模型可以很好地建模双向语境信息,性能优于基于自回归语言模型的预训练方法。然而,由于需要 mask 一部分输入,BERT 忽略了被 mask 位置之间的依赖关系,因此出现预训练和微调效果的差异(pretrain-finetune discrepancy)。 基于这些优缺点,该研究提出了一种泛化的自回归预训练模型 XLNet。XLNet 可以: 通过最大化所有可能的因式分解顺序的对数似然,学习双向语境信息; 用自回归本身的特点克服 BERT 的缺点; 此外,XLNet 还融合了当前最优自回归模型 Transformer-XL 的思路。 2. 自回归语言模型(Autoregressive LM)在ELMO/BERT出来之前,大家通常讲的语言模型其实是根据上文内容预测下一个可能跟随的单词,就是常说的自左向右的语言模型任务,或者反过来也行,就是根据下文预测前面的单词,这种类型的LM被称为自回归语言模型。GPT 就是典型的自回归语言模型。ELMO尽管看上去利用了上文,也利用了下文,但是本质上仍然是自回归LM,这个跟模型具体怎么实现有关系。ELMO是做了两个方向(从左到右以及从右到左两个方向的语言模型),但是是分别有两个方向的自回归LM,然后把LSTM的两个方向的隐节点状态拼接到一起,来体现双向语言模型这个事情的。所以其实是两个自回归语言模型的拼接,本质上仍然是自回归语言模型。 自回归语言模型有优点有缺点: 缺点是只能利用上文或者下文的信息,不能同时利用上文和下文的信息,当然,貌似ELMO这种双向都做,然后拼接看上去能够解决这个问题,因为融合模式过于简单,所以效果其实并不是太好。 优点其实跟下游NLP任务有关,比如生成类NLP任务,比如文本摘要,机器翻译等,在实际生成内容的时候,就是从左向右的,自回归语言模型天然匹配这个过程。而Bert这种DAE模式,在生成类NLP任务中,就面临训练过程和应用过程不一致的问题,导致生成类的NLP任务到目前为止都做不太好。 3. 自编码语言模型(Autoencoder LM)自回归语言模型只能根据上文预测下一个单词,或者反过来,只能根据下文预测前面一个单词。相比而言,Bert通过在输入X中随机Mask掉一部分单词,然后预训练过程的主要任务之一是根据上下文单词来预测这些被Mask掉的单词,如果你对Denoising Autoencoder比较熟悉的话,会看出,这确实是典型的DAE的思路。那些被Mask掉的单词就是在输入侧加入的所谓噪音。类似Bert这种预训练模式,被称为DAE LM。 这种DAE LM的优缺点正好和自回归LM反过来,它能比较自然地融入双向语言模型,同时看到被预测单词的上文和下文,这是好处。缺点是啥呢?主要在输入侧引入[Mask]标记,导致预训练阶段和Fine-tuning阶段不一致的问题,因为Fine-tuning阶段是看不到[Mask]标记的。DAE吗,就要引入噪音,[Mask] 标记就是引入噪音的手段,这个正常。 XLNet的出发点就是:能否融合自回归LM和DAE LM两者的优点。就是说如果站在自回归LM的角度,如何引入和双向语言模型等价的效果;如果站在DAE LM的角度看,它本身是融入双向语言模型的,如何抛掉表面的那个[Mask]标记,让预训练和Fine-tuning保持一致。当然,XLNet还讲到了一个Bert被Mask单词之间相互独立的问题。 4. XLNet模型4.1 排列语言建模(Permutation Language Modeling)Bert的自编码语言模型也有对应的缺点,就是XLNet在文中指出的: 第一个预训练阶段因为采取引入[Mask]标记来Mask掉部分单词的训练模式,而Fine-tuning阶段是看不到这种被强行加入的Mask标记的,所以两个阶段存在使用模式不一致的情形,这可能会带来一定的性能损失; 另外一个是,Bert在第一个预训练阶段,假设句子中多个单词被Mask掉,这些被Mask掉的单词之间没有任何关系,是条件独立的,而有时候这些单词之间是有关系的。 上面两点是XLNet在第一个预训练阶段,相对Bert来说要解决的两个问题。 其实思路也比较简洁,可以这么思考:XLNet仍然遵循两阶段的过程,第一个阶段是语言模型预训练阶段;第二阶段是任务数据Fine-tuning阶段。它主要希望改动第一个阶段,就是说不像Bert那种带Mask符号的Denoising-autoencoder的模式,而是采用自回归LM的模式。就是说,看上去输入句子X仍然是自左向右的输入,看到Ti单词的上文Context_before,来预测Ti这个单词。但是又希望在Context_before里,不仅仅看到上文单词,也能看到Ti单词后面的下文Context_after里的下文单词,这样的话,Bert里面预训练阶段引入的Mask符号就不需要了,于是在预训练阶段,看上去是个标准的从左向右过程,Fine-tuning当然也是这个过程,于是两个环节就统一起来。当然,这是目标。剩下是怎么做到这一点的问题。 首先,需要强调一点,尽管上面讲的是把句子X的单词排列组合后,再随机抽取例子作为输入,但是,实际上你是不能这么做的,因为Fine-tuning阶段你不可能也去排列组合原始输入。所以,就必须让预训练阶段的输入部分,看上去仍然是x1,x2,x3,x4这个输入顺序,但是可以在Transformer部分做些工作,来达成我们希望的目标。 具体而言,XLNet采取了Attention掩码的机制,你可以理解为,当前的输入句子是X,要预测的单词Ti是第i个单词,前面1到i-1个单词,在输入部分观察,并没发生变化,该是谁还是谁。但是在Transformer内部,通过Attention掩码,从X的输入单词里面,也就是Ti的上文和下文单词中,随机选择i-1个,放到Ti的上文位置中,把其它单词的输入通过Attention掩码隐藏掉,于是就能够达成我们期望的目标(当然这个所谓放到Ti的上文位置,只是一种形象的说法,其实在内部,就是通过Attention Mask,把其它没有被选到的单词Mask掉,不让它们在预测单词Ti的时候发生作用,如此而已。看着就类似于把这些被选中的单词放到了上文Context_before的位置了)。 具体实现的时候,XLNet是用“双流自注意力模型”实现的,细节可以参考论文,但是基本思想就如上所述,双流自注意力机制只是实现这个思想的具体方式,理论上,你可以想出其它具体实现方式来实现这个基本思想,也能达成让Ti看到下文单词的目标。 这里简单说下“双流自注意力机制”,一个是内容流自注意力,其实就是标准的Transformer的计算过程;主要是引入了Query流自注意力,这个是干嘛的呢?其实就是用来代替Bert的那个[Mask]标记的,因为XLNet希望抛掉[Mask]标记符号,但是比如知道上文单词x1,x2,要预测单词x3,此时在x3对应位置的Transformer最高层去预测这个单词,但是输入侧不能看到要预测的单词x3,Bert其实是直接引入[Mask]标记来覆盖掉单词x3的内容的,等于说[Mask]是个通用的占位符号。而XLNet因为要抛掉[Mask]标记,但是又不能看到x3的输入,于是Query流,就直接忽略掉x3输入了,只保留这个位置信息,用参数w来代表位置的embedding编码。其实XLNet只是扔了表面的[Mask]占位符号,内部还是引入Query流来忽略掉被Mask的这个单词。和Bert比,只是实现方式不同而已。 上面讲的Permutation Language Model是XLNet的主要理论创新,所以介绍的比较多,从模型角度讲,这个创新还是挺有意思的,因为它开启了自回归语言模型如何引入下文的一个思路,相信对于后续工作会有启发。当然,XLNet不仅仅做了这些,它还引入了其它的因素,也算是一个当前有效技术的集成体。感觉XLNet就是Bert、GPT 2.0和Transformer XL的综合体变身: 首先,它通过PLM(Permutation Language Model)预训练目标,吸收了Bert的双向语言模型; 然后,GPT2.0的核心其实是更多更高质量的预训练数据,这个明显也被XLNet吸收进来了; 再然后,Transformer XL的主要思想也被吸收进来,它的主要目标是解决Transformer对于长文档NLP应用不够友好的问题。 4.2 Transformer XL目前在NLP领域中,处理语言建模问题有两种最先进的架构:RNN和Transformer。RNN按照序列顺序逐个学习输入的单词或字符之间的关系,而Transformer则接收一整段序列,然后使用self-attention机制来学习它们之间的依赖关系。这两种架构目前来看都取得了令人瞩目的成就,但它们都局限在捕捉长期依赖性上。 为了解决这一问题,CMU联合Google Brain在2019年1月推出的一篇新论文《Transformer-XL:Attentive Language Models beyond a Fixed-Length Context》同时结合了RNN序列建模和Transformer自注意力机制的优点,在输入数据的每个段上使用Transformer的注意力模块,并使用循环机制来学习连续段之间的依赖关系。 4.2.1 vanilla Transformer为何要提这个模型?因为Transformer-XL是基于这个模型进行的改进。 Al-Rfou等人基于Transformer提出了一种训练语言模型的方法,来根据之前的字符预测片段中的下一个字符。例如,它使用 预测字符 ,而在 之后的序列则被mask掉。论文中使用64层模型,并仅限于处理 512个字符这种相对较短的输入,因此它将输入分成段,并分别从每个段中进行学习,如下图所示。 在测试阶段如需处理较长的输入,该模型会在每一步中将输入向右移动一个字符,以此实现对单个字符的预测。 该模型在常用的数据集如enwik8和text8上的表现比RNN模型要好,但它仍有以下缺点: 上下文长度受限:字符之间的最大依赖距离受输入长度的限制,模型看不到出现在几个句子之前的单词。 上下文碎片:对于长度超过512个字符的文本,都是从头开始单独训练的。段与段之间没有上下文依赖性,会让训练效率低下,也会影响模型的性能。 推理速度慢:在测试阶段,每次预测下一个单词,都需要重新构建一遍上下文,并从头开始计算,这样的计算速度非常慢。 4.2.2 Transformer XLTransformer-XL架构在vanilla Transformer的基础上引入了两点创新:循环机制(Recurrence Mechanism)和相对位置编码(Relative Positional Encoding),以克服vanilla Transformer的缺点。与vanilla Transformer相比,Transformer-XL的另一个优势是它可以被用于单词级和字符级的语言建模。 引入循环机制 与vanilla Transformer的基本思路一样,Transformer-XL仍然是使用分段的方式进行建模,但其与vanilla Transformer的本质不同是在于引入了段与段之间的循环机制,使得当前段在建模的时候能够利用之前段的信息来实现长期依赖性。如下图所示: 在训练阶段,处理后面的段时,每个隐藏层都会接收两个输入: 该段的前面隐藏层的输出,与vanilla Transformer相同(上图的灰色线)。 前面段的隐藏层的输出(上图的绿色线),可以使模型创建长期依赖关系。 这两个输入会被拼接,然后用于计算当前段的Key和Value矩阵。 该方法可以利用前面更多段的信息,测试阶段也可以获得更长的依赖。在测试阶段,与vanilla Transformer相比,其速度也会更快。在vanilla Transformer中,一次只能前进一个step,并且需要重新构建段,并全部从头开始计算;而在Transformer-XL中,每次可以前进一整个段,并利用之前段的数据来预测当前段的输出。 相对位置编码 在Transformer中,一个重要的地方在于其考虑了序列的位置信息。在分段的情况下,如果仅仅对于每个段仍直接使用Transformer中的位置编码,即每个不同段在同一个位置上的表示使用相同的位置编码,就会出现问题。比如,第i−2i-2i−2段和第i−1i-1i−1段的第一个位置将具有相同的位置编码,但它们对于第iii段的建模重要性显然并不相同(例如第i−2i-2i−2段中的第一个位置重要性可能要低一些)。因此,需要对这种位置进行区分。 论文对于这个问题,提出了一种新的位置编码的方式,即会根据词之间的相对距离而非像Transformer中的绝对位置进行编码。从另一个角度来解读公式的话,可以将attention的计算分为如下四个部分: 基于内容的“寻址”,即没有添加原始位置编码的原始分数。 基于内容的位置偏置,即相对于当前内容的位置偏差。 全局的内容偏置,用于衡量key的重要性。 全局的位置偏置,根据query和key之间的距离调整重要性。 详细公式见:Transformer-XL解读(论文 + PyTorch源码) 5. XLNet与BERT比较尽管看上去,XLNet在预训练机制引入的Permutation Language Model这种新的预训练目标,和Bert采用Mask标记这种方式,有很大不同。其实你深入思考一下,会发现,两者本质是类似的。 区别主要在于: Bert是直接在输入端显示地通过引入Mask标记,在输入侧隐藏掉一部分单词,让这些单词在预测的时候不发挥作用,要求利用上下文中其它单词去预测某个被Mask掉的单词; 而XLNet则抛弃掉输入侧的Mask标记,通过Attention Mask机制,在Transformer内部随机Mask掉一部分单词(这个被Mask掉的单词比例跟当前单词在句子中的位置有关系,位置越靠前,被Mask掉的比例越高,位置越靠后,被Mask掉的比例越低),让这些被Mask掉的单词在预测某个单词的时候不发生作用。 所以,本质上两者并没什么太大的不同,只是Mask的位置,Bert更表面化一些,XLNet则把这个过程隐藏在了Transformer内部而已。这样,就可以抛掉表面的[Mask]标记,解决它所说的预训练里带有[Mask]标记导致的和Fine-tuning过程不一致的问题。至于说XLNet说的,Bert里面被Mask掉单词的相互独立问题,也就是说,在预测某个被Mask单词的时候,其它被Mask单词不起作用,这个问题,你深入思考一下,其实是不重要的,因为XLNet在内部Attention Mask的时候,也会Mask掉一定比例的上下文单词,只要有一部分被Mask掉的单词,其实就面临这个问题。而如果训练数据足够大,其实不靠当前这个例子,靠其它例子,也能弥补被Mask单词直接的相互关系问题,因为总有其它例子能够学会这些单词的相互依赖关系。 当然,XLNet这种改造,维持了表面看上去的自回归语言模型的从左向右的模式,这个Bert做不到,这个有明显的好处,就是对于生成类的任务,能够在维持表面从左向右的生成过程前提下,模型里隐含了上下文的信息。所以看上去,XLNet貌似应该对于生成类型的NLP任务,会比Bert有明显优势。另外,因为XLNet还引入了Transformer XL的机制,所以对于长文档输入类型的NLP任务,也会比Bert有明显优势。 6. 代码实现中文XLNet预训练模型 【机器学习通俗易懂系列文章】 7. 参考文献 XLNet原理解读 XLNet:运行机制及和Bert的异同比较 Transformer-XL解读(论文 + PyTorch源码) 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】BERT","slug":"NLP/BERT","date":"2019-09-27T16:00:00.000Z","updated":"2019-12-25T06:10:08.890Z","comments":true,"path":"2019/09/28/NLP/BERT/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/09/28/NLP/BERT/","excerpt":"BERT的全称是BIDIRECTIONAL ENCODER REPRESENTATION FROM TRANSFORMERS,是Google2018年提出的预训练模型,即双向Transformer的Encoder,因为decoder是不能获要预测的信息的。模型的主要创新点都在pre-train方法…","text":"BERT的全称是BIDIRECTIONAL ENCODER REPRESENTATION FROM TRANSFORMERS,是Google2018年提出的预训练模型,即双向Transformer的Encoder,因为decoder是不能获要预测的信息的。模型的主要创新点都在pre-train方法… 1. 什么是BERTBERT的全称是Bidirectional Encoder Representation from Transformers,是Google2018年提出的预训练模型,即双向Transformer的Encoder,因为decoder是不能获要预测的信息的。模型的主要创新点都在pre-train方法上,即用了Masked LM和Next Sentence Prediction两种方法分别捕捉词语和句子级别的representation。 Bert最近很火,应该是最近最火爆的AI进展,网上的评价很高,那么Bert值得这么高的评价吗?我个人判断是值得。那为什么会有这么高的评价呢?是因为它有重大的理论或者模型创新吗?其实并没有,从模型创新角度看一般,创新不算大。但是架不住效果太好了,基本刷新了很多NLP的任务的最好性能,有些任务还被刷爆了,这个才是关键。另外一点是Bert具备广泛的通用性,就是说绝大部分NLP任务都可以采用类似的两阶段模式直接去提升效果,这个第二关键。客观的说,把Bert当做最近两年NLP重大进展的集大成者更符合事实。 2. 从Word Embedding到Bert模型的发展2.1 图像的预训练自从深度学习火起来后,预训练过程就是做图像或者视频领域的一种比较常规的做法,有比较长的历史了,而且这种做法很有效,能明显促进应用的效果。 那么图像领域怎么做预训练呢,上图展示了这个过程, 我们设计好网络结构以后,对于图像来说一般是CNN的多层叠加网络结构,可以先用某个训练集合比如训练集合A或者训练集合B对这个网络进行预先训练,在A任务上或者B任务上学会网络参数,然后存起来以备后用。 假设我们面临第三个任务C,网络结构采取相同的网络结构,在比较浅的几层CNN结构,网络参数初始化的时候可以加载A任务或者B任务学习好的参数,其它CNN高层参数仍然随机初始化。 之后我们用C任务的训练数据来训练网络,此时有两种做法: 一种是浅层加载的参数在训练C任务过程中不动,这种方法被称为“Frozen”; 另一种是底层网络参数尽管被初始化了,在C任务训练过程中仍然随着训练的进程不断改变,这种一般叫“Fine-Tuning”,顾名思义,就是更好地把参数进行调整使得更适应当前的C任务。 一般图像或者视频领域要做预训练一般都这么做。这样做的优点是:如果手头任务C的训练集合数据量较少的话,利用预训练出来的参数来训练任务C,加个预训练过程也能极大加快任务训练的收敛速度,所以这种预训练方式是老少皆宜的解决方案,另外疗效又好,所以在做图像处理领域很快就流行开来。 为什么预训练可行 对于层级的CNN结构来说,不同层级的神经元学习到了不同类型的图像特征,由底向上特征形成层级结构,所以预训练好的网络参数,尤其是底层的网络参数抽取出特征跟具体任务越无关,越具备任务的通用性,所以这是为何一般用底层预训练好的参数初始化新任务网络参数的原因。而高层特征跟任务关联较大,实际可以不用使用,或者采用Fine-tuning用新数据集合清洗掉高层无关的特征抽取器。 2.2 Word Embedding 神经网络语言模型(NNLM)的思路。先说训练过程。学习任务是输入某个句中单词 前面句子的t-1个单词,要求网络正确预测单词Bert,即最大化: 前面任意单词 用Onehot编码(比如:0001000)作为原始单词输入,之后乘以矩阵Q后获得向量 ,每个单词的 拼接,上接隐层,然后接softmax去预测后面应该后续接哪个单词。这个 是什么?这其实就是单词对应的Word Embedding值,那个矩阵Q包含V行,V代表词典大小,每一行内容代表对应单词的Word embedding值。只不过Q的内容也是网络参数,需要学习获得,训练刚开始用随机值初始化矩阵Q,当这个网络训练好之后,矩阵Q的内容被正确赋值,每一行代表一个单词对应的Word embedding值。所以你看,通过这个网络学习语言模型任务,这个网络不仅自己能够根据上文预测后接单词是什么,同时获得一个副产品,就是那个矩阵Q,这就是单词的Word Embedding。 2013年最火的用语言模型做Word Embedding的工具是Word2Vec,后来又出了Glove,Word2Vec。对于这两个模型不熟悉的可以参考我之前的文章,这里不再赘述: Word2Vec GloVe 上面这种模型做法就是18年之前NLP领域里面采用预训练的典型做法,之前说过,Word Embedding其实对于很多下游NLP任务是有帮助的,只是帮助没有大到闪瞎忘记戴墨镜的围观群众的双眼而已。那么新问题来了,为什么这样训练及使用Word Embedding的效果没有期待中那么好呢?答案很简单,因为Word Embedding有问题呗。这貌似是个比较弱的答案,关键是Word Embedding存在什么问题?这其实是个好问题。 这片在Word Embedding头上笼罩了好几年的乌云是什么?是多义词问题。我们知道,多义词是自然语言中经常出现的现象,也是语言灵活性和高效性的一种体现。多义词对Word Embedding来说有什么负面影响?如上图所示,比如多义词Bank,有两个常用含义,但是Word Embedding在对bank这个单词进行编码的时候,是区分不开这两个含义的,因为它们尽管上下文环境中出现的单词不同,但是在用语言模型训练的时候,不论什么上下文的句子经过word2vec,都是预测相同的单词bank,而同一个单词占的是同一行的参数空间,这导致两种不同的上下文信息都会编码到相同的word embedding空间里去。所以word embedding无法区分多义词的不同语义,这就是它的一个比较严重的问题。 有没有简单优美的解决方案呢?ELMO提供了一种简洁优雅的解决方案。 2.3 ELMOELMO是“Embedding from Language Models”的简称,其实这个名字并没有反应它的本质思想,提出ELMO的论文题目:“Deep contextualized word representation”更能体现其精髓,而精髓在哪里?在deep contextualized这个短语,一个是deep,一个是context,其中context更关键。 在此之前的Word Embedding本质上是个静态的方式,所谓静态指的是训练好之后每个单词的表达就固定住了,以后使用的时候,不论新句子上下文单词是什么,这个单词的Word Embedding不会跟着上下文场景的变化而改变,所以对于比如Bank这个词,它事先学好的Word Embedding中混合了几种语义 ,在应用中来了个新句子,即使从上下文中(比如句子包含money等词)明显可以看出它代表的是“银行”的含义,但是对应的Word Embedding内容也不会变,它还是混合了多种语义。这是为何说它是静态的,这也是问题所在。 ELMO的本质思想是:我事先用语言模型学好一个单词的Word Embedding,此时多义词无法区分,不过这没关系。在我实际使用Word Embedding的时候,单词已经具备了特定的上下文了,这个时候我可以根据上下文单词的语义去调整单词的Word Embedding表示,这样经过调整后的Word Embedding更能表达在这个上下文中的具体含义,自然也就解决了多义词的问题了。所以ELMO本身是个根据当前上下文对Word Embedding动态调整的思路。 ELMO采用了典型的两阶段过程,第一个阶段是利用语言模型进行预训练;第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的Word Embedding作为新特征补充到下游任务中。 上图展示的是其预训练过程,它的网络结构采用了双层双向LSTM,目前语言模型训练的任务目标是根据单词 的上下文去正确预测单词 , 之前的单词序列Context-before称为上文,之后的单词序列Context-after称为下文。 图中左端的前向双层LSTM代表正方向编码器,输入的是从左到右顺序的除了预测单词外 的上文Context-before;右端的逆向双层LSTM代表反方向编码器,输入的是从右到左的逆序的句子下文Context-after;每个编码器的深度都是两层LSTM叠加。 这个网络结构其实在NLP中是很常用的。使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子 ,句子中每个单词都能得到对应的三个Embedding: 最底层是单词的Word Embedding; 往上走是第一层双向LSTM中对应单词位置的Embedding,这层编码单词的句法信息更多一些; 再往上走是第二层LSTM中对应单词位置的Embedding,这层编码单词的语义信息更多一些。 也就是说,ELMO的预训练过程不仅仅学会单词的Word Embedding,还学会了一个双层双向的LSTM网络结构,而这两者后面都有用。 上面介绍的是ELMO的第一阶段:预训练阶段。那么预训练好网络结构后,如何给下游任务使用呢?上图展示了下游任务的使用过程,比如我们的下游任务仍然是QA问题: 此时对于问句X,我们可以先将句子X作为预训练好的ELMO网络的输入,这样句子X中每个单词在ELMO网络中都能获得对应的三个Embedding; 之后给予这三个Embedding中的每一个Embedding一个权重a,这个权重可以学习得来,根据各自权重累加求和,将三个Embedding整合成一个; 然后将整合后的这个Embedding作为X句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。对于上图所示下游任务QA中的回答句子Y来说也是如此处理。 因为ELMO给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为“Feature-based Pre-Training”。 前面我们提到静态Word Embedding无法解决多义词的问题,那么ELMO引入上下文动态调整单词的embedding后多义词问题解决了吗?解决了,而且比我们期待的解决得还要好。对于Glove训练出的Word Embedding来说,多义词比如play,根据它的embedding找出的最接近的其它单词大多数集中在体育领域,这很明显是因为训练数据中包含play的句子中体育领域的数量明显占优导致;而使用ELMO,根据上下文动态调整后的embedding不仅能够找出对应的“演出”的相同语义的句子,而且还可以保证找出的句子中的play对应的词性也是相同的,这是超出期待之处。之所以会这样,是因为我们上面提到过,第一层LSTM编码了很多句法信息,这在这里起到了重要作用。 ELMO有什么值得改进的缺点呢? 首先,一个非常明显的缺点在特征抽取器选择方面,ELMO使用了LSTM而不是新贵Transformer,Transformer是谷歌在17年做机器翻译任务的“Attention is all you need”的论文中提出的,引起了相当大的反响,很多研究已经证明了Transformer提取特征的能力是要远强于LSTM的。如果ELMO采取Transformer作为特征提取器,那么估计Bert的反响远不如现在的这种火爆场面。 另外一点,ELMO采取双向拼接这种融合特征的能力可能比Bert一体化的融合特征方式弱,但是,这只是一种从道理推断产生的怀疑,目前并没有具体实验说明这一点。 2.4 GPT GPT是“Generative Pre-Training”的简称,从名字看其含义是指的生成式的预训练。GPT也采用两阶段过程,第一个阶段是利用语言模型进行预训练,第二阶段通过Fine-tuning的模式解决下游任务。 上图展示了GPT的预训练过程,其实和ELMO是类似的,主要不同在于两点: 首先,特征抽取器不是用的RNN,而是用的Transformer,上面提到过它的特征抽取能力要强于RNN,这个选择很明显是很明智的; 其次,GPT的预训练虽然仍然是以语言模型作为目标任务,但是采用的是单向的语言模型,所谓“单向”的含义是指:语言模型训练的任务目标是根据 单词的上下文去正确预测单词 , 之前的单词序列Context-before称为上文,之后的单词序列Context-after称为下文。 如果对Transformer模型不太了解的,可以参考我写的文章:Transformer ELMO在做语言模型预训练的时候,预测单词 同时使用了上文和下文,而GPT则只采用Context-before这个单词的上文来进行预测,而抛开了下文。这个选择现在看不是个太好的选择,原因很简单,它没有把单词的下文融合进来,这限制了其在更多应用场景的效果,比如阅读理解这种任务,在做任务的时候是可以允许同时看到上文和下文一起做决策的。如果预训练时候不把单词的下文嵌入到Word Embedding中,是很吃亏的,白白丢掉了很多信息。 2.5 BERTBert采用和GPT完全相同的两阶段模型,首先是语言模型预训练;其次是使用Fine-Tuning模式解决下游任务。和GPT的最主要不同在于在预训练阶段采用了类似ELMO的双向语言模型,即双向的Transformer,当然另外一点是语言模型的数据规模要比GPT大。所以这里Bert的预训练过程不必多讲了。模型结构如下: 对比OpenAI GPT(Generative pre-trained transformer),BERT是双向的Transformer block连接;就像单向rnn和双向rnn的区别,直觉上来讲效果会好一些。 对比ELMo,虽然都是“双向”,但目标函数其实是不同的。ELMo是分别以 和 作为目标函数,独立训练处两个representation然后拼接,而BERT则是以 作为目标函数训练LM。 BERT预训练模型分为以下三个步骤:Embedding、Masked LM、Next Sentence Prediction 2.5.1 Embedding这里的Embedding由三种Embedding求和而成: Token Embeddings是词向量,第一个单词是CLS标志,可以用于之后的分类任务 Segment Embeddings用来区别两种句子,因为预训练不光做LM还要做以两个句子为输入的分类任务 Position Embeddings和之前文章中的Transformer不一样,不是三角函数而是学习出来的 2.5.2 Masked LMMLM可以理解为完形填空,作者会随机mask每一个句子中15%的词,用其上下文来做预测,例如:my dog is hairy → my dog is [MASK] 此处将hairy进行了mask处理,然后采用非监督学习的方法预测mask位置的词是什么,但是该方法有一个问题,因为是mask15%的词,其数量已经很高了,这样就会导致某些词在fine-tuning阶段从未见过,为了解决这个问题,作者做了如下的处理: 80%是采用[mask],my dog is hairy → my dog is [MASK] 10%是随机取一个词来代替mask的词,my dog is hairy -> my dog is apple 10%保持不变,my dog is hairy -> my dog is hairy 注意:这里的10%是15%需要mask中的10% 那么为啥要以一定的概率使用随机词呢?这是因为transformer要保持对每个输入token分布式的表征,否则Transformer很可能会记住这个[MASK]就是”hairy”。至于使用随机词带来的负面影响,文章中解释说,所有其他的token(即非”hairy”的token)共享15%*10% = 1.5%的概率,其影响是可以忽略不计的。Transformer全局的可视,又增加了信息的获取,但是不让模型获取全量信息。 2.5.3 Next Sentence Prediction选择一些句子对A与B,其中50%的数据B是A的下一条句子,剩余50%的数据B是语料库中随机选择的,学习其中的相关性,添加这样的预训练的目的是目前很多NLP的任务比如QA和NLI都需要理解两个句子之间的关系,从而能让预训练的模型更好的适应这样的任务。个人理解: Bert先是用Mask来提高视野范围的信息获取量,增加duplicate再随机Mask,这样跟RNN类方法依次训练预测没什么区别了除了mask不同位置外; 全局视野极大地降低了学习的难度,然后再用A+B/C来作为样本,这样每条样本都有50%的概率看到一半左右的噪声; 但直接学习Mask A+B/C是没法学习的,因为不知道哪些是噪声,所以又加上next_sentence预测任务,与MLM同时进行训练,这样用next来辅助模型对噪声/非噪声的辨识,用MLM来完成语义的大部分的学习。 3. BERT的评价总结下BERT的主要贡献: 引入了Masked LM,使用双向LM做模型预训练。 为预训练引入了新目标NSP,它可以学习句子与句子间的关系。 进一步验证了更大的模型效果更好: 12 –> 24 层。 为下游任务引入了很通用的求解框架,不再为任务做模型定制。 刷新了多项NLP任务的记录,引爆了NLP无监督预训练技术。 BERT优点 Transformer Encoder因为有Self-attention机制,因此BERT自带双向功能。 因为双向功能以及多层Self-attention机制的影响,使得BERT必须使用Cloze版的语言模型Masked-LM来完成token级别的预训练。 为了获取比词更高级别的句子级别的语义表征,BERT加入了Next Sentence Prediction来和Masked-LM一起做联合训练。 为了适配多任务下的迁移学习,BERT设计了更通用的输入层和输出层。 微调成本小。 BERT缺点 task1的随机遮挡策略略显粗犷,推荐阅读《Data Nosing As Smoothing In Neural Network Language Models》。 [MASK]标记在实际预测中不会出现,训练时用过多[MASK]影响模型表现。每个batch只有15%的token被预测,所以BERT收敛得比left-to-right模型要慢(它们会预测每个token)。 BERT对硬件资源的消耗巨大(大模型需要16个tpu,历时四天;更大的模型需要64个tpu,历时四天。 评价 Bert是NLP里里程碑式的工作,对于后面NLP的研究和工业应用会产生长久的影响,这点毫无疑问。但是从上文介绍也可以看出,从模型或者方法角度看,Bert借鉴了ELMO,GPT及CBOW,主要提出了Masked 语言模型及Next Sentence Prediction,但是这里Next Sentence Prediction基本不影响大局,而Masked LM明显借鉴了CBOW的思想。所以说Bert的模型没什么大的创新,更像最近几年NLP重要进展的集大成者,这点如果你看懂了上文估计也没有太大异议,如果你有大的异议,杠精这个大帽子我随时准备戴给你。如果归纳一下这些进展就是: 首先是两阶段模型,第一阶段双向语言模型预训练,这里注意要用双向而不是单向,第二阶段采用具体任务Fine-tuning或者做特征集成; 第二是特征抽取要用Transformer作为特征提取器而不是RNN或者CNN; 第三,双向语言模型可以采取CBOW的方法去做(当然我觉得这个是个细节问题,不算太关键,前两个因素比较关键)。 Bert最大的亮点在于效果好及普适性强,几乎所有NLP任务都可以套用Bert这种两阶段解决思路,而且效果应该会有明显提升。可以预见的是,未来一段时间在NLP应用领域,Transformer将占据主导地位,而且这种两阶段预训练方法也会主导各种应用。 4. 代码实现bert中文分类实践 【机器学习通俗易懂系列文章】 5. 参考文献 【NLP】Google BERT详解 从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史 一文读懂BERT(原理篇) 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】Transformer","slug":"NLP/Transformer","date":"2019-09-25T16:00:00.000Z","updated":"2019-12-25T06:17:01.488Z","comments":true,"path":"2019/09/26/NLP/Transformer/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/09/26/NLP/Transformer/","excerpt":"什么是Transformer 《Attention Is All You Need》是一篇Google提出的将Attention思想发挥到极致的论文。这篇论文中提出一个全新的模型,叫 Transformer,抛弃了以往深度学习任务里面使用到的 CNN 和 RNN。目前大热…","text":"什么是Transformer 《Attention Is All You Need》是一篇Google提出的将Attention思想发挥到极致的论文。这篇论文中提出一个全新的模型,叫 Transformer,抛弃了以往深度学习任务里面使用到的 CNN 和 RNN。目前大热… 1. 什么是Transformer《Attention Is All You Need》是一篇Google提出的将Attention思想发挥到极致的论文。这篇论文中提出一个全新的模型,叫 Transformer,抛弃了以往深度学习任务里面使用到的 CNN 和 RNN。目前大热的Bert就是基于Transformer构建的,这个模型广泛应用于NLP领域,例如机器翻译,问答系统,文本摘要和语音识别等等方向。 2. Transformer结构2.1 总体结构Transformer的结构和Attention模型一样,Transformer模型中也采用了 encoer-decoder 架构。但其结构相比于Attention更加复杂,论文中encoder层由6个encoder堆叠在一起,decoder层也一样。 不了解Attention模型的,可以回顾之前的文章:Attention 每一个encoder和decoder的内部结构如下图: encoder,包含两层,一个self-attention层和一个前馈神经网络,self-attention能帮助当前节点不仅仅只关注当前的词,从而能获取到上下文的语义。 decoder也包含encoder提到的两层网络,但是在这两层中间还有一层attention层,帮助当前节点获取到当前需要关注的重点内容。 2.2 Encoder层结构首先,模型需要对输入的数据进行一个embedding操作,也可以理解为类似w2c的操作,enmbedding结束之后,输入到encoder层,self-attention处理完数据后把数据送给前馈神经网络,前馈神经网络的计算可以并行,得到的输出会输入到下一个encoder。 2.2.1 Positional Encodingtransformer模型中缺少一种解释输入序列中单词顺序的方法,它跟序列模型还不不一样。为了处理这个问题,transformer给encoder层和decoder层的输入添加了一个额外的向量Positional Encoding,维度和embedding的维度一样,这个向量采用了一种很独特的方法来让模型学习到这个值,这个向量能决定当前词的位置,或者说在一个句子中不同的词之间的距离。这个位置向量的具体计算方法有很多种,论文中的计算方法如下: $$PE(pos,2i)=sin(\\frac{pos}{10000^{\\frac{2i}{d_{model}}}})$$ $$PE(pos,2i+1)=cos(\\frac{pos}{10000^{\\frac{2i}{d_{model}}}})$$ 其中pos是指当前词在句子中的位置,i是指向量中每个值的index,可以看出,在偶数位置,使用正弦编码,在奇数位置,使用余弦编码。 最后把这个Positional Encoding与embedding的值相加,作为输入送到下一层。 2.2.2 Self-Attention接下来我们详细看一下self-attention,其思想和attention类似,但是self-attention是Transformer用来将其他相关单词的“理解”转换成我们正在处理的单词的一种思路,我们看个例子: The animal didn’t cross the street because it was too tired 这里的 it 到底代表的是 animal 还是 street 呢,对于我们来说能很简单的判断出来,但是对于机器来说,是很难判断的,self-attention就能够让机器把 it 和 animal 联系起来,接下来我们看下详细的处理过程。 首先,self-attention会计算出三个新的向量,在论文中,向量的维度是512维,我们把这三个向量分别称为Query、Key、Value,这三个向量是用embedding向量与一个矩阵相乘得到的结果,这个矩阵是随机初始化的,维度为(64,512)注意第二个维度需要和embedding的维度一样,其值在BP的过程中会一直进行更新,得到的这三个向量的维度是64。 计算self-attention的分数值,该分数值决定了当我们在某个位置encode一个词时,对输入句子的其他部分的关注程度。这个分数值的计算方法是Query与Key做点成,以下图为例,首先我们需要针对Thinking这个词,计算出其他词对于该词的一个分数值,首先是针对于自己本身即q1·k1,然后是针对于第二个词即q1·k2。 接下来,把点成的结果除以一个常数,这里我们除以8,这个值一般是采用上文提到的矩阵的第一个维度的开方即64的开方8,当然也可以选择其他的值,然后把得到的结果做一个softmax的计算。得到的结果即是每个词对于当前位置的词的相关性大小,当然,当前位置的词相关性肯定会会很大。 下一步就是把Value和softmax得到的值进行相乘,并相加,得到的结果即是self-attetion在当前节点的值。 在实际的应用场景,为了提高计算速度,我们采用的是矩阵的方式,直接计算出Query, Key, Value的矩阵,然后把embedding的值与三个矩阵直接相乘,把得到的新矩阵 Q 与 K 相乘,乘以一个常数,做softmax操作,最后乘上 V 矩阵。 这种通过 query 和 key 的相似性程度来确定 value 的权重分布的方法被称为scaled dot-product attention。 2.2.3 Multi-Headed Attention这篇论文更牛逼的地方是给self-attention加入了另外一个机制,被称为“multi-headed” attention,该机制理解起来很简单,就是说不仅仅只初始化一组Q、K、V的矩阵,而是初始化多组,tranformer是使用了8组,所以最后得到的结果是8个矩阵。 2.2.4 Layer normalization在transformer中,每一个子层(self-attetion,Feed Forward Neural Network)之后都会接一个残缺模块,并且有一个Layer normalization。 Normalization有很多种,但是它们都有一个共同的目的,那就是把输入转化成均值为0方差为1的数据。我们在把数据送入激活函数之前进行normalization(归一化),因为我们不希望输入数据落在激活函数的饱和区。 Batch Normalization BN的主要思想就是:在每一层的每一批数据上进行归一化。我们可能会对输入数据进行归一化,但是经过该网络层的作用后,我们的数据已经不再是归一化的了。随着这种情况的发展,数据的偏差越来越大,我的反向传播需要考虑到这些大的偏差,这就迫使我们只能使用较小的学习率来防止梯度消失或者梯度爆炸。BN的具体做法就是对每一小批数据,在批这个方向上做归一化。 Layer normalization 它也是归一化数据的一种方式,不过LN 是在每一个样本上计算均值和方差,而不是BN那种在批方向计算均值和方差!公式如下: $$LN(x_i)=\\alpha*\\frac{x_i-\\mu_L}{\\sqrt{\\sigma_L^2+\\varepsilon}}+\\beta$$ 2.2.5 Feed Forward Neural Network这给我们留下了一个小的挑战,前馈神经网络没法输入 8 个矩阵呀,这该怎么办呢?所以我们需要一种方式,把 8 个矩阵降为 1 个,首先,我们把 8 个矩阵连在一起,这样会得到一个大的矩阵,再随机初始化一个矩阵和这个组合好的矩阵相乘,最后得到一个最终的矩阵。 2.3 Decoder层结构根据上面的总体结构图可以看出,decoder部分其实和encoder部分大同小异,刚开始也是先添加一个位置向量Positional Encoding,方法和 2.2.1 节一样,接下来接的是masked mutil-head attetion,这里的mask也是transformer一个很关键的技术,下面我们会进行一一介绍。 其余的层结构与Encoder一样,请参考Encoder层结构。 2.3.1 masked mutil-head attetionmask 表示掩码,它对某些值进行掩盖,使其在参数更新时不产生效果。Transformer 模型里面涉及两种 mask,分别是 padding mask 和 sequence mask。其中,padding mask 在所有的 scaled dot-product attention 里面都需要用到,而 sequence mask 只有在 decoder 的 self-attention 里面用到。 padding mask 什么是 padding mask 呢?因为每个批次输入序列长度是不一样的也就是说,我们要对输入序列进行对齐。具体来说,就是给在较短的序列后面填充 0。但是如果输入的序列太长,则是截取左边的内容,把多余的直接舍弃。因为这些填充的位置,其实是没什么意义的,所以我们的attention机制不应该把注意力放在这些位置上,所以我们需要进行一些处理。 具体的做法是,把这些位置的值加上一个非常大的负数(负无穷),这样的话,经过 softmax,这些位置的概率就会接近0! 而我们的 padding mask 实际上是一个张量,每个值都是一个Boolean,值为 false 的地方就是我们要进行处理的地方。 Sequence mask 文章前面也提到,sequence mask 是为了使得 decoder 不能看见未来的信息。也就是对于一个序列,在 time_step 为 t 的时刻,我们的解码输出应该只能依赖于 t 时刻之前的输出,而不能依赖 t 之后的输出。因此我们需要想一个办法,把 t 之后的信息给隐藏起来。 那么具体怎么做呢?也很简单:产生一个上三角矩阵,上三角的值全为0。把这个矩阵作用在每一个序列上,就可以达到我们的目的。 对于 decoder 的 self-attention,里面使用到的 scaled dot-product attention,同时需要padding mask 和 sequence mask 作为 attn_mask,具体实现就是两个mask相加作为attn_mask。 其他情况,attn_mask 一律等于 padding mask。 2.3.2 Output层当decoder层全部执行完毕后,怎么把得到的向量映射为我们需要的词呢,很简单,只需要在结尾再添加一个全连接层和softmax层,假如我们的词典是1w个词,那最终softmax会输入1w个词的概率,概率值最大的对应的词就是我们最终的结果。 2.4 动态流程图编码器通过处理输入序列开启工作。顶端编码器的输出之后会变转化为一个包含向量K(键向量)和V(值向量)的注意力向量集 ,这是并行化操作。这些向量将被每个解码器用于自身的“编码-解码注意力层”,而这些层可以帮助解码器关注输入序列哪些位置合适: 在完成编码阶段后,则开始解码阶段。解码阶段的每个步骤都会输出一个输出序列(在这个例子里,是英语翻译的句子)的元素。 接下来的步骤重复了这个过程,直到到达一个特殊的终止符号,它表示transformer的解码器已经完成了它的输出。每个步骤的输出在下一个时间步被提供给底端解码器,并且就像编码器之前做的那样,这些解码器会输出它们的解码结果 。 3. Transformer为什么需要进行Multi-head Attention原论文中说到进行Multi-head Attention的原因是将模型分为多个头,形成多个子空间,可以让模型去关注不同方面的信息,最后再将各个方面的信息综合起来。其实直观上也可以想到,如果自己设计这样的一个模型,必然也不会只做一次attention,多次attention综合的结果至少能够起到增强模型的作用,也可以类比CNN中同时使用多个卷积核的作用,直观上讲,多头的注意力有助于网络捕捉到更丰富的特征/信息。 4. Transformer相比于RNN/LSTM,有什么优势?为什么? RNN系列的模型,并行计算能力很差。RNN并行计算的问题就出在这里,因为 T 时刻的计算依赖 T-1 时刻的隐层计算结果,而 T-1 时刻的计算依赖 T-2 时刻的隐层计算结果,如此下去就形成了所谓的序列依赖关系。 Transformer的特征抽取能力比RNN系列的模型要好。 具体实验对比可以参考:放弃幻想,全面拥抱Transformer:自然语言处理三大特征抽取器(CNN/RNN/TF)比较 但是值得注意的是,并不是说Transformer就能够完全替代RNN系列的模型了,任何模型都有其适用范围,同样的,RNN系列模型在很多任务上还是首选,熟悉各种模型的内部原理,知其然且知其所以然,才能遇到新任务时,快速分析这时候该用什么样的模型,该怎么做好。 5. 为什么说Transformer可以代替seq2seq?seq2seq缺点:这里用代替这个词略显不妥当,seq2seq虽已老,但始终还是有其用武之地,seq2seq最大的问题在于将Encoder端的所有信息压缩到一个固定长度的向量中,并将其作为Decoder端首个隐藏状态的输入,来预测Decoder端第一个单词(token)的隐藏状态。在输入序列比较长的时候,这样做显然会损失Encoder端的很多信息,而且这样一股脑的把该固定向量送入Decoder端,Decoder端不能够关注到其想要关注的信息。 Transformer优点:transformer不但对seq2seq模型这两点缺点有了实质性的改进(多头交互式attention模块),而且还引入了self-attention模块,让源序列和目标序列首先“自关联”起来,这样的话,源序列和目标序列自身的embedding表示所蕴含的信息更加丰富,而且后续的FFN层也增强了模型的表达能力,并且Transformer并行计算的能力是远远超过seq2seq系列的模型,因此我认为这是transformer优于seq2seq模型的地方。 6. 代码实现地址:https://github.com/Kyubyong/transformer 代码解读:Transformer解析与tensorflow代码解读 【机器学习通俗易懂系列文章】 7. 参考文献 Transformer模型详解 图解Transformer(完整版) 关于Transformer的若干问题整理记录 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"推荐系统","slug":"Recommendation System/Recommendation System","date":"2019-09-08T16:00:00.000Z","updated":"2019-12-25T06:13:27.594Z","comments":true,"path":"2019/09/09/Recommendation System/Recommendation System/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/09/09/Recommendation%20System/Recommendation%20System/","excerpt":"推荐系统是利用电子商务网站向客户提供商品信息和建议,帮助用户决定应该购买什么产品,模拟销售人员帮助客户完成购买过程。个性化推荐是根据用户的兴趣特点和购买行为,向用户推荐用户感兴趣的信息和商品。 随着电子商务规模的不断扩大,商品个数和种类快速增长,顾客需要花费大量的时间才能找到自己想买的商品。这种浏…","text":"推荐系统是利用电子商务网站向客户提供商品信息和建议,帮助用户决定应该购买什么产品,模拟销售人员帮助客户完成购买过程。个性化推荐是根据用户的兴趣特点和购买行为,向用户推荐用户感兴趣的信息和商品。 随着电子商务规模的不断扩大,商品个数和种类快速增长,顾客需要花费大量的时间才能找到自己想买的商品。这种浏… 1. 什么是推荐系统推荐系统是利用电子商务网站向客户提供商品信息和建议,帮助用户决定应该购买什么产品,模拟销售人员帮助客户完成购买过程。个性化推荐是根据用户的兴趣特点和购买行为,向用户推荐用户感兴趣的信息和商品。 随着电子商务规模的不断扩大,商品个数和种类快速增长,顾客需要花费大量的时间才能找到自己想买的商品。这种浏览大量无关的信息和产品过程无疑会使淹没在信息过载问题中的消费者不断流失。 为了解决这些问题,个性化推荐系统应运而生。个性化推荐系统是建立在海量数据挖掘基础上的一种高级商务智能平台,以帮助电子商务网站为其顾客购物提供完全个性化的决策支持和信息服务。 常见的推荐栏位例如:淘宝的猜你喜欢、看了又看、推荐商品,美团的首页推荐、附近推荐等。 推荐系统是比较偏向于工程类的系统,要做得更加的精确,需要的不仅仅是推荐算法,还有用户意图识别、文本分析、行为分析等,是一个综合性很强的系统。 2. 总体架构本节介绍的几种推荐系统架构,并不是互相独立的关系,实际的推荐系统可能会用到其中一种或者几种的架构。在实际设计的过程中,读者可以把本文介绍的架构作为一个设计的起点,更多地结合自身业务特点进行独立思考,从而设计出适合自身业务的系统。 根据响应用户行为的速度不同,推荐系统可以大致分为基于离线训练和在线训练的推荐系统。 2.1 离线推荐于离线训练的推荐系统架构是最常见的一种推荐系统架构。这里的“离线”训练指的是使用历史一段时间( 比如周或者几周 )的数据进行训练,模型迭代的周期较长(一般 以小时为单位 )。模型拟合的是用户的中长期兴趣。 如下图所示, 一个典型的基于离线训练的推荐系统架构由数据上报、离线训练、在线存储、实时计算和 A/B 测试这几个模块组成。其中,数据上报和离线训练组成了监督学习中的学习系统,而实时计算和 A/B 测试组成了预测系统。另外,除了模型之外,还有一个在线存储模块,用于存储模型和模型需要的特征信息供实时计算模块调用。图中的各个模块组成了训练和预测两条数据流,训练的数据流搜集业务的数据最后生成模型存储于在线存储模块;预测的数据流接受业务的预测请求,通过 A/B 测试模块访问实时计算模块获取预测结果。 数据上报:据上报模块的作用是搜集业务数据组成训练样本。一般分为收集、验证、清洗和转换几个步骤。将收集的数据转化为训练所需要的样本格式,保存到离线存储模块。 离线训练:线训练模块又细分为离线存储和离线计算。实际业务中使用的推荐系统一般都需要处理海量的用户行为数据,所以离线存储模块需要有一个分布式的文件系统或者存储平台来存储这些数据。离线计算常见的操作有:样本抽样、特征工程、模型训练、相似度计算等。 在线存储:因为线上的服务对于时延都有严格的要求。比如,某个用户打开手机 APP ,他肯定希望APP 能够快速响应,如果耗时过长,就会影响用户的体验。一般来说,这就要求推荐系统在几十毫秒以内处理完用户请求返回推荐结果,所以,针对线上的服务,需要有一个专门的在线存储模块,负责存储用于线上的模型和特征数据 。 实时推荐:实时推荐模块的功能是对来自业务的新请求进行预测。1.获取用户特征;2.调用推荐模型;3.结果排序。 在实际应用中,因为业务的物品列表太大,如果实时计算对每 个物品使用复杂的模型进行打分,就有可能耗时过长而影响用户满意度。所以,一种常见的做法是将推荐列表生成分为召回和排序两步。召回的作用是从大量的候选物品中(例如上百万)筛选出一批用户较可能喜欢的候选集 (一般是几百)。排序的作用是对召回得到的相对较小的候选集使用排序模型进行打分。更进一步,在排序得到推荐列表后,为了多样性和运营的一些考虑,还会加上第三步重排过滤,用于对精排后的推荐列表进行处理。 A/B测试:对于互联网产品来说, A/B 测试基本上是一个必备的模块,对于推荐系统来说也不例外,它可以帮助开发人员评估新算法对客户行为的影响。除了 离线的指标外,一个新的推荐算法上线之前 般都会经过 A/B 测试来测试新算法的有效性。 下图是与之对应的实际系统中各个组件的流转过程。需要注意的是生成推荐列表就已经做完了召回和排序的操作,业务层直接调用API就可以得到这个推荐列表。 2.2 在线训练对于业务来说,我们希望用户对于上 个广告的反馈 (喜欢或者不 欢,有没有点击 ,可以很快地用于下一个广告的推荐中。这就要求我们用另 种方法来解决这个问题,这个方法就是在线训练。 基于在线训练的推荐系统架构适合于广告和电商等高维度大数据量且对实时性要求很高的场景 相比较基于离线训练的推荐系统,基于在线训练的推荐系统不区分训练和测试阶段,每个回合都在学习,通过实时的反馈来调整策略。 方面,在线训练要求其样本、特征和模型的处理都是实时的,以便推荐的内容更快地反映用户实时的喜好;另一方面,因为在线训练井不需要将所有的训练数据都存储下来,所以不需要巨大的离线存储开销,使得系统具有很好的伸缩性,可以支持超大的数据量和模型。 样本处理:和基于离线训练的推荐系统相比,在线训练在数据上报阶段的主要不同体现在样本处理上。,对于离线训练来说,上报后的数据先是被存储到一个分布式文件系统,然后等待离线计算任务来对样本进行处理;对于在线训练来说,对样本的去重、过滤和采样等计算都需要实时进行。 实时特性:实时特征模块通过实时处理样本数据拼接训练需要的特征构造训练样本,输入流式训练模块用于更新模型。该模块的主要的功能是特征拼接和特征工程。 流式训练:、流式训练模块的主要作用是使用实时训练样本来更新模型。推荐算法中增量更新部分的计算,通过流式计算的方式来进行更新。在线训练的优势之一,是可以支持模型的稀疏存储。训练方面,在线模型不一定都是从零开始训练,而是可以将离线训练得到的模型参数作为基础,在这个基础上进行增量训练。 模型存储和加载:模型一般存储在参数服务器中。模型更新后,将模型文件推送到线上存储,并由线上服务模块动态加载。 3. 特征数据要训练推荐模型,就需要先收集用户的行为数据生成特征向量以后才能进行训练,而一个特征向量由特征以及特征的权重组成,在利用用户行为计算特征向量时需要考虑以下因素。 用户行为的种类:在一个网站中,用户可以对物品产生很多不同种类的行为。用户可以浏览物品、单击物品的链接、收藏物品、给物品打分、购买物品、评论物品、给物品打上不同的标签、和好友分享物品、搜索不同的关键词等。这些行为都会对物品特征的权重产生影响,但不同行为的影响不同,大多时候很难确定什么行为更加重要,一般的标准就是用户付出代价越大的行为权重越高。 用户行为产生的时间:一般来说,用户近期的行为比较重要,而用户很久之前的行为相对比较次要。因此,如果用户最近购买过某一个物品,那么这个物品对应的特征将会具有比较高的权重。 用户行为的次数:有时用户对一个物品会产生很多次行为。比如用户会听一首歌很多次,看一部电视剧的很多集等。因此用户对同一个物品的同一种行为发生的次数也反映了用户对物品的兴趣,行为次数多的物品对应的特征权重越高。 物品的热门程度:如果用户对一个很热门的物品产生了行为,往往不能代表用户的个性,因为用户可能是在跟风,可能对该物品并没有太大兴趣,特别是在用户对一个热门物品产生了偶尔几次不重要的行为(比如浏览行为)时,就更说明用户对这个物品可能没有什么兴趣,可能只是因为这个物品的链接到处都是,很容易点到而已。反之,如果用户对一个不热门的物品产生了行为,就说明了用户的个性需求。因此,推荐引擎在生成用户特征时会加重不热门物品对应的特征的权重。 数据去燥:对样本做去噪。对于数据中混杂的刷单等类作弊行为的数据,要将其排除出训练数据,否则它会直接影响模型的效果;样本中的缺失值也要做处理。 正负样本均衡:一般我们收集用户的行为数据都是属于正样本,造成了严重的不平衡。所以对于一个用户,从他没有过行为的物品中采样出一些物品作为负样本,但采样时,保证每个用户的正负样本数目相当。 特征组合:我们需要考虑特征与特征之间的关系。例如在美团酒店搜索排序中,酒店的销量、价格、用户的消费水平等是强相关的因素,用户的年龄、位置可能是弱相关的因素,用户的ID是完全无关的因素。在确定了哪些因素可能与预测目标相关后,我们需要将此信息表示为数值类型,即为特征抽取的过程。除此之外,用户在App上的浏览、交易等行为记录中包含了大量的信息,特征抽取则主要是从这些信息抽取出相关因素,用数值变量进行表示。常用的统计特征有计数特征,如浏览次数、下单次数等;比率特征,如点击率、转化率等;统计量特征,如价格均值、标准差、分位数、偏度、峰度等。 4. 协同过滤算法协同过滤算法起源于 1992 年,被 Xerox 公司用于个性化定制邮件系统。Xerox 司的用户需要在数十种主题中选择三到五种主题,协同过滤算法根据不同的主题过滤邮件,最终达到个性化的目的。 协同过滤算法分为基于物品的协同过滤和基于用户的协同过滤,输出结果为 TOPn 的推荐列表。 4.1 基于物品的协同过滤(ItemCF)基于物品的协同过滤算法的核心思想:给用户推荐那些和他们之前喜欢的物品相似的物品。 基于物品的协同过滤算法首先计算物品之间的相似度, 计算相似度的方法有以下几种: 基于共同喜欢物品的用户列表计算 $$w_{ij}=\\frac{|N(i)\\cap{}N(j)|}{\\sqrt{|N(i)|*|N(j)|}}$$ 在此,分母中 N(i) 是购买物品 i 的用户数,N(j) 是购买物品 j 的用户数,而分子 $N(i)\\cap{}N(j)$ 是同时购买物品i 和物品 j 的用户数。。可见上述的公式的核心是计算同时购买这件商品的人数比例 。当同时购买这两个物品人数越多,他们的相似度也就越高。另外值得注意的是,在分母中我们用了物品总购买人数做惩罚,也就是说某个物品可能很热门,导致它经常会被和其他物品一起购买,所以除以它的总购买人数,来降低它和其他物品的相似分数。 基于余弦的相似度计算 上面的方法计算物品相似度是直接使同时购买这两个物品的人数。但是也有可能存在用户购买了但不喜欢的情况 所以如果数据集包含了具体的评分数据 我们可以进一步把用户评分引入到相似度计算中 。 $$w_{ij}=cos\\theta=\\frac{N_iN_j}{||N_i||||N_j||}=\\frac{\\sum_{k=1}^{len}(n_{ki}n_{kj})}{\\sqrt{\\sum_{k=1}^{len}n_{ki}^2}*\\sqrt{\\sum_{k=1}^{len}n_{kj}^2}}$$ 其中 $n_{ki}$ 是用户 k 对物品 i 的评分,如果没有评分则为 0。 热门物品的惩罚 对于热门物品的问题,可以用如下公式解决: $$w_{ij}=\\frac{|N(i)\\cap{}N(j)|}{|N(i)|^\\alpha*|N(j)|^{1-\\alpha}}$$ 当 $\\alpha\\in(0,0.5)$ 时,N(i) 越小,惩罚得越厉害,从而会使热 物品相关性分数下降。 4.2 基于用户的协同过滤(UserCF)基于用户的协同过滤(User CF )的原理其实是和基于物品的协同过滤类似的。所不同的是,基于物品的协同过滤的原理是用户 U 购买了 A 物品,推荐给用户 U 和 A 相似的物品 B、C、D。而基于用户的协同过滤,是先计算用户 U 与其他的用户的相似度,然后取和 U 最相似的几个用户,把他们购买过的物品推荐给用户U。 为了计算用户相似度,我们首先要把用户购买过物品的索引数据转化成物品被用户购买过的索引数据,即物品的倒排索引: 建立好物品的倒排索引后,就可以根据相似度公式计算用户之间的相似度: $$w_{ab}=\\frac{|N(a)\\cap{}N(b)|}{\\sqrt{|N(a)|*|N(b)|}}$$ 其中 N(a) 表示用户 a 购买物品的数量,N(b) 表示用户 b 购买物品的数量,N(a)∩N(b) 表示用户 a 和 b 购买相同物品的数量。有了用户的相似数据,针对用户 U 挑选 K 个最相似的用户,把他们购买过的物品中,U 未购买过的物品推荐给用户 U 即可。 4.3 矩阵分解上述计算会得到一个相似度矩阵,而这个矩阵的大小和纬度都是很大的,需要进行降维处理,用到的是SVD的降维方法,具体可以参考我之前写的降维方法:2.5 降维方法 基于稀疏自编码的矩阵分解 矩阵分解技术在推荐领域的应用比较成熟,但是通过上一节的介绍,我们不难发现矩阵分解本质上只通过一次分解来对 原矩阵进行逼近,特征挖掘的层次不够深入。另外矩阵分解也没有运用到物品本身的内容特征,例如书本的类别分类、音乐的流派分类等。随着神经网络技术的兴起,笔者发现通过多层感知机,可以得到更加深度的特征表示,并且可以对内容分类特征加以应用。首先,我们介绍一下稀疏自编码神经网络的设计思路。 基础的自编码结构 最简单的自编码结构如下图,构造个三层的神经网络,我们让输出层等于输入层,且中间层的维度远低于输入层和输出层,这样就得到了第一层的特征压缩。 简单来说自编码神经网络尝试学习中间层约等于输入层的函数。换句话说,它尝试逼近一个恒等函数。如果网络的输入数据是完全随机的,比如每一个输入都是一个跟其他特征完全无关的独立同分布高斯随机变 ,那么这一压缩表示将会非常难于学习。但是如果输入数据中隐含着 些特定的结构,比如某些输入特征是彼此相关的,那么这一算法就可以发现输入数据中的这些相关性。 多层结构 基于以上的单层隐藏层的网络结构,我们可以扩展至多层网络结构,学习到更高层次的抽象特征。 5. 隐语义模型5.1 基本思想推荐系统中一个重要的分支,隐语义建模。隐语义模型LFM:Latent Factor Model,其核心思想就是通过隐含特征联系用户兴趣和物品。 过程分为三个部分,将物品映射到隐含分类,确定用户对隐含分类的兴趣,然后选择用户感兴趣的分类中的物品推荐给用户。它是基于用户行为统计的自动聚类。 隐语义模型在Top-N推荐中的应用十分广泛。常用的隐语义模型,LSA(Latent Semantic Analysis),LDA(Latent Dirichlet Allocation),主题模型(Topic Model),矩阵分解(Matrix Factorization)等等。 首先通过一个例子来理解一下这个模型,比如说有两个用户A和B,目前有用户的阅读列表,用户A的兴趣涉及侦探小说,科普图书以及一些计算机技术书,而用户B的兴趣比较集中在数学和机器学习方面。那么如何给A和B推荐图书呢? 对于UserCF,首先需要找到和他们看了同样书的其他用户(兴趣相似的用户),然后在给他们推荐那些用户喜欢的其他书。对于ItemCF,需要给他们推荐和他们已经看的书相似的书,比如用户B 看了很多数据挖掘方面的书,那么可以给他推荐机器学习或者模式识别方面的书。 还有一种方法就是使用隐语义模型,可以对书和物品的兴趣进行分类。对于某个用户,首先得到他的兴趣分类,然后从分类中挑选他可能喜欢的物品。 5.2 模型理解 如何给物品进行分类? 如何确定用户对哪些类的物品感兴趣,以及感兴趣的程度? 对于一个给定的类,选择哪些属于这个类的物品推荐给用户,以及如何确定这些物品在一个类中的权重? 为了解决上面的问题,研究人员提出:为什么我们不从数据出发,自动地找到那些类,然后进行个性化推荐,隐语义分析技术因为采取基于用户行为统计的自动聚类,较好地解决了上面的问题。隐语义分析技术从诞生到今天产生了很多著名的模型和方法,其中和推荐技术相关的有pLSA,LDA,隐含类别模型(latent class model), 隐含主题模型(latent topic model), 矩阵分解(matrix factorization)。 LFM通过如下公式计算用户 u 对物品 i 的兴趣: $$preference(u,i)=r_{ui}=p_u^Tq_i=\\sum_{f=1}^Fp_{u,k}q_{i,k}$$ 这个公式中 $p_{u,k}$ 和 $q_{i,k}$ 是模型的参数,其中 $p_{u,k}$ 度量了用户 u 的兴趣和第 k 个隐类的关系,而$q_{i,k}$度量了第 k 个隐类和物品 i 之间的关系。那么,下面的问题就是如何计算这两个参数。 对最优化理论或者机器学习有所了解的读者,可能对如何计算这两个参数都比较清楚。这两个参数是从数据集中计算出来的。要计算这两个参数,需要一个训练集,对于每个用户u,训练集里都包含了用户u喜欢的物品和不感兴趣的物品,通过学习这个数据集,就可以获得上面的模型参数。 6. 排序算法在工业应用中,推荐系统通常可分为两部分,召回和排序。协同过滤属于召回的算法,从召回中得到一个比较小的推荐列表,然后经过排序之后才会输出到最终的推荐列表里,是一个有序的推荐列表。 这个过程会从几千万 item 中筛选出几百或者上千的候选集,然后在排序阶段选出30个给到每位用户。这个排序可理解为一个函数,F(user, item, context),输入为用户、物品、环境,输出一个0到1之间的分数,取分数最高的几首。这一过程通常称为 CTR 预估。那么 F 函数常见的运作形式有: Logistic Regression 最简单的是逻辑回归(Logistic Regression),一个广义线性模型。拿某 user 的用户画像(一个向量)比如[3, 1],拼接上某 item 的物品画像比如[4, 0],再加上代表 context 的向量[0, 1, 1]后得到[3, 1, 4, 0, 0, 1, 1],若该 user 曾与该 item 发生过联系则 label 为1,这些加起来是一个正样本,同时可以将用户“跳过”的 item 或热门的却没有与用户产生过联系的 item 作为负样本,label 为0。按照这样的输入和输出就可以训练出排序算法了。详细模型见:2. 逻辑回归 GBDT 使用梯度提升决策树(GBDT) 的方案也可以解决这个排序的问题,只是模型与 LR 不一样。GBDT作为集成模型,会使用多棵决策树,每棵树去拟合前一棵树的残差来得到很好的拟合效果。一个样本输入到一棵树中,会根据各节点的条件往下走到某个叶子节点,将此节点值置为1,其余置为0。详细模型算法见:3.2 GBDT GBDT+LR GBDT与LR的stacking模型相对于只用GBDT会有略微的提升,更大的好处是防止GBDT过拟合。升级为GBDT+LR后,线上效果提升了约5%,并且因为省去了对新特征进行人工转换的步骤,增加特征的迭代测试也更容易了。 GBDT+FM GBDT是不支持高维稀疏特征的,如果将高维特征加到LR中,一方面需要人工组合高维特征,另一方面模型维度和计算复杂度会是O(N^2)级别的增长。所以设计了GBDT+FM的模型如图所示,采用Factorization Machines模型替换LR。 Factorization Machines(FM)模型如下所示: $$\\hat{y}(x)=w_0+\\sum_{i=1}^nw_ix_i+\\sum_{i=1}^n\\sum_{j=i+1}^n<v_i,v_j>x_ix_j$$ 具有以下几个优点①前两项为一个线性模型,相当于LR模型的作用②第三项为一个二次交叉项,能够自动对特征进行交叉组合③通过增加隐向量,模型训练和预测的计算复杂度降为了O(N)④支持稀疏特征。 几个优点,使的GBDT+FM具有了良好的稀疏特征支持,FM使用GBDT的叶子结点和稀疏特征(内容特征)作为输入,模型结构示意图如下,GBDT+FM模型上线后相比GBDT+LR在各项指标的效果提升在4%~6%之间。 DNN+GBDT+FM GBDT+FM模型,对embedding等具有结构信息的深度特征利用不充分,而深度学习(Deep Neural Network)能够对嵌入式(embedding)特征和普通稠密特征进行学习,抽取出深层信息,提高模型的准确性,并已经成功应用到众多机器学习领域。因此我们将DNN引入到排序模型中,提高排序整体质量。 DNN+GBDT+FM的ensemble模型架构如图所示,FM层作为模型的最后一层,即融合层,其输入由三部分组成:DNN的最后一层隐藏层、GBDT的输出叶子节点、高维稀疏特征。DNN+GBDT+FM的ensemble模型架构介绍如下所示,该模型上线后相对于GBDT+FM有4%的效果提升。 使用分布式的TensorFlow进行训练,使用基于TensorFlow Serving的微服务进行在线预测,DNN+GBDT+FM的ensemble模型使用的是Adam优化器。Adam结合了The Adaptive Gradient Algorithm(AdaGrad)和Root Mean Square Propagation(RMSProp)算法。具有更优的收敛速率,每个变量有独自的下降步长,整体下降步长会根据当前梯度进行调节,能够适应带噪音的数据。实验测试了多种优化器,Adam的效果是最优的。 工业界DNN ranking现状 Youtube于2016年推出DNN排序算法。 上海交通大学和UCL于2016年推出Product-based Neural Network(PNN)网络进行用户点击预测。PNN相当于在DNN层做了特征交叉,我们的做法是把特征交叉交给FM去做,DNN专注于深层信息的提取。 Google于2016年推出Wide And Deep Model,这个也是我们当前模型的基础,在此基础上使用FM替换了Cross Feature LR,简化了计算复杂度,提高交叉的泛化能力。 阿里今年使用attention机制推出了Deep Interest Network(DIN)进行商品点击率预估,优化embedding向量的准确性,值得借鉴。 7. 评估测试7.1 A/B测试新的推荐模型上线后要进行A/B测试,将它和旧的算法进行比较。 AB测试是一种很常用的在线评测算法的实验方法。它通过一定的规则将用户随机分成几组,并对不同组的用户采用不同的算法,然后通过统计不同组用户的各种不同的评测指标比较不同算法,比如可以统计不同组用户的点击率,通过点击率比较不同算法的性能。对AB测试感兴趣的读者可以浏览一下网站http://www.abtests.com/ ,该网站给出了很多通过实际AB测试提高网站用户满意度的例子,从中我们可以学习到如何进行合理的AB测试。 切分流量是AB测试中的关键,不同的层以及控制这些层的团队需要从一个统一的地方获得自己AB测试的流量,而不同层之间的流量应该是正交的。 “正交性”是从几何中借来的术语。如果两条直线相交成直角,他们就是正交的。用向量术语来说,这两条直线互不依赖。 下图是一个简单的AB测试系统。用户进入网站后,流量分配系统决定用户是否需要被进行AB测试,如果需要的话,流量分配系统会给用户打上在测试中属于什么分组的标签。然后用户浏览网页,而用户在浏览网页时的行为都会被通过日志系统发回后台的日志数据库。此时,如果用户有测试分组的标签,那么该标签也会被发回后台数据库。在后台,实验人员的工作首先是配置流量分配系统,决定满足什么条件的用户参加什么样的测试。其次,实验人员需要统计日志数据库中的数据,通过评测系统生成不同分组用户的实验报告,并比较和评测实验结果。 当完成了AB测试后,根据指标结果,如果优于之前的推荐算法,那么旧的算法就可以替换成新的了。 7.2 其它评估方法模型准备就绪后,一般会先通过离线指标来评估模型的好坏, 然后再决定能否上线测试。离线算法评估常见的指标包括准确率、覆盖度 、多样性、新颖性和 UC 等。在线测试一般通过 A/B 测试进行,常见的指标有点击率、用户停留时间、 广告收入等,需要注意分析统计显著性。同时,需要注意短期的指标和长期的指标相结合, 一些短期指标的提升有时候反而会导致长期指标下降 比如 ,经常推荐美女或者搞笑类的内容会带来短期的点击率提高,但是可能会引起长期的用户粘性下降。设计者需要从自己的产品角度出发,根据产品的需要制定评估指标,这样才能更好地指导推荐系统的优化方向。常见的评价指标如下: 8. 推荐系统冷启动问题冷启动( cold start )在推荐系统中表示该系统积累数据量过少,无法给新用户作个性化推荐的问题,这是产品推荐的一大难题。每个有推荐功能的产品都会遇到冷启动的问题。一方面,当新商品时上架 会遇到冷启动的问题,没有收集到任何一个用户对其浏览、点击或者购买的行为,也无从判断如何将商品进行推荐;另一方面,新用户到来的时候,如果没有他在应用上的行为数据,也无法预测其兴趣,如果给用户的推荐千篇律,没有亮点,会使用户在一开始就对产品失去兴趣,从而放弃使用。所以在冷启动的时候要同时考虑用户的冷启动和物品的冷启动。 基本上,冷启动题可以分为以下三类。 8.1 用户冷启动用户冷启动主要解决如何给新用户作个性化推荐的问题。当新用户到来时,我 没有他的行为数据,所以也无法根据他的历史行为预 其兴趣,从而无法借此给他做个性化推荐。解决方法参考以下: 利用用户的账号信息。 利用用户的手机 IMEI 号进行冷启动。 制造选工页,让用户选择自己感兴趣的点后,即时生成粗粒度的推荐。 8.2 物品冷启动物品冷启动主要解决如何将新的物品推荐给可能对它感兴趣的用户这一问题。解决方法参考以下: 利用物品的内容、分类信息。 利用专家标注的数据。 8.3 系统冷启动系统冷启动主要解决如何在一个新开发的网站上(还没有用户,也没有用户行为,只有一些物品的信息)设计个性推荐系统,从而在产品刚上线时就让用户体验到个性 推荐服务这一问题。 9. 参考文献 推荐系统实践–项亮 推荐系统与深度学习 美团机器学习实践 【机器学习通俗易懂系列文章】 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"推荐系统","slug":"推荐系统","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F/"}],"tags":[]},{"title":"【NLP】注意力机制(Attention)","slug":"NLP/Attention","date":"2019-08-30T16:00:00.000Z","updated":"2019-12-25T06:21:24.858Z","comments":true,"path":"2019/08/31/NLP/Attention/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/31/NLP/Attention/","excerpt":"什么是Attention机制 在“编码器—解码器(seq2seq)”⼀节⾥,解码器在各个时间步依赖相同的背景变量来获取输⼊序列信息。当编码器为循环神经⽹络时,背景变量来⾃它最终时间步的隐藏状态。 现在,让我们再次思考那⼀节提到的翻译例⼦:输⼊为英语序列“They”“are…","text":"什么是Attention机制 在“编码器—解码器(seq2seq)”⼀节⾥,解码器在各个时间步依赖相同的背景变量来获取输⼊序列信息。当编码器为循环神经⽹络时,背景变量来⾃它最终时间步的隐藏状态。 现在,让我们再次思考那⼀节提到的翻译例⼦:输⼊为英语序列“They”“are… 1. 什么是Attention机制在“编码器—解码器(seq2seq)”⼀节⾥,解码器在各个时间步依赖相同的背景变量来获取输⼊序列信息。当编码器为循环神经⽹络时,背景变量来⾃它最终时间步的隐藏状态。 现在,让我们再次思考那⼀节提到的翻译例⼦:输⼊为英语序列“They”“are”“watching”“.”,输出为法语序列“Ils”“regardent”“.”。不难想到,解码器在⽣成输出序列中的每⼀个词时可能只需利⽤输⼊序列某⼀部分的信息。例如,在输出序列的时间步1,解码器可以主要依赖“They”“are”的信息来⽣成“Ils”,在时间步2则主要使⽤来⾃“watching”的编码信息⽣成“regardent”,最后在时间步3则直接映射句号“.”。这看上去就像是在解码器的每⼀时间步对输⼊序列中不同时间步的表征或编码信息分配不同的注意⼒⼀样。这也是注意⼒机制的由来。 仍然以循环神经⽹络为例,注意⼒机制通过对编码器所有时间步的隐藏状态做加权平均来得到背景变量。解码器在每⼀时间步调整这些权重,即注意⼒权重,从而能够在不同时间步分别关注输⼊序列中的不同部分并编码进相应时间步的背景变量。 在注意⼒机制中,解码器的每⼀时间步将使⽤可变的背景变量。记 ct′ 是解码器在时间步 t′ 的背景变量,那么解码器在该时间步的隐藏状态可以改写为: $$s_{t^{′}}=g(y_{t^{′}-1},c_{t^{′}},s_{t^{′}-1})$$ 这⾥的关键是如何计算背景变量 ct′ 和如何利⽤它来更新隐藏状态 st′。下⾯将分别描述这两个关键点。 2. 编解码器中的Attention2.1 计算背景变量我们先描述第⼀个关键点,即计算背景变量。下图描绘了注意⼒机制如何为解码器在时间步 2 计算背景变量。 函数 a 根据解码器在时间步 1 的隐藏状态和编码器在各个时间步的隐藏状态计算softmax运算的输⼊。 softmax运算输出概率分布并对编码器各个时间步的隐藏状态做加权平均,从而得到背景变量。 令编码器在时间步t的隐藏状态为 ht,且总时间步数为 T。那么解码器在时间步 t′ 的背景变量为所有编码器隐藏状态的加权平均: $$c_{t^{′}}=\\sum_{t=1}^{T}\\alpha_{t^{′}t}h_t$$ 矢量化计算背景变量 我们还可以对注意⼒机制采⽤更⾼效的⽮量化计算。我们先定义,在上⾯的例⼦中,查询项为解码器的隐藏状态,键项和值项均为编码器的隐藏状态。 ⼴义上,注意⼒机制的输⼊包括查询项以及⼀⼀对应的键项和值项,其中值项是需要加权平均的⼀组项。在加权平均中,值项的权重来⾃查询项以及与该值项对应的键项的计算。 让我们考虑⼀个常⻅的简单情形,即编码器和解码器的隐藏单元个数均为 h,且函数 $a(s,h)=s^Th$。假设我们希望根据解码器单个隐藏状态 st′−1 和编码器所有隐藏状态 ht, t = 1, . . . , T来计算背景向量 ct′ 。我们可以将查询项矩阵 Q 设为 $s_{t^{′}-1}^T$,并令键项矩阵 K 和值项矩阵 V 相同且第 t ⾏均为 $h_t^T$。此时,我们只需要通过⽮量化计算: $$softmax(QK^T)V$$ 即可算出转置后的背景向量 $c_{t^{′}}^T$。当查询项矩阵 Q 的⾏数为 n 时,上式将得到 n ⾏的输出矩阵。输出矩阵与查询项矩阵在相同⾏上⼀⼀对应。 2.3 更新隐藏状态现在我们描述第⼆个关键点,即更新隐藏状态。以⻔控循环单元为例,在解码器中我们可以对⻔控循环单元(GRU)中⻔控循环单元的设计稍作修改,从而变换上⼀时间步 t′−1 的输出 yt′−1、隐藏状态 st′−1 和当前时间步t′ 的含注意⼒机制的背景变量 ct′。解码器在时间步: math:t’ 的隐藏状态为: $$s_{t^{′}}=z_{t^{′}}⊙s_{t^{′}-1}+(1-z_{t^{′}})⊙\\tilde{s}_{t^{′}}$$ 其中的重置⻔、更新⻔和候选隐藏状态分别为: $$r_{t^{′}}=\\sigma(W_{yr}y_{t^{′}-1}+W_{sr}s_{t^{′}-1}+W_{cr}c_{t^{′}}+b_r)$$ $$z_{t^{′}}=\\sigma(W_{yz}y_{t^{′}-1}+W_{sz}s_{t^{′}-1}+W_{cz}c_{t^{′}}+b_z)$$ $$\\tilde{s}{t^{′}}=tanh(W{ys}y_{t^{′}-1}+W_{ss}(s_{t^{′}-1}⊙r_{t^{′}})+W_{cs}c_{t^{′}}+b_s)$$ 其中含下标的 W 和 b 分别为⻔控循环单元的权重参数和偏差参数。 3. Attention本质3.1 机器翻译说明Attention本节先以机器翻译作为例子讲解最常见的Soft Attention模型的基本原理,之后抛离Encoder-Decoder框架抽象出了注意力机制的本质思想。 如果拿机器翻译来解释这个Encoder-Decoder框架更好理解,比如输入的是英文句子:Tom chase Jerry,Encoder-Decoder框架逐步生成中文单词:“汤姆”,“追逐”,“杰瑞”。 在翻译“杰瑞”这个中文单词的时候,模型里面的每个英文单词对于翻译目标单词“杰瑞”贡献是相同的,很明显这里不太合理,显然“Jerry”对于翻译成“杰瑞”更重要,但是模型是无法体现这一点的,这就是为何说它没有引入注意力的原因。 没有引入注意力的模型在输入句子比较短的时候问题不大,但是如果输入句子比较长,此时所有语义完全通过一个中间语义向量来表示,单词自身的信息已经消失,可想而知会丢失很多细节信息,这也是为何要引入注意力模型的重要原因。 上面的例子中,如果引入Attention模型的话,应该在翻译“杰瑞”的时候,体现出英文单词对于翻译当前中文单词不同的影响程度,比如给出类似下面一个概率分布值: (Tom,0.3)(Chase,0.2) (Jerry,0.5) 每个英文单词的概率代表了翻译当前单词“杰瑞”时,注意力分配模型分配给不同英文单词的注意力大小。这对于正确翻译目标语单词肯定是有帮助的,因为引入了新的信息。 同理,目标句子中的每个单词都应该学会其对应的源语句子中单词的注意力分配概率信息。这意味着在生成每个单词yi的时候,原先都是相同的中间语义表示C会被替换成根据当前生成单词而不断变化的Ci。理解Attention模型的关键就是这里,即由固定的中间语义表示C换成了根据当前输出单词来调整成加入注意力模型的变化的Ci。增加了注意力模型的Encoder-Decoder框架理解起来如下图所示。 每个Ci可能对应着不同的源语句子单词的注意力分配概率分布,比如对于上面的英汉翻译来说,其对应的信息可能如下: $$C_{汤姆}=g(0.6f2(tom),0.2f2(chase),0.2*f2(jerry))$$ $$C(追逐)=g(0.2f2(tom),0.7f2(chase),0.1*f2(jerry))$$ $$C(杰瑞)=g(0.3f2(tom),0.2f2(chase),0.5*f2(jerry))$$ 其中,f2函数代表Encoder对输入英文单词的某种变换函数,比如如果Encoder是用的RNN模型的话,这个f2函数的结果往往是某个时刻输入xi后隐层节点的状态值;g代表Encoder根据单词的中间表示合成整个句子中间语义表示的变换函数,一般的做法中,g函数就是对构成元素加权求和,即下列公式: $$C_i=\\sum_{j=1}^{L_x}a_{ij}h_j$$ 其中,Lx代表输入句子Source的长度,aij代表在Target输出第i个单词时Source输入句子中第j个单词的注意力分配系数,而hj则是Source输入句子中第j个单词的语义编码。假设下标i就是上面例子所说的“ 汤姆” ,那么Lx就是3,h1=f(“Tom”),h2=f(“Chase”),h3=f(“Jerry”)分别是输入句子每个单词的语义编码,对应的注意力模型权值则分别是0.6,0.2,0.2,所以g函数本质上就是个加权求和函数。 3.2 注意力分配概率计算这里还有一个问题:生成目标句子某个单词,比如“汤姆”的时候,如何知道Attention模型所需要的输入句子单词注意力分配概率分布值呢?就是说“汤姆”对应的输入句子Source中各个单词的概率分布:(Tom,0.6)(Chase,0.2) (Jerry,0.2) 是如何得到的呢? 对于采用RNN的Decoder来说,在时刻i,如果要生成yi单词,我们是可以知道Target在生成Yi之前的时刻i-1时,隐层节点i-1时刻的输出值Hi-1的,而我们的目的是要计算生成Yi时输入句子中的单词“Tom”、“Chase”、“Jerry”对Yi来说的注意力分配概率分布,那么可以用Target输出句子i-1时刻的隐层节点状态Hi-1去一一和输入句子Source中每个单词对应的RNN隐层节点状态hj进行对比,即通过函数F(hj,Hi-1)来获得目标单词yi和每个输入单词对应的对齐可能性,这个F函数在不同论文里可能会采取不同的方法,然后函数F的输出经过Softmax进行归一化就得到了符合概率分布取值区间的注意力分配概率分布数值。 3.3 Attention的物理含义一般在自然语言处理应用里会把Attention模型看作是输出Target句子中某个单词和输入Source句子每个单词的对齐模型,这是非常有道理的。 目标句子生成的每个单词对应输入句子单词的概率分布可以理解为输入句子单词和这个目标生成单词的对齐概率,这在机器翻译语境下是非常直观的:传统的统计机器翻译一般在做的过程中会专门有一个短语对齐的步骤,而注意力模型其实起的是相同的作用。 如果把Attention机制从上文讲述例子中的Encoder-Decoder框架中剥离,并进一步做抽象,可以更容易看懂Attention机制的本质思想。 我们可以这样来看待Attention机制(参考图9):将Source中的构成元素想象成是由一系列的<Key,Value>数据对构成,此时给定Target中的某个元素Query,通过计算Query和各个Key的相似性或者相关性,得到每个Key对应Value的权重系数,然后对Value进行加权求和,即得到了最终的Attention数值。所以本质上Attention机制是对Source中元素的Value值进行加权求和,而Query和Key用来计算对应Value的权重系数。即可以将其本质思想改写为如下公式: $$Attention(Query,Source)=\\sum_{i=1}^{L_x}Similarity(Query,key_i)*Value_i$$ 其中,Lx=||Source||代表Source的长度,公式含义即如上所述。上文所举的机器翻译的例子里,因为在计算Attention的过程中,Source中的Key和Value合二为一,指向的是同一个东西,也即输入句子中每个单词对应的语义编码,所以可能不容易看出这种能够体现本质思想的结构。 至于Attention机制的具体计算过程,如果对目前大多数方法进行抽象的话,可以将其归纳为两个过程:第一个过程是根据Query和Key计算权重系数,第二个过程根据权重系数对Value进行加权求和。而第一个过程又可以细分为两个阶段:第一个阶段根据Query和Key计算两者的相似性或者相关性;第二个阶段对第一阶段的原始分值进行归一化处理; 4. Self-Attention模型Self Attention也经常被称为intra Attention(内部Attention),最近一年也获得了比较广泛的使用,比如Google最新的机器翻译模型内部大量采用了Self Attention模型。 在一般任务的Encoder-Decoder框架中,输入Source和输出Target内容是不一样的,比如对于英-中机器翻译来说,Source是英文句子,Target是对应的翻译出的中文句子,Attention机制发生在Target的元素Query和Source中的所有元素之间。而Self Attention顾名思义,指的不是Target和Source之间的Attention机制,而是Source内部元素之间或者Target内部元素之间发生的Attention机制,也可以理解为Target=Source这种特殊情况下的注意力计算机制。其具体计算过程是一样的,只是计算对象发生了变化而已,所以此处不再赘述其计算过程细节。 很明显,引入Self Attention后会更容易捕获句子中长距离的相互依赖的特征,因为如果是RNN或者LSTM,需要依次序序列计算,对于远距离的相互依赖的特征,要经过若干时间步步骤的信息累积才能将两者联系起来,而距离越远,有效捕获的可能性越小。 但是Self Attention在计算过程中会直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,所以远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征。除此外,Self Attention对于增加计算的并行性也有直接帮助作用。这是为何Self Attention逐渐被广泛使用的主要原因。 5. 发展本质上,注意⼒机制能够为表征中较有价值的部分分配较多的计算资源。这个有趣的想法⾃提出后得到了快速发展,特别是启发了依靠注意⼒机制来编码输⼊序列并解码出输出序列的变换器(Transformer)模型的设计。变换器抛弃了卷积神经⽹络和循环神经⽹络的架构。它在计算效率上⽐基于循环神经⽹络的编码器—解码器模型通常更具明显优势。含注意⼒机制的变换器的编码结构在后来的BERT预训练模型中得以应⽤并令后者⼤放异彩:微调后的模型在多达11项⾃然语⾔处理任务中取得了当时最先进的结果。不久后,同样是基于变换器设计的GPT-2模型于新收集的语料数据集预训练后,在7个未参与训练的语⾔模型数据集上均取得了当时最先进的结果。除了⾃然语⾔处理领域,注意⼒机制还被⼴泛⽤于图像分类、⾃动图像描述、唇语解读以及语⾳识别。 6. 代码实现注意力模型实现中英文机器翻译 数据预处理 首先先下载本目录的数据和代码,并执行 datautil.py,生成中、英文字典。 执行 train.ipynb,训练时间会比较长。 测试模型,运行test.py文件。 【机器学习通俗易懂系列文章】 7. 参考文献动手学深度学习 注意力机制的基本思想和实现原理 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】seq2seq","slug":"NLP/seq2seq","date":"2019-08-29T16:00:00.000Z","updated":"2019-12-25T06:06:46.794Z","comments":true,"path":"2019/08/30/NLP/seq2seq/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/30/NLP/seq2seq/","excerpt":"在⾃然语⾔处理的很多应⽤中,输⼊和输出都可以是不定⻓序列。以机器翻译为例,输⼊可以是⼀段不定⻓的英语⽂本序列,输出可以是⼀段不定⻓的法语⽂本序列,例如: 英语输⼊:“They”、“are”、“watching”、“.” 法语输出:“Ils”、“regardent”、“.” 当输⼊和输出都是不定⻓序…","text":"在⾃然语⾔处理的很多应⽤中,输⼊和输出都可以是不定⻓序列。以机器翻译为例,输⼊可以是⼀段不定⻓的英语⽂本序列,输出可以是⼀段不定⻓的法语⽂本序列,例如: 英语输⼊:“They”、“are”、“watching”、“.” 法语输出:“Ils”、“regardent”、“.” 当输⼊和输出都是不定⻓序… 1. 什么是seq2seq在⾃然语⾔处理的很多应⽤中,输⼊和输出都可以是不定⻓序列。以机器翻译为例,输⼊可以是⼀段不定⻓的英语⽂本序列,输出可以是⼀段不定⻓的法语⽂本序列,例如: 英语输⼊:“They”、“are”、“watching”、“.” 法语输出:“Ils”、“regardent”、“.” 当输⼊和输出都是不定⻓序列时,我们可以使⽤编码器—解码器(encoder-decoder)或者seq2seq模型。序列到序列模型,简称seq2seq模型。这两个模型本质上都⽤到了两个循环神经⽹络,分别叫做编码器和解码器。编码器⽤来分析输⼊序列,解码器⽤来⽣成输出序列。两 个循环神经网络是共同训练的。 下图描述了使⽤编码器—解码器将上述英语句⼦翻译成法语句⼦的⼀种⽅法。在训练数据集中,我们可以在每个句⼦后附上特殊符号“<eos>”(end of sequence)以表⽰序列的终⽌。编码器每个时间步的输⼊依次为英语句⼦中的单词、标点和特殊符号“<eos>”。下图中使⽤了编码器在 最终时间步的隐藏状态作为输⼊句⼦的表征或编码信息。解码器在各个时间步中使⽤输⼊句⼦的 编码信息和上个时间步的输出以及隐藏状态作为输⼊。我们希望解码器在各个时间步能正确依次 输出翻译后的法语单词、标点和特殊符号“<eos>”。需要注意的是,解码器在最初时间步的输⼊ ⽤到了⼀个表⽰序列开始的特殊符号“”(beginning of sequence)。 2. 编码器编码器的作⽤是把⼀个不定⻓的输⼊序列变换成⼀个定⻓的背景变量 c,并在该背景变量中编码输⼊序列信息。常⽤的编码器是循环神经⽹络。 让我们考虑批量⼤小为1的时序数据样本。假设输⼊序列是 x1, . . . , xT,例如 xi 是输⼊句⼦中的第 i 个词。在时间步 t,循环神经⽹络将输⼊ xt 的特征向量 xt 和上个时间步的隐藏状态$h_{t-1}$变换为当前时间步的隐藏状态ht。我们可以⽤函数 f 表达循环神经⽹络隐藏层的变换: $$h_t=f(x_t,h_{t-1})$$ 接下来,编码器通过⾃定义函数 q 将各个时间步的隐藏状态变换为背景变量: $$c=q(h_1,…,h_T)$$ 例如,当选择 q(h1, . . . , h*T* ) = h*T* 时,背景变量是输⼊序列最终时间步的隐藏状态h*T*。 以上描述的编码器是⼀个单向的循环神经⽹络,每个时间步的隐藏状态只取决于该时间步及之前的输⼊⼦序列。我们也可以使⽤双向循环神经⽹络构造编码器。在这种情况下,编码器每个时间步的隐藏状态同时取决于该时间步之前和之后的⼦序列(包括当前时间步的输⼊),并编码了整个序列的信息。 3. 解码器刚刚已经介绍,编码器输出的背景变量 c 编码了整个输⼊序列 x1, . . . , xT 的信息。给定训练样本中的输出序列 y1, y2, . . . , yT′ ,对每个时间步 t′(符号与输⼊序列或编码器的时间步 t 有区别),解码器输出 yt′ 的条件概率将基于之前的输出序列 $y_1,…,y_{t^{′}-1}$ 和背景变量 c,即: $$P(y_{t^{′}}|y_1,…,y_{t^{′}-1},c)$$ 为此,我们可以使⽤另⼀个循环神经⽹络作为解码器。在输出序列的时间步 t′,解码器将上⼀时间步的输出 $y_{t^{′}-1}$ 以及背景变量 c 作为输⼊,并将它们与上⼀时间步的隐藏状态 $s_{t^{′}-1}$ 变换为当前时间步的隐藏状态st′。因此,我们可以⽤函数 g 表达解码器隐藏层的变换: $$s_{t^{′}}=g(y_{t^{′}-1},c,s_{t^{′}-1})$$ 有了解码器的隐藏状态后,我们可以使⽤⾃定义的输出层和softmax运算来计算$P(y_{t^{′}}|y_1,…,y_{t^{′}-1},c)$,例如,基于当前时间步的解码器隐藏状态 st′、上⼀时间步的输出$s_{t^{′}-1}$以及背景变量 c 来计算当前时间步输出 yt′ 的概率分布。 4. 训练模型根据最⼤似然估计,我们可以最⼤化输出序列基于输⼊序列的条件概率: $$P(y_1,…,y_{t^{′}-1}|x_1,…,x_T)=\\prod_{t^{′}=1}^{T^{′}}P(y_{t^{′}}|y_1,…,y_{t^{′}-1},x_1,…,x_T)$$ $$=\\prod_{t^{′}=1}^{T^{′}}P(y_{t^{′}}|y_1,…,y_{t^{′}-1},c)$$ 并得到该输出序列的损失: $$-logP(y_1,…,y_{t^{′}-1}|x_1,…,x_T)=-\\sum_{t^{′}=1}^{T^{′}}logP(y_{t^{′}}|y_1,…,y_{t^{′}-1},c)$$ 在模型训练中,所有输出序列损失的均值通常作为需要最小化的损失函数。在上图所描述的模型预测中,我们需要将解码器在上⼀个时间步的输出作为当前时间步的输⼊。与此不同,在训练中我们也可以将标签序列(训练集的真实输出序列)在上⼀个时间步的标签作为解码器在当前时间步的输⼊。这叫作强制教学(teacher forcing)。 5. seq2seq模型预测以上介绍了如何训练输⼊和输出均为不定⻓序列的编码器—解码器。本节我们介绍如何使⽤编码器—解码器来预测不定⻓的序列。 在准备训练数据集时,我们通常会在样本的输⼊序列和输出序列后面分别附上⼀个特殊符号“<eos>”表⽰序列的终⽌。我们在接下来的讨论中也将沿⽤上⼀节的全部数学符号。为了便于讨论,假设解码器的输出是⼀段⽂本序列。设输出⽂本词典Y(包含特殊符号“<eos>”)的⼤小为|Y|,输出序列的最⼤⻓度为T′。所有可能的输出序列⼀共有 $O(|y|^{T^{′}})$ 种。这些输出序列中所有特殊符号“<eos>”后⾯的⼦序列将被舍弃。 5.1 贪婪搜索贪婪搜索(greedy search)。对于输出序列任⼀时间步t′,我们从|Y|个词中搜索出条件概率最⼤的词: $$y_{t^{′}}=argmax_{y\\in_{}Y}P(y|y_1,…,y_{t^{′}-1},c)$$ 作为输出。⼀旦搜索出“<eos>”符号,或者输出序列⻓度已经达到了最⼤⻓度T′,便完成输出。我们在描述解码器时提到,基于输⼊序列⽣成输出序列的条件概率是$\\prod_{t^{′}=1}^{T^{′}}P(y_{t^{′}}|y_1,…,y_{t^{′}-1},c)$。我们将该条件概率最⼤的输出序列称为最优输出序列。而贪婪搜索的主要问题是不能保证得到最优输出序列。 下⾯来看⼀个例⼦。假设输出词典⾥⾯有“A”“B”“C”和“<eos>”这4个词。下图中每个时间步下的4个数字分别代表了该时间步⽣成“A”“B”“C”和“<eos>”这4个词的条件概率。在每个时间步,贪婪搜索选取条件概率最⼤的词。因此,图10.9中将⽣成输出序列“A”“B”“C”“<eos>”。该输出序列的条件概率是0.5 × 0.4 × 0.4 × 0.6 = 0.048。 接下来,观察下面演⽰的例⼦。与上图中不同,在时间步2中选取了条件概率第⼆⼤的词“C”。由于时间步3所基于的时间步1和2的输出⼦序列由上图中的“A”“B”变为了下图中的“A”“C”,下图中时间步3⽣成各个词的条件概率发⽣了变化。我们选取条件概率最⼤的词“B”。此时时间步4所基于的前3个时间步的输出⼦序列为“A”“C”“B”,与上图中的“A”“B”“C”不同。因此,下图中时间步4⽣成各个词的条件概率也与上图中的不同。我们发现,此时的输出序列“A”“C”“B”“<eos>”的条件概率是0.5 × 0.3 × 0.6 × 0.6 = 0.054,⼤于贪婪搜索得到的输出序列的条件概率。因此,贪婪搜索得到的输出序列“A”“B”“C”“<eos>”并⾮最优输出序列。 5.2 穷举搜索如果⽬标是得到最优输出序列,我们可以考虑穷举搜索(exhaustive search):穷举所有可能的输出序列,输出条件概率最⼤的序列。 虽然穷举搜索可以得到最优输出序列,但它的计算开销 $O(|y|^{T^{′}})$ 很容易过⼤。例如,当|Y| =10000且T′ = 10时,我们将评估 $10000^{10}=10^{40}$ 个序列:这⼏乎不可能完成。而贪婪搜索的计算开销是 $O(|y|^{T^{′}})$,通常显著小于穷举搜索的计算开销。例如,当|Y| = 10000且T′ = 10时,我们只需评估 $10000*10=10^5$ 个序列。 5.3 束搜索束搜索(beam search)是对贪婪搜索的⼀个改进算法。它有⼀个束宽(beam size)超参数。我们将它设为 k。在时间步 1 时,选取当前时间步条件概率最⼤的 k 个词,分别组成 k 个候选输出序列的⾸词。在之后的每个时间步,基于上个时间步的 k 个候选输出序列,从 k |Y| 个可能的输出序列中选取条件概率最⼤的 k 个,作为该时间步的候选输出序列。最终,我们从各个时间步的候选输出序列中筛选出包含特殊符号“<eos>”的序列,并将它们中所有特殊符号“<eos>”后⾯的⼦序列舍弃,得到最终候选输出序列的集合。 束宽为2,输出序列最⼤⻓度为3。候选输出序列有A、C、AB、CE、ABD和CED。我们将根据这6个序列得出最终候选输出序列的集合。在最终候选输出序列的集合中,我们取以下分数最⾼的序列作为输出序列: $$\\frac{1}{L^{\\alpha}}logP(y_1,…,y_L)=\\frac{1}{L^{\\alpha}}\\sum_{t^{′}=1}^{T^{′}}logP(y_{t^{′}}|y_1,…,y_{t^{′}-1},c)$$ 其中 L 为最终候选序列⻓度,α ⼀般可选为0.75。分⺟上的 Lα 是为了惩罚较⻓序列在以上分数中较多的对数相加项。分析可知,束搜索的计算开销为 $O(k|y|^{T^{′}})$。这介于贪婪搜索和穷举搜索的计算开销之间。此外,贪婪搜索可看作是束宽为 1 的束搜索。束搜索通过灵活的束宽 k 来权衡计算开销和搜索质量。 6. Bleu得分评价机器翻译结果通常使⽤BLEU(Bilingual Evaluation Understudy)(双语评估替补)。对于模型预测序列中任意的⼦序列,BLEU考察这个⼦序列是否出现在标签序列中。 具体来说,设词数为 n 的⼦序列的精度为 pn。它是预测序列与标签序列匹配词数为 n 的⼦序列的数量与预测序列中词数为 n 的⼦序列的数量之⽐。举个例⼦,假设标签序列为A、B、C、D、E、F,预测序列为A、B、B、C、D,那么: $$P1= \\frac{预测序列中的 1 元词组在标签序列是否存在的个数}{预测序列 1 元词组的个数之和}$$ 预测序列一元词组:A/B/C/D,都在标签序列里存在,所以P1=4/5,以此类推,p2 = 3/4, p3 = 1/3, p4 = 0。设 $len_{label}和len_{pred}$ 分别为标签序列和预测序列的词数,那么,BLEU的定义为: $$exp(min(0,1-\\frac{len_{label}}{len_{pred}}))\\prod_{n=1}^{k}p_n^{\\frac{1}{2^n}}$$ 其中 k 是我们希望匹配的⼦序列的最⼤词数。可以看到当预测序列和标签序列完全⼀致时,BLEU为1。 因为匹配较⻓⼦序列⽐匹配较短⼦序列更难,BLEU对匹配较⻓⼦序列的精度赋予了更⼤权重。例如,当 pn 固定在0.5时,随着n的增⼤,$0.5^{\\frac{1}{2}}\\approx0.7,0.5^{\\frac{1}{4}}\\approx0.84,0.5^{\\frac{1}{8}}\\approx0.92,0.5^{\\frac{1}{16}}\\approx0.96$。另外,模型预测较短序列往往会得到较⾼pn 值。因此,上式中连乘项前⾯的系数是为了惩罚较短的输出而设的。举个例⼦,当k = 2时,假设标签序列为A、B、C、D、E、F,而预测序列为A、 B。虽然p1 = p2 = 1,但惩罚系数exp(1-6/2) ≈ 0.14,因此BLEU也接近0.14。 7. 代码实现TensorFlow seq2seq的基本实现 【机器学习通俗易懂系列文章】 8. 参考文献动手学深度学习 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】textRNN & textCNN","slug":"NLP/textRNN & textCNN","date":"2019-08-26T16:00:00.000Z","updated":"2019-12-25T06:05:51.332Z","comments":true,"path":"2019/08/27/NLP/textRNN & textCNN/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/27/NLP/textRNN%20&%20textCNN/","excerpt":"TEXTRNN指的是利用RNN循环神经网络解决文本分类问题,文本分类是自然语言处理的一个基本任务,试图推断出给定文本(句子、文档等)的标签或标签集合。 在一些自然语言处理任务中,当对序列进行处理时,我们一般会采用循环神经网络RNN,尤其是它的一些变种,如LSTM(更常用),GRU。当然我们也可以把…","text":"TEXTRNN指的是利用RNN循环神经网络解决文本分类问题,文本分类是自然语言处理的一个基本任务,试图推断出给定文本(句子、文档等)的标签或标签集合。 在一些自然语言处理任务中,当对序列进行处理时,我们一般会采用循环神经网络RNN,尤其是它的一些变种,如LSTM(更常用),GRU。当然我们也可以把… 1. 什么是textRNNtextRNN指的是利用RNN循环神经网络解决文本分类问题,文本分类是自然语言处理的一个基本任务,试图推断出给定文本(句子、文档等)的标签或标签集合。 文本分类的应用非常广泛,如: 垃圾邮件分类:2分类问题,判断邮件是否为垃圾邮件 情感分析:2分类问题:判断文本情感是积极还是消极;多分类问题:判断文本情感属于{非常消极,消极,中立,积极,非常积极}中的哪一类。 新闻主题分类:判断一段新闻属于哪个类别,如财经、体育、娱乐等。根据类别标签的数量,可以是2分类也可以是多分类。 自动问答系统中的问句分类 社区问答系统中的问题分类:多标签多分类(对一段文本进行多分类,该文本可能有多个标签),如知乎看山杯 让AI做法官:基于案件事实描述文本的罚金等级分类(多分类)和法条分类(多标签多分类) 判断新闻是否为机器人所写:2分类 1.1 textRNN的原理在一些自然语言处理任务中,当对序列进行处理时,我们一般会采用循环神经网络RNN,尤其是它的一些变种,如LSTM(更常用),GRU。当然我们也可以把RNN运用到文本分类任务中。 这里的文本可以一个句子,文档(短文本,若干句子)或篇章(长文本),因此每段文本的长度都不尽相同。在对文本进行分类时,我们一般会指定一个固定的输入序列/文本长度:该长度可以是最长文本/序列的长度,此时其他所有文本/序列都要进行填充以达到该长度;该长度也可以是训练集中所有文本/序列长度的均值,此时对于过长的文本/序列需要进行截断,过短的文本则进行填充。总之,要使得训练集中所有的文本/序列长度相同,该长度除之前提到的设置外,也可以是其他任意合理的数值。在测试时,也需要对测试集中的文本/序列做同样的处理。 假设训练集中所有文本/序列的长度统一为n,我们需要对文本进行分词,并使用词嵌入得到每个词固定维度的向量表示。对于每一个输入文本/序列,我们可以在RNN的每一个时间步长上输入文本中一个单词的向量表示,计算当前时间步长上的隐藏状态,然后用于当前时间步骤的输出以及传递给下一个时间步长并和下一个单词的词向量一起作为RNN单元输入,然后再计算下一个时间步长上RNN的隐藏状态,以此重复…直到处理完输入文本中的每一个单词,由于输入文本的长度为n,所以要经历n个时间步长。 基于RNN的文本分类模型非常灵活,有多种多样的结构。接下来,我们主要介绍两种典型的结构。 2. textRNN网络结构2.1 structure 1流程:embedding—>BiLSTM—>concat final output/average all output—–>softmax layer 结构图如下图所示: 一般取前向/反向LSTM在最后一个时间步长上隐藏状态,然后进行拼接,在经过一个softmax层(输出层使用softmax激活函数)进行一个多分类;或者取前向/反向LSTM在每一个时间步长上的隐藏状态,对每一个时间步长上的两个隐藏状态进行拼接,然后对所有时间步长上拼接后的隐藏状态取均值,再经过一个softmax层(输出层使用softmax激活函数)进行一个多分类(2分类的话使用sigmoid激活函数)。 上述结构也可以添加dropout/L2正则化或BatchNormalization 来防止过拟合以及加速模型训练。 2.2 structure 2流程:embedding–>BiLSTM—->(dropout)–>concat ouput—>UniLSTM—>(droput)–>softmax layer 结构图如下图所示: 与之前结构不同的是,在双向LSTM(上图不太准确,底层应该是一个双向LSTM)的基础上又堆叠了一个单向的LSTM。把双向LSTM在每一个时间步长上的两个隐藏状态进行拼接,作为上层单向LSTM每一个时间步长上的一个输入,最后取上层单向LSTM最后一个时间步长上的隐藏状态,再经过一个softmax层(输出层使用softamx激活函数,2分类的话则使用sigmoid)进行一个多分类。 2.3 总结TextRNN的结构非常灵活,可以任意改变。比如把LSTM单元替换为GRU单元,把双向改为单向,添加dropout或BatchNormalization以及再多堆叠一层等等。TextRNN在文本分类任务上的效果非常好,与TextCNN不相上下,但RNN的训练速度相对偏慢,一般2层就已经足够多了。 3. 什么是textCNN在“卷积神经⽹络”中我们探究了如何使⽤⼆维卷积神经⽹络来处理⼆维图像数据。在之前的语⾔模型和⽂本分类任务中,我们将⽂本数据看作是只有⼀个维度的时间序列,并很⾃然地使⽤循环神经⽹络来表征这样的数据。其实,我们也可以将⽂本当作⼀维图像,从而可以⽤⼀维卷积神经⽹络来捕捉临近词之间的关联。本节将介绍将卷积神经⽹络应⽤到⽂本分析的开创性⼯作之⼀:textCNN。 3.1 ⼀维卷积层在介绍模型前我们先来解释⼀维卷积层的⼯作原理。与⼆维卷积层⼀样,⼀维卷积层使⽤⼀维的互相关运算。在⼀维互相关运算中,卷积窗口从输⼊数组的最左⽅开始,按从左往右的顺序,依次在输⼊数组上滑动。当卷积窗口滑动到某⼀位置时,窗口中的输⼊⼦数组与核数组按元素相乘并求和,得到输出数组中相应位置的元素。如下图所⽰,输⼊是⼀个宽为7的⼀维数组,核数组的宽为2。可以看到输出的宽度为 7 - 2 + 1 = 6,且第⼀个元素是由输⼊的最左边的宽为2的⼦数组与核数组按元素相乘后再相加得到的:0 × 1 + 1 × 2 = 2。 多输⼊通道的⼀维互相关运算也与多输⼊通道的⼆维互相关运算类似:在每个通道上,将核与相应的输⼊做⼀维互相关运算,并将通道之间的结果相加得到输出结果。下图展⽰了含3个输⼊ 通道的⼀维互相关运算,其中阴影部分为第⼀个输出元素及其计算所使⽤的输⼊和核数组元素: 0 × 1 + 1 × 2 + 1 × 3 + 2 × 4 + 2 × (-1) + 3 × (-3) = 2。 由⼆维互相关运算的定义可知,多输⼊通道的⼀维互相关运算可以看作单输⼊通道的⼆维互相关运算。如下图所⽰,我们也可以将上图中多输⼊通道的⼀维互相关运算以等价的单输⼊通道的⼆维互相关运算呈现。这⾥核的⾼等于输⼊的⾼。下图的阴影部分为第⼀个输出元素及其计算所使⽤的输⼊和核数组元素:2 × (-1) + 3 × (-3) + 1 × 3 + 2 × 4 + 0 × 1 + 1 × 2 = 2。 以上都是输出都只有⼀个通道。我们在“多输⼊通道和多输出通道”⼀节中介绍了如何在⼆维卷积层中指定多个输出通道。类似地,我们也可以在⼀维卷积层指定多个输出通道,从而拓展卷积层中的模型参数。 3. 2 时序最⼤池化层类似地,我们有⼀维池化层。textCNN中使⽤的时序最⼤池化(max-over-time pooling)层实际上对应⼀维全局最⼤池化层:假设输⼊包含多个通道,各通道由不同时间步上的数值组成,各通道的输出即该通道所有时间步中最⼤的数值。因此,时序最⼤池化层的输⼊在各个通道上的时间步数可以不同。为提升计算性能,我们常常将不同⻓度的时序样本组成⼀个小批量,并通过在较短序列后附加特殊字符(如0)令批量中各时序样本⻓度相同。这些⼈为添加的特殊字符当然是⽆意义的。由于时序最⼤池化的主要⽬的是抓取时序中最重要的特征,它通常能使模型不受⼈为添加字符的影响。 3.3 textCNN模型textCNN模型主要使⽤了⼀维卷积层和时序最⼤池化层。假设输⼊的⽂本序列由n个词组成,每个词⽤d维的词向量表⽰。那么输⼊样本的宽为n,⾼为1,输⼊通道数为d。textCNN的计算主要分为以下⼏步: 定义多个⼀维卷积核,并使⽤这些卷积核对输⼊分别做卷积计算。宽度不同的卷积核可能会捕捉到不同个数的相邻词的相关性。 对输出的所有通道分别做时序最⼤池化,再将这些通道的池化输出值连结为向量。 通过全连接层将连结后的向量变换为有关各类别的输出。这⼀步可以使⽤丢弃层应对过拟合。 下图⽤⼀个例⼦解释了textCNN的设计。这⾥的输⼊是⼀个有11个词的句⼦,每个词⽤6维词向量表⽰。因此输⼊序列的宽为11,输⼊通道数为6。给定2个⼀维卷积核,核宽分别为2和4,输出通道数分别设为4和5。因此,⼀维卷积计算后,4个输出通道的宽为 11 - 2 + 1 = 10,而其他5个通道的宽为 11 - 4 + 1 = 8。尽管每个通道的宽不同,我们依然可以对各个通道做时序最⼤池化,并将9个通道的池化输出连结成⼀个9维向量。最终,使⽤全连接将9维向量变换为2维输出,即正⾯情感和负⾯情感的预测。 4. 代码实现清华新闻分类数据集下载:https://www.lanzous.com/i5t0lsd textRNN实现新闻分类 textCNN实现新闻分类 【机器学习通俗易懂系列文章】 5. 参考文献 基于TextRNN的文本分类原理 动手学深度学习 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】GloVe","slug":"NLP/GloVe","date":"2019-08-23T16:00:00.000Z","updated":"2019-12-25T06:04:59.088Z","comments":true,"path":"2019/08/24/NLP/GloVe/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/24/NLP/GloVe/","excerpt":"正如GloVe论文的标题而言,GloVe的全称叫Global Vectors for Word Representation,它是一个基于全局词频统计(count-based & overall statistics)的词表征(word representation)工具,它可以把一个单词表达…","text":"正如GloVe论文的标题而言,GloVe的全称叫Global Vectors for Word Representation,它是一个基于全局词频统计(count-based & overall statistics)的词表征(word representation)工具,它可以把一个单词表达… 1. 说说GloVe正如GloVe论文的标题而言,GloVe的全称叫Global Vectors for Word Representation,它是一个基于全局词频统计(count-based & overall statistics)的词表征(word representation)工具,它可以把一个单词表达成一个由实数组成的向量,这些向量捕捉到了单词之间一些语义特性,比如相似性(similarity)、类比性(analogy)等。我们通过对向量的运算,比如欧几里得距离或者cosine相似度,可以计算出两个单词之间的语义相似性。 2. GloVe的实现步骤2.1 构建共现矩阵什么是共现矩阵? 共现矩阵顾名思义就是共同出现的意思,词文档的共现矩阵主要用于发现主题(topic),用于主题模型,如LSA。 局域窗中的word-word共现矩阵可以挖掘语法和语义信息,例如: I like deep learning. I like NLP. I enjoy flying 有以上三句话,设置滑窗为2,可以得到一个词典:{“I like”,”like deep”,”deep learning”,”like NLP”,”I enjoy”,”enjoy flying”,”I like”}。 我们可以得到一个共现矩阵(对称矩阵): 中间的每个格子表示的是行和列组成的词组在词典总共同出现的次数,也就体现了共现的特性。 GloVe的共现矩阵 根据语料库(corpus)构建一个共现矩阵(Co-ocurrence Matrix)X,矩阵中的每一个元素 Xij 代表单词 i 和上下文单词 j 在特定大小的上下文窗口(context window)内共同出现的次数。一般而言,这个次数的最小单位是1,但是GloVe不这么认为:它根据两个单词在上下文窗口的距离 d,提出了一个衰减函数(decreasing weighting):decay=1/d 用于计算权重,也就是说距离越远的两个单词所占总计数(total count)的权重越小。 2.2 词向量和共现矩阵的近似关系构建词向量(Word Vector)和共现矩阵(Co-ocurrence Matrix)之间的近似关系,论文的作者提出以下的公式可以近似地表达两者之间的关系: $$w_i^T\\tilde{w_j}+b_i+\\tilde{b}j=log(X{ij})$$ 其中,$w_i^T和\\tilde{w}_j$ 是我们最终要求解的词向量;$b_i和\\tilde{b}_j$ 分别是两个词向量的bias term。当然你对这个公式一定有非常多的疑问,比如它到底是怎么来的,为什么要使用这个公式,为什么要构造两个词向量 $$w_i^T和\\tilde{w}_j$$?请参考文末的参考文献。 2.3 构造损失函数有了2.2的公式之后我们就可以构造它的loss function了: $$J=\\sum_{i,j=1}^Vf(X_{ij})(w_i^T\\tilde{w}j+b_i+\\tilde{b}_j-log(X{ij}))^2$$ 这个loss function的基本形式就是最简单的mean square loss,只不过在此基础上加了一个权重函数 $f(X_{ij})$,那么这个函数起了什么作用,为什么要添加这个函数呢?我们知道在一个语料库中,肯定存在很多单词他们在一起出现的次数是很多的(frequent co-occurrences),那么我们希望: 这些单词的权重要大于那些很少在一起出现的单词(rare co-occurrences),所以这个函数要是非递减函数(non-decreasing); 但我们也不希望这个权重过大(overweighted),当到达一定程度之后应该不再增加; 如果两个单词没有在一起出现,也就是 $X_{ij}=0$,那么他们应该不参与到 loss function 的计算当中去,也就是f(x) 要满足 f(0)=0。 满足以上三个条件的函数有很多,论文作者采用了如下形式的分段函数: 这个函数图像如下所示: 2.4 训练GloVe模型虽然很多人声称GloVe是一种无监督(unsupervised learing)的学习方式(因为它确实不需要人工标注label),但其实它还是有label的,这个label就是以上公式中的 log(Xij),而公式中的向量 $w和\\tilde{w}$ 就是要不断更新/学习的参数,所以本质上它的训练方式跟监督学习的训练方法没什么不一样,都是基于梯度下降的。 具体地,这篇论文里的实验是这么做的:采用了AdaGrad的梯度下降算法,对矩阵 X 中的所有非零元素进行随机采样,学习曲率(learning rate)设为0.05,在vector size小于300的情况下迭代了50次,其他大小的vectors上迭代了100次,直至收敛。最终学习得到的是两个vector是 $w和\\tilde{w}$,因为 X 是对称的(symmetric),所以从原理上讲 $w和\\tilde{w}$ 是也是对称的,他们唯一的区别是初始化的值不一样,而导致最终的值不一样。 所以这两者其实是等价的,都可以当成最终的结果来使用。但是为了提高鲁棒性,我们最终会选择两者之和 $w+\\tilde{w}$ 作为最终的vector(两者的初始化不同相当于加了不同的随机噪声,所以能提高鲁棒性)。在训练了400亿个token组成的语料后,得到的实验结果如下图所示: 这个图一共采用了三个指标:语义准确度,语法准确度以及总体准确度。那么我们不难发现Vector Dimension在300时能达到最佳,而context Windows size大致在6到10之间。 3. GloVe与LSA、Word2Vec的比较LSA(Latent Semantic Analysis)是一种比较早的count-based的词向量表征工具,它也是基于co-occurance matrix的,只不过采用了基于奇异值分解(SVD)的矩阵分解技术对大矩阵进行降维,而我们知道SVD的复杂度是很高的,所以它的计算代价比较大。还有一点是它对所有单词的统计权重都是一致的。而这些缺点在GloVe中被一一克服了。 而word2vec最大的缺点则是没有充分利用所有的语料,所以GloVe其实是把两者的优点结合了起来。从这篇论文给出的实验结果来看,GloVe的性能是远超LSA和word2vec的,但网上也有人说GloVe和word2vec实际表现其实差不多。 4. 代码实现生成词向量 下载GitHub项目:https://github.com/stanfordnlp/GloVe/archive/master.zip 解压后,进入目录执行 make 进行编译操作。 然后执行 sh demo.sh 进行训练并生成词向量文件:vectors.txt和vectors.bin GloVe代码实现 【机器学习通俗易懂系列文章】 5. 参考文献 GloVe详解 NLP从词袋到Word2Vec的文本表示 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】fastText","slug":"NLP/fastText","date":"2019-08-22T16:00:00.000Z","updated":"2019-12-25T06:03:23.477Z","comments":true,"path":"2019/08/23/NLP/fastText/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/23/NLP/fastText/","excerpt":"英语单词通常有其内部结构和形成⽅式。例如,我们可以从“dog”“dogs”和“dogcatcher”的字⾯上推测它们的关系。这些词都有同⼀个词根“dog”,但使⽤不同的后缀来改变词的含义。而且,这个关联可以推⼴⾄其他词汇。 在word2vec中,我们并没有直接利⽤构词学中的信息。⽆论是在跳字模型还…","text":"英语单词通常有其内部结构和形成⽅式。例如,我们可以从“dog”“dogs”和“dogcatcher”的字⾯上推测它们的关系。这些词都有同⼀个词根“dog”,但使⽤不同的后缀来改变词的含义。而且,这个关联可以推⼴⾄其他词汇。 在word2vec中,我们并没有直接利⽤构词学中的信息。⽆论是在跳字模型还… 1. 什么是fastText英语单词通常有其内部结构和形成⽅式。例如,我们可以从“dog”“dogs”和“dogcatcher”的字⾯上推测它们的关系。这些词都有同⼀个词根“dog”,但使⽤不同的后缀来改变词的含义。而且,这个关联可以推⼴⾄其他词汇。 在word2vec中,我们并没有直接利⽤构词学中的信息。⽆论是在跳字模型还是连续词袋模型中,我们都将形态不同的单词⽤不同的向量来表⽰。例如,“dog”和“dogs”分别⽤两个不同的向量表⽰,而模型中并未直接表达这两个向量之间的关系。鉴于此,fastText提出了⼦词嵌⼊(subword embedding)的⽅法,从而试图将构词信息引⼊word2vec中的CBOW。 这里有一点需要特别注意,一般情况下,使用fastText进行文本分类的同时也会产生词的embedding,即embedding是fastText分类的产物。除非你决定使用预训练的embedding来训练fastText分类模型,这另当别论。 2. n-gram表示单词word2vec把语料库中的每个单词当成原子的,它会为每个单词生成一个向量。这忽略了单词内部的形态特征,比如:“book” 和“books”,“阿里巴巴”和“阿里”,这两个例子中,两个单词都有较多公共字符,即它们的内部形态类似,但是在传统的word2vec中,这种单词内部形态信息因为它们被转换成不同的id丢失了。 为了克服这个问题,fastText使用了字符级别的n-grams来表示一个单词。对于单词“book”,假设n的取值为3,则它的trigram有: “<bo”, “boo”, “ook”, “ok>” 其中,<表示前缀,>表示后缀。于是,我们可以用这些trigram来表示“book”这个单词,进一步,我们可以用这4个trigram的向量叠加来表示“apple”的词向量。 这带来两点好处: 对于低频词生成的词向量效果会更好。因为它们的n-gram可以和其它词共享。 对于训练词库之外的单词,仍然可以构建它们的词向量。我们可以叠加它们的字符级n-gram向量。 3. fastText模型架构之前提到过,fastText模型架构和word2vec的CBOW模型架构非常相似。下面是fastText模型架构图: 注意:此架构图没有展示词向量的训练过程。可以看到,和CBOW一样,fastText模型也只有三层:输入层、隐含层、输出层(Hierarchical Softmax),输入都是多个经向量表示的单词,输出都是一个特定的target,隐含层都是对多个词向量的叠加平均。 不同的是, CBOW的输入是目标单词的上下文,fastText的输入是多个单词及其n-gram特征,这些特征用来表示单个文档; CBOW的输入单词被one-hot编码过,fastText的输入特征是被embedding过; CBOW的输出是目标词汇,fastText的输出是文档对应的类标。 值得注意的是,fastText在输入时,将单词的字符级别的n-gram向量作为额外的特征;在输出时,fastText采用了分层Softmax,大大降低了模型训练时间。这两个知识点在前文中已经讲过,这里不再赘述。 fastText相关公式的推导和CBOW非常类似,这里也不展开了。 4. fastText核心思想现在抛开那些不是很讨人喜欢的公式推导,来想一想fastText文本分类的核心思想是什么? 仔细观察模型的后半部分,即从隐含层输出到输出层输出,会发现它就是一个softmax线性多类别分类器,分类器的输入是一个用来表征当前文档的向量; 模型的前半部分,即从输入层输入到隐含层输出部分,主要在做一件事情:生成用来表征文档的向量。那么它是如何做的呢?叠加构成这篇文档的所有词及n-gram的词向量,然后取平均。叠加词向量背后的思想就是传统的词袋法,即将文档看成一个由词构成的集合。 于是fastText的核心思想就是:将整篇文档的词及n-gram向量叠加平均得到文档向量,然后使用文档向量做softmax多分类。这中间涉及到两个技巧:字符级n-gram特征的引入以及分层Softmax分类。 5. 输出分类的效果还有个问题,就是为何fastText的分类效果常常不输于传统的非线性分类器? 假设我们有两段文本: 肚子 饿了 我 要 吃饭 肚子 饿了 我 要 吃东西 这两段文本意思几乎一模一样,如果要分类,肯定要分到同一个类中去。但在传统的分类器中,用来表征这两段文本的向量可能差距非常大。传统的文本分类中,你需要计算出每个词的权重,比如TF-IDF值, “吃饭”和“吃东西” 算出的TF-IDF值相差可能会比较大,其它词类似,于是,VSM(向量空间模型)中用来表征这两段文本的文本向量差别可能比较大。 但是fastText就不一样了,它是用单词的embedding叠加获得的文档向量,词向量的重要特点就是向量的距离可以用来衡量单词间的语义相似程度,于是,在fastText模型中,这两段文本的向量应该是非常相似的,于是,它们很大概率会被分到同一个类中。 使用词embedding而非词本身作为特征,这是fastText效果好的一个原因;另一个原因就是字符级n-gram特征的引入对分类效果会有一些提升 。 6. fastText与Word2Vec的不同有意思的是,fastText和Word2Vec的作者是同一个人。 相同点: 图模型结构很像,都是采用embedding向量的形式,得到word的隐向量表达。 都采用很多相似的优化方法,比如使用Hierarchical softmax优化训练和预测中的打分速度。 之前一直不明白fasttext用层次softmax时叶子节点是啥,CBOW很清楚,它的叶子节点是词和词频,后来看了源码才知道,其实fasttext叶子节点里是类标和类标的频数。 Word2Vec fastText 输入 one-hot形式的单词的向量 embedding过的单词的词向量和n-gram向量 输出 对应的是每一个term,计算某term概率最大 对应的是分类的标签。 本质不同,体现在softmax的使用: word2vec的目的是得到词向量,该词向量最终是在输入层得到的,输出层对应的h-softmax也会生成一系列的向量,但是最终都被抛弃,不会使用。 fastText则充分利用了h-softmax的分类功能,遍历分类树的所有叶节点,找到概率最大的label fastText优点: 适合大型数据+高效的训练速度:能够训练模型“在使用标准多核CPU的情况下10分钟内处理超过10亿个词汇” 支持多语言表达:利用其语言形态结构,fastText能够被设计用来支持包括英语、德语、西班牙语、法语以及捷克语等多种语言。FastText的性能要比时下流行的word2vec工具明显好上不少,也比其他目前最先进的词态词汇表征要好。 专注于文本分类,在许多标准问题上实现当下最好的表现(例如文本倾向性分析或标签预测)。 7. 代码实现清华文本分类数据集下载:https://thunlp.oss-cn-qingdao.aliyuncs.com/THUCNews.zip 新闻文本分类代码 【机器学习通俗易懂系列文章】 8. 参考文献fastText原理及实践 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】词嵌入(Embedding)","slug":"NLP/Word Embeddings","date":"2019-08-21T16:00:00.000Z","updated":"2019-12-25T06:04:01.794Z","comments":true,"path":"2019/08/22/NLP/Word Embeddings/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/22/NLP/Word%20Embeddings/","excerpt":"顾名思义,词向量是⽤来表⽰词的向量,也可被认为是词的特征向量或表征。把词映射为实数域向量的技术也叫词嵌⼊(word embedding)。近年来,词嵌⼊已逐渐成为⾃然语⾔处理的基础知识。","text":"顾名思义,词向量是⽤来表⽰词的向量,也可被认为是词的特征向量或表征。把词映射为实数域向量的技术也叫词嵌⼊(word embedding)。近年来,词嵌⼊已逐渐成为⾃然语⾔处理的基础知识。 1. 什么是词嵌入(Word Embedding)⾃然语⾔是⼀套⽤来表达含义的复杂系统。在这套系统中,词是表义的基本单元。顾名思义,词向量是⽤来表⽰词的向量,也可被认为是词的特征向量或表征。把词映射为实数域向量的技术也叫词嵌⼊(word embedding)。近年来,词嵌⼊已逐渐成为⾃然语⾔处理的基础知识。 在NLP(自然语言处理)领域,文本表示是第一步,也是很重要的一步,通俗来说就是把人类的语言符号转化为机器能够进行计算的数字,因为普通的文本语言机器是看不懂的,必须通过转化来表征对应文本。早期是基于规则的方法进行转化,而现代的方法是基于统计机器学习的方法。 数据决定了机器学习的上限,而算法只是尽可能逼近这个上限,在本文中数据指的就是文本表示,所以,弄懂文本表示的发展历程,对于NLP学习者来说是必不可少的。接下来开始我们的发展历程。文本表示分为离散表示和分布式表示: 2.离散表示2.1 One-hot表示One-hot简称读热向量编码,也是特征工程中最常用的方法。其步骤如下: 构造文本分词后的字典,每个分词是一个比特值,比特值为0或者1。 每个分词的文本表示为该分词的比特位为1,其余位为0的矩阵表示。 例如:John likes to watch movies. Mary likes too John also likes to watch football games. 以上两句可以构造一个词典,*{“John”: 1, “likes”: 2, “to”: 3, “watch”: 4, “movies”: 5, “also”: 6, “football”: 7, “games”: 8, “Mary”: 9, “too”: 10} * 每个词典索引对应着比特位。那么利用One-hot表示为: *John: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] * likes: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0] …….等等,以此类推。 One-hot表示文本信息的缺点: 随着语料库的增加,数据特征的维度会越来越大,产生一个维度很高,又很稀疏的矩阵。 这种表示方法的分词顺序和在句子中的顺序是无关的,不能保留词与词之间的关系信息。 2.2 词袋模型词袋模型(Bag-of-words model),像是句子或是文件这样的文字可以用一个袋子装着这些词的方式表现,这种表现方式不考虑文法以及词的顺序。 文档的向量表示可以直接将各词的词向量表示加和。例如: John likes to watch movies. Mary likes too John also likes to watch football games. 以上两句可以构造一个词典,*{“John”: 1, “likes”: 2, “to”: 3, “watch”: 4, “movies”: 5, “also”: 6, “football”: 7, “games”: 8, “Mary”: 9, “too”: 10} * 那么第一句的向量表示为:[1,2,1,1,1,0,0,0,1,1],其中的2表示likes在该句中出现了2次,依次类推。 词袋模型同样有一下缺点: 词向量化后,词与词之间是有大小关系的,不一定词出现的越多,权重越大。 词与词之间是没有顺序关系的。 2.3 TF-IDFTF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF意思是词频(Term Frequency),IDF意思是逆文本频率指数(Inverse Document Frequency)。 字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章。 $$TF_w=\\frac{在某一类中词条w出现的次数}{该类中所有的词条数目}$$ $$IDF=log(\\frac{语料库的文档总数}{包含词条w的文档总数+1})$$,分母之所以加1,是为了避免分母为0。 那么,$TF-IDF=TF*IDF$,从这个公式可以看出,当w在文档中出现的次数增大时,而TF-IDF的值是减小的,所以也就体现了以上所说的了。 缺点:还是没有把词与词之间的关系顺序表达出来。 2.4 n-gram模型n-gram模型为了保持词的顺序,做了一个滑窗的操作,这里的n表示的就是滑窗的大小,例如2-gram模型,也就是把2个词当做一组来处理,然后向后移动一个词的长度,再次组成另一组词,把这些生成一个字典,按照词袋模型的方式进行编码得到结果。改模型考虑了词的顺序。 例如: John likes to watch movies. Mary likes too John also likes to watch football games. 以上两句可以构造一个词典,{“John likes”: 1, “likes to”: 2, “to watch”: 3, “watch movies”: 4, “Mary likes”: 5, “likes too”: 6, “John also”: 7, “also likes”: 8, “watch football”: 9, “football games”: 10} 那么第一句的向量表示为:[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],其中第一个1表示John likes在该句中出现了1次,依次类推。 缺点:随着n的大小增加,词表会成指数型膨胀,会越来越大。 2.5 离散表示存在的问题由于存在以下的问题,对于一般的NLP问题,是可以使用离散表示文本信息来解决问题的,但对于要求精度较高的场景就不适合了。 无法衡量词向量之间的关系。 词表的维度随着语料库的增长而膨胀。 n-gram词序列随语料库增长呈指数型膨胀,更加快。 离散数据来表示文本会带来数据稀疏问题,导致丢失了信息,与我们生活中理解的信息是不一样的。 3. 分布式表示科学家们为了提高模型的精度,又发明出了分布式的表示文本信息的方法,这就是这一节需要介绍的。 用一个词附近的其它词来表示该词,这是现代统计自然语言处理中最有创见的想法之一。当初科学家发明这种方法是基于人的语言表达,认为一个词是由这个词的周边词汇一起来构成精确的语义信息。就好比,物以类聚人以群分,如果你想了解一个人,可以通过他周围的人进行了解,因为周围人都有一些共同点才能聚集起来。 3.1 共现矩阵共现矩阵顾名思义就是共同出现的意思,词文档的共现矩阵主要用于发现主题(topic),用于主题模型,如LSA。 局域窗中的word-word共现矩阵可以挖掘语法和语义信息,例如: I like deep learning. I like NLP. I enjoy flying 有以上三句话,设置滑窗为2,可以得到一个词典:{“I like”,”like deep”,”deep learning”,”like NLP”,”I enjoy”,”enjoy flying”,”I like”}。 我们可以得到一个共现矩阵(对称矩阵): 中间的每个格子表示的是行和列组成的词组在词典中共同出现的次数,也就体现了共现的特性。 存在的问题: 向量维数随着词典大小线性增长。 存储整个词典的空间消耗非常大。 一些模型如文本分类模型会面临稀疏性问题。 模型会欠稳定,每新增一份语料进来,稳定性就会变化。 4.神经网络表示4.1 NNLMNNLM (Neural Network Language model),神经网络语言模型是03年提出来的,通过训练得到中间产物–词向量矩阵,这就是我们要得到的文本表示向量矩阵。 NNLM说的是定义一个前向窗口大小,其实和上面提到的窗口是一个意思。把这个窗口中最后一个词当做y,把之前的词当做输入x,通俗来说就是预测这个窗口中最后一个词出现概率的模型。 以下是NNLM的网络结构图: input层是一个前向词的输入,是经过one-hot编码的词向量表示形式,具有V*1的矩阵。 C矩阵是投影矩阵,也就是稠密词向量表示,在神经网络中是w参数矩阵,该矩阵的大小为DV,正好与input层进行全连接(相乘)得到D\\1的矩阵,采用线性映射将one-hot表示投影到稠密D维表示。 output层(softmax)自然是前向窗中需要预测的词。 通过BP+SGD得到最优的C投影矩阵,这就是NNLM的中间产物,也是我们所求的文本表示矩阵,通过NNLM将稀疏矩阵投影到稠密向量矩阵中。 4.2 Word2Vec谷歌2013年提出的Word2Vec是目前最常用的词嵌入模型之一。Word2Vec实际是一种浅层的神经网络模型,它有两种网络结构,分别是CBOW(Continues Bag of Words)连续词袋和Skip-gram。Word2Vec和上面的NNLM很类似,但比NNLM简单。 CBOW CBOW获得中间词两边的的上下文,然后用周围的词去预测中间的词,把中间词当做y,把窗口中的其它词当做x输入,x输入是经过one-hot编码过的,然后通过一个隐层进行求和操作,最后通过激活函数softmax,可以计算出每个单词的生成概率,接下来的任务就是训练神经网络的权重,使得语料库中所有单词的整体生成概率最大化,而求得的权重矩阵就是文本表示词向量的结果。 Skip-gram: Skip-gram是通过当前词来预测窗口中上下文词出现的概率模型,把当前词当做x,把窗口中其它词当做y,依然是通过一个隐层接一个Softmax激活函数来预测其它词的概率。如下图所示: 优化方法: 层次Softmax:至此还没有结束,因为如果单单只是接一个softmax激活函数,计算量还是很大的,有多少词就会有多少维的权重矩阵,所以这里就提出层次Softmax(Hierarchical Softmax),使用Huffman Tree来编码输出层的词典,相当于平铺到各个叶子节点上,瞬间把维度降低到了树的深度,可以看如下图所示。这课Tree把出现频率高的词放到靠近根节点的叶子节点处,每一次只要做二分类计算,计算路径上所有非叶子节点词向量的贡献即可。 哈夫曼树(Huffman Tree):给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。 负例采样(Negative Sampling):这种优化方式做的事情是,在正确单词以外的负样本中进行采样,最终目的是为了减少负样本的数量,达到减少计算量效果。将词典中的每一个词对应一条线段,所有词组成了[0,1]间的剖分,如下图所示,然后每次随机生成一个[1, M-1]间的整数,看落在哪个词对应的剖分上就选择哪个词,最后会得到一个负样本集合。 Word2Vec存在的问题 对每个local context window单独训练,没有利用包 含在global co-currence矩阵中的统计信息。 对多义词无法很好的表示和处理,因为使用了唯一的词向量 4.3 sense2vecword2vec模型的问题在于词语的多义性。比如duck这个单词常见的含义有水禽或者下蹲,但对于 word2vec 模型来说,它倾向于将所有概念做归一化平滑处理,得到一个最终的表现形式。 5. 词嵌入为何不采用one-hot向量虽然one-hot词向量构造起来很容易,但通常并不是⼀个好选择。⼀个主要的原因是,one-hot词向量⽆法准确表达不同词之间的相似度,如我们常常使⽤的余弦相似度。由于任何两个不同词的one-hot向量的余弦相似度都为0,多个不同词之间的相似度难以通过one\u0002hot向量准确地体现出来。 word2vec⼯具的提出正是为了解决上⾯这个问题。它将每个词表⽰成⼀个定⻓的向量,并使得这些向量能较好地表达不同词之间的相似和类⽐关系。 6. Word2Vec代码实现数据下载 中文维基百科的打包文件地址为链接: https://pan.baidu.com/s/1H-wuIve0d_fvczvy3EOKMQ 提取码: uqua 百度网盘加速下载地址:https://www.baiduwp.com/?m=index Word2Vec训练维基百科文章代码 【机器学习通俗易懂系列文章】 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【NLP】自然语言处理","slug":"NLP/NLP","date":"2019-08-19T16:00:00.000Z","updated":"2019-12-25T05:57:41.212Z","comments":true,"path":"2019/08/20/NLP/NLP/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/20/NLP/NLP/","excerpt":"自然语言处理 (Natural Language Processing) 是人工智能(AI)的一个子领域。自然语言处理是研究在人与人交互中以及在人与计算机交互中的语言问题的一门学科。为了建设和完善语言模型,自然语言处理建立计算框架,提出相应的方法来不断的完善设计各种实用系统,并探讨这些实用…","text":"自然语言处理 (Natural Language Processing) 是人工智能(AI)的一个子领域。自然语言处理是研究在人与人交互中以及在人与计算机交互中的语言问题的一门学科。为了建设和完善语言模型,自然语言处理建立计算框架,提出相应的方法来不断的完善设计各种实用系统,并探讨这些实用… 1. 什么是NLP自然语言处理 (Natural Language Processing) 是人工智能(AI)的一个子领域。自然语言处理是研究在人与人交互中以及在人与计算机交互中的语言问题的一门学科。为了建设和完善语言模型,自然语言处理建立计算框架,提出相应的方法来不断的完善设计各种实用系统,并探讨这些实用系统的评测方法。 2. NLP主要研究方向 信息抽取:从给定文本中抽取重要的信息,比如时间、地点、人物、事件、原因、结果、数字、日期、货币、专有名词等等。通俗说来,就是要了解谁在什么时候、什么原因、对谁、做了什么事、有什么结果。 文本生成:机器像人一样使用自然语言进行表达和写作。依据输入的不同,文本生成技术主要包括数据到文本生成和文本到文本生成。数据到文本生成是指将包含键值对的数据转化为自然语言文本;文本到文本生成对输入文本进行转化和处理从而产生新的文本。 问答系统:对一个自然语言表达的问题,由问答系统给出一个精准的答案。需要对自然语言查询语句进行某种程度的语义分析,包括实体链接、关系识别,形成逻辑表达式,然后到知识库中查找可能的候选答案并通过一个排序机制找出最佳的答案。 对话系统:系统通过一系列的对话,跟用户进行聊天、回答、完成某一项任务。涉及到用户意图理解、通用聊天引擎、问答引擎、对话管理等技术。此外,为了体现上下文相关,要具备多轮对话能力。 文本挖掘:包括文本聚类、分类、情感分析以及对挖掘的信息和知识的可视化、交互式的表达界面。目前主流的技术都是基于统计机器学习的。 语音识别和生成:语音识别是将输入计算机的语音符号识别转换成书面语表示。语音生成又称文语转换、语音合成,它是指将书面文本自动转换成对应的语音表征。 信息过滤:通过计算机系统自动识别和过滤符合特定条件的文档信息。通常指网络有害信息的自动识别和过滤,主要用于信息安全和防护,网络内容管理等。 舆情分析:是指收集和处理海量信息,自动化地对网络舆情进行分析,以实现及时应对网络舆情的目的。 信息检索:对大规模的文档进行索引。可简单对文档中的词汇,赋之以不同的权重来建立索引,也可建立更加深层的索引。在查询的时候,对输入的查询表达式比如一个检索词或者一个句子进行分析,然后在索引里面查找匹配的候选文档,再根据一个排序机制把候选文档排序,最后输出排序得分最高的文档。 机器翻译:把输入的源语言文本通过自动翻译获得另外一种语言的文本。机器翻译从最早的基于规则的方法到二十年前的基于统计的方法,再到今天的基于神经网络(编码-解码)的方法,逐渐形成了一套比较严谨的方法体系。 3. NLP的发展 1950年前:图灵测试1950年前阿兰·图灵图灵测试:人和机器进行交流,如果人无法判断自己交流的对象是人还是机器,就说明这个机器具有智能。 1950-1970:主流:基于规则形式语言理论 乔姆斯基,根据数学中的公理化方法研究自然语言,采用代数和集合论把形式语言定义为符号的序列。他试图使用有限的规则描述无限的语言现象,发现人类普遍的语言机制,建立所谓的普遍语法。 1970-至今:主流:基于统计谷歌、微软、IBM,20世纪70年代,弗里德里克·贾里尼克及其领导的IBM华生实验室将语音识别率从70%提升到90%。1988年,IBM的彼得·布朗提出了基于统计的机器翻译方法。2005年,Google机器翻译打败基于规则的Sys Tran。 2010年以后:逆袭:机器学习 AlphaGo先后战胜李世石、柯洁等,掀起人工智能热潮。深度学习、人工神经网络成为热词。领域:语音识别、图像识别、机器翻译、自动驾驶、智能家居。 4. NLP任务的一般步骤下面图片看不清楚的,可以百度脑图查看,点击链接 5. 我的NLP启蒙读本《数学之美》–吴军 6. NLP、CV,选哪个?NLP:自然语言处理,数据是文本。 CV:计算机视觉,数据是图像。 两者属于不同的领域,在遇到这个问题的时候,我也是犹豫了很久,想了很多,于是乎得出一个结论:都是利用深度学习去解决现实世界存在的问题,离开了CV,NLP存活不了;离开了NLP,CV存活不了。两者就像兄弟姐妹一样,整个“家庭”不能分割但个体又存在差异! NLP/CV属于两个不同的研究领域,都是很好的领域,可以根据自己的爱好作出适合自己的选择,人工智能是一个多学科交叉的领域,需要的不仅仅是单方面的能力,而是多方面的能力。对于每个人来说都有自己的侧重点,毕竟人的精力是有限的。只要在自己擅长的领域里持续深耕,我相信都会有所成就! 这里提供一些参考资料给大家阅读阅读,做出适合自己的选择: 一文看尽2018全年AI技术大突破:NLP跨过分水岭、CV研究效果惊人 《数学之美》–吴军 BERT时代与后时代的NLP 【机器学习通俗易懂系列文章】 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"NLP","slug":"NLP","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/NLP/"}],"tags":[]},{"title":"【深度学习】深度学习-优化方法","slug":"DL/DL Optimizer","date":"2019-08-18T16:00:00.000Z","updated":"2019-12-25T05:55:47.647Z","comments":true,"path":"2019/08/19/DL/DL Optimizer/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/19/DL/DL%20Optimizer/","excerpt":"机器学习模型在训练数据集和测试数据集上的表现。如果你改变过实验中的模型结构或者超参数,你也许发现了:当模型在训练数据集上更准确时,它在测试数据集上却不⼀定更准确。这是为什么呢? 训练误差的期望小于或等于泛化误差。也就是说,⼀般情况下,由训练数据集学到的模型参数会使模型在训练数据集上的表现优于或等于…","text":"机器学习模型在训练数据集和测试数据集上的表现。如果你改变过实验中的模型结构或者超参数,你也许发现了:当模型在训练数据集上更准确时,它在测试数据集上却不⼀定更准确。这是为什么呢? 训练误差的期望小于或等于泛化误差。也就是说,⼀般情况下,由训练数据集学到的模型参数会使模型在训练数据集上的表现优于或等于… 1. 训练误差和泛化误差机器学习模型在训练数据集和测试数据集上的表现。如果你改变过实验中的模型结构或者超参数,你也许发现了:当模型在训练数据集上更准确时,它在测试数据集上却不⼀定更准确。这是为什么呢? 因为存在着训练误差和泛化误差: 训练误差:模型在训练数据集上表现出的误差。 泛化误差:模型在任意⼀个测试数据样本上表现出的误差的期望,并常常通过测试数据集上的误差来近似。 训练误差的期望小于或等于泛化误差。也就是说,⼀般情况下,由训练数据集学到的模型参数会使模型在训练数据集上的表现优于或等于在测试数据集上的表现。由于⽆法从训练误差估计泛化误差,⼀味地降低训练误差并不意味着泛化误差⼀定会降低。 机器学习模型应关注降低泛化误差。 2. 该如何选择模型在机器学习中,通常需要评估若⼲候选模型的表现并从中选择模型。这⼀过程称为模型选择(model selection)。可供选择的候选模型可以是有着不同超参数的同类模型。以多层感知机为例,我们可以选择隐藏层的个数,以及每个隐藏层中隐藏单元个数和激活函数。为了得到有效的模型,我们通常要在模型选择上下⼀番功夫。 2.1 验证数据集从严格意义上讲,测试集只能在所有超参数和模型参数选定后使⽤⼀次。不可以使⽤测试数据选择模型,如调参。由于⽆法从训练误差估计泛化误差,因此也不应只依赖训练数据选择模型。鉴于此,我们可以预留⼀部分在训练数据集和测试数据集以外的数据来进⾏模型选择。这部分数据被称为验证数据集,简称验证集(validation set)。例如,我们可以从给定的训练集中随机选取⼀小部分作为验证集,而将剩余部分作为真正的训练集。 可以通过预留这样的验证集来进行模型选择,判断验证集在模型中的表现能力。 2.2 K 折交叉验证由于验证数据集不参与模型训练,当训练数据不够⽤时,预留⼤量的验证数据显得太奢侈。⼀种改善的⽅法是K折交叉验证(K-fold cross-validation)。在K折交叉验证中,我们把原始训练数据集分割成K个不重合的⼦数据集,然后我们做K次模型训练和验证。每⼀次,我们使⽤⼀个⼦数据集验证模型,并使⽤其他K − 1个⼦数据集来训练模型。在这K次训练和验证中,每次⽤来验证模型的⼦数据集都不同。最后,我们对这K次训练误差和验证误差分别求平均。 3. ⽋拟合和过拟合 欠拟合:模型⽆法得到较低的训练误差。 过拟合:是模型的训练误差远小于它在测试数据集上的误差。 给定训练数据集, 如果模型的复杂度过低,很容易出现⽋拟合; 如果模型复杂度过⾼,很容易出现过拟合。 应对⽋拟合和过拟合的⼀个办法是针对数据集选择合适复杂度的模型。 训练数据集⼤⼩ 影响⽋拟合和过拟合的另⼀个重要因素是训练数据集的⼤小。⼀般来说,如果训练数据集中样本数过少,特别是⽐模型参数数量(按元素计)更少时,过拟合更容易发⽣。此外,泛化误差不会随训练数据集⾥样本数量增加而增⼤。因此,在计算资源允许的范围之内,我们通常希望训练数据集⼤⼀些,特别是在模型复杂度较⾼时,例如层数较多的深度学习模型。 正则化 应对过拟合问题的常⽤⽅法:权重衰减(weight decay),权重衰减等价于L2范数正则化(regularization)。正则化通过为模型损失函数添加惩罚项使学出的模型参数值较小,是应对过拟合的常⽤⼿段。 4. 丢弃法(Dropout)除了上面提到的权重衰减以外,深度学习模型常常使⽤丢弃法(dropout)来应对过拟合问题。丢弃法有⼀些不同的变体。本节中提到的丢弃法特指倒置丢弃法(inverted dropout)。 回忆⼀下,“多层感知机”描述了⼀个单隐藏层的多层感知机。其中输⼊个数为4,隐藏单元个数为5,且隐藏单元hi(i = 1, . . . , 5)的计算表达式为: $$h_i=\\phi(x_1w_{1i}+x_2w_{2i}+x_3w_{3i}+x_4w_{4i}+b_i)$$ 这⾥ϕ是激活函数,x1, . . . , x4是输⼊,隐藏单元i的权重参数为w1i, . . . , w4i,偏差参数为bi。当对该隐藏层使⽤丢弃法时,该层的隐藏单元将有⼀定概率被丢弃掉。设丢弃概率为p,那么有p的概率hi会被清零,有1 − p的概率hi会除以1 − p做拉伸。丢弃概率是丢弃法的超参数。具体来说,设随机变量ξi为0和1的概率分别为p和1 − p。使⽤丢弃法时我们计算新的隐藏单元 $h_i^{′}$。 $$h_i^{′}=\\frac{\\xi_i}{1-p}$$ 由于E(ξi) = 1 − p,因此: $$E(h_i^{′})=\\frac{E(\\xi_i)}{1-p}h_i=h_i$$ 即丢弃法不改变其输⼊的期望值。让我们对隐藏层使⽤丢弃法,⼀种可能的结果如下图所⽰,其中h2和h5被清零。这时输出值的计算不再依赖h2和h5,在反向传播时,与这两个隐藏单元相关的权重的梯度均为0。由于在训练中隐藏层神经元的丢弃是随机的,即h1, . . . , h5都有可能被清零,输出层的计算⽆法过度依赖h1, . . . , h5中的任⼀个,从而在训练模型时起到正则化的作⽤,并可以⽤来应对过拟合。在测试模型时,我们为了拿到更加确定性的结果,⼀般不使⽤丢弃法。 5. 梯度消失/梯度爆炸(Vanishing / Exploding gradients)训练神经网络,尤其是深度神经所面临的一个问题就是梯度消失或梯度爆炸,也就是你训练神经网络的时候,导数或坡度有时会变得非常大,或者非常小,甚至于以指数方式变小,这加大了训练的难度。 本质上,梯度消失和爆炸是一种情况。在深层网络中,由于网络过深,如果初始得到的梯度过小,或者传播途中在某一层上过小,则在之后的层上得到的梯度会越来越小,即产生了梯度消失。梯度爆炸也是同样的。一般地,不合理的初始化以及激活函数,如sigmoid等,都会导致梯度过大或者过小,从而引起消失/爆炸。 解决方案 预训练加微调 其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。 此方法有一定的好处,但是目前应用的不是很多了。 梯度剪切、正则 梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。 另外一种解决梯度爆炸的手段是采用权重正则化(weithts regularization)比较常见的是L1和L2正则。 ReLu、leakReLu等激活函数 ReLu:其函数的导数在正数部分是恒等于1,这样在深层网络中,在激活函数部分就不存在导致梯度过大或者过小的问题,缓解了梯度消失或者爆炸。同时也方便计算。当然,其也存在存在一些缺点,例如过滤到了负数部分,导致部分信息的丢失,输出的数据分布不在以0为中心,改变了数据分布。 leakReLu:就是为了解决relu的0区间带来的影响,其数学表达为:leakrelu=max(k*x,0)其中k是leak系数,一般选择0.01或者0.02,或者通过学习而来。 Batch Normalization Batch Normalization是深度学习发展以来提出的最重要的成果之一了,目前已经被广泛的应用到了各大网络中,具有加速网络收敛速度,提升训练稳定性的效果,Batch Normalization本质上是解决反向传播过程中的梯度问题。Batch Normalization,简称BN,即批规范化,通过规范化操作将输出信号x规范化到均值为0,方差为1保证网络的稳定性。 有一些从 0 到 1 而不是从 1 到 1000 的特征值,通过归一化所有的输入特征值𝑥,以获得类似范围的值,可以加速学习。所以 Batch 归一化起的作用的原因,直观的一点就是,它在做类似的工作,但不仅仅对于这里的输入值,还有隐藏单元的值。 它可以使权重比你的网络更滞后或更深层,比如,第 10 层的权重更能经受得住变化。 残差结构 残差的方式,能使得深层的网络梯度通过跳级连接路径直接返回到浅层部分,使得网络无论多深都能将梯度进行有效的回传。 LSTM LSTM全称是长短期记忆网络(long-short term memory networks),是不那么容易发生梯度消失的,主要原因在于LSTM内部复杂的“门”(gates)。在计算时,将过程中的梯度进行了抵消。 6. 随机梯度下降法(SGD)6.1 mini-batch梯度下降你可以把训练集分割为小一点的子集训练,这些子集被取名为 mini-batch,假设每一个子集中只有 1000 个样本,那么把其中的𝑥 (1)到𝑥 (1000)取出来,将其称为第一个子训练集,也叫做 mini-batch,然后你再取出接下来的 1000 个样本,从𝑥 (1001)到𝑥 (2000),然后再取 1000个样本,以此类推。 在训练集上运行 mini-batch 梯度下降法,你运行 for t=1……5000,因为我们有5000个各有 1000 个样本的组,在 for 循环里你要做得基本就是对𝑋 {𝑡}和𝑌 {𝑡}执行一步梯度下降法。 batch_size=1,就是SGD。 batch_size=n,就是mini-batch batch_size=m,就是batch 其中1<n<m,m表示整个训练集大小。 优缺点: batch:相对噪声低些,幅度也大一些,你可以继续找最小值。 SGD:大部分时候你向着全局最小值靠近,有时候你会远离最小值,因为那个样本恰好给你指的方向不对,因此随机梯度下降法是有很多噪声的,平均来看,它最终会靠近最小值,不过有时候也会方向错误,因为随机梯度下降法永远不会收敛,而是会一直在最小值附近波动。一次性只处理了一个训练样本,这样效率过于低下。 mini-batch:实践中最好选择不大不小的 mini-batch,得到了大量向量化,效率高,收敛快。 首先,如果训练集较小,直接使用 batch 梯度下降法,这里的少是说小于 2000 个样本。一般的 mini-batch 大小为 64 到 512,考虑到电脑内存设置和使用的方式,如果 mini-batch 大小是 2 的𝑛次方,代码会运行地快一些。 6.2 调节 Batch_Size 对训练效果影响到底如何? Batch_Size 太小,模型表现效果极其糟糕(error飙升)。 随着 Batch_Size 增大,处理相同数据量的速度越快。 随着 Batch_Size 增大,达到相同精度所需要的 epoch 数量越来越多。 由于上述两种因素的矛盾, Batch_Size 增大到某个时候,达到时间上的最优。 由于最终收敛精度会陷入不同的局部极值,因此 Batch_Size 增大到某些时候,达到最终收敛精度上的最优。 7. 优化算法7.1 动量法在每次迭代中,梯度下降根据⾃变量当前位置,沿着当前位置的梯度更新⾃变量。然而,如果⾃变量的迭代⽅向仅仅取决于⾃变量当前位置,这可能会带来⼀些问题。 让我们考虑⼀个输⼊和输出分别为⼆维向量x = [x1, x2]⊤和标量的⽬标函数 $f(x)=0.1x_1^2+2x_2^2$。,这⾥将$x_1^2$系数从1减小到了0.1。下⾯实现基于这个⽬标函数的梯度下降,并演⽰使⽤学习率为0.4时⾃变量的迭代轨迹。 可以看到,同⼀位置上,⽬标函数在竖直⽅向(x2轴⽅向)⽐在⽔平⽅向(x1轴⽅向)的斜率的绝对值更⼤。因此,给定学习率,梯度下降迭代⾃变量时会使⾃变量在竖直⽅向⽐在⽔平⽅向移动幅度更⼤。那么,我们需要⼀个较小的学习率从而避免⾃变量在竖直⽅向上越过⽬标函数最优解。然而,这会造成⾃变量在⽔平⽅向上朝最优解移动变慢。 动量法的提出是为了解决梯度下降的上述问题。由于小批量随机梯度下降⽐梯度下降更为⼴义,本章后续讨论将沿⽤“小批量随机梯度下降”⼀节中时间步t的小批量随机梯度gt的定义。设时间步t的⾃变量为xt,学习率为ηt。在时间步0,动量法创建速度变量v0,并将其元素初始化成0。在时间步t > 0,动量法对每次迭代的步骤做如下修改: $$v_t\\leftarrow\\gamma_{}v_{t-1}+\\eta_tg_t$$ $$x_t\\leftarrow_{}x_{t-1}-v_t$$ 其中,动量超参数γ满⾜0 ≤ γ < 1。当γ = 0时,动量法等价于小批量随机梯度下降。在梯度下降时候使用动量法后的迭代轨迹: 可以看到使⽤较小的学习率η = 0.4和动量超参数γ = 0.5时,动量法在竖直⽅向上的移动更加平滑,且在⽔平⽅向上更快逼近最优解。 所以,在动量法中,⾃变量在各个⽅向上的移动幅度不仅取决当前梯度,还取决于过去的各个梯度在各个⽅向上是否⼀致。在本节之前⽰例的优化问题中,所有梯度在⽔平⽅向上为正(向右),而在竖直⽅向上时正(向上)时负(向下)。这样,我们就可以使⽤较⼤的学习率,从而使⾃变量向最优解更快移动。 7.2 AdaGrad算法优化算法中,⽬标函数⾃变量的每⼀个元素在相同时间步都使⽤同⼀个学习率来⾃我迭代。在“动量法”⾥我们看到当x1和x2的梯度值有较⼤差别时,需要选择⾜够小的学习率使得⾃变量在梯度值较⼤的维度上不发散。但这样会导致⾃变量在梯度值较小的维度上迭代过慢。动量法依赖指数加权移动平均使得⾃变量的更新⽅向更加⼀致,从而降低发散的可能。本节我们介绍AdaGrad算法,它根据⾃变量在每个维度的梯度值的⼤小来调整各个维度上的学习率,从而避免统⼀的学习率难以适应所有维度的问题。 AdaGrad算法会使⽤⼀个小批量随机梯度gt按元素平⽅的累加变量st。在时间步0,AdaGrad将s0中每个元素初始化为0。在时间步t,⾸先将小批量随机梯度gt按元素平⽅后累加到变量st: $$s_t=s_{t-1}+g_t⊙g_t$$ 其中⊙是按元素相乘。接着,我们将⽬标函数⾃变量中每个元素的学习率通过按元素运算重新调整⼀下: $$x_t=x_{t-1}-\\frac{\\eta}{\\sqrt{s_t+\\varepsilon}}⊙g_t$$ 其中η是学习率,ϵ是为了维持数值稳定性而添加的常数,如10的-6次方。这⾥开⽅、除法和乘法的运算都是按元素运算的。这些按元素运算使得⽬标函数⾃变量中每个元素都分别拥有⾃⼰的学习率。 需要强调的是,小批量随机梯度按元素平⽅的累加变量st出现在学习率的分⺟项中。因此, 如果⽬标函数有关⾃变量中某个元素的偏导数⼀直都较⼤,那么该元素的学习率将下降较快; 反之,如果⽬标函数有关⾃变量中某个元素的偏导数⼀直都较小,那么该元素的学习率将下降较慢。 然而,由于st⼀直在累加按元素平⽅的梯度,⾃变量中每个元素的学习率在迭代过程中⼀直在降低(或不变)。所以,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到⼀个有⽤的解。 7.3 RMSProp算法当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到⼀个有⽤的解。为了解决这⼀问题,RMSProp算法对AdaGrad算法做了⼀点小小的修改。 不同于AdaGrad算法⾥状态变量st是截⾄时间步t所有小批量随机梯度gt按元素平⽅和,RMSProp算法将这些梯度按元素平⽅做指数加权移动平均。具体来说,给定超参数0 ≤ γ < 1,RMSProp算法在时间步t > 0计算: $$s_t=\\gamma_{}s_{t-1}+(1-\\gamma)g_t⊙g_t$$ 和AdaGrad算法⼀样,RMSProp算法将⽬标函数⾃变量中每个元素的学习率通过按元素运算重新调整,然后更新⾃变量: $$x_t=x_{t-1}-\\frac{\\eta}{\\sqrt{s_t+\\varepsilon}}⊙g_t$$ 其中η是学习率,ϵ是为了维持数值稳定性而添加的常数,如10的-6次方。因为RMSProp算法的状态变量st是对平⽅项gt ⊙ gt的指数加权移动平均,所以可以看作是最近1/(1 − γ)个时间步的小批量随机梯度平⽅项的加权平均。如此⼀来,⾃变量每个元素的学习率在迭代过程中就不再⼀直降低(或不变)。 7.4 AdaDelta算法除了RMSProp算法以外,另⼀个常⽤优化算法AdaDelta算法也针对AdaGrad算法在迭代后期可能较难找到有⽤解的问题做了改进。有意思的是,AdaDelta算法没有学习率这⼀超参数。 AdaDelta算法也像RMSProp算法⼀样,使⽤了小批量随机梯度gt按元素平⽅的指数加权移动平均变量st。在时间步0,它的所有元素被初始化为0。给定超参数0 ≤ ρ < 1(对应RMSProp算法中的γ),在时间步t > 0,同RMSProp算法⼀样计算: $$s_t=ps_{t-1}+(1-p)g_t⊙g_t$$ 与RMSProp算法不同的是,AdaDelta算法还维护⼀个额外的状态变量∆xt,其元素同样在时间步0时被初始化为0。我们使⽤∆xt−1来计算⾃变量的变化量: $$g_t^{′}=\\sqrt{\\frac{\\Delta{}x_{t-1}+\\varepsilon}{s_t+\\varepsilon}}⊙g_t$$ 最后,我们使⽤∆xt来记录⾃变量变化量 $g_t^{′}$ 按元素平⽅的指数加权移动平均: $$\\Delta{}x_t=p\\Delta{}x_{t-1}+(1-p)g_t^{′}⊙g_t^{′}$$ 可以看到,如不考虑ϵ的影响,AdaDelta算法与RMSProp算法的不同之处在于使⽤ $\\sqrt{\\Delta{}x_{t-1}}$ 来替代超参数η。 7.5 Adam算法Adam算法在RMSProp算法基础上对小批量随机梯度也做了指数加权移动平均。 Adam算法使⽤了动量变量vt和RMSProp算法中小批量随机梯度按元素平⽅的指数加权移动平均变量st,并在时间步0将它们中每个元素初始化为0。给定超参数0 ≤ β1 < 1(算法作者建议设为0.9),时间步t的动量变量vt即小批量随机梯度gt的指数加权移动平均: $$v_t=\\beta_1v_{t-1}+(1-\\beta_1)g_t$$ 和RMSProp算法中⼀样,给定超参数0 ≤ β2 < 1(算法作者建议设为0.999),将小批量随机梯度按元素平⽅后的项gt ⊙ gt做指数加权移动平均得到st: $$s_t=\\beta_{2}s_{t-1}+(1-\\beta_2)g_t⊙g_t$$ 由于我们将 v0 和 s0 中的元素都初始化为 0,在时间步 t 我们得到 $v_t=(1-\\beta_1)\\sum_{i=1}^t\\beta_1^{t-i}g_i$。将过去各时间步小批量随机梯度的权值相加,得到 $(1-\\beta_1)\\sum_{i=1}^t\\beta_1^{t-i}=1-\\beta_1^t$。需要注意的是,当 t 较小时,过去各时间步小批量随机梯度权值之和会较小。例如,当β1 = 0.9时,v1 = 0.1g1。为了消除这样的影响,对于任意时间步 t,我们可以将 vt 再除以 $1-\\beta_1^t$,从而使过去各时间步小批量随机梯度权值之和为1。这也叫作偏差修正。在Adam算法中,我们对变量 vt 和 st 均作偏差修正: $$\\check{v}_t=\\frac{v_t}{1-\\beta_1^t}$$ $$\\check{s}_t=\\frac{s_t}{1-\\beta_2^t}$$ 接下来,Adam算法使⽤以上偏差修正后的变量vˆt和sˆt,将模型参数中每个元素的学习率通过按元素运算重新调整: $$g_t^{′}=\\frac{\\eta{}\\check{v}_t}{\\sqrt{\\check{s}_t}+\\varepsilon}$$ 其中η是学习率,ϵ是为了维持数值稳定性而添加的常数,如10的-8次方。和AdaGrad算法、RMSProp算法以及AdaDelta算法⼀样,⽬标函数⾃变量中每个元素都分别拥有⾃⼰的学习率。最后,使⽤ $g_t^{′}$ 迭代⾃变量: $$x_t=x_{t-1}-g_t^{′}$$ 7.6 局部最优–鞍点问题一个具有高维度空间的函数,如果梯度为 0,那么在每个方向,它可能是凸函数,也可能是凹函数。如果你在 2 万维空间中,那么想要得到局部最优,所有的 2 万个方向都需要是这样,但发生的机率也许很小,也许是2的-20000次方,你更有可能遇到有些方向的曲线会这样向上弯曲,另一些方向曲线向下弯,而不是所有的都向上弯曲,因此在高维度空间,你更可能碰到鞍点。 而不会碰到局部最优。至于为什么会把一个曲面叫做鞍点,你想象一下,就像是放在马背上的马鞍一样,如果这是马,这是马的头,这就是马的眼睛,画得不好请多包涵,然后你就是骑马的人,要坐在马鞍上,因此这里的这个点,导数为 0 的点,这个点叫做鞍点。我想那确实是你坐在马鞍上的那个点,而这里导数为 0。 鞍点中的平稳段是一个问题,这样使得学习十分缓慢,这也是像 Momentum 或是RMSprop,Adam 这样的算法,能够加速学习算法的地方。在这些情况下,更成熟的优化算法,如 Adam 算法,能够加快速度,让你尽早往下走出平稳段。 8. 如何解决训练样本少的问题 利用预训练模型进行迁移微调(fine-tuning),预训练模型通常在特征上拥有很好的语义表达。此时,只需将模型在小数据集上进行微调就能取得不错的效果。CV有ImageNet,NLP有BERT等。 数据集进行下采样操作,使得符合数据同分布。 数据集增强、正则或者半监督学习等方式来解决小样本数据集的训练问题。 9. 如何提升模型的稳定性? 正则化(L2, L1, dropout):模型方差大,很可能来自于过拟合。正则化能有效的降低模型的复杂度,增加对更多分布的适应性。 提前停止训练:提前停止是指模型在验证集上取得不错的性能时停止训练。这种方式本质和正则化是一个道理,能减少方差的同时增加的偏差。目的为了平衡训练集和未知数据之间在模型的表现差异。 扩充训练集:正则化通过控制模型复杂度,来增加更多样本的适应性。 特征选择:过高的特征维度会使模型过拟合,减少特征维度和正则一样可能会处理好方差问题,但是同时会增大偏差。 10. 有哪些改善模型的思路 *数据角度 * 增强数据集。无论是有监督还是无监督学习,数据永远是最重要的驱动力。更多的类型数据对良好的模型能带来更好的稳定性和对未知数据的可预见性。对模型来说,“看到过的总比没看到的更具有判别的信心”。 模型角度 模型的容限能力决定着模型可优化的空间。在数据量充足的前提下,对同类型的模型,增大模型规模来提升容限无疑是最直接和有效的手段。 调参优化角度 如果你知道模型的性能为什么不再提高了,那已经向提升性能跨出了一大步。 超参数调整本身是一个比较大的问题。一般可以包含模型初始化的配置,优化算法的选取、学习率的策略以及如何配置正则和损失函数等等。 训练角度 在越大规模的数据集或者模型上,诚然一个好的优化算法总能加速收敛。但你在未探索到模型的上限之前,永远不知道训练多久算训练完成。所以在改善模型上充分训练永远是最必要的过程。充分训练的含义不仅仅只是增大训练轮数。有效的学习率衰减和正则同样是充分训练中非常必要的手段。 11. 如何提高深度学习系统的性能 提高模型的结构。 改进模型的初始化方式,保证早期梯度具有某些有益的性质,或者具备大量的稀疏性,或者利用线性代数原理的优势。 择更强大的学习算法。 12. 参考文献 动手学–深度学习 吴恩达–深度学习笔记 GitHub 百面机器学习 【机器学习通俗易懂系列文章】 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"深度学习","slug":"深度学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【深度学习】强化学习","slug":"DL/Reinforcement","date":"2019-08-17T16:00:00.000Z","updated":"2019-12-25T05:54:50.329Z","comments":true,"path":"2019/08/18/DL/Reinforcement/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/18/DL/Reinforcement/","excerpt":"其他许多机器学习算法中学习器都是学得怎样做,而强化学习(Reinforcement Learning, RL)是在尝试的过程中学习到在特定的情境下选择哪种行动可以得到最大的回报。在很多场景中,当前的行动不仅会影响当前的rewards,还会影响之后的状态和一系列的rewards。RL最重要的3个特定…","text":"其他许多机器学习算法中学习器都是学得怎样做,而强化学习(Reinforcement Learning, RL)是在尝试的过程中学习到在特定的情境下选择哪种行动可以得到最大的回报。在很多场景中,当前的行动不仅会影响当前的rewards,还会影响之后的状态和一系列的rewards。RL最重要的3个特定… 1. 什么是强化学习其他许多机器学习算法中学习器都是学得怎样做,而强化学习(Reinforcement Learning, RL)是在尝试的过程中学习到在特定的情境下选择哪种行动可以得到最大的回报。在很多场景中,当前的行动不仅会影响当前的rewards,还会影响之后的状态和一系列的rewards。RL最重要的3个特定在于: 基本是以一种闭环的形式; 不会直接指示选择哪种行动(actions); 一系列的actions和奖励信号(reward signals)都会影响之后较长的时间。 强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题 [1] 。 上图中agent代表自身,如果是自动驾驶,agent就是车;如果你玩游戏它就是你当前控制的游戏角色,如马里奥,马里奥往前走时环境就一直在发生变化,有小怪物或者障碍物出现,它需要通过跳跃来进行躲避,就是要做action(如向前走和跳起的动作);无人驾驶的action就是车左转、右转或刹车等等,它无时无刻都在与环境产生交互,action会反馈给环境,进而改变环境,如果自动驾驶的车行驶目标是100米,它向前开了10米,那环境就发生了变化,所以每次产生action都会导致环境改变,环境的改变会反馈给自身(agent),就是这样的一个循环;反馈又两种方式: 做的好(reward)即正反馈, 做得不好(punishment惩罚)即负反馈。 Agent可能做得好,也可能做的不好,环境始终都会给它反馈,agent会尽量去做对自身有利的决策,通过反反复复这样的一个循环,agent会越来越做的好,就像孩子在成长过程中会逐渐明辨是非,这就是强化学习。 2. 强化学习模型 如上图左边所示,一个agent(例如:玩家/智能体等)做出了一个action,对environment造成了影响,也就是改变了state,而environment为了反馈给agent,agent就得到了一个奖励(例如:积分/分数),不断的进行这样的循环,直到结束为止。 上述过程就相当于一个马尔可夫决策过程,为什么这样叫呢?因为符合马儿可夫假设: 当前状态 St 只由上一个状态 St-1 和行为所决定,而和前序的更多的状态是没有关系的。 上图右边所示,S0 状态经过了 a0 的行为后,获得了奖励 r1 ,变成了状态S1,后又经过了 a0 行为得到奖励 r2,变成了状态 S2 ,如此往复循环,直到结束为止。 2.1 打折的未来奖励通过以上的描述,大家都已经确定了一个概念,也就是agent(智能体)在当下做出的决定肯定使得未来收益最大化,那么,一个马儿可夫决策过程对应的奖励总和为: $$R=r_1+r_2+r_3+…+r_n$$ t 时刻(当下)的未来奖励,只考虑后面的奖励,前面的改变不了: $$R_t=r_t+r_{t+1}+r_{t+2}+…+r_n$$ 接下来,当前的情况下做出的动作是能够得到结果的,但对于未来的影响是一个不确定的,这也符合我们的真实世界,比如谁都不知道一只蝴蝶只是煽动了一次翅膀会造成飓风式的影响(蝴蝶效应)。所以,当前的行为对于未来是不确定性的,要打一个折扣,也就是加入一个系数gamma,是一个 0 到 1 的值: $$R_t=r_1+\\gamma_{}r_{t+1}+\\gamma^2r_{t+2}+…+\\gamma^{n-1}r_n$$ 离当前越远的时间,gamma的惩罚系数就会越大,也就是越不确定。为的就是在当前和未来的决策中取得一个平衡。gamma取 0 ,相当于不考虑未来,只考虑当下,是一种很短视的做法;而gamma取 1 ,则完全考虑了未来,又有点过虑了。所以一般gamma会取 0 到 1 之间的一个值。 Rt 可以用 Rt+1 来表示,写成递推式: $$R_t=r_t+\\gamma(r_{t+1}+\\gamma(r_{t+2}+…))=r_t+\\gamma_{}R_{t+1}$$ 2.2 Q-Learning算法Q(s, a)函数(Quality),质量函数用来表示智能体在s状态下采用a动作并在之后采取最优动作条件下的打折的未来奖励(先不管未来的动作如何选择): $$Q(s_t,a_t)=maxR_{t+1}$$ 假设有了这个Q函数,那么我们就能够求得在当前 t 时刻当中,做出各个决策的最大收益值,通过对比这些收益值,就能够得到 t 时刻某个决策是这些决策当中收益最高。 $$\\pi(s)=argmax_aQ(s,a)$$ 于是乎,根据Q函数的递推公式可以得到: $$Q(s_t,a_t)=r+\\gamma_{}max_aQ(s_{t+1},a_{t+1})$$ 这就是注明的贝尔曼公式。贝尔曼公式实际非常合理。对于某个状态来讲,最大化未来奖励相当于最大化即刻奖励与下一状态最大未来奖励之和。 Q-learning的核心思想是:我们能够通过贝尔曼公式迭代地近似Q-函数。 2.3 Deep Q Learning(DQN)Deep Q Learning(DQN)是一种融合了神经网络和的Q-Learning方法。 2.3.1 神经网络的作用 使用表格来存储每一个状态 state, 和在这个 state 每个行为 action 所拥有的 Q 值. 而当今问题是在太复杂, 状态可以多到比天上的星星还多(比如下围棋). 如果全用表格来存储它们, 恐怕我们的计算机有再大的内存都不够, 而且每次在这么大的表格中搜索对应的状态也是一件很耗时的事. 不过, 在机器学习中, 有一种方法对这种事情很在行, 那就是神经网络. 我们可以将状态和动作当成神经网络的输入, 然后经过神经网络分析后得到动作的 Q 值, 这样我们就没必要在表格中记录 Q 值, 而是直接使用神经网络生成 Q 值. 还有一种形式的是这样, 我们也能只输入状态值, 输出所有的动作值, 然后按照 Q learning 的原则, 直接选择拥有最大值的动作当做下一步要做的动作. 我们可以想象, 神经网络接受外部的信息, 相当于眼睛鼻子耳朵收集信息, 然后通过大脑加工输出每种动作的值, 最后通过强化学习的方式选择动作. 2.3.2 神经网络计算Q值这一部分就跟监督学习的神经网络一样了我,输入状态值,输出为Q值,根据大量的数据去训练神经网络的参数,最终得到Q-Learning的计算模型,这时候我们就可以利用这个模型来进行强化学习了。 3. 强化学习和监督学习、无监督学习的区别 监督式学习就好比你在学习的时候,有一个导师在旁边指点,他知道怎么是对的怎么是错的。 强化学习会在没有任何标签的情况下,通过先尝试做出一些行为得到一个结果,通过这个结果是对还是错的反馈,调整之前的行为,就这样不断的调整,算法能够学习到在什么样的情况下选择什么样的行为可以得到最好的结果。 监督式学习出的是之间的关系,可以告诉算法什么样的输入对应着什么样的输出。监督学习做了比较坏的选择会立刻反馈给算法。 强化学习出的是给机器的反馈 reward function,即用来判断这个行为是好是坏。 另外强化学习的结果反馈有延时,有时候可能需要走了很多步以后才知道以前的某一步的选择是好还是坏。 监督学习的输入是独立同分布的。 强化学习面对的输入总是在变化,每当算法做出一个行为,它影响下一次决策的输入。 监督学习算法不考虑这种平衡,就只是 exploitative。 强化学习,一个 agent 可以在探索和开发(exploration and exploitation)之间做权衡,并且选择一个最大的回报。 非监督式不是学习输入到输出的映射,而是模式(自动映射)。 对强化学习来说,它通过对没有概念标记、但与一个延迟奖赏或效用(可视为延迟的概念标记)相关联的训练例进行学习,以获得某种从状态到行动的映射。 强化学习和前二者的本质区别:没有前两者具有的明确数据概念,它不知道结果,只有目标。数据概念就是大量的数据,有监督学习、无监督学习需要大量数据去训练优化你建立的模型。 监督学习 非监督学习 强化学习 标签 正确且严格的标签 没有标签 没有标签,通过结果反馈调整 输入 独立同分布 独立同分布 输入总是在变化,每当算法做出一个行为,它影响下一次决策的输入。 输出 输入对应输出 自学习映射关系 reward function,即结果用来判断这个行为是好是坏 4. 什么是多任务学习在机器学习中,我们通常关心优化某一特定指标,不管这个指标是一个标准值,还是企业KPI。为了达到这个目标,我们训练单一模型或多个模型集合来完成指定得任务。然后,我们通过精细调参,来改进模型直至性能不再提升。尽管这样做可以针对一个任务得到一个可接受得性能,但是我们可能忽略了一些信息,这些信息有助于在我们关心的指标上做得更好。具体来说,这些信息就是相关任务的监督数据。通过在相关任务间共享表示信息,我们的模型在原始任务上泛化性能更好。这种方法称为多任务学习(Multi-Task Learning) 在不同的任务中都会有一些共性,而这些共性就构成了多任务学习的一个连接点,也就是任务都需要通过这个共性能得出结果来的。比如电商场景中的点击率和转化率,都要依赖于同一份数据的输入和神经网络层次。多语种语音识别等。 5. 参考文献 GitHub 强化学习 【机器学习通俗易懂系列文章】 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"深度学习","slug":"深度学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【深度学习】迁移学习","slug":"DL/Transfer Learning","date":"2019-08-17T16:00:00.000Z","updated":"2019-12-25T05:54:00.762Z","comments":true,"path":"2019/08/18/DL/Transfer Learning/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/18/DL/Transfer%20Learning/","excerpt":"迁移学习(Transformer Learning)是一种机器学习方法,就是把为任务 A 开发的模型作为初始点,重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务,虽然大多数机器学习算法都是为了解决单个任务而设计的,但是促进迁移学习的算法的开发是机…","text":"迁移学习(Transformer Learning)是一种机器学习方法,就是把为任务 A 开发的模型作为初始点,重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务,虽然大多数机器学习算法都是为了解决单个任务而设计的,但是促进迁移学习的算法的开发是机… 1. 什么是迁移学习迁移学习(Transfer Learning)是一种机器学习方法,就是把为任务 A 开发的模型作为初始点,重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务,虽然大多数机器学习算法都是为了解决单个任务而设计的,但是促进迁移学习的算法的开发是机器学习社区持续关注的话题。 迁移学习对人类来说很常见,例如,我们可能会发现学习识别苹果可能有助于识别梨,或者学习弹奏电子琴可能有助于学习钢琴。 找到目标问题的相似性,迁移学习任务就是从相似性出发,将旧领域(domain)学习过的模型应用在新领域上。 2. 为什么需要迁移学习? 大数据与少标注的矛盾:虽然有大量的数据,但往往都是没有标注的,无法训练机器学习模型。人工进行数据标定太耗时。 大数据与弱计算的矛盾:普通人无法拥有庞大的数据量与计算资源。因此需要借助于模型的迁移。 普适化模型与个性化需求的矛盾:即使是在同一个任务上,一个模型也往往难以满足每个人的个性化需求,比如特定的隐私设置。这就需要在不同人之间做模型的适配。 特定应用(如冷启动)的需求。 3. 迁移学习的基本问题有哪些?基本问题主要有3个: How to transfer: 如何进行迁移学习?(设计迁移方法) What to transfer: 给定一个目标领域,如何找到相对应的源领域,然后进行迁移?(源领域选择) When to transfer: 什么时候可以进行迁移,什么时候不可以?(避免负迁移) 4. 迁移学习有哪些常用概念? 基本定义 域(Domain):数据特征和特征分布组成,是学习的主体 源域 (Source domain):已有知识的域 目标域 (Target domain):要进行学习的域 任务 (Task):由目标函数和学习结果组成,是学习的结果 按特征空间分类 同构迁移学习(Homogeneous TL): 源域和目标域的特征空间相同,$D_s=D_t$ 异构迁移学习(Heterogeneous TL):源域和目标域的特征空间不同,$D_s\\ne D_t$ 按迁移情景分类 归纳式迁移学习(Inductive TL):源域和目标域的学习任务不同 直推式迁移学习(Transductive TL):源域和目标域不同,学习任务相同 无监督迁移学习(Unsupervised TL):源域和目标域均没有标签 按迁移方法分类 基于样本的迁移 (Instance based TL):通过权重重用源域和目标域的样例进行迁移 基于样本的迁移学习方法 (Instance based Transfer Learning) 根据一定的权重生成规则,对数据样本进行重用,来进行迁移学习。下图形象地表示了基于样本迁移方法的思想源域中存在不同种类的动物,如狗、鸟、猫等,目标域只有狗这一种类别。在迁移时,为了最大限度地和目标域相似,我们可以人为地提高源域中属于狗这个类别的样本权重。 基于特征的迁移 (Feature based TL):将源域和目标域的特征变换到相同空间 基于特征的迁移方法 (Feature based Transfer Learning) 是指将通过特征变换的方式互相迁移,来减少源域和目标域之间的差距;或者将源域和目标域的数据特征变换到统一特征空间中,然后利用传统的机器学习方法进行分类识别。根据特征的同构和异构性,又可以分为同构和异构迁移学习。下图很形象地表示了两种基于特 征的迁移学习方法。 基于模型的迁移 (Parameter based TL):利用源域和目标域的参数共享模型 基于模型的迁移方法 (Parameter/Model based Transfer Learning) 是指从源域和目标域中找到他们之间共享的参数信息,以实现迁移的方法。这种迁移方式要求的假设条件是: 源域中的数据与目标域中的数据可以共享一些模型的参数。下图形象地表示了基于模型的迁移学习方法的基本思想。 基于关系的迁移 (Relation based TL):利用源域中的逻辑网络关系进行迁移 基于关系的迁移学习方法 (Relation Based Transfer Learning) 与上述三种方法具有截然不同的思路。这种方法比较关注源域和目标域的样本之间的关系。下图形象地表示了不 同领域之间相似的关系。 5. 迁移学习与传统机器学习有什么区别? 迁移学习 传统机器学习 数据分布 训练和测试数据不需要同分布 训练和测试数据同分布 数据标签 不需要足够的数据标注 足够的数据标注 建模 可以重用之前的模型 每个任务分别建模 6. 迁移学习的核心及度量准则?迁移学习的总体思路可以概括为:开发算法来最大限度地利用有标注的领域的知识,来辅助目标领域的知识获取和学习。 迁移学习的核心是:找到源领域和目标领域之间的相似性,并加以合理利用。这种相似性非常普遍。比如,不同人的身体构造是相似的;自行车和摩托车的骑行方式是相似的;国际象棋和中国象棋是相似的;羽毛球和网球的打球方式是相似的。这种相似性也可以理解为不变量。以不变应万变,才能立于不败之地。 有了这种相似性后,下一步工作就是, 如何度量和利用这种相似性。度量工作的目标有两点:一是很好地度量两个领域的相似性,不仅定性地告诉我们它们是否相似,更定量地给出相似程度。二是以度量为准则,通过我们所要采用的学习手段,增大两个领域之间的相似性,从而完成迁移学习。 一句话总结: 相似性是核心,度量准则是重要手段。 7. 迁移学习与其他概念的区别? 迁移学习与多任务学习关系: 多任务学习:多个相关任务一起协同学习; 迁移学习:强调信息复用,从一个领域(domain)迁移到另一个领域。 迁移学习与领域自适应:领域自适应:使两个特征分布不一致的domain一致。 迁移学习与协方差漂移:协方差漂移:数据的条件概率分布发生变化。 8. 什么情况下可以使用迁移学习?迁移学习最有用的场合是,如果你尝试优化任务B的性能,通常这个任务数据相对较少。 例如,在放射科中你知道很难收集很多射线扫描图来搭建一个性能良好的放射科诊断系统,所以在这种情况下,你可能会找一个相关但不同的任务,如图像识别,其中你可能用 1 百万张图片训练过了,并从中学到很多低层次特征,所以那也许能帮助网络在任务在放射科任务上做得更好,尽管任务没有这么多数据。 假如两个领域之间的区别特别的大,不可以直接采用迁移学习,因为在这种情况下效果不是很好。在这种情况下,推荐以上的方法,在两个相似度很低的domain之间一步步迁移过去(踩着石头过河)。 9. 什么是finetune?度网络的finetune也许是最简单的深度网络迁移方法。Finetune,也叫微调、fine-tuning, 是深度学习中的一个重要概念。简而言之,finetune就是利用别人己经训练好的网络,针对自己的任务再进行调整。从这个意思上看,我们不难理解finetune是迁移学习的一部分。 为什么需要已经训练好的网络? 在实际的应用中,我们通常不会针对一个新任务,就去从头开始训练一个神经网络。这样的操作显然是非常耗时的。尤其是,我们的训练数据不可能像ImageNet那么大,可以训练出泛化能力足够强的深度神经网络。即使有如此之多的训练数据,我们从头开始训练,其代价也是不可承受的。 为什么需要 finetune? 因为别人训练好的模型,可能并不是完全适用于我们自己的任务。可能别人的训练数据和我们的数据之间不服从同一个分布;可能别人的网络能做比我们的任务更多的事情;可能别人的网络比较复杂,我们的任务比较简单。 10. 什么是深度网络自适应?深度网络的 finetune 可以帮助我们节省训练时间,提高学习精度。但是 finetune 有它的先天不足:它无法处理训练数据和测试数据分布不同的情况。而这一现象在实际应用中比比皆是。因为 finetune 的基本假设也是训练数据和测试数据服从相同的数据分布。这在迁移学习中也是不成立的。因此,我们需要更进一步,针对深度网络开发出更好的方法使之更好地完成迁移学习任务。 以我们之前介绍过的数据分布自适应方法为参考,许多深度学习方法都开发出了自适应层(AdaptationLayer)来完成源域和目标域数据的自适应。自适应能够使得源域和目标域的数据分布更加接近,从而使得网络的效果更好。 11. GAN在迁移学习中的应用生成对抗网络 GAN(Generative Adversarial Nets) 受到自博弈论中的二人零和博弈 (two-player game) 思想的启发而提出。它一共包括两个部分: 一部分为生成网络(Generative Network),此部分负责生成尽可能地以假乱真的样本,这部分被成为生成器(Generator); 另一部分为判别网络(Discriminative Network), 此部分负责判断样本是真实的,还是由生成器生成的,这部分被成为判别器(Discriminator) 生成器和判别器的互相博弈,就完成了对抗训练。 GAN 的目标很明确:生成训练样本。这似乎与迁移学习的大目标有些许出入。然而,由于在迁移学习中,天然地存在一个源领域,一个目标领域,因此,我们可以免去生成样本的过程,而直接将其中一个领域的数据 (通常是目标域) 当作是生成的样本。此时,生成器的职能发生变化,不再生成新样本,而是扮演了特征提取的功能:不断学习领域数据的特征使得判别器无法对两个领域进行分辨。这样,原来的生成器也可以称为特征提取器 (Feature Extractor)。 12. 代码实现Transfer Learning例子 数据集下载: Inception-v3模型:点击下载 flower_photos数据集:点击下载 【机器学习通俗易懂系列文章】 13. 参考文献https://github.com/scutan90/DeepLearning-500-questions/tree/master/ch11_%E8%BF%81%E7%A7%BB%E5%AD%A6%E4%B9%A0 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"深度学习","slug":"深度学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【深度学习】长短期记忆(LSTM)","slug":"DL/LSTM","date":"2019-08-16T16:00:00.000Z","updated":"2019-12-25T05:52:51.815Z","comments":true,"path":"2019/08/17/DL/LSTM/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/17/DL/LSTM/","excerpt":"在你阅读这篇文章时候,你都是基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。我们不会将所有的东西都全部丢弃,然后用空白的大脑进行思考。我们的思想拥有持久性。LSTM就是具备了这一特性。 这篇将介绍另⼀种常⽤的⻔控循环神经⽹络:⻓短期记忆(long short-term memory…","text":"在你阅读这篇文章时候,你都是基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。我们不会将所有的东西都全部丢弃,然后用空白的大脑进行思考。我们的思想拥有持久性。LSTM就是具备了这一特性。 这篇将介绍另⼀种常⽤的⻔控循环神经⽹络:⻓短期记忆(long short-term memory… 1. 什么是LSTM在你阅读这篇文章时候,你都是基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。我们不会将所有的东西都全部丢弃,然后用空白的大脑进行思考。我们的思想拥有持久性。LSTM就是具备了这一特性。 这篇将介绍另⼀种常⽤的⻔控循环神经⽹络:⻓短期记忆(long short-term memory,LSTM)[1]。它⽐⻔控循环单元的结构稍微复杂⼀点,也是为了解决在RNN网络中梯度衰减的问题,是GRU的一种扩展。 可以先理解GRU的过程,在来理解LSTM会容易许多,链接地址:三步理解–门控循环单元(GRU) LSTM 中引⼊了3个⻔,即输⼊⻔(input gate)、遗忘⻔(forget gate)和输出⻔(output gate),以及与隐藏状态形状相同的记忆细胞(某些⽂献把记忆细胞当成⼀种特殊的隐藏状态),从而记录额外的信息。 2. 输⼊⻔、遗忘⻔和输出⻔与⻔控循环单元中的重置⻔和更新⻔⼀样,⻓短期记忆的⻔的输⼊均为当前时间步输⼊Xt与上⼀时间步隐藏状态Ht−1,输出由激活函数为sigmoid函数的全连接层计算得到。如此⼀来,这3个⻔元素的值域均为[0, 1]。如下图所示: 具体来说,假设隐藏单元个数为 h,给定时间步 t 的小批量输⼊ $X_t\\in_{}\\mathbb{R}^{nd}$(样本数为n,输⼊个数为d)和上⼀时间步隐藏状态 $H_{t-1}\\in_{}\\mathbb{R}^{nh}$ 。三个门的公式如下: 输入门:$$I_t=\\sigma(X_tW_{xi}+H_{t-1}W_{hi}+b_i)$$ 遗忘问: $$F_t=\\sigma(X_tW_{xf}+H_{t-1}W_{hf}+b_f)$$ 输出门: $$O_t=\\sigma(X_tW_{xo}+H_{t-1}W_{ho}+b_o)$$ 3. 候选记忆细胞接下来,⻓短期记忆需要计算候选记忆细胞 $\\tilde{C}_t$。它的计算与上⾯介绍的3个⻔类似,但使⽤了值域在[−1, 1]的tanh函数作为激活函数,如下图所示: 具体来说,时间步t的候选记忆细胞计算如下: $$\\tilde{C}t=tanh(X_tWxc+H{t-1}W_{hc}+b_c)$$ 4. 记忆细胞我们可以通过元素值域在[0, 1]的输⼊⻔、遗忘⻔和输出⻔来控制隐藏状态中信息的流动,这⼀般也是通过使⽤按元素乘法(符号为⊙)来实现的。当前时间步记忆细胞$H_{t}\\in_{}\\mathbb{R}^{n*h}$的计算组合了上⼀时间步记忆细胞和当前时间步候选记忆细胞的信息,并通过遗忘⻔和输⼊⻔来控制信息的流动: $$C_t=F_t⊙C_{t-1}+I_t⊙\\tilde{C}_t$$ 如下图所⽰,遗忘⻔控制上⼀时间步的记忆细胞Ct−1中的信息是否传递到当前时间步,而输⼊⻔则控制当前时间步的输⼊Xt通过候选记忆细胞C˜t如何流⼊当前时间步的记忆细胞。如果遗忘⻔⼀直近似1且输⼊⻔⼀直近似0,过去的记忆细胞将⼀直通过时间保存并传递⾄当前时间步。这个设计可以应对循环神经⽹络中的梯度衰减问题,并更好地捕捉时间序列中时间步距离较⼤的依赖关系。 5. 隐藏状态有了记忆细胞以后,接下来我们还可以通过输出⻔来控制从记忆细胞到隐藏状态Ht的信息的流动: $$H_t=O_t⊙tanh(C_t)$$ 这⾥的tanh函数确保隐藏状态元素值在-1到1之间。需要注意的是,当输出⻔近似1时,记忆细胞信息将传递到隐藏状态供输出层使⽤;当输出⻔近似0时,记忆细胞信息只⾃⼰保留。下图展⽰了⻓短期记忆中隐藏状态的全部计算: 6. LSTM与GRU的区别LSTM与GRU二者结构十分相似,不同在于: 新的记忆都是根据之前状态及输入进行计算,但是GRU中有一个重置门控制之前状态的进入量,而在LSTM里没有类似门; 产生新的状态方式不同,LSTM有两个不同的门,分别是遗忘门(forget gate)和输入门(input gate),而GRU只有一种更新门(update gate); LSTM对新产生的状态可以通过输出门(output gate)进行调节,而GRU对输出无任何调节。 GRU的优点是这是个更加简单的模型,所以更容易创建一个更大的网络,而且它只有两个门,在计算性上也运行得更快,然后它可以扩大模型的规模。 LSTM更加强大和灵活,因为它有三个门而不是两个。 7. LSTM可以使用别的激活函数吗?关于激活函数的选取,在LSTM中,遗忘门、输入门和输出门使用Sigmoid函数作为激活函数;在生成候选记忆时,使用双曲正切函数Tanh作为激活函数。 值得注意的是,这两个激活函数都是饱和的,也就是说在输入达到一定值的情况下,输出就不会发生明显变化了。如果是用非饱和的激活函数,例如ReLU,那么将难以实现门控的效果。 Sigmoid函数的输出在0~1之间,符合门控的物理定义。且当输入较大或较小时,其输出会非常接近1或0,从而保证该门开或关。在生成候选记忆时,使用Tanh函数,是因为其输出在−1~1之间,这与大多数场景下特征分布是0中心的吻合。此外,Tanh函数在输入为0附近相比Sigmoid函数有更大的梯度,通常使模型收敛更快。 激活函数的选择也不是一成不变的,但要选择合理的激活函数。 8. 代码实现MIST数据分类–TensorFlow实现LSTM 【机器学习通俗易懂系列文章】 9. 参考文献《动手学–深度学习》 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"深度学习","slug":"深度学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【深度学习】门控循环神经⽹络(GRU)","slug":"DL/GRU","date":"2019-08-15T16:00:00.000Z","updated":"2019-12-25T05:53:13.178Z","comments":true,"path":"2019/08/16/DL/GRU/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/16/DL/GRU/","excerpt":"在循环神经⽹络中的梯度计算⽅法中,我们发现,当时间步数较⼤或者时间步较小时,循环神经⽹络的梯度较容易出现衰减或爆炸。虽然裁剪梯度可以应对梯度爆炸,但⽆法解决梯度衰减的问题。通常由于这个原因,循环神经⽹络在实际中较难捕捉时间序列中时间步距离较⼤的依赖关系。 门控循环神经⽹络(gated …","text":"在循环神经⽹络中的梯度计算⽅法中,我们发现,当时间步数较⼤或者时间步较小时,循环神经⽹络的梯度较容易出现衰减或爆炸。虽然裁剪梯度可以应对梯度爆炸,但⽆法解决梯度衰减的问题。通常由于这个原因,循环神经⽹络在实际中较难捕捉时间序列中时间步距离较⼤的依赖关系。 门控循环神经⽹络(gated … 1. 什么是GRU在循环神经⽹络中的梯度计算⽅法中,我们发现,当时间步数较⼤或者时间步较小时,循环神经⽹络的梯度较容易出现衰减或爆炸。虽然裁剪梯度可以应对梯度爆炸,但⽆法解决梯度衰减的问题。通常由于这个原因,循环神经⽹络在实际中较难捕捉时间序列中时间步距离较⼤的依赖关系。 门控循环神经⽹络(gated recurrent neural network)的提出,正是为了更好地捕捉时间序列中时间步距离较⼤的依赖关系。它通过可以学习的⻔来控制信息的流动。其中,门控循环单元(gatedrecurrent unit,GRU)是⼀种常⽤的门控循环神经⽹络。 2. ⻔控循环单元2.1 重置门和更新门GRU它引⼊了重置⻔(reset gate)和更新⻔(update gate)的概念,从而修改了循环神经⽹络中隐藏状态的计算⽅式。 门控循环单元中的重置⻔和更新⻔的输⼊均为当前时间步输⼊ $X_t$ 与上⼀时间步隐藏状态$H_{t-1}$,输出由激活函数为sigmoid函数的全连接层计算得到。 如下图所示: 具体来说,假设隐藏单元个数为 h,给定时间步 t 的小批量输⼊ $X_t\\in_{}\\mathbb{R}^{nd}$(样本数为n,输⼊个数为d)和上⼀时间步隐藏状态 $H_{t-1}\\in_{}\\mathbb{R}^{nh}$。重置⻔ $H_t\\in_{}\\mathbb{R}^{nh}$ 和更新⻔ $Z_t\\in_{}\\mathbb{R}^{nh}$ 的计算如下: $$R_t=\\sigma(X_tW_{xr}+H_{t-1}W_{hr}+b_r)$$ $$Z_t=\\sigma(X_tW_{xz}+H_{t-1}W_{hz}+b_z)$$ sigma函数可以将元素的值变换到0和1之间。因此,重置⻔ $R_t$ 和更新⻔ $Z_t$ 中每个元素的值域都是[0, 1]。 2.2 候选隐藏状态接下来,⻔控循环单元将计算候选隐藏状态来辅助稍后的隐藏状态计算。我们将当前时间步重置⻔的输出与上⼀时间步隐藏状态做按元素乘法(符号为⊙)。如果重置⻔中元素值接近0,那么意味着重置对应隐藏状态元素为0,即丢弃上⼀时间步的隐藏状态。如果元素值接近1,那么表⽰保留上⼀时间步的隐藏状态。然后,将按元素乘法的结果与当前时间步的输⼊连结,再通过含激活函数tanh的全连接层计算出候选隐藏状态,其所有元素的值域为[-1,1]。 具体来说,时间步 t 的候选隐藏状态 $\\tilde{H}\\in_{}\\mathbb{R}^{n*h}$ 的计算为: $$\\tilde{H}t=tanh(X_tW{xh}+(R_t⊙H_{t-1})W_{hh}+b_h)$$ 从上⾯这个公式可以看出,重置⻔控制了上⼀时间步的隐藏状态如何流⼊当前时间步的候选隐藏状态。而上⼀时间步的隐藏状态可能包含了时间序列截⾄上⼀时间步的全部历史信息。因此,重置⻔可以⽤来丢弃与预测⽆关的历史信息。 2.3 隐藏状态最后,时间步t的隐藏状态 $H_t\\in_{}\\mathbb{R}^{n*h}$ 的计算使⽤当前时间步的更新⻔$Z_t$来对上⼀时间步的隐藏状态 $H_{t-1}$ 和当前时间步的候选隐藏状态 $\\tilde{H}_t$ 做组合: 值得注意的是,更新⻔可以控制隐藏状态应该如何被包含当前时间步信息的候选隐藏状态所更新,如上图所⽰。假设更新⻔在时间步 $t^{′}到t(t^{′}<t)$ 之间⼀直近似1。那么,在时间步 $t^{′}到t$ 间的输⼊信息⼏乎没有流⼊时间步 t 的隐藏状态$H_t$实际上,这可以看作是较早时刻的隐藏状态 $H_{t^{′}-1}$ 直通过时间保存并传递⾄当前时间步 t。这个设计可以应对循环神经⽹络中的梯度衰减问题,并更好地捕捉时间序列中时间步距离较⼤的依赖关系。 我们对⻔控循环单元的设计稍作总结: 重置⻔有助于捕捉时间序列⾥短期的依赖关系; 更新⻔有助于捕捉时间序列⾥⻓期的依赖关系。 3. 代码实现GRUMNIST–GRU实现 【机器学习通俗易懂系列文章】 4. 参考文献《动手学–深度学习》 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"深度学习","slug":"深度学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【深度学习】循环神经网络(RNN)","slug":"DL/RNN","date":"2019-08-14T16:00:00.000Z","updated":"2019-12-25T05:49:48.681Z","comments":true,"path":"2019/08/15/DL/RNN/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/15/DL/RNN/","excerpt":"1.2 为什么有了CNN,还要RNN? 现在我们考虑输⼊数据存在时间相关性的情况。假设 是序列中时间步t的小批量输⼊, 是该时间步的隐藏变量。那么根据以上结构图当前的隐藏变量的公式如下: 从以上公式我们可以看出,这⾥我们保存上⼀时间步的隐藏变量 ,并引⼊⼀个新的权重参数,该参数⽤来描述在当前时间步…","text":"1.2 为什么有了CNN,还要RNN? 现在我们考虑输⼊数据存在时间相关性的情况。假设 是序列中时间步t的小批量输⼊, 是该时间步的隐藏变量。那么根据以上结构图当前的隐藏变量的公式如下: 从以上公式我们可以看出,这⾥我们保存上⼀时间步的隐藏变量 ,并引⼊⼀个新的权重参数,该参数⽤来描述在当前时间步… 1. 什么是RNN 循环神经网络(Recurrent Neural Network, RNN)是一类以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network) 1.1 RNN的应用 文本生成(生成序列) 机器翻译 看图说话 文本(情感)分析 智能客服 聊天机器人 语音识别 搜索引擎 个性化推荐 1.2 为什么有了CNN,还要RNN? 传统神经网络(包括CNN),输入和输出都是互相独立的。图像上的猫和狗是分隔开的,但有些任务,后续的输出和之前的内容是相关的。例如:我是中国人,我的母语是____。这是一道填空题,需要依赖于之前的输入。 所以,RNN引入“记忆”的概念,也就是输出需要依赖于之前的输入序列,并把关键输入记住。循环2字来源于其每个元素都执行相同的任务。 它并⾮刚性地记忆所有固定⻓度的序列,而是通过隐藏状态来存储之前时间步的信息。 1.3 RNN的网络结构首先先上图,然后再解释: 现在我们考虑输⼊数据存在时间相关性的情况。假设 $X_t\\in_{}\\mathbb{R}^{nd}$ 是序列中时间步t的小批量输⼊,$H_t\\in_{}\\mathbb{R}^{nh}$ 是该时间步的隐藏变量。那么根据以上结构图当前的隐藏变量的公式如下: $$H_t=\\phi(X_tW_{xh}+H_{t-1}W_{hh}+b_h)$$ 从以上公式我们可以看出,这⾥我们保存上⼀时间步的隐藏变量 $H_{t-1}$,并引⼊⼀个新的权重参数,该参数⽤来描述在当前时间步如何使⽤上⼀时间步的隐藏变量。具体来说,时间步 t 的隐藏变量的计算由当前时间步的输⼊和上⼀时间步的隐藏变量共同决定。 $\\phi$ 函数其实就是激活函数。 我们在这⾥添加了 $H_{t-1}W_{hh}$ ⼀项。由上式中相邻时间步的隐藏变量 $H_t 和H_{t-1}$ 之间的关系可知,这⾥的隐藏变量能够捕捉截⾄当前时间步的序列的历史信息,就像是神经⽹络当前时间步的状态或记忆⼀样。因此,该隐藏变量也称为隐藏状态。由于隐藏状态在当前时间步的定义使⽤了上⼀时间步的隐藏状态,上式的计算是循环的。使⽤循环计算的⽹络即循环神经⽹络(recurrent neural network)。 在时间步t,输出层的输出和多层感知机中的计算类似: $$O_t=H_tW_{hq}+b_q$$ 1.4 双向RNN之前介绍的循环神经⽹络模型都是假设当前时间步是由前⾯的较早时间步的序列决定的,因此它们都将信息通过隐藏状态从前往后传递。有时候,当前时间步也可能由后⾯时间步决定。例如,当我们写下⼀个句⼦时,可能会根据句⼦后⾯的词来修改句⼦前⾯的⽤词。双向循环神经⽹络通过增加从后往前传递信息的隐藏层来更灵活地处理这类信息。下图演⽰了⼀个含单隐藏层的双向循环神经⽹络的架构。 在双向循环神经⽹络的架构中,设该时间步正向隐藏状态为 $\\overrightarrow{H}t\\in{}\\mathbb{R}^{nh}$(正向隐藏单元个数为h),反向隐藏状态为 $\\overleftarrow{H}t\\in{}\\mathbb{R}^{nh}$(反向隐藏单元个数为h)。我们可以分别计算正向隐藏状态和反向隐藏状态: $$\\overrightarrow{H}t=\\phi(X_tW{xh}^{(f)}+\\overrightarrow{H}{t-1}W{hh}^{(f)}+b_h^{(f)})$$ $$\\overleftarrow{H}t=\\phi(X_tW{xh}^{(b)}+\\overleftarrow{H}{t-1}W{hh}^{(b)}+b_h^{(b)})$$ 然后我们连结两个⽅向的隐藏状态 $\\overrightarrow{H}t和\\overleftarrow{H}_t$ 来得到隐藏状态 $H_t\\in{}\\mathbb{R}^{n2h}$,并将其输⼊到输出层。输出层计算输出 $O_t\\in_{}\\mathbb{R}^{nq}$(输出个数为q): $$O_t=H_tW_{hq}+b_q$$ 双向循环神经⽹络在每个时间步的隐藏状态同时取决于该时间步之前和之后的⼦序列(包括当前时间步的输⼊)。 1.5 BPTT算法 在之前你已经见过对于前向传播(上图蓝色箭头所指方向)怎样在神经网络中从左到右地计算这些激活项,直到输出所有地预测结果。而对于反向传播,我想你已经猜到了,反向传播地计算方向(上图红色箭头所指方向)与前向传播基本上是相反的。 我们先定义一个元素损失函数: $$L^{(t)}(y^{‘(t)},y^{(t)})=-y^{(t)}logy^{‘(t)}-(1-y^{‘(t)})log(1-y^{‘(t)})$$ 整个序列的损失函数: $$L(y^{‘},y)=\\sum_{t=1}^{T_x}L^{(t)}(y^{‘(t)},y^{(t)})$$$ 在这个计算图中,通过$y^{‘(1)}$可以计算对应的损失函数,于是计算出第一个时间步的损失函数,然后计算出第二个时间步的损失函数,然后是第三个时间步,一直到最后一个时间步,最后为了计算出总体损失函数,我们要把它们都加起来,通过等式计算出最后的𝐿,也就是把每个单独时间步的损失函数都加起来。然后你就可以通过导数相关的参数,用梯度下降法来更新参数。 在这个反向传播的过程中,最重要的信息传递或者说最重要的递归运算就是这个从右到左的运算,这也就是为什么这个算法有一个很别致的名字,叫做“通过(穿越)时间反向传播(backpropagation through time)”。取这个名字的原因是对于前向传播,你需要从左到右进行计算,在这个过程中,时刻𝑡不断增加。而对于反向传播,你需要从右到左进行计算,就像时间倒流。“通过时间反向传播”,就像穿越时光,这种说法听起来就像是你需要一台时光机来实现这个算法一样。 2. 其它类型的RNN One to one:这个可能没有那么重要,这就是一个小型的标准的神经网络,输入𝑥然后得到输出𝑦。 One to many:音乐生成,你的目标是使用一个神经网络输出一些音符。对应于一段音乐,输入𝑥 可以是一个整数,表示你想要的音乐类型或者是你想要的音乐的第一个音符,并且如果你什么都不想输入,𝑥可以是空的输入,可设为 0 向量。 Many to one:句子分类问题,输入文档,输出文档的类型。 Many to many:命名实体识别。 Many to many:机器翻译。 3. CNN与RNN的区别 类别 特点描述 相同点 1、传统神经网络的扩展。2、前向计算产生结果,反向计算模型更新。3、每层神经网络横向可以多个神经元共存,纵向可以有多层神经网络连接。 不同点 1、CNN空间扩展,神经元与特征卷积;RNN时间扩展,神经元与多个时间输出计算2、RNN可以用于描述时间上连续状态的输出,有记忆功能,CNN用于静态输出 4. 为什么RNN 训练的时候Loss波动很大由于RNN特有的memory会影响后期其他的RNN的特点,梯度时大时小,learning rate没法个性化的调整,导致RNN在train的过程中,Loss会震荡起伏,为了解决RNN的这个问题,在训练的时候,可以设置临界值,当梯度大于某个临界值,直接截断,用这个临界值作为梯度的大小,防止大幅震荡。 5. 实例代码TensorFlow实现RNN 【机器学习通俗易懂系列文章】 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"深度学习","slug":"深度学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【深度学习】卷积神经网络(CNN)","slug":"DL/CNN","date":"2019-08-10T16:00:00.000Z","updated":"2019-12-25T05:50:02.207Z","comments":true,"path":"2019/08/11/DL/CNN/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/11/DL/CNN/","excerpt":"上图中CNN要做的事情是:给定一张图片,是车还是马未知,是什么车也未知,现在需要模型判断这张图片里具体是一个什么东西,总之输出一个结果:如果是车 那是什么车。 这几个部分中,卷积计算层是CNN的核心。 在做输入的时候,需要把图片处理成同样大小的图片才能够进行处理。 TIPS:在训练集和测试…","text":"上图中CNN要做的事情是:给定一张图片,是车还是马未知,是什么车也未知,现在需要模型判断这张图片里具体是一个什么东西,总之输出一个结果:如果是车 那是什么车。 这几个部分中,卷积计算层是CNN的核心。 在做输入的时候,需要把图片处理成同样大小的图片才能够进行处理。 TIPS:在训练集和测试… 1. 什么是CNN 卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一。 我们先来看卷积神经网络各个层级结构图: 上图中CNN要做的事情是:给定一张图片,是车还是马未知,是什么车也未知,现在需要模型判断这张图片里具体是一个什么东西,总之输出一个结果:如果是车那是什么车。 最左边是数据输入层(input layer),对数据做一些处理,比如去均值(把输入数据各个维度都中心化为0,避免数据过多偏差,影响训练效果)、归一化(把所有的数据都归一到同样的范围)、PCA/白化等等。CNN只对训练集做“去均值”这一步。 CONV:卷积计算层(conv layer),线性乘积求和。 RELU:激励层(activation layer),下文有提到:ReLU是激活函数的一种。 POOL:池化层(pooling layer),简言之,即取区域平均或最大。 FC:全连接层(FC layer)。 这几个部分中,卷积计算层是CNN的核心。 1.1 输入层在做输入的时候,需要把图片处理成同样大小的图片才能够进行处理。 常见的处理数据的方式有: 去均值(常用) AlexNet:训练集中100万张图片,对每个像素点求均值,得到均值图像,当训练时用原图减去均值图像。 VGG:对所有输入在三个颜色通道R/G/B上取均值,只会得到3个值,当训练时减去对应的颜色通道均值。(此种方法效率高) TIPS:在训练集和测试集上减去训练集的均值。 归一化 幅度归一化到同样的范围。 PCA/白化(很少用) 用PCA降维 白化是对数据每个特征轴上的幅度归一化。 1.2 卷积计算层(conv)对图像(不同的数据窗口数据)和滤波矩阵(一组固定的权重:因为每个神经元的多个权重固定,所以又可以看做一个恒定的滤波器filter)做内积(逐个元素相乘再求和)的操作就是所谓的『卷积』操作,也是卷积神经网络的名字来源。 滤波器filter是什么呢!请看下图。图中左边部分是原始输入数据,图中中间部分是滤波器filter,图中右边是输出的新的二维数据。 不同的滤波器filter会得到不同的输出数据,比如颜色深浅、轮廓。相当于提取图像的不同特征,模型就能够学习到多种特征。用不同的滤波器filter,提取想要的关于图像的特定信息:颜色深浅或轮廓。如下图所示。 在CNN中,滤波器filter(带着一组固定权重的神经元)对局部输入数据进行卷积计算。每计算完一个数据窗口内的局部数据后,数据窗口不断平移滑动,直到计算完所有数据。这个过程中,有这么几个参数: 深度depth:神经元个数,决定输出的depth厚度。同时代表滤波器个数。 步长stride:决定滑动多少步可以到边缘。 填充值zero-padding:在外围边缘补充若干圈0,方便从初始位置以步长为单位可以刚好滑倒末尾位置,通俗地讲就是为了总长能被步长整除。 参数共享机制 假设每个神经元连接数据窗的权重是固定对的。固定每个神经元连接权重,可以看做模板,每个神经元只关注一个特性(模板),这使得需要估算的权重个数减少:一层中从1亿到3.5万。 一组固定的权重和不同窗口内数据做内积:卷积 作用在于捕捉某一种模式,具体表现为很大的值。 卷积操作的本质特性包括稀疏交互和参数共享。 1.3 激励层把卷积层输出结果做非线性映射。 激活函数有: sigmoid:在两端斜率接近于0,梯度消失。 ReLu:修正线性单元,有可能出现斜率为0,但概率很小,因为mini-batch是一批样本损失求导之和。 TIPS: CNN慎用sigmoid!慎用sigmoid!慎用sigmoid! 首先试RELU,因为快,但要小心点。 如果RELU失效,请用 Leaky ReLU或者Maxout。 某些情况下tanh倒是有不错的结果,但是很少。 1.4 池化层也叫下采样层,就算通过了卷积层,纬度还是很高 ,需要进行池化层操作。 夹在连续的卷积层中间。 压缩数据和参数的量,降低维度。 减小过拟合。 具有特征不变性。 方式有:Max pooling、average pooling Max pooling 取出每个部分的最大值作为输出,例如上图左上角的4个黄色方块取最大值为3作为输出,以此类推。 average pooling 每个部分进行计算得到平均值作为输出,例如上图左上角的4个黄色方块取得平均值2作为输出,以此类推。 1.5 全连接层全连接层的每一个结点都与上一层的所有结点相连,用来把前边提取到的特征综合起来。由于其全连接的特性,一般全连接层的参数也是最多的。 两层之间所有神经元都有权重连接 通常全连接层在卷积神经网络尾部 1.6 层次结构小结 CNN层次结构 作用 输入层 卷积网络的原始输入,可以是原始或预处理后的像素矩阵 卷积层 参数共享、局部连接,利用平移不变性从全局特征图提取局部特征 激活层 将卷积层的输出结果进行非线性映射 池化层 进一步筛选特征,可以有效减少后续网络层次所需的参数量 全连接层 用于把该层之前提取到的特征综合起来。 1.7 CNN优缺点优点: 共享卷积核,优化计算量。 无需手动选取特征,训练好权重,即得特征。 深层次的网络抽取图像信息丰富,表达效果好。 保持了层级网络结构。 不同层次有不同形式与功能。 缺点: 需要调参,需要大样本量,GPU等硬件依赖。 物理含义不明确。 与NLP/Speech共性: 都存在局部与整体的关系,由低层次的特征经过组合,组成高层次的特征,并且得到不同特征之间的空间相关性。 2. 典型CNN发展历程 LeNet,这是最早用于数字识别的CNN AlexNet, 2012 ILSVRC比赛远超第2名的CNN,比LeNet更深,用多层小卷积层叠加替换单大卷积层。 ZF Net, 2013 ILSVRC比赛冠军 GoogLeNet, 2014 ILSVRC比赛冠军 VGGNet, 2014 ILSVRC比赛中的模型,图像识别略差于GoogLeNet,但是在很多图像转化学习问题(比如objectdetection)上效果很好 ResNet(深度残差网络(Deep Residual Network,ResNet)), 2015ILSVRC比赛冠军,结构修正(残差学习)以适应深层次CNN训练。 DenseNet, CVPR2017 best paper,把ResNet的add变成concat 3. 图像相关任务 3.1 图像识别与定位 classification:C个类别识别 input:Image Output:类别标签 Evaluation metric:准确率 Localization定位) Input:Image Output:物体边界框(x,y,w,h) Evaluation metric:交并准则(IOU) > 0.5 图中阴影部分所占面积 3.1.1 思路1:识别+定位过程 识别可以看作多分类问题(用softmax),用别人训练好的CNN模型做fine-tune 定位的目标是(x,y,w,h)是连续值,当回归问题解决(mse) 在1的CNN尾部展开(例如把最后一层拿开),接上一个(x,y,w,h)的神经网络,成为classification+regression的模型。 更细致的识别可以提前规定好有k个组成部分,做成k个部分的回归, 例如:框出两只眼睛和两条腿,4元祖*4=16(个连续值) Regression部分用欧氏距离损失,使用SGD训练。 3.1.2 思路2:图窗+识别 类似刚才的classification+regression思路 咱们取不同大小的“框” 让框出现在不同的位置 判定得分 按照得分的高低对“结果框”做抽样和合并 3.2 物体检测(object detection)3.2.1 过程当图像有很多物体怎么办的?难度可是一下暴增啊。 那任务就变成了:多物体识别+定位多个物体,那把这个任务看做分类问题? 看成分类问题有何不妥? 你需要找很多位置, 给很多个不同大小的框 你还需要对框内的图像分类 当然, 如果你的GPU很强大, 恩, 那加油做吧… 边缘策略:想办法先找到可能包含内容的图框(候选框),然后进行分类问题的识别。 方法:根据RGB值做区域融合。fast-CNN,共享图窗,从而加速候选框的形成。 R-CNN => fast-CNN => faster-RCNN 速度对比 3.2.2 R-CNNR-CNN的简要步骤如下: 输入测试图像。 利用选择性搜索Selective Search算法在图像中从下到上提取2000个左右的可能包含物体的候选区域Region Proposal。 因为取出的区域大小各自不同,所以需要将每个Region Proposal缩放(warp)成统一的227x227的大小并输入到CNN,将CNN的fc7层的输出作为特征。 将每个Region Proposal提取到的CNN特征输入到SVM进行分类。 3.2.3 SPP-NetSPP:Spatial Pyramid Pooling(空间金字塔池化),SPP-Net是出自2015年发表在IEEE上的论文。 众所周知,CNN一般都含有卷积部分和全连接部分,其中,卷积层不需要固定尺寸的图像,而全连接层是需要固定大小的输入。所以当全连接层面对各种尺寸的输入数据时,就需要对输入数据进行crop(crop就是从一个大图扣出网络输入大小的patch,比如227×227),或warp(把一个边界框bounding box(红框)的内容resize成227×227)等一系列操作以统一图片的尺寸大小,比如224224(ImageNet)、3232(LenNet)、96*96等。 所以才如你在上文中看到的,在R-CNN中,“因为取出的区域大小各自不同,所以需要将每个Region Proposal缩放(warp)成统一的227x227的大小并输入到CNN”。 但warp/crop这种预处理,导致的问题要么被拉伸变形、要么物体不全,限制了识别精确度。没太明白?说句人话就是,一张16:9比例的图片你硬是要Resize成1:1的图片,你说图片失真不? SPP Net的作者Kaiming He等人逆向思考,既然由于全连接FC层的存在,普通的CNN需要通过固定输入图片的大小来使得全连接层的输入固定。那借鉴卷积层可以适应任何尺寸,为何不能在卷积层的最后加入某种结构,使得后面全连接层得到的输入变成固定的呢? 这个“化腐朽为神奇”的结构就是spatial pyramid pooling layer。 它的特点有两个: 结合空间金字塔方法实现CNNs的多尺度输入。 SPP Net的第一个贡献就是在最后一个卷积层后,接入了金字塔池化层,保证传到下一层全连接层的输入固定。 换句话说,在普通的CNN机构中,输入图像的尺寸往往是固定的(比如224*224像素),输出则是一个固定维数的向量。SPP Net在普通的CNN结构中加入了ROI池化层(ROI Pooling),使得网络的输入图像可以是任意尺寸的,输出则不变,同样是一个固定维数的向量。 简言之,CNN原本只能固定输入、固定输出,CNN加上SSP之后,便能任意输入、固定输出。神奇吧? 只对原图提取一次卷积特征 在R-CNN中,每个候选框先resize到统一大小,然后分别作为CNN的输入,这样是很低效的。 而SPP Net根据这个缺点做了优化:只对原图进行一次卷积计算,便得到整张图的卷积特征feature map,然后找到每个候选框在feature map上的映射patch,将此patch作为每个候选框的卷积特征输入到SPP layer和之后的层,完成特征提取工作。 如此这般,R-CNN要对每个区域计算卷积,而SPPNet只需要计算一次卷积,从而节省了大量的计算时间,比R-CNN有一百倍左右的提速。 3.2.4 Fast R-CNNSPP Net真是个好方法,R-CNN的进阶版Fast R-CNN就是在R-CNN的基础上采纳了SPP Net方法,对R-CNN作了改进,使得性能进一步提高。 R-CNN有一些相当大的缺点(把这些缺点都改掉了,就成了Fast R-CNN)。 大缺点:由于每一个候选框都要独自经过CNN,这使得花费的时间非常多。 解决:共享卷积层,现在不是每一个候选框都当做输入进入CNN了,而是输入一张完整的图片,在第五个卷积层再得到每个候选框的特征。 原来的方法:许多候选框(比如两千个)–>CNN–>得到每个候选框的特征–>分类+回归 现在的方法:一张完整图片–>CNN–>得到每张候选框的特征–>分类+回归 所以容易看见,Fast R-CNN相对于R-CNN的提速原因就在于:不过不像R-CNN把每个候选区域给深度网络提特征,而是整张图提一次特征,再把候选框映射到conv5上,而SPP只需要计算一次特征,剩下的只需要在conv5层上操作就可以了。 算法步骤: 在图像中确定约1000-2000个候选框 (使用选择性搜索)。 对整张图片输进CNN,得到feature map。 找到每个候选框在feature map上的映射patch,将此patch作为每个候选框的卷积特征输入到SPP layer和之后的层。 对候选框中提取出的特征,使用分类器判别是否属于一个特定类。 对于属于某一类别的候选框,用回归器进一步调整其位置。 3.2.5 Faster R-CNNFast R-CNN存在的问题:存在瓶颈:选择性搜索,找出所有的候选框,这个也非常耗时。那我们能不能找出一个更加高效的方法来求出这些候选框呢? 解决:加入一个提取边缘的神经网络,也就说找到候选框的工作也交给神经网络来做了。 所以,rgbd在Fast R-CNN中引入Region Proposal Network(RPN)替代Selective Search,同时引入anchor box应对目标形状的变化问题(anchor就是位置和大小固定的box,可以理解成事先设置好的固定的proposal)。这就是Faster R-CNN。 算法步骤: 对整张图片输进CNN,得到feature map。 卷积特征输入到RPN,得到候选框的特征信息。 对候选框中提取出的特征,使用分类器判别是否属于一个特定类。 对于属于某一类别的候选框,用回归器进一步调整其位置。 3.2.6 YOLOFaster R-CNN的方法目前是主流的目标检测方法,但是速度上并不能满足实时的要求。YOLO一类的方法慢慢显现出其重要性,这类方法使用了回归的思想,利用整张图作为网络的输入,直接在图像的多个位置上回归出这个位置的目标边框,以及目标所属的类别。 我们直接看上面YOLO的目标检测的流程图: 给个一个输入图像,首先将图像划分成7*7的网格。 对于每个网格,我们都预测2个边框(包括每个边框是目标的置信度以及每个边框区域在多个类别上的概率)。 根据上一步可以预测出772个目标窗口,然后根据阈值去除可能性比较低的目标窗口,最后NMS去除冗余窗口即可。 小结:YOLO将目标检测任务转换成一个回归问题,大大加快了检测的速度,使得YOLO可以每秒处理45张图像。而且由于每个网络预测目标窗口时使用的是全图信息,使得false positive比例大幅降低(充分的上下文信息)。 但是YOLO也存在问题:没有了Region Proposal机制,只使用7*7的网格回归会使得目标不能非常精准的定位,这也导致了YOLO的检测精度并不是很高。 3.2.7 SSDSSD: Single Shot MultiBox Detector。上面分析了YOLO存在的问题,使用整图特征在7*7的粗糙网格内回归对目标的定位并不是很精准。那是不是可以结合region proposal的思想实现精准一些的定位?SSD结合YOLO的回归思想以及Faster R-CNN的anchor机制做到了这点。 上图是SSD的一个框架图,首先SSD获取目标位置和类别的方法跟YOLO一样,都是使用回归,但是YOLO预测某个位置使用的是全图的特征,SSD预测某个位置使用的是这个位置周围的特征(感觉更合理一些)。 那么如何建立某个位置和其特征的对应关系呢?可能你已经想到了,使用Faster R-CNN的anchor机制。如SSD的框架图所示,假如某一层特征图(图b)大小是8*8,那么就使用3*3的滑窗提取每个位置的特征,然后这个特征回归得到目标的坐标信息和类别信息(图c)。 不同于Faster R-CNN,这个anchor是在多个feature map上,这样可以利用多层的特征并且自然的达到多尺度(不同层的feature map 3*3滑窗感受野不同)。 小结:SSD结合了YOLO中的回归思想和Faster R-CNN中的anchor机制,使用全图各个位置的多尺度区域特征进行回归,既保持了YOLO速度快的特性,也保证了窗口预测的跟Faster R-CNN一样比较精准。SSD在VOC2007上mAP可以达到72.1%,速度在GPU上达到58帧每秒。 3.3 语义(图像)分割识别图上pixel的类别,用全卷积网络。 4. 代码实现CNNcifar10数据集分类–CNN 【机器学习通俗易懂系列文章】 5. 参考文献 基于深度学习的目标检测技术演进:R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD 通俗理解卷积神经网络 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"深度学习","slug":"深度学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【深度学习】神经网络","slug":"DL/Neural Network","date":"2019-08-03T16:00:00.000Z","updated":"2019-12-25T05:48:06.418Z","comments":true,"path":"2019/08/04/DL/Neural Network/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/04/DL/Neural%20Network/","excerpt":"我们以房价预测的案例来说明一下,把房屋的面积作为神经网络的输入(我们称之为𝑥),通过一个节点(一个小圆圈),最终输出了价格(我们用𝑦表示)。其实这个小圆圈就是一个单独的神经元,就像人的大脑神经元一样。如果这是一个单神经元网络,不管规模大小,它正是通过把这些单个神经元叠加在一起来形成。如果你把这些神…","text":"我们以房价预测的案例来说明一下,把房屋的面积作为神经网络的输入(我们称之为𝑥),通过一个节点(一个小圆圈),最终输出了价格(我们用𝑦表示)。其实这个小圆圈就是一个单独的神经元,就像人的大脑神经元一样。如果这是一个单神经元网络,不管规模大小,它正是通过把这些单个神经元叠加在一起来形成。如果你把这些神… 1. 深度学习有哪些应用 图像:图像识别、物体识别、图片美化、图片修复、目标检测。 自然语言处理:机器创作、个性化推荐、文本分类、翻译、自动纠错、情感分析。 数值预测、量化交易 2. 什么是神经网络我们以房价预测的案例来说明一下,把房屋的面积作为神经网络的输入(我们称之为𝑥),通过一个节点(一个小圆圈),最终输出了价格(我们用𝑦表示)。其实这个小圆圈就是一个单独的神经元,就像人的大脑神经元一样。如果这是一个单神经元网络,不管规模大小,它正是通过把这些单个神经元叠加在一起来形成。如果你把这些神经元想象成单独的乐高积木,你就通过搭积木来完成一个更大的神经网络。 神经网络与大脑关联不大。这是一个过度简化的对比,把一个神经网络的逻辑单元和右边的生物神经元对比。至今为止其实连神经科学家们都很难解释,究竟一个神经元能做什么。 2.1 什么是感知器这要从逻辑回归讲起,我们都知道逻辑回归的目标函数如下所示: $$z=\\theta_0+\\theta_1X_1+\\theta_2X_2$$ $$a=g(z)=\\frac{1}{1+e^{-z}}$$ 我们用网络来表示,这个网络就叫做感知器: 如果在这个感知器的基础上加上隐藏层,就会得到下面我们要说的神经网络结构了。 2.2 神经网络的结构神经网络的一般结构是由输入层、隐藏层(神经元)、输出层构成的。隐藏层可以是1层或者多层叠加,层与层之间是相互连接的,如下图所示。 一般说到神经网络的层数是这样计算的,输入层不算,从隐藏层开始一直到输出层,一共有几层就代表着这是一个几层的神经网络,例如上图就是一个三层结构的神经网络。 解释隐藏层的含义:在一个神经网络中,当你使用监督学习训练它的时候,训练集包含了输入𝑥也包含了目标输出𝑦,所以术语隐藏层的含义是在训练集中,这些中间结点的准确值我们是不知道到的,也就是说你看不见它们在训练集中应具有的值。 多隐藏层的神经网络比 单隐藏层的神经网络工程效果好很多。 提升隐层层数或者隐层神经元个数,神经网络“容量”会变大,空间表达力会变强。 过多的隐层和神经元节点,会带来过拟合问题。 不要试图通过降低神经网络参数量来减缓过拟合,用正则化或者dropout。 2.3 为什么神经网络具有非线性切分能力假设对下图进行分类,圆圈为一类,红叉叉为另一类,如果用线性切分的话无论如何都不能把它们进行分开。 这时,引入神经网络(2层神经网络),包含一个隐藏层,在隐藏层中,分别得到了P1和P2的图形,P1这条线以上的部分都是红叉叉,P2这条线以下的部分都是红叉叉,两个神经元就有2条线性直线。从隐藏层到输出层要做的事情就是把这两条直线给合并起来,就会得到h(x)的图形,也就是说P1以上的空间交上P2以下的空间就是红叉叉的分类,其余空间分类为圆圈。这就使得原本不能够线性切分变成非线性切分了。 如果隐藏层更加复杂的话,就能够完美的实现复杂平面样本点分布的划分(类似于抠图),如下图所示: 3. 神经网络的计算过程3.1 计算过程如下图所示。用圆圈表示神经网络的计算单元,逻辑回归的计算有两个步骤,首先你按步骤计算出𝑧,然后在第二步中你以 sigmoid 函数为激活函数计算𝑧(得出𝑎),一个神经网络只是这样子做了好多次重复计算。 其中的一个神经元计算如下图所示: 向量化计算,如果你执行神经网络的程序,用 for 循环来做这些看起来真的很低效。所以接下来我们要做的就是把这四个等式向量化。向量化的过程是将神经网络中的一层神经元参数纵向堆积起来,例如隐藏层中的𝑤纵向堆积起来变成一个(4,3)的矩阵,用符号𝑊[1]表示。另一个看待这个的方法是我们有四个逻辑回归单元,且每一个逻辑回归单元都有相对应的参数——向量𝑤,把这四个向量堆积在一起,你会得出这 4×3 的矩阵。 上面公式表示的是一个样本的向量化计算,那么多样本向量化计算其实就是在上面公式的基础上再增列数,每一列相当于一个样本。 3.2 随机初始化模型参数在神经⽹络中,通常需要随机初始化模型参数。下⾯我们来解释这样做的原因。 假设输出层只保留⼀个输出单元o1(删去o2和o3以及指向它们的箭头),且隐藏层使⽤相同的激活函数。如果将每个隐藏单元的参数都初始化为相等的值,那么在正向传播时每个隐藏单元将根据相同的输⼊计算出相同的值, 并传递⾄输出层。在反向传播中,每个隐藏单元的参数梯度值相等。因此,这些参数在使⽤基于梯度的优化算法迭代后值依然相等。之后的迭代也是如此。 在这种情况下,⽆论隐藏单元有多少, 隐藏层本质上只有1个隐藏单元在发挥作⽤。因此,正如在前⾯的实验中所做的那样,我们通常将神经⽹络的模型参数,特别是权重参数,进⾏随机初始化。 有两种初始化方法: 采用正态分布的随机初始化方法。 Xavier初始化方法:假设某全连接层的输入个数为a,输出个数为b,Xavier随机初始化将使该层中权重参数的每个元素都随机采样于均匀分布: $$U[-\\sqrt{\\frac{6}{a+b}},\\sqrt{\\frac{6}{a+b}}]$$ 初始化后,每层输出的方差不会受该层输入个数的影响,且每层梯度的方差也不受该层输出个数的影响。 3.3 激活函数3.3.1 激活函数有哪些在隐层接一个线性变换后 ,再接一个非线性变换(如sigmoid),这个非线性变换叫做传递函数或者激活函数。上面的例子用的都是逻辑回归的Sigmoid激活函数,如果还不明白激活函数在哪,可以看下面这幅图。 sigmoid函数 $$a=g(z)=\\frac{1}{1+e^{-z}}$$ $$g(z)^{‘}=\\frac{d}{dz}g(z)=\\alpha(1-\\alpha)$$ tanh(双曲正切)函数 事实上,tanh 函数是 sigmoid 的向下平移和伸缩后的结果。对它进行了变形后,穿过了(0,0)点,并且值域介于+1 和-1 之间。但有一个例外:在二分类的问题中,对于输出层,因为𝑦的值是 0 或 1,所以想让𝑦^的数值介于0和1之间,而不是在-1和+1之间。所以需要使用sigmoid激活函数。 $$a=g(z)=tanh(z)=\\frac{e^z-e^{-z}}{e^z+e^{-z}}$$ $$g(z)^{‘}=\\frac{d}{dz}g(z)=1-(tanh(z))^2$$ sigmoid函数和tanh函数两者共同的缺点是,在𝑧特别大或者特别小的情况下,导数的梯度或者函数的斜率会变得特别小,最后就会接近于 0,导致降低梯度下降的速度。 ReLu(修正线性单元)函数 只要𝑧是正值的情况下,导数恒等于 1,当𝑧是负值的时候,导数恒等于 0。 $$a=max(0,z)$$ $$ g(x){‘}=\\left{\\begin{aligned}0 & & if z < 0 \\1 & & if z > 0 \\undefined & & if z =0\\end{aligned}\\right.$$ 这有一些选择激活函数的经验法则: 如果输出是 0、1 值(二分类问题),则输出层选择 sigmoid 函数,然后其它的所有单元都选择 Relu 函数。 softmax激活函数 非线性变换之前计算:$z^{(l)}=W^{(l)}a^{(l-1)}+b^{(l)}$ 经过非线性变换,临时变量:$t=e^{z^{(l)}}$ $a^{l}=\\frac{t_i}{\\sum_{j=1}^{n}t_i}$ 归一化 $a^l$表示的就是第几个类别的概率值,这些概率值和为1 之前,我们的激活函数都是接受单行数值输入,例如 Sigmoid 和 ReLu 激活函数,输入一个实数,输出一个实数。Softmax 激活函数的特殊之处在于,因为需要将所有可能的输出归一化,就需要输入一个向量,最后输出一个向量。 hardmax 函数会观察𝑧的元素,然后在𝑧中最大元素的位置放上 1,其它位置放上 0,Softmax 所做的从𝑧到这些概率的映射更为温和。 Softmax 回归将 logistic 回归推广到了两种分类以上。 3.3.2 优缺点 在𝑧的区间变动很大的情况下,激活函数的导数或者激活函数的斜率都会远大于0,在程序实现就是一个 if-else 语句,而 sigmoid 函数需要进行浮点四则运算,在实践中,使用 ReLu 激活函数神经网络通常会比使用 sigmoid 或者 tanh 激活函数学习的更快。 sigmoid 和 tanh 函数的导数在正负饱和区的梯度都会接近于 0,这会造成梯度弥散,而 Relu 和 Leaky ReLu 函数大于 0 部分都为常数,不会产生梯度弥散现象。(同时应该注意到的是,Relu 进入负半区的时候,梯度为 0,神经元此时不会训练,产生所谓的稀疏性,而 Leaky ReLu 不会有这问题) 𝑧在 ReLu 的梯度一半都是 0,但是,有足够的隐藏层使得 z 值大于 0,所以对大多数的训练数据来说学习过程仍然可以很快。 3.3.3 为什么使用激活函数如果你使用线性激活函数或者没有使用一个激活函数,那么无论你的神经网络有多少层一直在做的只是计算线性函数,所以不如直接去掉全部隐藏层。在我们的简明案例中,事实证明如果你在隐藏层用线性激活函数,在输出层用 sigmoid 函数,那么这个模型的复杂度和没有任何隐藏层。的标准 Logistic 回归是一样的。 在这里线性隐层一点用也没有,因为这两个线性函数的组合本身就是线性函数,所以除非你引入非线性,否则你无法计算更有趣的函数,即使你的网络层数再多也不行。 3.3.4 人工神经网络中为什么ReLu要好过于tanh和sigmoid function? 采用sigmoid等函数,算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法和指数运算,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。 对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(在sigmoid接近饱和区时,变换太缓慢,导数趋于0,这种情况会造成信息丢失),这种现象称为饱和,从而无法完成深层网络的训练。而ReLU就不会有饱和倾向,不会有特别小的梯度出现。 Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生(以及一些人的生物解释balabala)。当然现在也有一些对relu的改进,比如prelu,random relu等,在不同的数据集上会有一些训练速度上或者准确率上的改进,具体的大家可以找相关的paper看。 3.3.5 激活函数有哪些性质? 非线性: 当激活函数是线性的,一个两层的神经网络就可以基本上逼近所有的函数。但如果激活函数是恒等激活函数的时候,即 $ f(x)=x $,就不满足这个性质,而且如果 MLP 使用的是恒等激活函数,那么其实整个网络跟单层神经网络是等价的; 可微性: 当优化方法是基于梯度的时候,就体现了该性质; 单调性: 当激活函数是单调的时候,单层网络能够保证是凸函数; $ f(x)≈x $: 当激活函数满足这个性质的时候,如果参数的初始化是随机的较小值,那么神经网络的训练将会很高效;如果不满足这个性质,那么就需要详细地去设置初始值; 输出值的范围: 当激活函数输出值是有限的时候,基于梯度的优化方法会更加稳定,因为特征的表示受有限权值的影响更显著;当激活函数的输出是无限的时候,模型的训练会更加高效,不过在这种情况小,一般需要更小的 Learning Rate。 3.4 正向传播正向传播(forward-propagation)是指对神经网络沿着从输入层到输出层的顺序,依次计算并存储模型的中间变量(包括输出)。 逻辑回归的计算步骤:所以回想当时我们讨论逻辑回归的时候,我们有这个正向传播步骤,其中我们计算𝑧,然后𝑎,然后损失函数𝐿。 正向传播类似,计算$z^{[1]}$,$a^{[1]}$,再计算$z^{[2]}$,$a^{[2]}$,最后得到loss function。 $$ \\left.\\begin{aligned}x \\w \\b\\end{aligned}\\right}\\Rightarrow{z}=w^Tx+b\\Rightarrow{a=\\sigma(z)}\\Rightarrow{L(a,y)}$$ 3.5 反向传播(BP)反向传播(back-propagation)指的是计算神经网络参数梯度的方法。总的来说,反向传播依据微积分中的链式法则,沿着从输出层到输入层的顺序,依次计算并存储目标函数有关神经网络各层的中间变量以及参数的梯度。 由正向传播经过所有的隐藏层到达输出层,会得到一个输出结果$O_L$,然后根据这个$O_L$带入loss funcation中,利用SGD算法进行最优化求解,其中每次梯度下降都会使用一次BP来更新各个网络层中的参数值,这就是BP回传误差的意思。 正向传播求损失,BP回传误差。 根据误差信号修正每层的权重。对各个w进行求导,然后更新各个w。 链式依赖损失函数:$y^{-}=h(g(f(x)))$ 3.6 随机梯度下降法(SGD)3.6.1 mini-batch梯度下降你可以把训练集分割为小一点的子集训练,这些子集被取名为 mini-batch,假设每一个子集中只有 1000 个样本,那么把其中的𝑥 (1)到𝑥 (1000)取出来,将其称为第一个子训练集,也叫做 mini-batch,然后你再取出接下来的 1000 个样本,从𝑥 (1001)到𝑥 (2000),然后再取 1000个样本,以此类推。 在训练集上运行 mini-batch 梯度下降法,你运行 for t=1……5000,因为我们有5000个各有 1000 个样本的组,在 for 循环里你要做得基本就是对𝑋 {𝑡}和𝑌 {𝑡}执行一步梯度下降法。 batch_size=1,就是SGD。 batch_size=n,就是mini-batch batch_size=m,就是batch 其中1<n<m,m表示整个训练集大小。 优缺点: batch:相对噪声低些,幅度也大一些,你可以继续找最小值。 SGD:大部分时候你向着全局最小值靠近,有时候你会远离最小值,因为那个样本恰好给你指的方向不对,因此随机梯度下降法是有很多噪声的,平均来看,它最终会靠近最小值,不过有时候也会方向错误,因为随机梯度下降法永远不会收敛,而是会一直在最小值附近波动。一次性只处理了一个训练样本,这样效率过于低下。 mini-batch:实践中最好选择不大不小的 mini-batch,得到了大量向量化,效率高,收敛快。 首先,如果训练集较小,直接使用 batch 梯度下降法,这里的少是说小于 2000 个样本。一般的 mini-batch 大小为 64 到 512,考虑到电脑内存设置和使用的方式,如果 mini-batch 大小是 2 的𝑛次方,代码会运行地快一些。 3.6.2 调节 Batch_Size 对训练效果影响到底如何? Batch_Size 太小,模型表现效果极其糟糕(error飙升)。 随着 Batch_Size 增大,处理相同数据量的速度越快。 随着 Batch_Size 增大,达到相同精度所需要的 epoch 数量越来越多。 由于上述两种因素的矛盾, Batch_Size 增大到某个时候,达到时间上的最优。 由于最终收敛精度会陷入不同的局部极值,因此 Batch_Size 增大到某些时候,达到最终收敛精度上的最优。 4. 为什么说神经网络是端到端的网络?端到端学习(end-to-end)是一种解决问题的思路,与之对应的是多步骤解决问题,也就是将一个问题拆分为多个步骤分步解决,而端到端是由输入端的数据直接得到输出端的结果。 就是不要预处理和特征提取,直接把原始数据扔进去得到最终结果。 特征提取包含在神经网络内部,所以说神经网络是端到端的网络。 优点: 通过缩减人工预处理和后续处理,尽可能使模型从原始输入到最终输出,给模型更多可以根据数据自动调节的空间,增加模型的整体契合度。 缺点 它可能需要大量的数据。要直接学到这个𝑥到𝑦的映射,你可能需要大量(𝑥, 𝑦)数据。 它排除了可能有用的手工设计组件。 5. 深度学习框架比较现有的深度学习开源平台主要有 Caffe, PyTorch, MXNet, CNTK, Theano, TensorFlow, Keras, fastai等。 平台 优点 缺点 TensorFlow 1.功能很齐全,能够搭建的网络更丰富。2.支持多种编程语言。3.拥有强大的计算集群。4.谷歌支持5.社区活跃度高。6.支持多GPU。7.TensorBoard支持图形可视化。 1.编程入门难度较大。2.计算图是纯 Python 的,因此速度较慢3.图构造是静态的,意味着图必须先被「编译」再运行 Keras 1.Keras是TensorFlow高级集成APi2.Keras是一个简洁的API。 可以快速帮助您创建应用程序。3.代码更加可读和简洁。4.Keras处于高度集成框架。 5.社区活跃。 1.Keras框架环境配置比其他底层框架要复杂一些。2.虽然更容易创建模型,但是面对复杂的网络结构时可能不如TensorFlow。3.性能方面比较欠缺。 Pytorch 1.它可以在流程中更改体系结构。2.训练神经网络的过程简单明了。3.可以使用标准 Python 语法编写 for 循环语句。4.大量预训练模型 1.不够TensorFlow全面,不过未来会弥补。2.PyTorch部署移动端不是很好。 MXNet 1.支持多语言。2.文档齐全。3.支持多个GPU。4.清晰且易于维护的代码。5.命令式和符号式编程风格之间进行选择。 1.不被广泛使用。2.社区不够活跃。3.学习难度大一些。 目前从招聘来说,公司使用TensorFlow的占大多数,毕竟TensorFlow的社区、性能、部署方面都是很强的,所以之后写的实例代码都使用TensorFlow来完成。 6. softmax分类器6.1 什么是softmax在图像分类的情景中,softmax分类器输出可以是一个图像类别的离散值,和线性回归不同的是,softmax输出单元从一个变成了多个。 softmax回归和线性回归一样将输入特征与权重做线性叠加。与线性回归的一个主要不同在于,softmax回归的输出值个数等于标签里的类别数。下图是用神经网络描绘了softmax回归,也是一个单层神经网络,由于每个输出 $o_1,o_2,o_3$ 的计算都要依赖于所有的输入 $x_1,x_2,x_3,x_4$ ,softmax回归的输出层也是一个全连接层。 $$o_1=x_1w_{11}+x_2w_{21}+x_3w_{31}+x_4w_{41}$$ $$o_2=x_1w_{12}+x_2w_{22}+x_3w_{32}+x_4w_{42}$$ $$o_3=x_1w_{13}+x_2w_{23}+x_3w_{33}+x_4w_{43}$$ $$o_4=x_1w_{14}+x_2w_{24}+x_3w_{34}+x_4w_{44}$$ 6.2 softmax的计算一个简单的办法是将输出值 $o_i$ 当做预测类别是i的置信度,并将值最大的输出所对应的类别作为预测输出。例如,如果 $o_1,o_2,o_3$ 分别为0.1 ; 10 ; 0.1,由于 $o_2$ 最大,那么预测类别为2。 然而,直接使用输出层的输出会有两个问题: 由于输出层的输出值的范围不确定,我们难以直观上判断这些值得意义。 由于真实标签是离散值,这些离散值与不确定范围的输出值之间的误差难以衡量。 softmax运算解决了以上两个问题。它通过下面的公式将输出值变换成值为正且和为1的概率分布: $$softmax(o_i)=\\frac{exp(o_i)}{\\sum_{i=1}^{n}exp(o_i)}$$ 6.3 交叉熵损失函数我们已经知道,softmax运算将输出变换成一个合法的类别预测分布。实际上,真实标签也可以用类别分布表达: 对于样本i,我们构造向量 $y^{(i)}\\in_{}R^q$ ,使其第 $y^{(i)}$ 个元素为1,其余为0。这样我们的训练目标可以设为使预测概率分布 $\\hat{y}^{(i)}$ 尽可能接近真实的标签概率 $y^{(i)}$。 想要预测分类结果正确,我们其实并不需要预测概率完全等于标签概率,而平方损失则过于严格。改善这个问题的一个方法是使用更适合衡量两个概率分布差异的测量函数。其中,交叉熵(cross entropy)是一个常用的衡量方法: $$H(y^{(i)},\\hat{y}^{(i)})=-\\sum_{j=1}^{q}y_j^{(i)}log{\\hat{y}}j^{(i)}=-log{\\hat{y}}{y^{(i)}}^{(i)}$$ 其中带下标的 $y_j^{(i)}$ 是向量 $y^{(i)}$ 中非 0 即 1 的元素。也就是说,交叉熵只关心对正确类别的预测概率,因为只要其值足够大,就可以确保分类结果正确。即最小化交叉熵损失函数等价于最大化训练数据集所有标签类别的联合预测概率。 我们知道,当 y = 1 时,其损失函数是最小的,如下图所示:$H(y^{(i)},\\hat{y}^{(i)})=-log{\\hat{y}}_{y^{(i)}}^{(i)}$ 当 y = 0 时,其损失函数是最大的,如下图所示:$H(y^{(i)},\\hat{y}^{(i)})=-log(1-{\\hat{y}}_{y^{(i)}}^{(i)})$ 7. 神经网络实现TensorFlow示例:线性回归 【机器学习通俗易懂系列文章】 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"深度学习","slug":"深度学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】KNN","slug":"ML/KNN","date":"2019-08-01T16:00:00.000Z","updated":"2019-12-25T05:44:43.685Z","comments":true,"path":"2019/08/02/ML/KNN/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/08/02/ML/KNN/","excerpt":"何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居。 用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该…","text":"何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居。 用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该… 1. 什么是KNN1.1 KNN的通俗解释何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居。 用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居),这K个实例的多数属于某个类,就把该输入实例分类到这个类中。 如上图所示,有两类不同的样本数据,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的那个绿色的圆所标示的数据则是待分类的数据。也就是说,现在,我们不知道中间那个绿色的数据是从属于哪一类(蓝色小正方形or红色小三角形),KNN就是解决这个问题的。 如果K=3,绿色圆点的最近的3个邻居是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。 如果K=5,绿色圆点的最近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。 于此我们看到,当无法判定当前待分类点是从属于已知分类中的哪一类时,我们可以依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。这就是K近邻算法的核心思想。 1.2 近邻的距离度量我们看到,K近邻算法的核心在于找到实例点的邻居,这个时候,问题就接踵而至了,如何找到邻居,邻居的判定标准是什么,用什么来度量。这一系列问题便是下面要讲的距离度量表示法。 有哪些距离度量的表示法(普及知识点,可以跳过): 欧氏距离,最常见的两点之间或多点之间的距离表示法,又称之为欧几里得度量,它定义于欧几里得空间中,如点 x = (x1,…,xn) 和 y = (y1,…,yn) 之间的距离为: $$d(x,y)=\\sqrt{(x_1-y_1)^2+(x_2-y_2)^2+…+(x_n-y_n)^2}=\\sqrt{\\sum_{i=1}^{n}(x_i-y_i)^2}$$ 二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离: $$d_{12}=\\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}$$ 三维空间两点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离: $$d_{12}=\\sqrt{(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2}$$ 两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离: $$d_{12}=\\sqrt{\\sum_{k=1}^{n}(x_{1k}-x_{2k})^2}$$ 也可以用表示成向量运算的形式: $$d_{12}=\\sqrt{(a-b)(a-b)^T}$$ 曼哈顿距离,我们可以定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里得空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。例如在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为:$|x_1-x_2|+|y_1-y_2|$,要注意的是,曼哈顿距离依赖座标系统的转度,而非系统在座标轴上的平移或映射。 通俗来讲,想象你在曼哈顿要从一个十字路口开车到另外一个十字路口,驾驶距离是两点间的直线距离吗?显然不是,除非你能穿越大楼。而实际驾驶距离就是这个“曼哈顿距离”,此即曼哈顿距离名称的来源, 同时,曼哈顿距离也称为城市街区距离(City Block distance)。 二维平面两点a(x1,y1)与b(x2,y2)间的曼哈顿距离 $$d_{12}=|x_1-x_2|+|y_1-y_2|$$ 两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的曼哈顿距离 $$d_{12}=\\sum_{k=1}^{n}|x_{1k}-x_{2k}|$$ 切比雪夫距离,若二个向量或二个点p 、and q,其座标分别为Pi及qi,则两者之间的切比雪夫距离定义如下: $$D_{Chebyshev}(p,q)=max_i(|p_i-q_i|)$$ 这也等于以下Lp度量的极值:$\\lim_{x \\to \\infty}(\\sum_{i=1}^{n}|p_i-q_i|^k)^{1/k}$,因此切比雪夫距离也称为L∞度量。 以数学的观点来看,切比雪夫距离是由一致范数(uniform norm)(或称为上确界范数)所衍生的度量,也是超凸度量(injective metric space)的一种。 在平面几何中,若二点p及q的直角坐标系坐标为(x1,y1)及(x2,y2),则切比雪夫距离为: $$D_{Chess}=max(|x_2-x_1|,|y_2-y_1|)$$ 玩过国际象棋的朋友或许知道,国王走一步能够移动到相邻的8个方格中的任意一个。那么国王从格子(x1,y1)走到格子(x2,y2)最少需要多少步?。你会发现最少步数总是max( | x2-x1 | , | y2-y1 | ) 步 。有一种类似的一种距离度量方法叫切比雪夫距离。 二维平面两点a(x1,y1)与b(x2,y2)间的切比雪夫距离 : $$d_{12}=max(|x_2-x_1|,|y_2-y_1|)$$ 两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的切比雪夫距离: $$d_{12}=max_i(|x_{1i}-x_{2i}|)$$ 这个公式的另一种等价形式是 $$d_{12}=lim_{k\\to\\infin}(\\sum_{i=1}^{n}|x_{1i}-x_{2i}|^k)^{1/k}$$ 闵可夫斯基距离(Minkowski Distance),闵氏距离不是一种距离,而是一组距离的定义。 两个n维变量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的闵可夫斯基距离定义为: $$d_{12}=\\sqrt[p]{\\sum_{k=1}^{n}|x_{1k}-x_{2k}|^p}$$ 其中p是一个变参数。当p=1时,就是曼哈顿距离当p=2时,就是欧氏距离当p→∞时,就是切比雪夫距离根据变参数的不同,闵氏距离可以表示一类的距离。 标准化欧氏距离,标准化欧氏距离是针对简单欧氏距离的缺点而作的一种改进方案。标准欧氏距离的思路:既然数据各维分量的分布不一样,那先将各个分量都“标准化”到均值、方差相等。至于均值和方差标准化到多少,先复习点统计学知识。 假设样本集X的数学期望或均值(mean)为m,标准差(standard deviation,方差开根)为s,那么X的“标准化变量”X*表示为:(X-m)/s,而且标准化变量的数学期望为0,方差为1。即,样本集的标准化过程(standardization)用公式描述就是: $$X^*=\\frac{X-m}{s}$$ 标准化后的值 = ( 标准化前的值 - 分量的均值 ) /分量的标准差 经过简单的推导就可以得到两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的标准化欧氏距离的公式: $$d_{12}=\\sqrt{\\sum_{k=1}^{n}(\\frac{x_{1k}-x_{2k}}{s_k})^2}$$ 马氏距离 有M个样本向量X1~Xm,协方差矩阵记为S,均值记为向量μ,则其中样本向量X到u的马氏距离表示为: $$D(X)=\\sqrt{(X-u)^TS^{-1}(X_i-X_j)}$$ 若协方差矩阵是单位矩阵(各个样本向量之间独立同分布),则公式就成了,也就是欧氏距离了: $$D(X_i,X_j)=\\sqrt{(X_i-X_j)^T(X_i-X_j)}$$ 若协方差矩阵是对角矩阵,公式变成了标准化欧氏距离。 马氏距离的优缺点:量纲无关,排除变量之间的相关性的干扰。 巴氏距离 在统计中,巴氏距离距离测量两个离散或连续概率分布的相似性。它与衡量两个统计样品或种群之间的重叠量的巴氏距离系数密切相关。巴氏距离距离和巴氏距离系数以20世纪30年代曾在印度统计研究所工作的一个统计学家A. Bhattacharya命名。同时,Bhattacharyya系数可以被用来确定两个样本被认为相对接近的,它是用来测量中的类分类的可分离性。 对于离散概率分布 p和q在同一域 X,它被定义为: $$D_B(p,q)=-ln(BC(p,q))$$ 其中: $$BC(p,q)=\\sum_{x\\in_{}X}\\sqrt{p(x)q(x)}$$ 是Bhattacharyya系数。 汉明距离 两个等长字符串s1与s2之间的汉明距离定义为将其中一个变为另外一个所需要作的最小替换次数。例如字符串“1111”与“1001”之间的汉明距离为2。应用:信息编码(为了增强容错性,应使得编码间的最小汉明距离尽可能大)。 夹角余弦 几何中夹角余弦可用来衡量两个向量方向的差异,机器学习中借用这一概念来衡量样本向量之间的差异。 在二维空间中向量A(x1,y1)与向量B(x2,y2)的夹角余弦公式: $$cos\\theta=\\frac{x_1x_2+y_1y_2}{\\sqrt{x_1^2+y_1^2}\\sqrt{x_2^2+y_2^2}}$$ 两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夹角余弦: $$cos\\theta=\\frac{a*b}{|a||b|}$$ 夹角余弦取值范围为[-1,1]。夹角余弦越大表示两个向量的夹角越小,夹角余弦越小表示两向量的夹角越大。当两个向量的方向重合时夹角余弦取最大值1,当两个向量的方向完全相反夹角余弦取最小值-1。 杰卡德相似系数 两个集合A和B的交集元素在A,B的并集中所占的比例,称为两个集合的杰卡德相似系数,用符号J(A,B)表示。杰卡德相似系数是衡量两个集合的相似度一种指标。 $$J(A,B)=\\frac{|A\\cap_{}B|}{|A\\cup_{}B|}$$ 与杰卡德相似系数相反的概念是杰卡德距离: $$J_{\\delta}(A,B)=1-J(A,B)=\\frac{|A\\cup_{}B|-|A\\cap_{}B|}{|A\\cup_{}B|}$$ 皮尔逊系数 在统计学中,皮尔逊积矩相关系数用于度量两个变量X和Y之间的相关(线性相关),其值介于-1与1之间。通常情况下通过以下取值范围判断变量的相关强度: 0.8-1.0 极强相关0.6-0.8 强相关0.4-0.6 中等程度相关0.2-0.4 弱相关0.0-0.2 极弱相关或无相关 简单说来,各种“距离”的应用场景简单概括为, 空间:欧氏距离, 路径:曼哈顿距离,国际象棋国王:切比雪夫距离, 以上三种的统一形式:闵可夫斯基距离, 加权:标准化欧氏距离, 排除量纲和依存:马氏距离, 向量差距:夹角余弦, 编码差别:汉明距离, 集合近似度:杰卡德类似系数与距离, 相关:相关系数与相关距离。 1.3 K值选择 如果选择较小的K值,就相当于用较小的领域中的训练实例进行预测,“学习”近似误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是“学习”的估计误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合; 如果选择较大的K值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少学习的估计误差,但缺点是学习的近似误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。 K=N,则完全不足取,因为此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的累,模型过于简单,忽略了训练实例中大量有用信息。 在实际应用中,K值一般取一个比较小的数值,例如采用交叉验证法(简单来说,就是一部分样本做训练集,一部分做测试集)来选择最优的K值。 1.4 KNN最近邻分类算法的过程 计算测试样本和训练样本中每个样本点的距离(常见的距离度量有欧式距离,马氏距离等); 对上面所有的距离值进行排序; 选前 k 个最小距离的样本; 根据这 k 个样本的标签进行投票,得到最后的分类类别; 2. KDD的实现:KD树Kd-树是K-dimension tree的缩写,是对数据点在k维空间(如二维(x,y),三维(x,y,z),k维(x1,y,z..))中划分的一种数据结构,主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)。本质上说,Kd-树就是一种平衡二叉树。 首先必须搞清楚的是,k-d树是一种空间划分树,说白了,就是把整个空间划分为特定的几个部分,然后在特定空间的部分内进行相关搜索操作。想像一个三维(多维有点为难你的想象力了)空间,kd树按照一定的划分规则把这个三维空间划分了多个空间,如下图所示: 2.1 构建KD树kd树构建的伪代码如下图所示: 再举一个简单直观的实例来介绍k-d树构建算法。假设有6个二维数据点{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},数据点位于二维空间内,如下图所示。为了能有效的找到最近邻,k-d树采用分而治之的思想,即将整个空间划分为几个小部分,首先,粗黑线将空间一分为二,然后在两个子空间中,细黑直线又将整个空间划分为四部分,最后虚黑直线将这四部分进一步划分。 6个二维数据点{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)}构建kd树的具体步骤为: 确定:split域=x。具体是:6个数据点在x,y维度上的数据方差分别为39,28.63,所以在x轴上方差更大,故split域值为x; 确定:Node-data = (7,2)。具体是:根据x维上的值将数据排序,6个数据的中值(所谓中值,即中间大小的值)为7,所以Node-data域位数据点(7,2)。这样,该节点的分割超平面就是通过(7,2)并垂直于:split=x轴的直线x=7; 确定:左子空间和右子空间。具体是:分割超平面x=7将整个空间分为两部分:x<=7的部分为左子空间,包含3个节点={(2,3),(5,4),(4,7)};另一部分为右子空间,包含2个节点={(9,6),(8,1)}; 如上算法所述,kd树的构建是一个递归过程,我们对左子空间和右子空间内的数据重复根节点的过程就可以得到一级子节点(5,4)和(9,6),同时将空间和数据集进一步细分,如此往复直到空间中只包含一个数据点。 与此同时,经过对上面所示的空间划分之后,我们可以看出,点(7,2)可以为根结点,从根结点出发的两条红粗斜线指向的(5,4)和(9,6)则为根结点的左右子结点,而(2,3),(4,7)则为(5,4)的左右孩子(通过两条细红斜线相连),最后,(8,1)为(9,6)的左孩子(通过细红斜线相连)。如此,便形成了下面这样一棵k-d树: 对于n个实例的k维数据来说,建立kd-tree的时间复杂度为O(knlogn)。 k-d树算法可以分为两大部分,除了上部分有关k-d树本身这种数据结构建立的算法,另一部分是在建立的k-d树上各种诸如插入,删除,查找(最邻近查找)等操作涉及的算法。下面,咱们依次来看kd树的插入、删除、查找操作。 2.2 KD树的插入元素插入到一个K-D树的方法和二叉检索树类似。本质上,在偶数层比较x坐标值,而在奇数层比较y坐标值。当我们到达了树的底部,(也就是当一个空指针出现),我们也就找到了结点将要插入的位置。生成的K-D树的形状依赖于结点插入时的顺序。给定N个点,其中一个结点插入和检索的平均代价是O(log2N)。 插入的过程如下: 应该清楚,这里描述的插入过程中,每个结点将其所在的平面分割成两部分。因比,Chicago 将平面上所有结点分成两部分,一部分所有的结点x坐标值小于35,另一部分结点的x坐标值大于或等于35。同样Mobile将所有x坐标值大于35的结点以分成两部分,一部分结点的Y坐标值是小于10,另一部分结点的Y坐标值大于或等于10。后面的Toronto、Buffalo也按照一分为二的规则继续划分。 2.3 KD树的删除KD树的删除可以用递归程序来实现。我们假设希望从K-D树中删除结点(a,b)。如果(a,b)的两个子树都为空,则用空树来代替(a,b)。否则,在(a,b)的子树中寻找一个合适的结点来代替它,譬如(c,d),则递归地从K-D树中删除(c,d)。一旦(c,d)已经被删除,则用(c,d)代替(a,b)。假设(a,b)是一个X识别器,那么,它得替代节点要么是(a,b)左子树中的X坐标最大值的结点,要么是(a,b)右子树中x坐标最小值的结点。 下面来举一个实际的例子(来源:中国地质大学电子课件,原课件错误已经在下文中订正),如下图所示,原始图像及对应的kd树,现在要删除图中的A结点,请看一系列删除步骤: 要删除上图中结点A,选择结点A的右子树中X坐标值最小的结点,这里是C,C成为根,如下图: 从C的右子树中找出一个结点代替先前C的位置, 这里是D,并将D的左子树转为它的右子树,D代替先前C的位置,如下图: 在D的新右子树中,找X坐标最小的结点,这里为H,H代替D的位置, 在D的右子树中找到一个Y坐标最小的值,这里是I,将I代替原先H的位置,从而A结点从图中顺利删除,如下图所示: 从K-D树中删除一个结点是代价很高的,很清楚删除子树的根受到子树中结点个数的限制。用TPL(T)表示树T总的路径长度。可看出树中子树大小的总和为TPL(T)+N。 以随机方式插入N个点形成树的TPL是O(N*log2N),这就意味着从一个随机形成的K-D树中删除一个随机选取的结点平均代价的上界是O(log2N) 。 2.4 KD树的最近邻搜索算法k-d树查询算法的伪代码如下所示: 我写了一个递归版本的二维kd tree的搜索函数你对比的看看: 举例 星号表示要查询的点查询点(2,4.5)。通过二叉搜索,顺着搜索路径很快就能找到最邻近的近似点。而找到的叶子节点并不一定就是最邻近的,最邻近肯定距离查询点更近,应该位于以查询点为圆心且通过叶子节点的圆域内。为了找到真正的最近邻,还需要进行相关的‘回溯’操作。也就是说,算法首先沿搜索路径反向查找是否有距离查询点更近的数据点。 二叉树搜索:先从(7,2)查找到(5,4)节点,在进行查找时是由y = 4为分割超平面的,由于查找点为y值为4.5,因此进入右子空间查找到(4,7),形成搜索路径<(7,2),(5,4),(4,7)>,但(4,7)与目标查找点的距离为3.202,而(5,4)与查找点之间的距离为3.041,所以(5,4)为查询点的最近点; 回溯查找:以(2,4.5)为圆心,以3.041为半径作圆,如下图所示。可见该圆和y = 4超平面交割,所以需要进入(5,4)左子空间进行查找,也就是将(2,3)节点加入搜索路径中得<(7,2),(2,3)>;于是接着搜索至(2,3)叶子节点,(2,3)距离(2,4.5)比(5,4)要近,所以最近邻点更新为(2,3),最近距离更新为1.5; 回溯查找至(5,4),直到最后回溯到根结点(7,2)的时候,以(2,4.5)为圆心1.5为半径作圆,并不和x = 7分割超平面交割,如下图所示。至此,搜索路径回溯完,返回最近邻点(2,3),最近距离1.5。 2.5 kd树近邻搜索算法的改进:BBF算法实例点是随机分布的,那么kd树搜索的平均计算复杂度是O(logN),这里的N是训练实例树。所以说,kd树更适用于训练实例数远大于空间维数时的k近邻搜索,当空间维数接近训练实例数时,它的效率会迅速下降,一降降到“解放前”:线性扫描的速度。 也正因为上述k最近邻搜索算法的第4个步骤中的所述:“回退到根结点时,搜索结束”,每个最近邻点的查询比较完成过程最终都要回退到根结点而结束,而导致了许多不必要回溯访问和比较到的结点,这些多余的损耗在高维度数据查找的时候,搜索效率将变得相当之地下,那有什么办法可以改进这个原始的kd树最近邻搜索算法呢? 从上述标准的kd树查询过程可以看出其搜索过程中的“回溯”是由“查询路径”决定的,并没有考虑查询路径上一些数据点本身的一些性质。一个简单的改进思路就是将“查询路径”上的结点进行排序,如按各自分割超平面(也称bin)与查询点的距离排序,也就是说,回溯检查总是从优先级最高(Best Bin)的树结点开始。 还是以上面的查询(2,4.5)为例,搜索的算法流程为: 将(7,2)压人优先队列中; 提取优先队列中的(7,2),由于(2,4.5)位于(7,2)分割超平面的左侧,所以检索其左子结点(5,4)。 同时,根据BBF机制”搜索左/右子树,就把对应这一层的兄弟结点即右/左结点存进队列”,将其(5,4)对应的兄弟结点即右子结点(9,6)压人优先队列中 此时优先队列为{(9,6)},最佳点为(7,2);然后一直检索到叶子结点(4,7),此时优先队列为{(2,3),(9,6)},“最佳点”则为(5,4); 提取优先级最高的结点(2,3),重复步骤2,直到优先队列为空。 2.6 KD树的应用SIFT+KD_BBF搜索算法,详细参考文末的参考文献。 3. 关于KNN的一些问题 在k-means或kNN,我们是用欧氏距离来计算最近的邻居之间的距离。为什么不用曼哈顿距离? 答:我们不用曼哈顿距离,因为它只计算水平或垂直距离,有维度的限制。另一方面,欧式距离可用于任何空间的距离计算问题。因为,数据点可以存在于任何空间,欧氏距离是更可行的选择。例如:想象一下国际象棋棋盘,象或车所做的移动是由曼哈顿距离计算的,因为它们是在各自的水平和垂直方向的运动。 KD-Tree相比KNN来进行快速图像特征比对的好处在哪里? 答:极大的节约了时间成本.点线距离如果 > 最小点,无需回溯上一层,如果<,则再上一层寻找。 4. 参考文献从K近邻算法、距离度量谈到KD树、SIFT+BBF算法 5. 手写数字识别案例KNN手写数字识别系统 【机器学习通俗易懂系列文章】 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"汇总&资源","slug":"ML/project","date":"2019-07-28T04:30:00.000Z","updated":"2019-12-25T09:59:51.159Z","comments":true,"path":"2019/07/28/ML/project/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/28/ML/project/","excerpt":"","text":"一:项目 ML-NLP 此项目是机器学习(Machine Learning)、深度学习(Deep Learning)、NLP面试中常考到的知识点和代码实现,也是作为一个算法工程师必会的理论基础知识。 CodingInterviews2-ByPython 此项目是《剑指offer》第二版里算法面试题的Python3实现版本,作为一本经典书籍,可以时常拿出来看一看、翻一翻、记一记。同时也是为了Python程序员能够更好的通过公司的技术面试,拿到心仪的offer。 二:总结汇总机器学习 线性回归 逻辑回归 决策树 3.1 随机森林 3.2 GBDT 3.3 XGBoost 3.4 LightGBM 支持向量机(SVM) 概率图模型 5.1 贝叶斯网络 5.2 马尔可夫模型 5.3 主题模型 EM算法 聚类算法 ML特征工程和优化方法 KNN 深度学习 神经网络 卷积神经网络CNN 循环神经网络RNN 12.1 门控循环单元GRU 12.2 长短期记忆LSTM 迁移学习 强化学习 深度学习优化方法 自然语言处理 自然语言处理 16.1 词嵌入(Embedding) 16.2 fastText 16.3 GloVe 16.4 textRNN & textCNN 16.5 seq2seq 16.6 注意力机制(Attention) 16.7 Transformer模型 16.8 BERT 16.9 XLNet 16.10 智能客服 推荐系统 推荐系统 二:资源2.1 书籍 《白面机器学习》:https://www.lanzous.com/i56i24f 《剑指offer》:https://www.lanzous.com/i4ya3wd 《数学之美》第二版:https://www.lanzous.com/i3ousch 《推荐系统实战》:https://www.lanzous.com/i6362bi 《自然语言处理综论》第二版:https://www.jianguoyun.com/p/DZIKYLwQj4G5BxiZjboC 2.2 GitHub 《动手学深度学习》TF2.0版:https://github.com/TrickyGo/Dive-into-DL-TensorFlow2.0 数据竞赛top解决方案开源整理:https://github.com/Smilexuhc/Data-Competition-TopSolution 吴恩达老师的课程笔记:https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes","categories":[],"tags":[]},{"title":"【机器学习】主题模型","slug":"ML/Topic Model","date":"2019-07-27T16:00:00.000Z","updated":"2019-12-25T05:39:46.723Z","comments":true,"path":"2019/07/28/ML/Topic Model/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/28/ML/Topic%20Model/","excerpt":"关于LDA有两种含义,一种是线性判别分析(Linear Discriminant Analysis),一种是概率主题模型:隐含狄利克雷分布(LATENT DIRICHLET ALLOCATION,简称LDA),本文讲后者。 按照wiki上的介绍,LDA由Blei, David M.、Ng, And…","text":"关于LDA有两种含义,一种是线性判别分析(Linear Discriminant Analysis),一种是概率主题模型:隐含狄利克雷分布(LATENT DIRICHLET ALLOCATION,简称LDA),本文讲后者。 按照wiki上的介绍,LDA由Blei, David M.、Ng, And… 1. LDA模型是什么LDA可以分为以下5个步骤: 一个函数:gamma函数。 四个分布:二项分布、多项分布、beta分布、Dirichlet分布。 一个概念和一个理念:共轭先验和贝叶斯框架。 两个模型:pLSA、LDA。 一个采样:Gibbs采样 关于LDA有两种含义,一种是线性判别分析(Linear Discriminant Analysis),一种是概率主题模型:隐含狄利克雷分布(Latent Dirichlet Allocation,简称LDA),本文讲后者。 按照wiki上的介绍,LDA由Blei, David M.、Ng, Andrew Y.、Jordan于2003年提出,是一种主题模型,它可以将文档集 中每篇文档的主题以概率分布的形式给出,从而通过分析一些文档抽取出它们的主题(分布)出来后,便可以根据主题(分布)进行主题聚类或文本分类。同时,它是一种典型的词袋模型,即一篇文档是由一组词构成,词与词之间没有先后顺序的关系。此外,一篇文档可以包含多个主题,文档中每一个词都由其中的一个主题生成。 人类是怎么生成文档的呢?首先先列出几个主题,然后以一定的概率选择主题,以一定的概率选择这个主题包含的词汇,最终组合成一篇文章。如下图所示(其中不同颜色的词语分别对应上图中不同主题下的词)。 那么LDA就是跟这个反过来:根据给定的一篇文档,反推其主题分布。 在LDA模型中,一篇文档生成的方式如下: 从狄利克雷分布 $\\alpha$ 中取样生成文档 i 的主题分布 $\\theta_i$。 从主题的多项式分布 $\\theta_i$ 中取样生成文档i第 j 个词的主题 $z_{i,j}$。 从狄利克雷分布 $\\beta$ 中取样生成主题 $z_{i,j}$ 对应的词语分布 $\\phi_{z_{i,j}}$。 从词语的多项式分布 $\\phi_{z_{i,j}}$ 中采样最终生成词语 $w_{i,j}$。 其中,类似Beta分布是二项式分布的共轭先验概率分布,而狄利克雷分布(Dirichlet分布)是多项式分布的共轭先验概率分布。此外,LDA的图模型结构如下图所示(类似贝叶斯网络结构): 1.1 5个分布的理解先解释一下以上出现的概念。 二项分布(Binomial distribution) 二项分布是从伯努利分布推进的。伯努利分布,又称两点分布或0-1分布,是一个离散型的随机分布,其中的随机变量只有两类取值,非正即负{+,-}。而二项分布即重复n次的伯努利试验,记为 $X\\sim_{}b(n,p)$。简言之,只做一次实验,是伯努利分布,重复做了n次,是二项分布。 多项分布 是二项分布扩展到多维的情况。多项分布是指单次试验中的随机变量的取值不再是0-1的,而是有多种离散值可能(1,2,3…,k)。比如投掷6个面的骰子实验,N次实验结果服从K=6的多项分布。其中: $$\\sum_{i=1}^{k}p_i=1,p_i>0$$ 共轭先验分布 在贝叶斯统计中,如果后验分布与先验分布属于同类,则先验分布与后验分布被称为共轭分布,而先验分布被称为似然函数的共轭先验。 Beta分布 二项分布的共轭先验分布。给定参数 $\\alpha>0$ 和 $\\beta>0$,取值范围为[0,1]的随机变量 x 的概率密度函数: $$f(x;\\alpha,\\beta)=\\frac{1}{B(\\alpha,\\beta)}x^{\\alpha-1}(1-x)^{\\beta-1}$$ 其中: $$\\frac{1}{B(\\alpha,\\beta)}=\\frac{\\Gamma(\\alpha+\\beta)}{\\Gamma(\\alpha)\\Gamma(\\beta)}$$ $$\\Gamma(z)=\\int_{0}^{\\infty}t^{z-1}e^{-t}dt$$ 注:这便是所谓的gamma函数,下文会具体阐述。 狄利克雷分布 是beta分布在高维度上的推广。Dirichlet分布的的密度函数形式跟beta分布的密度函数如出一辙: $$f(x_1,x_2,…,x_k;\\alpha_1,\\alpha_2,…,\\alpha_k)=\\frac{1}{B(\\alpha)}\\prod_{i=1}^{k}x_i^{\\alpha^i-1}$$ 其中 $$B(\\alpha)=\\frac{\\prod_{i=1}^{k}\\Gamma(\\alpha^i)}{\\Gamma(\\sum_{i=1}^{k}\\alpha^i)},\\sum_{}x_i=1$$ 至此,我们可以看到二项分布和多项分布很相似,Beta分布和Dirichlet 分布很相似。 如果想要深究其原理可以参考:通俗理解LDA主题模型,也可以先往下走,最后在回过头来看详细的公式,就更能明白了。 总之,可以得到以下几点信息。 beta分布是二项式分布的共轭先验概率分布:对于非负实数 $\\alpha$ 和 $\\beta$ ,我们有如下关系: $$Beta(p|\\alpha,\\beta)+Count(m_1,m_2)=Beta(p|\\alpha+m_1,\\beta+m_2)$$ 其中 $(m_1,m_2)$ 对应的是二项分布 $B(m_1+m_2,p)$ 的记数。针对于这种观测到的数据符合二项分布,参数的先验分布和后验分布都是Beta分布的情况,就是Beta-Binomial 共轭。” 狄利克雷分布(Dirichlet分布)是多项式分布的共轭先验概率分布,一般表达式如下: $$Dir(\\vec{p}|\\vec\\alpha)+MultCount(\\vec{m})=Dir(p|\\vec{\\alpha}+\\vec{m})$$ 针对于这种观测到的数据符合多项分布,参数的先验分布和后验分布都是Dirichlet 分布的情况,就是 Dirichlet-Multinomial 共轭。 ” 贝叶斯派思考问题的固定模式: 先验分布 $\\pi(\\theta)$+ 样本信息 $X$ = 后验分布 $\\pi(\\theta|x)$。 1.2 3个基础模型的理解在讲LDA模型之前,再循序渐进理解基础模型:Unigram model、mixture of unigrams model,以及跟LDA最为接近的pLSA模型。为了方便描述,首先定义一些变量: $w$ 表示词,$V$ 表示所有单词的个数(固定值)。 $z$ 表示主题,$k$ 是主题的个数(预先给定,固定值)。 $D=(W_1,…,W_M)$ 表示语料库,其中的M是语料库中的文档数(固定值)。 $W=(w_1,w_2,…,w_N)$ 表示文档,其中的N表示一个文档中的词数(随机变量)。 Unigram model 对于文档$W=(w_1,w_2,…,w_N)$,用 $p(w_n)$ 表示词 $w_n$ 的先验概率,生成文档w的概率为: $$p(W)=\\prod_{n=1}^{N}p(w_n)$$ Mixture of unigrams model 该模型的生成过程是:给某个文档先选择一个主题z,再根据该主题生成文档,该文档中的所有词都来自一个主题。假设主题有 $z_1,…,z_n$,生成文档w的概率为: $$p(W)=p(z_1)\\prod_{n=1}^{N}p(w_n|z_1)+…+p(z_k)\\prod_{n=1}^{N}p(w_n|z_k)=\\sum_{z}p(z)\\prod_{n=1}^{N}p(w_n|z)$$ PLSA模型 理解了pLSA模型后,到LDA模型也就一步之遥——给pLSA加上贝叶斯框架,便是LDA。 在上面的Mixture of unigrams model中,我们假定一篇文档只有一个主题生成,可实际中,一篇文章往往有多个主题,只是这多个主题各自在文档中出现的概率大小不一样。比如介绍一个国家的文档中,往往会分别从教育、经济、交通等多个主题进行介绍。那么在pLSA中,文档是怎样被生成的呢? 假定你一共有K个可选的主题,有V个可选的词,咱们来玩一个扔骰子的游戏。 一、假设你每写一篇文档会制作一颗K面的“文档-主题”骰子(扔此骰子能得到K个主题中的任意一个),和K个V面的“主题-词项” 骰子(每个骰子对应一个主题,K个骰子对应之前的K个主题,且骰子的每一面对应要选择的词项,V个面对应着V个可选的词)。 比如可令K=3,即制作1个含有3个主题的“文档-主题”骰子,这3个主题可以是:教育、经济、交通。然后令V = 3,制作3个有着3面的“主题-词项”骰子,其中,教育主题骰子的3个面上的词可以是:大学、老师、课程,经济主题骰子的3个面上的词可以是:市场、企业、金融,交通主题骰子的3个面上的词可以是:高铁、汽车、飞机。 二、每写一个词,先扔该“文档-主题”骰子选择主题,得到主题的结果后,使用和主题结果对应的那颗“主题-词项”骰子,扔该骰子选择要写的词。 先扔“文档-主题”的骰子,假设(以一定的概率)得到的主题是教育,所以下一步便是扔教育主题筛子,(以一定的概率)得到教育主题筛子对应的某个词:大学。 上面这个投骰子产生词的过程简化下便是:“先以一定的概率选取主题,再以一定的概率选取词”。 三、最后,你不停的重复扔“文档-主题”骰子和”主题-词项“骰子,重复N次(产生N个词),完成一篇文档,重复这产生一篇文档的方法M次,则完成M篇文档。 上述过程抽象出来即是PLSA的文档生成模型。在这个过程中,我们并未关注词和词之间的出现顺序,所以PLSA是一种词袋方法。生成文档的整个过程便是选定文档生成主题,确定主题生成词。 反过来,既然文档已经产生,那么如何根据已经产生好的文档反推其主题呢?这个利用看到的文档推断其隐藏的主题(分布)的过程(其实也就是产生文档的逆过程),便是主题建模的目的:自动地发现文档集中的主题(分布)。 文档d和词w是我们得到的样本,可观测得到,所以对于任意一篇文档,其 $P(w_j|d_i)$ 是已知的。从而可以根据大量已知的文档-词项信息 $P(w_j|d_i)$,训练出文档-主题 $P(z_k|d_i)$ 和主题-词项 $P(w_j|z_k)$,如下公式所示: $$P(w_j|d_i)=\\sum_{k=1}^{K}P(w_j|z_k)P(z_k|d_i)$$ 故得到文档中每个词的生成概率为: $$P(d_i,w_j)=P(d_i)P(w_j|d_i)=P(d_i)\\sum_{k=1}^{K}P(w_j|z_k)P(z_k|d_i)$$ 由于 $P(d_i)$ 可事先计算求出,而 $P(w_j|z_k)^{}$ 和 $P(z_k|d_i)$ 未知,所以 $\\theta=(P(w_j|z_k),P(z_k|d_i))$ 就是我们要估计的参数(值),通俗点说,就是要最大化这个θ。 用什么方法进行估计呢,常用的参数估计方法有极大似然估计MLE、最大后验证估计MAP、贝叶斯估计等等。因为该待估计的参数中含有隐变量z,所以我们可以考虑EM算法。详细的EM算法可以参考之前写过的 EM算法 章节。 1.3 LDA模型事实上,理解了pLSA模型,也就差不多快理解了LDA模型,因为LDA就是在pLSA的基础上加层贝叶斯框架,即LDA就是pLSA的贝叶斯版本(正因为LDA被贝叶斯化了,所以才需要考虑历史先验知识,才加的两个先验参数)。 下面,咱们对比下本文开头所述的LDA模型中一篇文档生成的方式是怎样的: 按照先验概率 $P(d_i)$ 选择一篇文档 $d_i$。 从狄利克雷分布(即Dirichlet分布)$\\alpha$ 中取样生成文档 $d_i$ 的主题分布 $\\theta_i$,换言之,主题分布 $\\theta_i$ 由超参数为 $\\alpha$ 的Dirichlet分布生成。 从主题的多项式分布 $\\theta_i$ 中取样生成文档 $d_i$ 第 j 个词的主题 $z_{i,j}$。 从狄利克雷分布(即Dirichlet分布)$\\beta$ 中取样生成主题 $z_{i,j}$ 对应的词语分布 $\\phi_{z_{i,j}}$,换言之,词语分布 $\\phi_{z_{i,j}}$ 由参数为 $\\beta$ 的Dirichlet分布生成。 从词语的多项式分布 $\\phi_{z_{i,j}}$ 中采样最终生成词语 $w_{i,j}$。 LDA中,选主题和选词依然都是两个随机的过程,依然可能是先从主题分布{教育:0.5,经济:0.3,交通:0.2}中抽取出主题:教育,然后再从该主题对应的词分布{大学:0.5,老师:0.3,课程:0.2}中抽取出词:大学。 那PLSA跟LDA的区别在于什么地方呢?区别就在于: PLSA中,主题分布和词分布是唯一确定的,能明确的指出主题分布可能就是{教育:0.5,经济:0.3,交通:0.2},词分布可能就是{大学:0.5,老师:0.3,课程:0.2}。但在LDA中,主题分布和词分布不再唯一确定不变,即无法确切给出。例如主题分布可能是{教育:0.5,经济:0.3,交通:0.2},也可能是{教育:0.6,经济:0.2,交通:0.2},到底是哪个我们不再确定(即不知道),因为它是随机的可变化的。但再怎么变化,也依然服从一定的分布,即主题分布跟词分布由Dirichlet先验随机确定。正因为LDA是PLSA的贝叶斯版本,所以主题分布跟词分布本身由先验知识随机给定。 换言之,LDA在pLSA的基础上给这两参数 $(P(z_k|d_i)、P(w_j|z_k))$ 加了两个先验分布的参数(贝叶斯化):一个主题分布的先验分布Dirichlet分布 $\\alpha$,和一个词语分布的先验分布Dirichlet分布 $\\beta$。 综上,LDA真的只是pLSA的贝叶斯版本,文档生成后,两者都要根据文档去推断其主题分布和词语分布(即两者本质都是为了估计给定文档生成主题,给定主题生成词语的概率),只是用的参数推断方法不同,在pLSA中用极大似然估计的思想去推断两未知的固定参数,而LDA则把这两参数弄成随机变量,且加入dirichlet先验。 所以,pLSA跟LDA的本质区别就在于它们去估计未知参数所采用的思想不同,前者用的是频率派思想,后者用的是贝叶斯派思想。 LDA参数估计:Gibbs采样,详见文末的参考文献。 2. 怎么确定LDA的topic个数? 基于经验 主观判断、不断调试、操作性强、最为常用。 基于困惑度(主要是比较两个模型之间的好坏)。 使用Log-边际似然函数的方法,这种方法也挺常用的。 非参数方法:Teh提出的基于狄利克雷过程的HDP法。 基于主题之间的相似度:计算主题向量之间的余弦距离,KL距离等。 3. 如何用主题模型解决推荐系统中的冷启动问题?推荐系统中的冷启动问题是指在没有大量用户数据的情况下如何给用户进行个性化推荐,目的是最优化点击率、转化率或用户 体验(用户停留时间、留存率等)。冷启动问题一般分为用户冷启动、物品冷启动和系统冷启动三大类。 用户冷启动是指对一个之前没有行为或行为极少的新用户进行推荐; 物品冷启动是指为一个新上市的商品或电影(这时没有与之相关的 评分或用户行为数据)寻找到具有潜在兴趣的用户; 系统冷启动是指如何为一个 新开发的网站设计个性化推荐系统。 解决冷启动问题的方法一般是基于内容的推荐。以Hulu的场景为例,对于用 户冷启动来说,我们希望根据用户的注册信息(如:年龄、性别、爱好等)、搜 索关键词或者合法站外得到的其他信息(例如用户使用Facebook账号登录,并得 到授权,可以得到Facebook中的朋友关系和评论内容)来推测用户的兴趣主题。 得到用户的兴趣主题之后,我们就可以找到与该用户兴趣主题相同的其他用户, 通过他们的历史行为来预测用户感兴趣的电影是什么。 同样地,对于物品冷启动问题,我们也可以根据电影的导演、演员、类别、关键词等信息推测该电影所属于的主题,然后基于主题向量找到相似的电影,并将新电影推荐给以往喜欢看这 些相似电影的用户。可以使用主题模型(pLSA、LDA等)得到用户和电影的主题。 以用户为例,我们将每个用户看作主题模型中的一篇文档,用户对应的特征 作为文档中的单词,这样每个用户可以表示成一袋子特征的形式。通过主题模型 学习之后,经常共同出现的特征将会对应同一个主题,同时每个用户也会相应地 得到一个主题分布。每个电影的主题分布也可以用类似的方法得到。 那么如何解决系统冷启动问题呢?首先可以得到每个用户和电影对应的主题向量,除此之外,还需要知道用户主题和电影主题之间的偏好程度,也就是哪些主题的用户可能喜欢哪些主题的电影。当系统中没有任何数据时,我们需要一些先验知识来指定,并且由于主题的数目通常比较小,随着系统的上线,收集到少量的数据之后我们就可以对主题之间的偏好程度得到一个比较准确的估计。 4. 参考文献通俗理解LDA主题模型 5. 代码实现LDA模型应用:一眼看穿希拉里的邮件 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】ML特征工程和优化方法","slug":"ML/ML feature","date":"2019-07-26T16:00:00.000Z","updated":"2019-12-25T05:43:22.488Z","comments":true,"path":"2019/07/27/ML/ML feature/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/27/ML/ML%20feature/","excerpt":"特征工程,顾名思义,是对原始数据进行一系列工程处理,将其提炼为特征,作为输入供算法和模型使用。从本质上来讲,特征工程是一个表示和展现数 据的过程。在实际工作中,特征工程旨在去除原始数据中的杂质和冗余,设计更高效的特征以刻画求解的问题与预测模型之间的关系。 主要讨论以下两种常用的数据类型。 为了消除…","text":"特征工程,顾名思义,是对原始数据进行一系列工程处理,将其提炼为特征,作为输入供算法和模型使用。从本质上来讲,特征工程是一个表示和展现数 据的过程。在实际工作中,特征工程旨在去除原始数据中的杂质和冗余,设计更高效的特征以刻画求解的问题与预测模型之间的关系。 主要讨论以下两种常用的数据类型。 为了消除… 1. 特征工程有哪些?特征工程,顾名思义,是对原始数据进行一系列工程处理,将其提炼为特征,作为输入供算法和模型使用。从本质上来讲,特征工程是一个表示和展现数 据的过程。在实际工作中,特征工程旨在去除原始数据中的杂质和冗余,设计更高效的特征以刻画求解的问题与预测模型之间的关系。 主要讨论以下两种常用的数据类型。 结构化数据。结构化数据类型可以看作关系型数据库的一张表,每列都 有清晰的定义,包含了数值型、类别型两种基本类型;每一行数据表示一个样本 的信息。 非结构化数据。非结构化数据主要包括文本、图像、音频、视频数据, 其包含的信息无法用一个简单的数值表示,也没有清晰的类别定义,并且每条数 据的大小各不相同。 1.1 特征归一化为了消除数据特征之间的量纲影响,我们需要对特征进行归一化处理,使得 不同指标之间具有可比性。例如,分析一个人的身高和体重对健康的影响,如果 使用米(m)和千克(kg)作为单位,那么身高特征会在1.6~1.8m的数值范围 内,体重特征会在50~100kg的范围内,分析出来的结果显然会倾向于数值差别比 较大的体重特征。想要得到更为准确的结果,就需要进行特征归一化 (Normalization)处理,使各指标处于同一数值量级,以便进行分析。 对数值类型的特征做归一化可以将所有的特征都统一到一个大致相同的数值 区间内。最常用的方法主要有以下两种。 线性函数归一化(Min-Max Scaling)。它对原始数据进行线性变换,使 结果映射到[0, 1]的范围,实现对原始数据的等比缩放。归一化公式如下,其中X为原始数据,$X_{max}、X_{min}$ 分别为数据最大值和最小值。 $$X_{norm}=\\frac{X-X_{min}}{X_{max}-X_{min}}$$ 零均值归一化(Z-Score Normalization)。它会将原始数据映射到均值为 0、标准差为1的分布上。具体来说,假设原始特征的均值为μ、标准差为σ,那么 归一化公式定义为 $$z=\\frac{x-u}{\\sigma}$$ 优点:训练数据归一化后,容易更快地通过梯度下降找 到最优解。 当然,数据归一化并不是万能的。在实际应用中,通过梯度下降法求解的模 型通常是需要归一化的,包括线性回归、逻辑回归、支持向量机、神经网络等模 型。但对于决策树模型则并不适用。 1.2 类别型特征类别型特征(Categorical Feature)主要是指性别(男、女)、血型(A、B、 AB、O)等只在有限选项内取值的特征。类别型特征原始输入通常是字符串形 式,除了决策树等少数模型能直接处理字符串形式的输入,对于逻辑回归、支持 向量机等模型来说,类别型特征必须经过处理转换成数值型特征才能正确工作。 序号编码 序号编码通常用于处理类别间具有大小关系的数据。例如成绩,可以分为 低、中、高三档,并且存在“高>中>低”的排序关系。序号编码会按照大小关系对 类别型特征赋予一个数值ID,例如高表示为3、中表示为2、低表示为1,转换后依 然保留了大小关系。 独热编码(one-hot) 独热编码通常用于处理类别间不具有大小关系的特征。例如血型,一共有4个 取值(A型血、B型血、AB型血、O型血),独热编码会把血型变成一个4维稀疏 向量,A型血表示为(1, 0, 0, 0),B型血表示为(0, 1, 0, 0),AB型表示为(0, 0, 1, 0),O型血表示为(0, 0, 0, 1)。对于类别取值较多的情况下使用独热编码。 *二进制编码 * 二进制编码主要分为两步,先用序号编码给每个类别赋予一个类别ID,然后 将类别ID对应的二进制编码作为结果。以A、B、AB、O血型为例,下图是二进制编码的过程。A型血的ID为1,二进制表示为001;B型血的ID为2,二进制表示为 010;以此类推可以得到AB型血和O型血的二进制表示。 1.3 高维组合特征的处理为了提高复杂关系的拟合能力,在特征工程中经常会把一阶离散特征两两组 合,构成高阶组合特征。以广告点击预估问题为例,原始数据有语言和类型两种 离散特征,第一张图是语言和类型对点击的影响。为了提高拟合能力,语言和类型可 以组成二阶特征,第二张图是语言和类型的组合特征对点击的影响。 1.4 文本表示模型文本是一类非常重要的非结构化数据,如何表示文本数据一直是机器学习领 域的一个重要研究方向。 词袋模型和N-gram模型 最基础的文本表示模型是词袋模型。顾名思义,就是将每篇文章看成一袋子 词,并忽略每个词出现的顺序。具体地说,就是将整段文本以词为单位切分开, 然后每篇文章可以表示成一个长向量,向量中的每一维代表一个单词,而该维对 应的权重则反映了这个词在原文章中的重要程度。常用TF-IDF来计算权重。 主题模型 主题模型用于从文本库中发现有代表性的主题(得到每个主题上面词的分布 特性),并且能够计算出每篇文章的主题分布。 词嵌入与深度学习模型 词嵌入是一类将词向量化的模型的统称,核心思想是将每个词都映射成低维 空间(通常K=50~300维)上的一个稠密向量(Dense Vector)。K维空间的每一 维也可以看作一个隐含的主题,只不过不像主题模型中的主题那样直观。 1.5 其它特征工程 如果某个特征当中有缺失值,缺失比较少的话,可以使用该特征的平均值或者其它比较靠谱的数据进行填充;缺失比较多的话可以考虑删除该特征。 可以分析特征与结果的相关性,把相关性小的特征去掉。 1.6 特征工程脑图 1.7 标准化和归一化的区别归一化是将样本的特征值转换到同一量纲下把数据映射到[0,1]或者[-1, 1]区间内,仅由变量的极值决定,因区间放缩法是归一化的一种。 标准化是依照特征矩阵的列处理数据,其通过求z-score的方法,转换为标准正态分布,和整体样本分布相关,每个样本点都能对标准化产生影响。 它们的相同点在于都能取消由于量纲不同引起的误差;都是一种线性变换,都是对向量X按照比例压缩再进行平移。 2. 机器学习优化方法优化是应用数学的一个分支,也是机器学习的核心组成部分。实际上,机器 学习算法 = 模型表征 + 模型评估 + 优化算法。其中,优化算法所做的事情就是在 模型表征空间中找到模型评估指标最好的模型。不同的优化算法对应的模型表征 和评估指标不尽相同。 2.1 机器学习常用损失函数损失函数(loss function)是用来估量你模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好。常见的损失函数如下: 平方损失函数 $$L(Y,f(X))=\\sum_{i=1}^{n}(Y-f(X))^2$$ Y-f(X)表示的是残差,整个式子表示的是残差的平方和,而我们的目的就是最小化这个目标函数值(注:该式子未加入正则项),也就是最小化残差的平方和。而在实际应用中,通常会使用均方差(MSE)作为一项衡量指标,公式如下: $$MSE=\\frac{1}{n}\\sum_{i=1}^{n}(Y_i^{‘}-Y_i)^2$$ 该损失函数一般使用在线性回归当中。 log损失函数 公式中的 y=1 表示的是真实值为1时用第一个公式,真实 y=0 用第二个公式计算损失。为什么要加上log函数呢?可以试想一下,当真实样本为1是,但h=0概率,那么log0=∞,这就对模型最大的惩罚力度;当h=1时,那么log1=0,相当于没有惩罚,也就是没有损失,达到最优结果。所以数学家就想出了用log函数来表示损失函数。 最后按照梯度下降法一样,求解极小值点,得到想要的模型效果。该损失函数一般使用在逻辑回归中。 Hinge损失函数 $$L_i=\\sum_{j\\neq t_i}max(0,f(x_i,W)j-(f(x_i,W){y_i}-\\bigtriangleup))$$ SVM采用的就是Hinge Loss,用于“最大间隔(max-margin)”分类。 详细见之前SVM的文章1.2.3 0-1损失函数 如果预测值和目标值相等,值为0,如果不相等,值为1。$$L(Y, f(x)) =\\begin{cases}1,& Y\\ne f(x)\\0,& Y = f(x)\\end{cases}$$一般的在实际使用中,相等的条件过于严格,可适当放宽条件: $$L(Y, f(x)) =\\begin{cases}1,& |Y-f(x)|\\geqslant T\\0,& |Y-f(x)|< T\\end{cases}$$ 绝对值损失函数和0-1损失函数相似,绝对值损失函数表示为:$$L(Y, f(x)) = |Y-f(x)|$$ 指数损失函数指数损失函数的标准形式为:$$L(Y, f(x)) = \\exp(-Yf(x))$$ 例如AdaBoost就是以指数损失函数为损失函数。 均方根误差 $$RMSE=\\sqrt{\\frac{1}{n}\\sum_{i=1}^n(y_i^{‘}-y_i)^2}$$ 平均绝对误差 $$MAE=\\frac{1}{n}\\sum_{i=1}^{n}|y_i^{‘}-y_i|$$ 2.2 什么是凸优化凸函数的严格定义为,函数L(·) 是凸函数当且仅当对定义域中的任意两点x,y和任意实数λ∈[0,1]总有: $$L(\\lambda_{}x+(1-\\lambda)y)\\leq\\lambda_{}L(x)+(1-\\lambda)L(y)$$ 该不等式的一个直观解释是,凸函数曲面上任意两点连接而成的线段,其上的任 意一点都不会处于该函数曲面的下方,如下图所示所示。 凸优化问题的例子包括支持向量机、线性回归等 线性模型,非凸优化问题的例子包括低秩模型(如矩阵分解)、深度神经网络模型等。 2.3 正则化项使用正则化项,也就是给loss function加上一个参数项,正则化项有L1正则化、L2正则化、ElasticNet。加入这个正则化项好处: 控制参数幅度,不让模型“无法无天”。 限制参数搜索空间 解决欠拟合与过拟合的问题。 详细请参考之前的文章:线性回归–第5点 2.4 常见的几种最优化方法 梯度下降法 梯度下降法是最早最简单,也是最为常用的最优化方法。梯度下降法实现简单,当目标函数是凸函数时,梯度下降法的解是全局解。一般情况下,其解不保证是全局最优解,梯度下降法的速度也未必是最快的。梯度下降法的优化思想是用当前位置负梯度方向作为搜索方向,因为该方向为当前位置的最快下降方向,所以也被称为是”最速下降法“。最速下降法越接近目标值,步长越小,前进越慢。梯度下降法的搜索迭代示意图如下图所示: 缺点:靠近极小值时收敛速度减慢;直线搜索时可能会产生一些问题;可能会“之字形”地下降。 牛顿法 牛顿法是一种在实数域和复数域上近似求解方程的方法。方法使用函数f (x)的泰勒级数的前面几项来寻找方程f (x) = 0的根。牛顿法最大的特点就在于它的收敛速度很快。具体步骤: 首先,选择一个接近函数 f (x)零点的 x0,计算相应的 f (x0) 和切线斜率f ‘ (x0)(这里f ‘ 表示函数 f 的导数)。 然后我们计算穿过点(x0, f (x0)) 并且斜率为f ‘(x0)的直线和 x 轴的交点的x坐标,也就是求如下方程的解: $$xf^{‘}(x_0)+f(x_0)-x_0f^{‘}(x_0)=0$$ 我们将新求得的点的 x 坐标命名为x1,通常x1会比x0更接近方程f (x) = 0的解。因此我们现在可以利用x1开始下一轮迭代。 由于牛顿法是基于当前位置的切线来确定下一次的位置,所以牛顿法又被很形象地称为是”切线法”。牛顿法搜索动态示例图: 从本质上去看,牛顿法是二阶收敛,梯度下降是一阶收敛,所以牛顿法就更快。缺点: 牛顿法是一种迭代算法,每一步都需要求解目标函数的Hessian矩阵的逆矩阵,计算比较复杂。 在高维情况下这个矩阵非常大,计算和存储都是问题。 在小批量的情况下,牛顿法对于二阶导数的估计噪声太大。 目标函数非凸的时候,牛顿法容易受到鞍点或者最大值点的吸引。 拟牛顿法 拟牛顿法是求解非线性优化问题最有效的方法之一,本质思想是改善牛顿法每次需要求解复杂的Hessian矩阵的逆矩阵的缺陷,它使用正定矩阵来近似Hessian矩阵的逆,从而简化了运算的复杂度。拟牛顿法和梯度下降法一样只要求每一步迭代时知道目标函数的梯度。通过测量梯度的变化,构造一个目标函数的模型使之足以产生超线性收敛性。这类方法大大优于梯度下降法,尤其对于困难的问题。另外,因为拟牛顿法不需要二阶导数的信息,所以有时比牛顿法更为有效。如今,优化软件中包含了大量的拟牛顿算法用来解决无约束,约束,和大规模的优化问题。 共轭梯度法 共轭梯度法是介于梯度下降法与牛顿法之间的一个方法,它仅需利用一阶导数信息,但克服了梯度下降法收敛慢的缺点,又避免了牛顿法需要存储和计算Hesse矩阵并求逆的缺点,共轭梯度法不仅是解决大型线性方程组最有用的方法之一,也是解大型非线性最优化最有效的算法之一。 在各种优化算法中,共轭梯度法是非常重要的一种。其优点是所需存储量小,具有步收敛性,稳定性高,而且不需要任何外来参数。 具体的实现步骤请参加wiki百科共轭梯度法。下图为共轭梯度法和梯度下降法搜索最优解的路径对比示意图: 2.5 降维方法2.5.1 线性判别分析(LDA)线性判别分析(Linear Discriminant Analysis,LDA)是一种经典的降维方法。和主成分分析PCA不考虑样本类别输出的无监督降维技术不同,LDA是一种监督学习的降维技术,数据集的每个样本有类别输出。 LDA分类思想简单总结如下: 多维空间中,数据处理分类问题较为复杂,LDA算法将多维空间中的数据投影到一条直线上,将d维数据转化成1维数据进行处理。 对于训练数据,设法将多维数据投影到一条直线上,同类数据的投影点尽可能接近,异类数据点尽可能远离。 对数据进行分类时,将其投影到同样的这条直线上,再根据投影点的位置来确定样本的类别。 如果用一句话概括LDA思想,即“投影后类内方差最小,类间方差最大”。 假设有红、蓝两类数据,这些数据特征均为二维,如下图所示。我们的目标是将这些数据投影到一维,让每一类相近的数据的投影点尽可能接近,不同类别数据尽可能远,即图中红色和蓝色数据中心之间的距离尽可能大。 左图和右图是两种不同的投影方式。 左图思路:让不同类别的平均点距离最远的投影方式。 右图思路:让同类别的数据挨得最近的投影方式。 从上图直观看出,右图红色数据和蓝色数据在各自的区域来说相对集中,根据数据分布直方图也可看出,所以右图的投影效果好于左图,左图中间直方图部分有明显交集。 以上例子是基于数据是二维的,分类后的投影是一条直线。如果原始数据是多维的,则投影后的分类面是一低维的超平面。 优缺点 优缺点 简要说明 优点 1. 可以使用类别的先验知识;2. 以标签、类别衡量差异性的有监督降维方式,相对于PCA的模糊性,其目的更明确,更能反映样本间的差异; 缺点 1. LDA不适合对非高斯分布样本进行降维;2. LDA降维最多降到分类数k-1维;3. LDA在样本分类信息依赖方差而不是均值时,降维效果不好;4. LDA可能过度拟合数据。 2.5.2 主成分分析(PCA) PCA就是将高维的数据通过线性变换投影到低维空间上去。 投影思想:找出最能够代表原始数据的投影方法。被PCA降掉的那些维度只能是那些噪声或是冗余的数据。 去冗余:去除可以被其他向量代表的线性相关向量,这部分信息量是多余的。 去噪声,去除较小特征值对应的特征向量,特征值的大小反映了变换后在特征向量方向上变换的幅度,幅度越大,说明这个方向上的元素差异也越大,要保留。 对角化矩阵,寻找极大线性无关组,保留较大的特征值,去除较小特征值,组成一个投影矩阵,对原始样本矩阵进行投影,得到降维后的新样本矩阵。 完成PCA的关键是——协方差矩阵。协方差矩阵,能同时表现不同维度间的相关性以及各个维度上的方差。协方差矩阵度量的是维度与维度之间的关系,而非样本与样本之间。 之所以对角化,因为对角化之后非对角上的元素都是0,达到去噪声的目的。对角化后的协方差矩阵,对角线上较小的新方差对应的就是那些该去掉的维度。所以我们只取那些含有较大能量(特征值)的维度,其余的就舍掉,即去冗余。 图解PCA PCA可解决训练数据中存在数据特征过多或特征累赘的问题。核心思想是将m维特征映射到n维(n < m),这n维形成主元,是重构出来最能代表原始数据的正交特征。 假设数据集是m个n维,$(\\boldsymbol x^{(1)}, \\boldsymbol x^{(2)}, \\cdots, \\boldsymbol x^{(m)})$。如果$n=2$,需要降维到$n’=1$,现在想找到某一维度方向代表这两个维度的数据。下图有$u_1, u_2$两个向量方向,但是哪个向量才是我们所想要的,可以更好代表原始数据集的呢? 从图可看出,$u_1$比$u_2$好,为什么呢?有以下两个主要评价指标: 样本点到这个直线的距离足够近。 样本点在这个直线上的投影能尽可能的分开。 如果我们需要降维的目标维数是其他任意维,则: 样本点到这个超平面的距离足够近。 样本点在这个超平面上的投影能尽可能的分开。 优缺点 优缺点 简要说明 优点 1. 仅仅需要以方差衡量信息量,不受数据集以外的因素影响。 2.各主成分之间正交,可消除原始数据成分间的相互影响的因素。3. 计算方法简单,主要运算是特征值分解,易于实现。 缺点 1.主成分各个特征维度的含义具有一定的模糊性,不如原始样本特征的解释性强。2. 方差小的非主成分也可能含有对样本差异的重要信息,因降维丢弃可能对后续数据处理有影响。 2.5.3 比较这两种方法降维的必要性: 多重共线性和预测变量之间相互关联。多重共线性会导致解空间的不稳定,从而可能导致结果的不连贯。 高维空间本身具有稀疏性。一维正态分布有68%的值落于正负标准差之间,而在十维空间上只有2%。 过多的变量,对查找规律造成冗余麻烦。 仅在变量层面上分析可能会忽略变量之间的潜在联系。例如几个预测变量可能落入仅反映数据某一方面特征的一个组内。 降维的目的: 减少预测变量的个数。 确保这些变量是相互独立的。 提供一个框架来解释结果。相关特征,特别是重要特征更能在数据中明确的显示出来;如果只有两维或者三维的话,更便于可视化展示。 数据在低维下更容易处理、更容易使用。 去除数据噪声。 降低算法运算开销。 LDA和PCA区别 异同点 LDA PCA 相同点 1. 两者均可以对数据进行降维;2. 两者在降维时均使用了矩阵特征分解的思想;3. 两者都假设数据符合高斯分布; 不同点 有监督的降维方法; 无监督的降维方法; 降维最多降到k-1维; 降维多少没有限制; 可以用于降维,还可以用于分类; 只用于降维; 选择分类性能最好的投影方向; 选择样本点投影具有最大方差的方向; 更明确,更能反映样本间差异; 目的较为模糊; 3. 机器学习评估方法混淆矩阵也称误差矩阵,是表示精度评价的一种标准格式,用n行n列的矩阵形式来表示。具体评价指标有总体精度、制图精度、用户精度等,这些精度指标从不同的侧面反映了图像分类的精度。下图为混淆矩阵 正类 负类 预测正确 TP(True Positives) FP(False Positives) 预测错误 FN(False Negatives) TN(True Negatives) 3.1 准确率(Accuracy)准确率(Accuracy)。顾名思义,就是所有的预测正确(正类负类)的占总的比重。 $$Accuracy=\\frac{TP+TN}{TP+TN+FP+FN}$$ 准确率是分类问题中最简单也是最直观的评价指标,但存在明显的缺陷。比 如,当负样本占99%时,分类器把所有样本都预测为负样本也可以获得99%的准确 率。所以,当不同类别的样本比例非常不均衡时,占比大的类别往往成为影响准 确率的最主要因素。 3.2 精确率(Precision)精确率(Precision),查准率。即正确预测为正的占全部预测为正的比例。个人理解:真正正确的占所有预测为正的比例。 $$Precision=\\frac{TP}{TP+FP}$$ 3.3 召回率(Recall)召回率(Recall),查全率。即正确预测为正的占全部实际为正的比例。个人理解:真正正确的占所有实际为正的比例。 $$Recall=\\frac{TP}{TP+FN}$$ 为了综合评估一个排序模型的好坏,不仅要看模型在不同 Top N下的Precision@N和Recall@N,而且最好绘制出模型的P-R(Precision- Recall)曲线。这里简单介绍一下P-R曲线的绘制方法。 P-R曲线的横轴是召回率,纵轴是精确率。对于一个排序模型来说,其P-R曲 线上的一个点代表着,在某一阈值下,模型将大于该阈值的结果判定为正样本, 小于该阈值的结果判定为负样本,此时返回结果对应的召回率和精确率。整条P-R 曲线是通过将阈值从高到低移动而生成的。下图是P-R曲线样例图,其中实线代表 模型A的P-R曲线,虚线代表模型B的P-R曲线。原点附近代表当阈值最大时模型的 精确率和召回率。 由图可见,当召回率接近于0时,模型A的精确率为0.9,模型B的精确率是1, 这说明模型B得分前几位的样本全部是真正的正样本,而模型A即使得分最高的几 个样本也存在预测错误的情况。并且,随着召回率的增加,精确率整体呈下降趋 势。但是,当召回率为1时,模型A的精确率反而超过了模型B。这充分说明,只用某个点对应的精确率和召回率是不能全面地衡量模型的性能,只有通过P-R曲线的 整体表现,才能够对模型进行更为全面的评估。 3.4 F1值(H-mean值)F1值(H-mean值)。F1值为算数平均数除以几何平均数,且越大越好,将Precision和Recall的上述公式带入会发现,当F1值小时,True Positive相对增加,而false相对减少,即Precision和Recall都相对增加,即F1对Precision和Recall都进行了加权。 $$\\frac{2}{F_1}=\\frac{1}{Precision}+\\frac{1}{Recall}$$ $$F_1=\\frac{2PR}{P+R}=\\frac{2TP}{2TP+FP+FN}$$ 3.4 ROC曲线3.4.1 ROC曲线ROC曲线。接收者操作特征曲线(receiver operating characteristic curve),是反映敏感性和特异性连续变量的综合指标,ROC曲线上每个点反映着对同一信号刺激的感受性。下图是ROC曲线例子。 横坐标:1-Specificity,伪正类率(False positive rate,FPR,FPR=FP/(FP+TN)),预测为正但实际为负的样本占所有负例样本的比例; 纵坐标:Sensitivity,真正类率(True positive rate,TPR,TPR=TP/(TP+FN)),预测为正且实际为正的样本占所有正例样本的比例。 真正的理想情况,TPR应接近1,FPR接近0,即图中的(0,1)点。ROC曲线越靠拢(0,1)点,越偏离45度对角线越好。 3.4.2 AUC值AUC (Area Under Curve) 被定义为ROC曲线下的面积,显然这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围一般在0.5和1之间。使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。 从AUC判断分类器(预测模型)优劣的标准: AUC = 1,是完美分类器,采用这个预测模型时,存在至少一个阈值能得出完美预测。绝大多数预测的场合,不存在完美分类器。 0.5 < AUC < 1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。 AUC = 0.5,跟随机猜测一样(例:丢铜板),模型没有预测价值。 AUC < 0.5,比随机猜测还差;但只要总是反预测而行,就优于随机猜测。 一句话来说,AUC值越大的分类器,正确率越高。 如何计算AUC 将坐标点按照横坐标FPR排序 。 计算第$i$个坐标点和第$i+1$个坐标点的间距$dx$ 。 获取第$i$或者$i+1$个坐标点的纵坐标y。 计算面积微元$ds=ydx$。 对面积微元进行累加,得到AUC。 3.4.3 为什么使用Roc和Auc评价分类器因为ROC曲线有个很好的特性:当测试集中的正负样本的分布变换的时候,ROC曲线能够保持不变。在实际的数据集中经常会出现样本类不平衡,即正负样本比例差距较大,而且测试数据中的正负样本也可能随着时间变化。 3.5 余弦距离和欧式距离余弦距离:$cos(A,B)=\\frac{A*B}{||A||_2||B||_2}$ 欧式距离:在数学中,欧几里得距离或欧几里得度量是欧几里得空间中两点间“普通”(即直线)距离。 对于两个向量A和B,余弦距离关注的是向量之间的角度关系,并不关心它们的绝对大小,其取值 范围是[−1,1]。当一对文本相似度的长度差距很大、但内容相近时,如果使用词频 或词向量作为特征,它们在特征空间中的的欧氏距离通常很大;而如果使用余弦 相似度的话,它们之间的夹角可能很小,因而相似度高。此外,在文本、图像、 视频等领域,研究的对象的特征维度往往很高,余弦相似度在高维情况下依然保 持“相同时为1,正交时为0,相反时为−1”的性质,而欧氏距离的数值则受维度的 影响,范围不固定,并且含义也比较模糊。 3.6 A/B测试AB测试是为Web或App界面或流程制作两个(A/B)或多个(A/B/n)版本,在同一时间维度,分别让组成成分相同(相似)的访客群组(目标人群)随机的访问这些版本,收集各群组的用户体验数据和业务数据,最后分析、评估出最好版本,正式采用。 3.7 模型评估方法 Holdout检验 Holdout 检验是最简单也是最直接的验证方法,它将原始的样本集合随机划分 成训练集和验证集两部分。比方说,对于一个点击率预测模型,我们把样本按照 70%~30% 的比例分成两部分,70% 的样本用于模型训练;30% 的样本用于模型 验证,包括绘制ROC曲线、计算精确率和召回率等指标来评估模型性能。 Holdout 检验的缺点很明显,即在验证集上计算出来的最后评估指标与原始分 组有很大关系。为了消除随机性,研究者们引入了“交叉检验”的思想。 交叉检验 k-fold交叉验证:首先将全部样本划分成k个大小相等的样本子集;依次遍历 这k个子集,每次把当前子集作为验证集,其余所有子集作为训练集,进行模型的 训练和评估;最后把k次评估指标的平均值作为最终的评估指标。在实际实验 中,k经常取10。 自助法 不管是Holdout检验还是交叉检验,都是基于划分训练集和测试集的方法进行 模型评估的。然而,当样本规模比较小时,将样本集进行划分会让训练集进一步 减小,这可能会影响模型训练效果。有没有能维持训练集样本规模的验证方法 呢?自助法可以比较好地解决这个问题。 自助法是基于自助采样法的检验方法。对于总数为n的样本集合,进行n次有 放回的随机抽样,得到大小为n的训练集。n次采样过程中,有的样本会被重复采 样,有的样本没有被抽出过,将这些没有被抽出的样本作为验证集,进行模型验 证,这就是自助法的验证过程。 3.8 超参数调优为了进行超参数调优,我们一般会采用网格搜索、随机搜索、贝叶斯优化等 算法。在具体介绍算法之前,需要明确超参数搜索算法一般包括哪几个要素。一 是目标函数,即算法需要最大化/最小化的目标;二是搜索范围,一般通过上限和 下限来确定;三是算法的其他参数,如搜索步长。 网格搜索,可能是最简单、应用最广泛的超参数搜索算法,它通过查找搜索范 围内的所有的点来确定最优值。如果采用较大的搜索范围以及较小的步长,网格 搜索有很大概率找到全局最优值。然而,这种搜索方案十分消耗计算资源和时间,特别是需要调优的超参数比较多的时候。因此,在实际应用中,网格搜索法一般会先使用较广的搜索范围和较大的步长,来寻找全局最优值可能的位置;然 后会逐渐缩小搜索范围和步长,来寻找更精确的最优值。这种操作方案可以降低 所需的时间和计算量,但由于目标函数一般是非凸的,所以很可能会错过全局最 优值。 随机搜索,随机搜索的思想与网格搜索比较相似,只是不再测试上界和下界之间的所有 值,而是在搜索范围中随机选取样本点。它的理论依据是,如果样本点集足够 大,那么通过随机采样也能大概率地找到全局最优值,或其近似值。随机搜索一 般会比网格搜索要快一些,但是和网格搜索的快速版一样,它的结果也是没法保证的。 贝叶斯优化算法,贝叶斯优化算法在寻找最优最值参数时,采用了与网格搜索、随机搜索完全 不同的方法。网格搜索和随机搜索在测试一个新点时,会忽略前一个点的信息; 而贝叶斯优化算法则充分利用了之前的信息。贝叶斯优化算法通过对目标函数形 状进行学习,找到使目标函数向全局最优值提升的参数。 3.9 过拟合和欠拟合过拟合是指模型对于训练数据拟合呈过当的情况,反映到评估指标上,就是 模型在训练集上的表现很好,但在测试集和新数据上的表现较差。欠拟合指的是 模型在训练和预测时表现都不好的情况。下图形象地描述了过拟合和欠拟合的区别。 防止过拟合: 从数据入手,获得更多的训练数据。 降低模型复杂度。 正则化方法,给模型的参数加上一定的正则约束。 集成学习方法,集成学习是把多个模型集成在一起。 防止欠拟合: 添加新特征。 增加模型复杂度。 减小正则化系数。 4. 检验方法4.1 KS检验Kolmogorov-Smirnov检验是基于累计分布函数的,用于检验一个分布是否符合某种理论分布或比较两个经验分布是否有显著差异。 单样本K-S检验是用来检验一个数据的观测经验分布是否符合已知的理论分布。 两样本K-S检验由于对两样本的经验分布函数的位置和形状参数的差异都敏感,所以成为比较两样本的最有用且最常用的非参数方法之一。 检验统计量为:$D_r=max_x|F_n(x)-F(x)|$ 其中 $F_n(x)$为观察序列值,$F(x)$为理论序列值或另一观察序列值。 4.2 T检验T检验,也称student t检验,主要用户样本含量较小,总体标准差未知的正态分布。 t检验是用t分布理论来推论差异发生的概率,从而比较两个平均数的差异是否显著。 t检验分为单总体检验和双总体检验。 4.3 F检验T检验和F检验的由来:为了确定从样本中的统计结果推论到总体时所犯错的概率。F检验又叫做联合假设检验,也称方差比率检验、方差齐性检验。是由英国统计学家Fisher提出。通过比较两组数据的方差,以确定他们的精密度是否有显著性差异。 4.4 Grubbs检验一组测量数据中,如果个别数据偏离平均值很远,那么称这个数据为“可疑值”。用格拉布斯法判断,能将“可疑值”从测量数据中剔除。 4.5 卡方检验卡方检验就是统计样本的实际观测值与理论推断值之间的偏离程度,实际观测值与理论推断值之间的偏离程度就决定卡方值的大小,卡方值越大,越不符合;卡方值越小,偏差越小,越趋于符合,若两个值完全相等时,卡方值就为0,表明理论值完全符合。 提出原假设H0:总体X的分布函数F(x); 将总体x的取值范围分成k个互不相交的小区间A1-Ak; 把落入第i个区间Ai的样本的个数记做fi,成为组频数,f1+f2+f3+…+fk = n; 当H0为真时,根据假设的总体理论分布,可算出总体X的值落入第i个小区间Ai的概率pi,于是n*pi就是落入第i个小区间Ai的样本值的理论频数; 当H0为真时,n次试验中样本落入第i个小区间Ai的频率fi/n与概率pi应该很接近。基于这种思想,皮尔逊引入检测统计量: $$x^2=\\sum_{i=1}^{k}\\frac{(f_i-np_i)^2}{np_i}$$ 在H0假设成立的情况下服从自由度为k-1的卡方分布。 KS检验与卡方检验 相同点:都采用实际频数和期望频数只差进行检验 不同点: 卡方检验主要用于类别数据,而KS检验主要用于有计量单位的连续和定量数据。 卡方检验也可以用于定量数据,但必须先将数据分组才能获得实际的观测频数,而KS检验能直接对原始数据进行检验,所以它对数据的利用比较完整。 5. 常用分类算法的优缺点? 算法 优点 缺点 Bayes 贝叶斯分类法 1)所需估计的参数少,对于缺失数据不敏感。2)有着坚实的数学基础,以及稳定的分类效率。 1)需要假设属性之间相互独立,这往往并不成立。(喜欢吃番茄、鸡蛋,却不喜欢吃番茄炒蛋)。2)需要知道先验概率。3)分类决策存在错误率。 Decision Tree决策树 1)不需要任何领域知识或参数假设。2)适合高维数据。3)简单易于理解。4)短时间内处理大量数据,得到可行且效果较好的结果。5)能够同时处理数据型和常规性属性。 1)对于各类别样本数量不一致数据,信息增益偏向于那些具有更多数值的特征。2)易于过拟合。3)忽略属性之间的相关性。4)不支持在线学习。 SVM支持向量机 1)可以解决小样本下机器学习的问题。2)提高泛化性能。3)可以解决高维、非线性问题。超高维文本分类仍受欢迎。4)避免神经网络结构选择和局部极小的问题。 1)对缺失数据敏感。2)内存消耗大,难以解释。3)运行和调参略烦人。 KNN K近邻 1)思想简单,理论成熟,既可以用来做分类也可以用来做回归; 2)可用于非线性分类; 3)训练时间复杂度为O(n); 4)准确度高,对数据没有假设,对outlier不敏感; 1)计算量太大。2)对于样本分类不均衡的问题,会产生误判。3)需要大量的内存。4)输出的可解释性不强。 Logistic Regression逻辑回归 1)速度快。2)简单易于理解,直接看到各个特征的权重。3)能容易地更新模型吸收新的数据。4)如果想要一个概率框架,动态调整分类阀值。 特征处理复杂。需要归一化和较多的特征工程。 Neural Network 神经网络 1)分类准确率高。2)并行处理能力强。3)分布式存储和学习能力强。4)鲁棒性较强,不易受噪声影响。 1)需要大量参数(网络拓扑、阀值、阈值)。2)结果难以解释。3)训练时间过长。 Adaboosting 1)adaboost是一种有很高精度的分类器。2)可以使用各种方法构建子分类器,Adaboost算法提供的是框架。3)当使用简单分类器时,计算出的结果是可以理解的。而且弱分类器构造极其简单。4)简单,不用做特征筛选。5)不用担心overfitting。 对outlier比较敏感 6. 参考文献百面机器学习 7. 机器学习系列教程GitHub:https://github.com/NLP-LOVE/ML-NLP 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】聚类算法","slug":"ML/Clustering","date":"2019-07-24T16:00:00.000Z","updated":"2019-12-25T06:17:45.327Z","comments":true,"path":"2019/07/25/ML/Clustering/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/25/ML/Clustering/","excerpt":"聚类算法都是无监督学习吗? 什么是聚类算法?聚类是一种机器学习技术,它涉及到数据点的分组。给定一组数据点,我们可以使用聚类算法将每个数据点划分为一个特定的组。理论上,同一组中的数据点应该具有相似的属性和/或特征,而不同组中的数据点应该具有高度不同的属性和/或特征。聚类是一…","text":"聚类算法都是无监督学习吗? 什么是聚类算法?聚类是一种机器学习技术,它涉及到数据点的分组。给定一组数据点,我们可以使用聚类算法将每个数据点划分为一个特定的组。理论上,同一组中的数据点应该具有相似的属性和/或特征,而不同组中的数据点应该具有高度不同的属性和/或特征。聚类是一… 1. 聚类算法都是无监督学习吗?什么是聚类算法?聚类是一种机器学习技术,它涉及到数据点的分组。给定一组数据点,我们可以使用聚类算法将每个数据点划分为一个特定的组。理论上,同一组中的数据点应该具有相似的属性和/或特征,而不同组中的数据点应该具有高度不同的属性和/或特征。聚类是一种无监督学习的方法,是许多领域中常用的统计数据分析技术。 常用的算法包括K-MEANS、高斯混合模型(Gaussian Mixed Model,GMM)、自组织映射神经网络(Self-Organizing Map,SOM) 2. k-means(k均值)算法2.1 算法过程K-均值是最普及的聚类算法,算法接受一个未标记的数据集,然后将数据聚类成不同的组。 K-均值是一个迭代算法,假设我们想要将数据聚类成 n 个组,其方法为: 首先选择𝐾个随机的点,称为聚类中心(cluster centroids); 对于数据集中的每一个数据,按照距离𝐾个中心点的距离,将其与距离最近的中心点关联起来,与同一个中心点关联的所有点聚成一类。 计算每一个组的平均值,将该组所关联的中心点移动到平均值的位置。 重复步骤,直至中心点不再变化。 用 $u^1,u^2,…,u^k$ 来表示聚类中心,用𝑐(1),𝑐(2),…,𝑐(𝑚)来存储与第𝑖个实例数据最近的聚类中心的索引,K-均值算法的伪代码如下: 123456Repeat { for i = 1 to m c(i) := index (form 1 to K) of cluster centroid closest to x(i) for k = 1 to K μk := average (mean) of points assigned to cluster k} 算法分为两个步骤,第一个 for 循环是赋值步骤,即:对于每一个样例𝑖,计算其应该属于的类。第二个 for 循环是聚类中心的移动,即:对于每一个类𝐾,重新计算该类的质心。 K-均值算法也可以很便利地用于将数据分为许多不同组,即使在没有非常明显区分的组群的情况下也可以。下图所示的数据集包含身高和体重两项特征构成的,利用 K-均值算法将数据分为三类,用于帮助确定将要生产的 T-恤衫的三种尺寸。 2.2 损失函数K-均值最小化问题,是要最小化所有的数据点与其所关联的聚类中心点之间的距离之和,因此 K-均值的代价函数(又称畸变函数 Distortion function)为: $$J(c^{(1)},c^{(2)},…,c^{(m)},u_1,…,u_k)=\\frac{1}{m}\\sum_{i=1}^{m}||X^{(1)}-u_{c^{(i)}}||^2$$ 其中 $u_{c^{(i)}}$ 代表与 $x^{(i)}$ 最近的聚类中心点。 我们的的优化目标便是找出使得代价函数最小的 $c^{(1)},c^{(2)},…,c^{(m)}$ 和 $u_1,u_2,…,u_k$ 。 2.3 k值的选择在运行 K-均值算法的之前,我们首先要随机初始化所有的聚类中心点,下面介绍怎样做: 我们应该选择𝐾 < 𝑚,即聚类中心点的个数要小于所有训练集实例的数量。 随机选择𝐾个训练实例,然后令𝐾个聚类中心分别与这𝐾个训练实例相等K-均值的一个问题在于,它有可能会停留在一个局部最小值处,而这取决于初始化的情况。 为了解决这个问题,我们通常需要多次运行 K-均值算法,每一次都重新进行随机初始化,最后再比较多次运行 K-均值的结果,选择代价函数最小的结果。这种方法在𝐾较小的时候(2–10)还是可行的,但是如果𝐾较大,这么做也可能不会有明显地改善。 没有所谓最好的选择聚类数的方法,通常是需要根据不同的问题,人工进行选择的。选择的时候思考我们运用 K-均值算法聚类的动机是什么。有一个可能会谈及的方法叫作“肘部法则”。关 于“肘部法则”,我们所需要做的是改变𝐾值,也就是聚类类别数目的总数。我们用一个聚类来运行 K 均值聚类方法。这就意味着,所有的数据都会分到一个聚类里,然后计算成本函数或者计算畸变函数𝐽。𝐾代表聚类数字。 我们可能会得到一条类似于这样的曲线。像一个人的肘部。这就是“肘部法则”所做的,让我们来看这样一个图,看起来就好像有一个很清楚的肘在那儿。你会发现这种模式,它的畸变值会迅速下降,从 1 到 2,从 2 到 3 之后,你会在 3 的时候达到一个肘点。在此之后,畸变值就下降的非常慢,看起来就像使用 3 个聚类来进行聚类是正确的,这是因为那个点是曲线的肘点,畸变值下降得很快,𝐾 = 3之后就下降得很慢,那么我们就选𝐾 = 3。当你应用“肘部法则”的时候,如果你得到了一个像上面这样的图,那么这将是一种用来选择聚类个数的合理方法。 2.4 KNN与K-means区别?K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。 KNN K-Means 1.KNN是分类算法2.属于监督学习3.训练数据集是带label的数据 1.K-Means是聚类算法2.属于非监督学习3.训练数据集是无label的数据,是杂乱无章的,经过聚类后变得有序,先无序,后有序。 没有明显的前期训练过程,属于memory based learning 有明显的前期训练过程 K的含义:一个样本x,对它进行分类,就从训练数据集中,在x附近找离它最近的K个数据点,这K个数据点,类别c占的个数最多,就把x的label设为c。 K的含义:K是人工固定好的数字,假设数据集合可以分为K个蔟,那么就利用训练数据来训练出这K个分类。 相似点 都包含这样的过程,给定一个点,在数据集中找离它最近的点。即二者都用到了NN(Nears Neighbor)算法思想。 2.5 K-Means优缺点及改进k-means:在大数据的条件下,会耗费大量的时间和内存。 优化k-means的建议: 减少聚类的数目K。因为,每个样本都要跟类中心计算距离。 减少样本的特征维度。比如说,通过PCA等进行降维。 考察其他的聚类算法,通过选取toy数据,去测试不同聚类算法的性能。 hadoop集群,K-means算法是很容易进行并行计算的。 算法可能找到局部最优的聚类,而不是全局最优的聚类。使用改进的二分k-means算法。 二分k-means算法:首先将整个数据集看成一个簇,然后进行一次k-means(k=2)算法将该簇一分为二,并计算每个簇的误差平方和,选择平方和最大的簇迭代上述过程再次一分为二,直至簇数达到用户指定的k为止,此时可以达到的全局最优。 3. 高斯混合模型(GMM)3.1 GMM的思想高斯混合模型(Gaussian Mixed Model,GMM)也是一种常见的聚类算法,与K均值算法类似,同样使用了EM算法进行迭代计算。高斯混合模型假设每个簇的数据都是符合高斯分布(又叫正态分布)的,当前数据呈现的分布就是各个簇的高斯分布叠加在一起的结果。 第一张图是一个数据分布的样例,如果只用一个高斯分布来拟合图中的数据,图 中所示的椭圆即为高斯分布的二倍标准差所对应的椭圆。直观来说,图中的数据 明显分为两簇,因此只用一个高斯分布来拟和是不太合理的,需要推广到用多个 高斯分布的叠加来对数据进行拟合。第二张图是用两个高斯分布的叠加来拟合得到的结果。这就引出了高斯混合模型,即用多个高斯分布函数的线形组合来对数据分布进行拟合。理论上,高斯混合模型可以拟合出任意类型的分布。 高斯混合模型的核心思想是,假设数据可以看作从多个高斯分布中生成出来 的。在该假设下,每个单独的分模型都是标准高斯模型,其均值 $u_i$ 和方差 $\\sum_i$ 是待估计的参数。此外,每个分模型都还有一个参数 $\\pi_i$,可以理解为权重或生成数据的概 率。高斯混合模型的公式为: $$p(x)=\\sum_{i=1}^{k}\\pi_iN(x|u_i,\\sum_i)$$ 通常我们并不能直接得到高斯混合模型的参数,而是观察到了一系列 数据点,给出一个类别的数量K后,希望求得最佳的K个高斯分模型。因此,高斯 混合模型的计算,便成了最佳的均值μ,方差Σ、权重π的寻找,这类问题通常通过 最大似然估计来求解。遗憾的是,此问题中直接使用最大似然估计,得到的是一 个复杂的非凸函数,目标函数是和的对数,难以展开和对其求偏导。 *在这种情况下,可以用EM算法。 *EM算法是在最大化目标函数时,先固定一个变量使整体函数变为凸优化函数,求导得到最值,然后利用最优参数更新被固定的变量,进入下一个循环。具体到高 斯混合模型的求解,EM算法的迭代过程如下。 首先,初始随机选择各参数的值。然后,重复下述两步,直到收敛。 E步骤。根据当前的参数,计算每个点由某个分模型生成的概率。 M步骤。使用E步骤估计出的概率,来改进每个分模型的均值,方差和权重。 高斯混合模型是一个生成式模型。可以这样理解数据的生成过程,假设一个最简单的情况,即只有两个一维标准高斯分布的分模型N(0,1)和N(5,1),其权重分别为0.7和0.3。那么,在生成第一个数据点时,先按照权重的比例,随机选择一个分布,比如选择第一个高斯分布,接着从N(0,1)中生成一个点,如−0.5,便是第一个数据点。在生成第二个数据点时,随机选择到第二个高斯分布N(5,1),生成了第二个点4.7。如此循环执行,便生成出了所有的数据点。 也就是说,我们并不知道最佳的K个高斯分布的各自3个参数,也不知道每个 数据点究竟是哪个高斯分布生成的。所以每次循环时,先固定当前的高斯分布不 变,获得每个数据点由各个高斯分布生成的概率。然后固定该生成概率不变,根据数据点和生成概率,获得一个组更佳的高斯分布。循环往复,直到参数的不再变化,或者变化非常小时,便得到了比较合理的一组高斯分布。 3.2 GMM与K-Means相比高斯混合模型与K均值算法的相同点是: 它们都是可用于聚类的算法; 都需要 指定K值; 都是使用EM算法来求解; 都往往只能收敛于局部最优。 而它相比于K 均值算法的优点是,可以给出一个样本属于某类的概率是多少;不仅仅可以用于聚类,还可以用于概率密度的估计;并且可以用于生成新的样本点。 4. 聚类算法如何评估由于数据以及需求的多样性,没有一种算法能够适用于所有的数据类型、数 据簇或应用场景,似乎每种情况都可能需要一种不同的评估方法或度量标准。例 如,K均值聚类可以用误差平方和来评估,但是基于密度的数据簇可能不是球形, 误差平方和则会失效。在许多情况下,判断聚类算法结果的好坏强烈依赖于主观 解释。尽管如此,聚类算法的评估还是必需的,它是聚类分析中十分重要的部分之一。 聚类评估的任务是估计在数据集上进行聚类的可行性,以及聚类方法产生结 果的质量。这一过程又分为三个子任务。 估计聚类趋势。 这一步骤是检测数据分布中是否存在非随机的簇结构。如果数据是基本随机 的,那么聚类的结果也是毫无意义的。我们可以观察聚类误差是否随聚类类别数 量的增加而单调变化,如果数据是基本随机的,即不存在非随机簇结构,那么聚 类误差随聚类类别数量增加而变化的幅度应该较不显著,并且也找不到一个合适 的K对应数据的真实簇数。 判定数据簇数。 确定聚类趋势之后,我们需要找到与真实数据分布最为吻合的簇数,据此判定聚类结果的质量。数据簇数的判定方法有很多,例如手肘法和Gap Statistic方 法。需要说明的是,用于评估的最佳数据簇数可能与程序输出的簇数是不同的。 例如,有些聚类算法可以自动地确定数据的簇数,但可能与我们通过其他方法确 定的最优数据簇数有所差别。 测定聚类质量。 在无监督的情况下,我们可以通过考察簇的分离情况和簇的紧 凑情况来评估聚类的效果。定义评估指标可以展现面试者实际解决和分析问题的 能力。事实上测量指标可以有很多种,以下列出了几种常用的度量指标,更多的 指标可以阅读相关文献。 轮廓系数、均方根标准偏差、R方(R-Square)、改进的HubertΓ统计。 5. 代码实现高斯混合模型代码 K-Means代码 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】EM算法","slug":"ML/EM","date":"2019-07-20T16:00:00.000Z","updated":"2019-12-25T05:40:45.778Z","comments":true,"path":"2019/07/21/ML/EM/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/21/ML/EM/","excerpt":"最大期望算法(Expectation-maximization algorithm,又译为期望最大化算法),是在概率模型中寻找参数最大似然估计或者最大后验估计的算法,其中概率模型依赖于无法观测的隐性变量。 最大期望算法经过两个步骤交替进行计算, 第一步是计算期望(E),利用对隐藏变量的现有估计值,…","text":"最大期望算法(Expectation-maximization algorithm,又译为期望最大化算法),是在概率模型中寻找参数最大似然估计或者最大后验估计的算法,其中概率模型依赖于无法观测的隐性变量。 最大期望算法经过两个步骤交替进行计算, 第一步是计算期望(E),利用对隐藏变量的现有估计值,… 1. 什么是EM算法最大期望算法(Expectation-maximization algorithm,又译为期望最大化算法),是在概率模型中寻找参数最大似然估计或者最大后验估计的算法,其中概率模型依赖于无法观测的隐性变量。 最大期望算法经过两个步骤交替进行计算, 第一步是计算期望(E),利用对隐藏变量的现有估计值,计算其最大似然估计值;第二步是最大化(M),最大化在E步上求得的最大似然值来计算参数的值。M步上找到的参数估计值被用于下一个E步计算中,这个过程不断交替进行。 极大似然估计用一句话概括就是:知道结果,反推条件θ。 1.1 似然函数在数理统计学中,似然函数是一种关于统计模型中的参数的函数,表示模型参数中的似然性。“似然性”与“或然性”或“概率”意思相近,都是指某种事件发生的可能性。而极大似然就相当于最大可能的意思。 比如你一位同学和一位猎人一起外出打猎,一只野兔从前方窜过。只听一声枪响,野兔应声到下,如果要你推测,这一发命中的子弹是谁打的?你就会想,只发一枪便打中,由于猎人命中的概率一般大于你那位同学命中的概率,从而推断出这一枪应该是猎人射中的。 这个例子所作的推断就体现了最大似然法的基本思想。 多数情况下我们是根据已知条件来推算结果,而最大似然估计是已经知道了结果,然后寻求使该结果出现的可能性最大的条件,以此作为估计值。 1.3 极大似然函数的求解步骤假定我们要从10万个人当中抽取100个人来做身高统计,那么抽到这100个人的概率就是(概率连乘): $$L(\\theta)=L(x_1,…,x_n|\\theta)=\\prod_{i=1}^{n}p(x_i|\\theta),\\theta\\in\\ominus$$ 现在要求的就是这个 $\\theta$ 值,也就是使得 $L(\\theta)$ 的概率最大化,那么这时的参数 $\\theta$ 就是所求。 为了便于分析,我们可以定义对数似然函数,将其变成连加的形式: $$H(\\theta)=lnL(\\theta)=ln\\prod_{i=1}^{n}p(x_i|\\theta)=\\sum_{i=1}^{n}lnp(x_i|\\theta)$$ 对于求一个函数的极值,通过我们在本科所学的微积分知识,最直接的设想是求导,然后让导数为0,那么解这个方程得到的θ就是了(当然,前提是函数L(θ)连续可微)。但,如果θ是包含多个参数的向量那怎么处理呢?当然是求L(θ)对所有参数的偏导数,也就是梯度了,从而n个未知的参数,就有n个方程,方程组的解就是似然函数的极值点了,最终得到这n个参数的值。 求极大似然函数估计值的一般步骤: 写出似然函数; 对似然函数取对数,并整理; 求导数,令导数为0,得到似然方程; 解似然方程,得到的参数即为所求; 1.4 EM算法两枚硬币A和B,假定随机抛掷后正面朝上概率分别为PA,PB。为了估计这两个硬币朝上的概率,咱们轮流抛硬币A和B,每一轮都连续抛5次,总共5轮: 硬币 结果 统计 A 正正反正反 3正-2反 B 反反正正反 2正-3反 A 正反反反反 1正-4反 B 正反反正正 3正-2反 A 反正正反反 2正-3反 硬币A被抛了15次,在第一轮、第三轮、第五轮分别出现了3次正、1次正、2次正,所以很容易估计出PA,类似的,PB也很容易计算出来(真实值),如下: PA = (3+1+2)/ 15 = 0.4PB= (2+3)/10 = 0.5 问题来了,如果我们不知道抛的硬币是A还是B呢(即硬币种类是隐变量),然后再轮流抛五轮,得到如下结果: 硬币 结果 统计 Unknown 正正反正反 3正-2反 Unknown 反反正正反 2正-3反 Unknown 正反反反反 1正-4反 Unknown 正反反正正 3正-2反 Unknown 反正正反反 2正-3反 OK,问题变得有意思了。现在我们的目标没变,还是估计PA和PB,需要怎么做呢? 显然,此时我们多了一个硬币种类的隐变量,设为z,可以把它认为是一个5维的向量(z1,z2,z3,z4,z5),代表每次投掷时所使用的硬币,比如z1,就代表第一轮投掷时使用的硬币是A还是B。 但是,这个变量z不知道,就无法去估计PA和PB,所以,我们必须先估计出z,然后才能进一步估计PA和PB。 可要估计z,我们又得知道PA和PB,这样我们才能用极大似然概率法则去估计z,这不是鸡生蛋和蛋生鸡的问题吗,如何破? 答案就是先随机初始化一个PA和PB,用它来估计z,然后基于z,还是按照最大似然概率法则去估计新的PA和PB,然后依次循环,如果新估计出来的PA和PB和我们真实值差别很大,直到PA和PB收敛到真实值为止。 我们不妨这样,先随便给PA和PB赋一个值,比如:硬币A正面朝上的概率PA = 0.2硬币B正面朝上的概率PB = 0.7 然后,我们看看第一轮抛掷最可能是哪个硬币。如果是硬币A,得出3正2反的概率为 0.20.20.20.80.8 = 0.00512如果是硬币B,得出3正2反的概率为0.70.70.70.30.3=0.03087然后依次求出其他4轮中的相应概率。做成表格如下: 轮数 若是硬币A 若是硬币B 1 0.00512,即0.2 0.2 0.2 0.8 0.8,3正-2反 0.03087,3正-2反 2 0.02048,即0.2 0.2 0.8 0.8 0.8,2正-3反 0.01323,2正-3反 3 0.08192,即0.2 0.8 0.8 0.8 0.8,1正-4反 0.00567,1正-4反 4 0.00512,即0.2 0.2 0.2 0.8 0.8,3正-2反 0.03087,3正-2反 5 0.02048,即0.2 0.2 0.8 0.8 0.8,2正-3反 0.01323,2正-3反 按照最大似然法则:第1轮中最有可能的是硬币B第2轮中最有可能的是硬币A第3轮中最有可能的是硬币A第4轮中最有可能的是硬币B第5轮中最有可能的是硬币A 我们就把概率更大,即更可能是A的,即第2轮、第3轮、第5轮出现正的次数2、1、2相加,除以A被抛的总次数15(A抛了三轮,每轮5次),作为z的估计值,B的计算方法类似。然后我们便可以按照最大似然概率法则来估计新的PA和PB。 PA = (2+1+2)/15 = 0.33PB =(3+3)/10 = 0.6 就这样,不断迭代 不断接近真实值,这就是EM算法的奇妙之处。 可以期待,我们继续按照上面的思路,用估计出的PA和PB再来估计z,再用z来估计新的PA和PB,反复迭代下去,就可以最终得到PA = 0.4,PB=0.5,此时无论怎样迭代,PA和PB的值都会保持0.4和0.5不变,于是乎,我们就找到了PA和PB的最大似然估计。 总结一下计算步骤: 随机初始化分布参数θ E步,求Q函数,对于每一个i,计算根据上一次迭代的模型参数来计算出隐性变量的后验概率(其实就是隐性变量的期望),来作为隐藏变量的现估计值: $$Q_i(z^{(i)})=p(z^{(i)}|x^{(i)};\\theta)$$ M步,求使Q函数获得极大时的参数取值)将似然函数最大化以获得新的参数值 $$\\theta=argmax\\sum_{i}\\sum_{z^{(i)}}Q_i(z^{(i)})log\\frac{p(x^{(i)},z^{(i)};\\theta)}{Q_i(z^{(i)})}$$ 然后循环重复2、3步直到收敛。 详细的推导过程请参考文末的参考文献。 2. 采用 EM 算法求解的模型有哪些?用EM算法求解的模型一般有GMM或者协同过滤,k-means其实也属于EM。EM算法一定会收敛,但是可能收敛到局部最优。由于求和的项数将随着隐变量的数目指数上升,会给梯度计算带来麻烦。 3.代码实现高斯混合模型 EM 算法 4. 参考文献如何通俗理解EM算法 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】马尔可夫模型","slug":"ML/Markov","date":"2019-07-16T16:00:00.000Z","updated":"2019-12-25T06:17:58.257Z","comments":true,"path":"2019/07/17/ML/Markov/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/17/ML/Markov/","excerpt":"马尔可夫网络、马尔可夫模型、马尔可夫过程、贝叶斯网络的区别 这一节我们重点来讲一下马尔可夫,正如题目所示,看了会一脸蒙蔽,好在我们会一点一点的来解释上面的概念,请大家按照顺序往下看就会完全弄明白了,这里我给一个通俗易懂的定义,后面我们再来一个个详解。 以下共分六点说明这些…","text":"马尔可夫网络、马尔可夫模型、马尔可夫过程、贝叶斯网络的区别 这一节我们重点来讲一下马尔可夫,正如题目所示,看了会一脸蒙蔽,好在我们会一点一点的来解释上面的概念,请大家按照顺序往下看就会完全弄明白了,这里我给一个通俗易懂的定义,后面我们再来一个个详解。 以下共分六点说明这些… 1. 马尔可夫网络、马尔可夫模型、马尔可夫过程、贝叶斯网络的区别相信大家都看过上一节我讲得贝叶斯网络,都明白了概率图模型是怎样构造的,如果现在还没明白,请看我上一节的总结:贝叶斯网络 这一节我们重点来讲一下马尔可夫,正如题目所示,看了会一脸蒙蔽,好在我们会一点一点的来解释上面的概念,请大家按照顺序往下看就会完全弄明白了,这里我给一个通俗易懂的定义,后面我们再来一个个详解。 以下共分六点说明这些概念,分成条目只是方便边阅读边思考,这6点是依次递进的,不要跳跃着看。 将随机变量作为结点,若两个随机变量相关或者不独立,则将二者连接一条边;若给定若干随机变量,则形成一个有向图,即构成一个网络。 如果该网络是有向无环图,则这个网络称为贝叶斯网络。 如果这个图退化成线性链的方式,则得到马尔可夫模型;因为每个结点都是随机变量,将其看成各个时刻(或空间)的相关变化,以随机过程的视角,则可以看成是马尔可夫过程。 若上述网络是无向的,则是无向图模型,又称马尔可夫随机场或者马尔可夫网络。 如果在给定某些条件的前提下,研究这个马尔可夫随机场,则得到条件随机场。 如果使用条件随机场解决标注问题,并且进一步将条件随机场中的网络拓扑变成线性的,则得到线性链条件随机场。 2. 马尔可夫模型2.1 马尔可夫过程马尔可夫过程(Markov process)是一类随机过程。它的原始模型马尔可夫链,由俄国数学家A.A.马尔可夫于1907年提出。该过程具有如下特性:在已知目前状态(现在)的条件下,它未来的演变(将来)不依赖于它以往的演变 (过去 )。例如森林中动物头数的变化构成——马尔可夫过程。在现实世界中,有很多过程都是马尔可夫过程,如液体中微粒所作的布朗运动、传染病受感染的人数、车站的候车人数等,都可视为马尔可夫过程。 每个状态的转移只依赖于之前的n个状态,这个过程被称为1个n阶的模型,其中n是影响转移状态的数目。最简单的马尔可夫过程就是一阶过程,每一个状态的转移只依赖于其之前的那一个状态,这个也叫作马尔可夫性质。用数学表达式表示就是下面的样子: 假设这个模型的每个状态都只依赖于之前的状态,这个假设被称为马尔科夫假设,这个假设可以大大的简化这个问题。显然,这个假设可能是一个非常糟糕的假设,导致很多重要的信息都丢失了。 $$P(X_{n+1}|X_1=x_1,X_2=x_2,…,X_n=x_n)=P(X_{n+1}=x|X_n=x_n)$$ 假设天气服从马尔可夫链: 从上面这幅图可以看出: 假如今天是晴天,明天变成阴天的概率是0.1 假如今天是晴天,明天任然是晴天的概率是0.9,和上一条概率之和为1,这也符合真实生活的情况。 晴 阴 晴 0.9 0,1 阴 0.5 0.5 由上表我们可以得到马尔可夫链的状态转移矩阵: 因此,一阶马尔可夫过程定义了以下三个部分: 状态:晴天和阴天 初始向量:定义系统在时间为0的时候的状态的概率 状态转移矩阵:每种天气转换的概率 马尔可夫模型(Markov Model)是一种统计模型,广泛应用在语音识别,词性自动标注,音字转换,概率文法等各个自然语言处理等应用领域。经过长期发展,尤其是在语音识别中的成功应用,使它成为一种通用的统计工具。到目前为止,它一直被认为是实现快速精确的语音识别系统的最成功的方法。 3. 隐马尔可夫模型(HMM)在某些情况下马尔科夫过程不足以描述我们希望发现的模式。回到之前那个天气的例子,一个隐居的人可能不能直观的观察到天气的情况,但是有一些海藻。民间的传说告诉我们海藻的状态在某种概率上是和天气的情况相关的。在这种情况下我们有两个状态集合,一个可以观察到的状态集合(海藻的状态)和一个隐藏的状态(天气的状况)。我们希望能找到一个算法可以根据海藻的状况和马尔科夫假设来预测天气的状况。 而这个算法就叫做隐马尔可夫模型(HMM)。 隐马尔可夫模型 (Hidden Markov Model) 是一种统计模型,用来描述一个含有隐含未知参数的马尔可夫过程。它是结构最简单的动态贝叶斯网,这是一种著名的有向图模型,主要用于时序数据建模,在语音识别、自然语言处理等领域有广泛应用。 3.1 隐马尔可夫三大问题 给定模型,如何有效计算产生观测序列的概率?换言之,如何评估模型与观测序列之间的匹配程度? 给定模型和观测序列,如何找到与此观测序列最匹配的状态序列?换言之,如何根据观测序列推断出隐藏的模型状态? 给定观测序列,如何调整模型参数使得该序列出现的概率最大?换言之,如何训练模型使其能最好地描述观测数据? 前两个问题是模式识别的问题:1) 根据隐马尔科夫模型得到一个可观察状态序列的概率(评价);2) 找到一个隐藏状态的序列使得这个序列产生一个可观察状态序列的概率最大(解码)。第三个问题就是根据一个可以观察到的状态序列集产生一个隐马尔科夫模型(学习)。 对应的三大问题解法: 向前算法(Forward Algorithm)、向后算法(Backward Algorithm) 维特比算法(Viterbi Algorithm) 鲍姆-韦尔奇算法(Baum-Welch Algorithm) (约等于EM算法) 下面我们以一个场景来说明这些问题的解法到底是什么? 小明现在有三天的假期,他为了打发时间,可以在每一天中选择三件事情来做,这三件事情分别是散步、购物、打扫卫生(对应着可观测序列),可是在生活中我们所做的决定一般都受到天气的影响,可能晴天的时候想要去购物或者散步,可能下雨天的时候不想出门,留在家里打扫卫生。而天气(晴天、下雨天)就属于隐藏状态,用一幅概率图来表示这一马尔可夫过程: 那么,我们提出三个问题,分别对应马尔可夫的三大问题: 已知整个模型,我观测到连续三天做的事情是:散步,购物,收拾。那么,根据模型,计算产生这些行为的概率是多少。 同样知晓这个模型,同样是这三件事,我想猜,这三天的天气是怎么样的。 最复杂的,我只知道这三天做了这三件事儿,而其他什么信息都没有。我得建立一个模型,晴雨转换概率,第一天天气情况的概率分布,根据天气情况选择做某事的概率分布。 下面我们就依据这个场景来一一解答这些问题。 3.1.1 第一个问题解法遍历算法: 这个是最简单的算法了,假设第一天(T=1 时刻)是晴天,想要购物,那么就把图上的对应概率相乘就能够得到了。 第二天(T=2 时刻)要做的事情,在第一天的概率基础上乘上第二天的概率,依次类推,最终得到这三天(T=3 时刻)所要做的事情的概率值,这就是遍历算法,简单而又粗暴。但问题是用遍历算法的复杂度会随着观测序列和隐藏状态的增加而成指数级增长。 复杂度为:$2TN^T$ 于是就有了第二种算法 前向算法: 假设第一天要购物,那么就计算出第一天购物的概率(包括晴天和雨天);假设第一天要散步,那么也计算出来,依次枚举。 假设前两天是购物和散步,也同样计算出这一种的概率;假设前两天是散步和打扫卫生,同样计算,枚举出前两天行为的概率。 第三步就是计算出前三天行为的概率。 细心的读者已经发现了,第二步中要求的概率可以在第一步的基础上进行,同样的,第三步也会依赖于第二步的计算结果。那么这样做就能够节省很多计算环节,类似于动态规划。 这种算法的复杂度为:$N^2T$ 后向算法 跟前向算法相反,我们知道总的概率肯定是1,那么B_t=1,也就是最后一个时刻的概率合为1,先计算前三天的各种可能的概率,在计算前两天、前一天的数据,跟前向算法相反的计算路径。 3.1.2 第二个问题解法维特比算法(Viterbi) 说起安德鲁·维特比(Andrew Viterbi),通信行业之外的人可能知道他的并不多,不过通信行业的从业者大多知道以他的名字命名的维特比算法(ViterbiAlgorithm)。维特比算法是现代数字通信中最常用的算法,同时也是很多自然语言处理采用的解码算法。可以毫不夸张地讲,维特比是对我们今天的生活影响力最大的科学家之一,因为基于CDMA的3G移动通信标准主要就是他和厄文·雅各布(Irwin Mark Jacobs)创办的高通公司(Qualcomm)制定的,并且高通公司在4G时代依然引领移动通信的发展。 维特比算法是一个特殊但应用最广的动态规划算法。利用动态规划,可以解决任何一个图中的最短路径问题。而维特比算法是针对一个特殊的图—篱笆网络(Lattice)的有向图最短路径问题而提出的。它之所以重要,是因为凡是使用隐含马尔可夫模型描述的问题都可以用它来解码,包括今天的数字通信、语音识别、机器翻译、拼音转汉字、分词等。 维特比算法一般用于模式识别,通过观测数据来反推出隐藏状态,下面一步步讲解这个算法。 因为是要根据观测数据来反推,所以这里要进行一个假设,假设这三天所做的行为分别是:散步、购物、打扫卫生,那么我们要求的是这三天的天气(路径)分别是什么。 初始计算第一天下雨和第一天晴天去散步的概率值: $\\bigtriangleup_1(R)$ 表示第一天下雨的概率 $\\pi_R$ 表示中间的状态(下雨)s概率 $b_R(O_1=w)$ 表示下雨并且散步的概率 $a_{R-R}$ 表示下雨天到下雨天的概率 $\\bigtriangleup_1(R)=\\pi_Rb_R(O_1=w)=0.60.1=0.06$ $\\bigtriangleup_1(S)=\\pi_Sb_S(O_1=w)=0.40.6=0.24$ 初始路径为: $\\phi_1(R)=Rainy$ $\\phi_1(S)=Sunny$ 计算第二天下雨和第二天晴天去购物的概率值: 对应路径为: 计算第三天下雨和第三天晴天去打扫卫生的概率值: 对应路径为: 比较每一步中 $\\bigtriangleup$ 的概率大小,选取最大值并找到对应的路径,依次类推就能找到最有可能的隐藏状态路径。 第一天的概率最大值为 $\\bigtriangleup_1S$,对应路径为Sunny, 第二天的概率最大值为 $\\bigtriangleup_2S$,对应路径为Sunny, 第三天的概率最大值为 $\\bigtriangleup_3R$,对应路径为Rainy。 合起来的路径就是Sunny->Sunny->Rainy,这就是我们所求。 以上是比较通俗易懂的维特比算法,如果需要严谨表述,可以查看《数学之美》这本书的第26章,讲的就是维特比算法,很详细。附:《数学之美》下载地址,点击下载 3.1.3 第三个问题解法鲍姆-韦尔奇算法(Baum-Welch Algorithm) (约等于EM算法),详细讲解请见:监督学习方法与Baum-Welch算法 4. 马尔可夫网络4.1 因子图wikipedia上是这样定义因子图的:将一个具有多变量的全局函数因子分解,得到几个局部函数的乘积,以此为基础得到的一个双向图叫做因子图(Factor Graph)。 通俗来讲,所谓因子图就是对函数进行因子分解得到的一种概率图。一般内含两种节点:变量节点和函数节点。我们知道,一个全局函数通过因式分解能够分解为多个局部函数的乘积,这些局部函数和对应的变量关系就体现在因子图上。 举个例子,现在有一个全局函数,其因式分解方程为: $$g(x_1,x_2,x_3,x_4,x_5)=f_A(x_1)f_B(x_2)f_C(x1,x2,x3)f_D(x_3,x_4)f_E(x_3,x_5)$$ 其中fA,fB,fC,fD,fE为各函数,表示变量之间的关系,可以是条件概率也可以是其他关系。其对应的因子图为: 4.2 马尔可夫网络我们已经知道,有向图模型,又称作贝叶斯网络,但在有些情况下,强制对某些结点之间的边增加方向是不合适的。使用没有方向的无向边,形成了无向图模型(Undirected Graphical Model,UGM), 又被称为马尔可夫随机场或者马尔可夫网络(Markov Random Field, MRF or Markov network)。 设X=(X1,X2…Xn)和Y=(Y1,Y2…Ym)都是联合随机变量,若随机变量Y构成一个无向图 G=(V,E)表示的马尔可夫随机场(MRF),则条件概率分布P(Y|X)称为条件随机场(Conditional Random Field, 简称CRF,后续新的博客中可能会阐述CRF)。如下图所示,便是一个线性链条件随机场的无向图模型: 在概率图中,求某个变量的边缘分布是常见的问题。这问题有很多求解方法,其中之一就是把贝叶斯网络或马尔可夫随机场转换成因子图,然后用sum-product算法求解。换言之,基于因子图可以用sum-product 算法高效的求各个变量的边缘分布。 详细的sum-product算法过程,请查看博文:从贝叶斯方法谈到贝叶斯网络 5. 条件随机场(CRF)一个通俗的例子 假设你有许多小明同学一天内不同时段的照片,从小明提裤子起床到脱裤子睡觉各个时间段都有(小明是照片控!)。现在的任务是对这些照片进行分类。比如有的照片是吃饭,那就给它打上吃饭的标签;有的照片是跑步时拍的,那就打上跑步的标签;有的照片是开会时拍的,那就打上开会的标签。问题来了,你准备怎么干? 一个简单直观的办法就是,不管这些照片之间的时间顺序,想办法训练出一个多元分类器。就是用一些打好标签的照片作为训练数据,训练出一个模型,直接根据照片的特征来分类。例如,如果照片是早上6:00拍的,且画面是黑暗的,那就给它打上睡觉的标签;如果照片上有车,那就给它打上开车的标签。 乍一看可以!但实际上,由于我们忽略了这些照片之间的时间顺序这一重要信息,我们的分类器会有缺陷的。举个例子,假如有一张小明闭着嘴的照片,怎么分类?显然难以直接判断,需要参考闭嘴之前的照片,如果之前的照片显示小明在吃饭,那这个闭嘴的照片很可能是小明在咀嚼食物准备下咽,可以给它打上吃饭的标签;如果之前的照片显示小明在唱歌,那这个闭嘴的照片很可能是小明唱歌瞬间的抓拍,可以给它打上唱歌的标签。 所以,为了让我们的分类器能够有更好的表现,在为一张照片分类时,我们必须将与它相邻的照片的标签信息考虑进来。这——就是条件随机场(CRF)大显身手的地方!这就有点类似于词性标注了,只不过把照片换成了句子而已,本质上是一样的。 如同马尔可夫随机场,条件随机场为具有无向的图模型,图中的顶点代表随机变量,顶点间的连线代表随机变量间的相依关系,在条件随机场中,随机变量Y 的分布为条件机率,给定的观察值则为随机变量 X。下图就是一个线性链条件随机场。 条件概率分布P(Y|X)称为条件随机场。 6. EM算法、HMM、CRF的比较 EM算法是用于含有隐变量模型的极大似然估计或者极大后验估计,有两步组成:E步,求期望(expectation);M步,求极大(maxmization)。本质上EM算法还是一个迭代算法,通过不断用上一代参数对隐变量的估计来对当前变量进行计算,直到收敛。注意:EM算法是对初值敏感的,而且EM是不断求解下界的极大化逼近求解对数似然函数的极大化的算法,也就是说EM算法不能保证找到全局最优值。对于EM的导出方法也应该掌握。 隐马尔可夫模型是用于标注问题的生成模型。有几个参数(π,A,B):初始状态概率向量π,状态转移矩阵A,观测概率矩阵B。称为马尔科夫模型的三要素。马尔科夫三个基本问题: 概率计算问题:给定模型和观测序列,计算模型下观测序列输出的概率。–》前向后向算法 学习问题:已知观测序列,估计模型参数,即用极大似然估计来估计参数。–》Baum-Welch(也就是EM算法)和极大似然估计。 预测问题:已知模型和观测序列,求解对应的状态序列。–》近似算法(贪心算法)和维比特算法(动态规划求最优路径) 条件随机场CRF,给定一组输入随机变量的条件下另一组输出随机变量的条件概率分布密度。条件随机场假设输出变量构成马尔科夫随机场,而我们平时看到的大多是线性链条随机场,也就是由输入对输出进行预测的判别模型。求解方法为极大似然估计或正则化的极大似然估计。 之所以总把HMM和CRF进行比较,主要是因为CRF和HMM都利用了图的知识,但是CRF利用的是马尔科夫随机场(无向图),而HMM的基础是贝叶斯网络(有向图)。而且CRF也有:概率计算问题、学习问题和预测问题。大致计算方法和HMM类似,只不过不需要EM算法进行学习问题。 HMM和CRF对比:其根本还是在于基本的理念不同,一个是生成模型,一个是判别模型,这也就导致了求解方式的不同。 7. 参考文献 条件随机场的简单理解 如何轻松愉快地理解条件随机场(CRF) 《数学之美》 监督学习方法与Baum-Welch算法 从贝叶斯方法谈到贝叶斯网络 8. 词性标注代码实现HMM词性标注,GitHub:点击进入 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】贝叶斯网络","slug":"ML/Bayes Network","date":"2019-07-12T16:00:00.000Z","updated":"2019-12-25T09:59:12.874Z","comments":true,"path":"2019/07/13/ML/Bayes Network/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/13/ML/Bayes%20Network/","excerpt":"概率图模型是用图来表示变量概率依赖关系的理论,结合概率论与图论的知识,利用图来表示与模型有关的变量的联合概率分布。由图灵奖获得者Pearl开发出来。 如果用一个词来形容概率图模型(Probabilistic Graphical Model)的话,那就是“优雅”。对于一个实际问题,我们希望能够挖掘隐…","text":"概率图模型是用图来表示变量概率依赖关系的理论,结合概率论与图论的知识,利用图来表示与模型有关的变量的联合概率分布。由图灵奖获得者Pearl开发出来。 如果用一个词来形容概率图模型(Probabilistic Graphical Model)的话,那就是“优雅”。对于一个实际问题,我们希望能够挖掘隐… 1. 对概率图模型的理解概率图模型是用图来表示变量概率依赖关系的理论,结合概率论与图论的知识,利用图来表示与模型有关的变量的联合概率分布。由图灵奖获得者Pearl开发出来。 如果用一个词来形容概率图模型(Probabilistic Graphical Model)的话,那就是“优雅”。对于一个实际问题,我们希望能够挖掘隐含在数据中的知识。概率图模型构建了这样一幅图,用观测结点表示观测到的数据,用隐含结点表示潜在的知识,用边来描述知识与数据的相互关系,最后基于这样的关系图获得一个概率分布,非常“优雅”地解决了问题。 概率图中的节点分为隐含节点和观测节点,边分为有向边和无向边。从概率论的角度,节点对应于随机变量,边对应于随机变量的依赖或相关关系,其中有向边表示单向的依赖,无向边表示相互依赖关系。 概率图模型分为贝叶斯网络(Bayesian Network)和马尔可夫网络(Markov Network)两大类。贝叶斯网络可以用一个有向图结构表示,马尔可夫网络可以表 示成一个无向图的网络结构。更详细地说,概率图模型包括了朴素贝叶斯模型、最大熵模型、隐马尔可夫模型、条件随机场、主题模型等,在机器学习的诸多场景中都有着广泛的应用。 2. 细数贝叶斯网络2.1 频率派观点长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生,要么不发生,从来不会去考虑某件事情发生的概率有多大,不发生的概率又是多大。而且概率虽然未知,但最起码是一个确定的值。比如如果问那时的人们一个问题:“有一个袋子,里面装着若干个白球和黑球,请问从袋子中取得白球的概率是多少?”他们会想都不用想,会立马告诉你,取出白球的概率就是1/2,要么取到白球,要么取不到白球,即θ只能有一个值,而且不论你取了多少次,取得白球的概率θ始终都是1/2,即不随观察结果X 的变化而变化。 这种频率派的观点长期统治着人们的观念,直到后来一个名叫Thomas Bayes的人物出现。 2.2 贝叶斯学派托马斯·贝叶斯Thomas Bayes(1702-1763)在世时,并不为当时的人们所熟知,很少发表论文或出版著作,与当时学术界的人沟通交流也很少,用现在的话来说,贝叶斯就是活生生一民间学术“屌丝”,可这个“屌丝”最终发表了一篇名为“An essay towards solving a problem in the doctrine of chances”,翻译过来则是:机遇理论中一个问题的解。你可能觉得我要说:这篇论文的发表随机产生轰动效应,从而奠定贝叶斯在学术史上的地位。 这篇论文可以用上面的例子来说明,“有一个袋子,里面装着若干个白球和黑球,请问从袋子中取得白球的概率θ是多少?”贝叶斯认为取得白球的概率是个不确定的值,因为其中含有机遇的成分。比如,一个朋友创业,你明明知道创业的结果就两种,即要么成功要么失败,但你依然会忍不住去估计他创业成功的几率有多大?你如果对他为人比较了解,而且有方法、思路清晰、有毅力、且能团结周围的人,你会不由自主的估计他创业成功的几率可能在80%以上。这种不同于最开始的“非黑即白、非0即1”的思考方式,便是贝叶斯式的思考方式。 先简单总结下频率派与贝叶斯派各自不同的思考方式: 频率派把需要推断的参数θ看做是固定的未知常数,即概率虽然是未知的,但最起码是确定的一个值,同时,样本X 是随机的,所以频率派重点研究样本空间,大部分的概率计算都是针对样本X 的分布; 而贝叶斯派的观点则截然相反,他们认为参数是随机变量,而样本X 是固定的,由于样本是固定的,所以他们重点研究的是参数的分布。 贝叶斯派既然把看做是一个随机变量,所以要计算的分布,便得事先知道的无条件分布,即在有样本之前(或观察到X之前),有着怎样的分布呢? 比如往台球桌上扔一个球,这个球落会落在何处呢?如果是不偏不倚的把球抛出去,那么此球落在台球桌上的任一位置都有着相同的机会,即球落在台球桌上某一位置的概率服从均匀分布。这种在实验之前定下的属于基本前提性质的分布称为先验分布,或着无条件分布。 其中,先验信息一般来源于经验跟历史资料。比如林丹跟某选手对决,解说一般会根据林丹历次比赛的成绩对此次比赛的胜负做个大致的判断。再比如,某工厂每天都要对产品进行质检,以评估产品的不合格率θ,经过一段时间后便会积累大量的历史资料,这些历史资料便是先验知识,有了这些先验知识,便在决定对一个产品是否需要每天质检时便有了依据,如果以往的历史资料显示,某产品的不合格率只有0.01%,便可视为信得过产品或免检产品,只每月抽检一两次,从而省去大量的人力物力。 而后验分布π(θ|X)一般也认为是在给定样本X的情况下的θ条件分布,而使π(θ|X)达到最大的值θMD称为最大后验估计,类似于经典统计学中的极大似然估计。 综合起来看,则好比是人类刚开始时对大自然只有少得可怜的先验知识,但随着不断观察、实验获得更多的样本、结果,使得人们对自然界的规律摸得越来越透彻。所以,贝叶斯方法既符合人们日常生活的思考方式,也符合人们认识自然的规律,经过不断的发展,最终占据统计学领域的半壁江山,与经典统计学分庭抗礼。 2.3 贝叶斯定理条件概率(又称后验概率)就是事件A在另外一个事件B已经发生条件下的发生概率。条件概率表示为P(A|B),读作“在B条件下A的概率”。 比如上图,在同一个样本空间Ω中的事件或者子集A与B,如果随机从Ω中选出的一个元素属于B,那么这个随机选择的元素还属于A的概率就定义为在B的前提下A的条件概率: $$P(A|B)=\\frac{P(A\\cap_{}B)}{P(B)}$$ 联合概率:$P(A\\cap_{}B)或者P(A,B)$ 边缘概率(先验概率):P(A)或者P(B) 2.4 贝叶斯网络贝叶斯网络(Bayesian network),又称信念网络(Belief Network),或有向无环图模型(directed acyclic graphical model),是一种概率图模型,于1985年由Judea Pearl首先提出。它是一种模拟人类推理过程中因果关系的不确定性处理模型,其网络拓朴结构是一个有向无环图(DAG)。 贝叶斯网络的有向无环图中的节点表示随机变量${X_1,X_2,…,X_n}$ 它们可以是可观察到的变量,或隐变量、未知参数等。认为有因果关系(或非条件独立)的变量或命题则用箭头来连接。若两个节点间以一个单箭头连接在一起,表示其中一个节点是“因(parents)”,另一个是“果(children)”,两节点就会产生一个条件概率值。 例如,假设节点E直接影响到节点H,即E→H,则用从E指向H的箭头建立结点E到结点H的有向弧(E,H),权值(即连接强度)用条件概率P(H|E)来表示,如下图所示: 简言之,把某个研究系统中涉及的随机变量,根据是否条件独立绘制在一个有向图中,就形成了贝叶斯网络。其主要用来描述随机变量之间的条件依赖,用圈表示随机变量(random variables),用箭头表示条件依赖(conditional dependencies)。 此外,对于任意的随机变量,其联合概率可由各自的局部条件概率分布相乘而得出: $$P(x_1,…,x_k)=P(x_k|x_1,…,x_{k-1})…P(x_2|x_1)P(x_1)$$ 2.4.1 贝叶斯网络的结构形式1. head-to-head 依上图,所以有:P(a,b,c) = P(a)P(b)P(c|a,b)成立,即在c未知的条件下,a、b被阻断(blocked),是独立的,称之为head-to-head条件独立。 2. tail-to-tail 考虑c未知,跟c已知这两种情况: 在c未知的时候,有:P(a,b,c)=P(c)P(a|c)P(b|c),此时,没法得出P(a,b) = P(a)P(b),即c未知时,a、b不独立。 在c已知的时候,有:P(a,b|c)=P(a,b,c)/P(c),然后将P(a,b,c)=P(c)P(a|c)P(b|c)带入式子中,得到:P(a,b|c)=P(a,b,c)/P(c) = P(c)P(a|c)P(b|c) / P(c) = P(a|c)*P(b|c),即c已知时,a、b独立。 3. head-to-tail 还是分c未知跟c已知这两种情况: c未知时,有:P(a,b,c)=P(a)P(c|a)P(b|c),但无法推出P(a,b) = P(a)P(b),即c未知时,a、b不独立。 c已知时,有:P(a,b|c)=P(a,b,c)/P(c),且根据P(a,c) = P(a)P(c|a) = P(c)P(a|c),可化简得到: $$P(a,b|c)$$ =$$P(a,b,c)/P(c)$$ =$$P(a)P(c|a)P(b|c) / P(c)$$ =$$P(a,c)*P(b|c)/P(c)$$ =$$P(a|c)*P(b|c)$$ 所以,在c给定的条件下,a,b被阻断(blocked),是独立的,称之为head-to-tail条件独立。 这个head-to-tail其实就是一个链式网络,如下图所示: 根据之前对head-to-tail的讲解,我们已经知道,在xi给定的条件下,xi+1的分布和x1,x2…xi-1条件独立。意味着啥呢?意味着:xi+1的分布状态只和xi有关,和其他变量条件独立。通俗点说,当前状态只跟上一状态有关,跟上上或上上之前的状态无关。这种顺次演变的随机过程,就叫做马尔科夫链(Markov chain)。对于马尔科夫链我们下一节再细讲。 2.4.2 因子图wikipedia上是这样定义因子图的:将一个具有多变量的全局函数因子分解,得到几个局部函数的乘积,以此为基础得到的一个双向图叫做因子图(Factor Graph)。 通俗来讲,所谓因子图就是对函数进行因子分解得到的一种概率图。一般内含两种节点:变量节点和函数节点。我们知道,一个全局函数通过因式分解能够分解为多个局部函数的乘积,这些局部函数和对应的变量关系就体现在因子图上。 举个例子,现在有一个全局函数,其因式分解方程为: $$g(x_1,x_2,x_3,x_4,x_5)=f_A(x_1)f_B(x_2)f_C(x1,x2,x3)f_D(x_3,x_4)f_E(x_3,x_5)$$ 其中fA,fB,fC,fD,fE为各函数,表示变量之间的关系,可以是条件概率也可以是其他关系。其对应的因子图为: 在概率图中,求某个变量的边缘分布是常见的问题。这问题有很多求解方法,其中之一就是把贝叶斯网络或马尔科夫随机场转换成因子图,然后用sum-product算法求解。换言之,基于因子图可以用sum-product 算法高效的求各个变量的边缘分布。 详细的sum-product算法过程,请查看博文:从贝叶斯方法谈到贝叶斯网络 2.5 朴素贝叶斯朴素贝叶斯(Naive Bayesian)是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法。朴素贝叶斯原理简单,也很容易实现,多用于文本分类,比如垃圾邮件过滤。*朴素贝叶斯可以看做是贝叶斯网络的特殊情况:即该网络中无边,各个节点都是独立的。 * 朴素贝叶斯朴素在哪里呢? —— 两个假设: 一个特征出现的概率与其他特征(条件)独立; 每个特征同等重要。 贝叶斯公式如下: $$P(A|B)=\\frac{P(B|A)P(A)}{P(B)}=P(类别|特征)=\\frac{P(特征|类别)P(类别)}{P(特征)}$$ 下面以一个例子来解释朴素贝叶斯,给定数据如下: 现在给我们的问题是,如果一对男女朋友,男生想女生求婚,男生的四个特点分别是不帅,性格不好,身高矮,不上进,请你判断一下女生是嫁还是不嫁? 这是一个典型的分类问题,转为数学问题就是比较p(嫁|(不帅、性格不好、身高矮、不上进))与p(不嫁|(不帅、性格不好、身高矮、不上进))的概率,谁的概率大,我就能给出嫁或者不嫁的答案!这里我们联系到朴素贝叶斯公式: $$P(嫁|不帅,性格不好,矮,不上进)=\\frac{P(不帅,性格不好,矮,不上进|嫁)P(嫁)}{P(不帅,性格不好,矮,不上进)}$$ 我们需要求p(嫁|(不帅、性格不好、身高矮、不上进),这是我们不知道的,但是通过朴素贝叶斯公式可以转化为好求的三个量,这三个变量都能通过统计的方法求得。 等等,为什么这个成立呢?学过概率论的同学可能有感觉了,这个等式成立的条件需要特征之间相互独立吧!对的!这也就是为什么朴素贝叶斯分类有朴素一词的来源,朴素贝叶斯算法是假设各个特征之间相互独立,那么这个等式就成立了! 但是为什么需要假设特征之间相互独立呢? 我们这么想,假如没有这个假设,那么我们对右边这些概率的估计其实是不可做的,这么说,我们这个例子有4个特征,其中帅包括{帅,不帅},性格包括{不好,好,爆好},身高包括{高,矮,中},上进包括{不上进,上进},那么四个特征的联合概率分布总共是4维空间,总个数为233*2=36个。 36个,计算机扫描统计还可以,但是现实生活中,往往有非常多的特征,每一个特征的取值也是非常之多,那么通过统计来估计后面概率的值,变得几乎不可做,这也是为什么需要假设特征之间独立的原因。 假如我们没有假设特征之间相互独立,那么我们统计的时候,就需要在整个特征空间中去找,比如统计p(不帅、性格不好、身高矮、不上进|嫁),我们就需要在嫁的条件下,去找四种特征全满足分别是不帅,性格不好,身高矮,不上进的人的个数,这样的话,由于数据的稀疏性,很容易统计到0的情况。 这样是不合适的。 根据上面俩个原因,朴素贝叶斯法对条件概率分布做了条件独立性的假设,由于这是一个较强的假设,朴素贝叶斯也由此得名!这一假设使得朴素贝叶斯法变得简单,但有时会牺牲一定的分类准确率。 朴素贝叶斯优点: 算法逻辑简单,易于实现(算法思路很简单,只要使用贝叶斯公式转化即可!) 分类过程中时空开销小(假设特征相互独立,只会涉及到二维存储) 朴素贝叶斯缺点: 理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。 朴素贝叶斯模型(Naive Bayesian Model)的朴素(Naive)的含义是”很简单很天真”地假设样本特征彼此独立. 这个假设现实中基本上不存在, 但特征相关性很小的实际情况还是很多的, 所以这个模型仍然能够工作得很好。 3. 基于贝叶斯的一些问题 解释朴素贝叶斯算法里面的先验概率、似然估计和边际似然估计? 先验概率:就是因变量(二分法)在数据集中的比例。这是在你没有任何进一步的信息的时候,是对分类能做出的最接近的猜测。 似然估计:似然估计是在其他一些变量的给定的情况下,一个观测值被分类为1的概率。例如,“FREE”这个词在以前的垃圾邮件使用的概率就是似然估计。 边际似然估计:边际似然估计就是,“FREE”这个词在任何消息中使用的概率。 4. 生成式模型和判别式模型的区别 判别模型(discriminative model)通过求解条件概率分布P(y|x)或者直接计算y的值来预测y。 线性回归(Linear Regression),逻辑回归(Logistic Regression),支持向量机(SVM), 传统神经网络(Traditional Neural Networks),线性判别分析(Linear Discriminative Analysis),条件随机场(Conditional Random Field) 生成模型(generative model)通过对观测值和标注数据计算联合概率分布P(x,y)来达到判定估算y的目的。 朴素贝叶斯(Naive Bayes), 隐马尔科夫模型(HMM),贝叶斯网络(Bayesian Networks)和隐含狄利克雷分布(Latent Dirichlet Allocation)、混合高斯模型 5. 代码实现新闻分类 GitHub:点击进入 6. 参考文献从贝叶斯方法谈到贝叶斯网络 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】支持向量机(SVM)","slug":"ML/SVM","date":"2019-07-10T16:00:00.000Z","updated":"2019-12-25T05:36:46.023Z","comments":true,"path":"2019/07/11/ML/SVM/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/11/ML/SVM/","excerpt":"1.1 一个关于SVM的童话故事 支持向量机(Support Vector Machine,SVM)是众多监督学习方法中十分出色的一种,几乎所有讲述经典机器学习方法的教材都会介绍。关于SVM,流传着一个关于天使与魔鬼的故事。 传说魔鬼和天使玩了一个游戏,魔鬼在桌上放了两种颜色的球。魔鬼让天使用一根…","text":"1.1 一个关于SVM的童话故事 支持向量机(Support Vector Machine,SVM)是众多监督学习方法中十分出色的一种,几乎所有讲述经典机器学习方法的教材都会介绍。关于SVM,流传着一个关于天使与魔鬼的故事。 传说魔鬼和天使玩了一个游戏,魔鬼在桌上放了两种颜色的球。魔鬼让天使用一根… 1. 讲讲SVM1.1 一个关于SVM的童话故事支持向量机(Support Vector Machine,SVM)是众多监督学习方法中十分出色的一种,几乎所有讲述经典机器学习方法的教材都会介绍。关于SVM,流传着一个关于天使与魔鬼的故事。 传说魔鬼和天使玩了一个游戏,魔鬼在桌上放了两种颜色的球。魔鬼让天使用一根木棍将它们分开。这对天使来说,似乎太容易了。天使不假思索地一摆,便完成了任务。魔鬼又加入了更多的球。随着球的增多,似乎有的球不能再被原来的木棍正确分开,如下图所示。 SVM实际上是在为天使找到木棒的最佳放置位置,使得两边的球都离分隔它们的木棒足够远。依照SVM为天使选择的木棒位置,魔鬼即使按刚才的方式继续加入新球,木棒也能很好地将两类不同的球分开。 看到天使已经很好地解决了用木棒线性分球的问题,魔鬼又给了天使一个新的挑战,如下图所示。 按照这种球的摆法,世界上貌似没有一根木棒可以将它们 完美分开。但天使毕竟有法力,他一拍桌子,便让这些球飞到了空中,然后凭借 念力抓起一张纸片,插在了两类球的中间。从魔鬼的角度看这些 球,则像是被一条曲线完美的切开了。 后来,“无聊”的科学家们把这些球称为“数据”,把木棍称为“分类面”,找到最 大间隔的木棒位置的过程称为“优化”,拍桌子让球飞到空中的念力叫“核映射”,在 空中分隔球的纸片称为“分类超平面”。这便是SVM的童话故事。 1.2 理解SVM:第一层支持向量机,因其英文名为support vector machine,故一般简称SVM,通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。 线性分类器:给定一些数据点,它们分别属于两个不同的类,现在要找到一个线性分类器把这些数据分成两类。如果用x表示数据点,用y表示类别(y可以取1或者0,分别代表两个不同的类),一个线性分类器的学习目标便是要在n维的数据空间中找到一个超平面(hyper plane),这个超平面的方程可以表示为( wT中的T代表转置): $$w^Tx+b=0$$ 这里可以查看我之前的逻辑回归章节回顾:点击打开 这个超平面可以用分类函数 $f(x)=w^Tx+b$ 表示,当f(x) 等于0的时候,x便是位于超平面上的点,而f(x)大于0的点对应 y=1 的数据点,f(x)小于0的点对应y=-1的点,如下图所示: 1.2.1 函数间隔与几何间隔在超平面wx+b=0确定的情况下,|wx+b|能够表示点x到距离超平面的远近,而通过观察wx+b的符号与类标记y的符号是否一致可判断分类是否正确,所以,可以用(y(wx+b))的正负性来判定或表示分类的正确性。于此,我们便引出了*函数间隔**(functional margin)的概念。 函数间隔公式:$$\\gamma=y(w^Tx+b)=yf(x)$$ 而超平面(w,b)关于数据集T中所有样本点(xi,yi)的函数间隔最小值(其中,x是特征,y是结果标签,i表示第i个样本),便为超平面(w, b)关于训练数据集T的函数间隔: $$\\gamma=min\\gamma i(i=1,…n)$$ 但这样定义的函数间隔有问题,即如果成比例的改变w和b(如将它们改成2w和2b),则函数间隔的值f(x)却变成了原来的2倍(虽然此时超平面没有改变),所以只有函数间隔还远远不够。 几何间隔 事实上,我们可以对法向量w加些约束条件,从而引出真正定义点到超平面的距离–几何间隔(geometrical margin)的概念。假定对于一个点 x ,令其垂直投影到超平面上的对应点为 x0 ,w 是垂直于超平面的一个向量,$\\gamma$为样本x到超平面的距离,如下图所示: 这里我直接给出几何间隔的公式,详细推到请查看博文:点击进入 几何间隔:$\\gamma^{‘}=\\frac{\\gamma}{||w||}$ 从上述函数间隔和几何间隔的定义可以看出:几何间隔就是函数间隔除以||w||,而且函数间隔y(wx+b) = yf(x)实际上就是|f(x)|,只是人为定义的一个间隔度量,而几何间隔|f(x)|/||w||才是直观上的点到超平面的距离。 1.2.2 最大间隔分类器的定义对一个数据点进行分类,当超平面离数据点的“间隔”越大,分类的确信度(confidence)也越大。所以,为了使得分类的确信度尽量高,需要让所选择的超平面能够最大化这个“间隔”值。这个间隔就是下图中的Gap的一半。 通过由前面的分析可知:函数间隔不适合用来最大化间隔值,因为在超平面固定以后,可以等比例地缩放w的长度和b的值,这样可以使得 $f(x)=w^Tx+b$ 的值任意大,亦即函数间隔可以在超平面保持不变的情况下被取得任意大。但几何间隔因为除上了,使得在缩放w和b的时候几何间隔的值是不会改变的,它只随着超平面的变动而变动,因此,这是更加合适的一个间隔。换言之,这里要找的最大间隔分类超平面中的“间隔”指的是几何间隔。 如下图所示,中间的实线便是寻找到的最优超平面(Optimal Hyper Plane),其到两条虚线边界的距离相等,这个距离便是几何间隔,两条虚线间隔边界之间的距离等于2倍几何间隔,而虚线间隔边界上的点则是支持向量。由于这些支持向量刚好在虚线间隔边界上,所以它们满足$y(w_Tx+b)=1$,对于所有不是支持向量的点,则显然有$y(w_Tx+b)>1$。 OK,到此为止,算是了解到了SVM的第一层,对于那些只关心怎么用SVM的朋友便已足够,不必再更进一层深究其更深的原理。 1.2.3 最大间隔损失函数Hinge lossSVM 求解使通过建立二次规划原始问题,引入拉格朗日乘子法,然后转换成对偶的形式去求解,这是一种理论非常充实的解法。这里换一种角度来思考,在机器学习领域,一般的做法是经验风险最小化 (empirical risk minimization,ERM),即构建假设函数(Hypothesis)为输入输出间的映射,然后采用损失函数来衡量模型的优劣。求得使损失最小化的模型即为最优的假设函数,采用不同的损失函数也会得到不同的机器学习算法。SVM采用的就是Hinge Loss,用于“最大间隔(max-margin)”分类。 $$L_i=\\sum_{j\\neq t_i}max(0,f(x_i,W)j-(f(x_i,W){y_i}-\\bigtriangleup))$$ 对于训练集中的第i个数据xi 在W下会有一个得分结果向量f(xi,W) 第j类的得分为我们记作f(xi,W)j 要理解这个公式,首先先看下面这张图片: 在生活中我们都会认为没有威胁的才是最好的,比如拿成绩来说,自己考了第一名99分,而第二名紧随其后98分,那么就会有不安全的感觉,就会认为那家伙随时都有可能超过我。如果第二名是85分,那就会感觉安全多了,第二名需要花费很大的力气才能赶上自己。拿这个例子套到上面这幅图也是一样的。 上面这幅图delta左边的红点是一个安全警戒线,什么意思呢?也就是说预测错误得分超过这个安全警戒线就会得到一个惩罚权重,让这个预测错误值退回到安全警戒线以外,这样才能够保证预测正确的结果具有唯一性。 对应到公式中,$f(x_i,W)_j$ 就是错误分类的得分。后面一项就是 正确得分 - delta = 安全警戒线值,两项的差代表的就是惩罚权重,越接近正确得分,权重越大。当错误得分在警戒线以外时,两项相减得到负数,那么损失函数的最大值是0,也就是没有损失。 一直往复循环训练数据,直到最小化损失函数为止,也就找到了分类超平面。 1.3 深入SVM:第二层1.3.1 从线性可分到线性不可分接着考虑之前得到的目标函数(令函数间隔=1): $$max\\frac{1}{||w||}s.t.,y_i(w^Tx_i+b)\\ge1,i=1,…,n$$ 转换为对偶问题,解释一下什么是对偶问题,对偶问题是实质相同但从不同角度提出不同提法的一对问题。 由于求 $\\frac{1}{||w||}$ 的最大值相当于求 $\\frac{1}{2}||w||^2$ 的最小值,所以上述目标函数等价于(w由分母变成分子,从而也有原来的max问题变为min问题,很明显,两者问题等价): $$min\\frac{1}{2}||w||^2s.t.,y_i(w^Tx_i+b)\\ge1,i=1,…,n$$ 因为现在的目标函数是二次的,约束条件是线性的,所以它是一个凸二次规划问题。这个问题可以用现成的QP (Quadratic Programming) 优化包进行求解。一言以蔽之:在一定的约束条件下,目标最优,损失最小。 此外,由于这个问题的特殊结构,还可以通过拉格朗日对偶性(Lagrange Duality)变换到对偶变量 (dual variable) 的优化问题,即通过求解与原问题等价的对偶问题(dual problem)得到原始问题的最优解,这就是线性可分条件下支持向量机的对偶算法,这样做的优点在于:一者对偶问题往往更容易求解;二者可以自然的引入核函数,进而推广到非线性分类问题。 详细过程请参考文章末尾给出的参考链接。 1.3.2 核函数Kernel事实上,大部分时候数据并不是线性可分的,这个时候满足这样条件的超平面就根本不存在。在上文中,我们已经了解到了SVM处理线性可分的情况,那对于非线性的数据SVM咋处理呢?对于非线性的情况,SVM 的处理方法是选择一个核函数 κ(⋅,⋅) ,通过将数据映射到高维空间,来解决在原始空间中线性不可分的问题。 具体来说,在线性不可分的情况下,支持向量机首先在低维空间中完成计算,然后通过核函数将输入空间映射到高维特征空间,最终在高维特征空间中构造出最优分离超平面,从而把平面上本身不好分的非线性数据分开。如图所示,一堆数据在二维空间无法划分,从而映射到三维空间里划分: 通常人们会从一些常用的核函数中选择(根据问题和数据的不同,选择不同的参数,实际上就是得到了不同的核函数),例如:多项式核、高斯核、线性核。 读者可能还是没明白核函数到底是个什么东西?我再简要概括下,即以下三点: 实际中,我们会经常遇到线性不可分的样例,此时,我们的常用做法是把样例特征映射到高维空间中去(映射到高维空间后,相关特征便被分开了,也就达到了分类的目的); 但进一步,如果凡是遇到线性不可分的样例,一律映射到高维空间,那么这个维度大小是会高到可怕的。那咋办呢? 此时,核函数就隆重登场了,核函数的价值在于它虽然也是将特征进行从低维到高维的转换,但核函数绝就绝在它事先在低维上进行计算,而将实质上的分类效果表现在了高维上,避免了直接在高维空间中的复杂计算。 如果数据中出现了离群点outliers,那么就可以使用松弛变量来解决。 常见的核函数有哪些 核函数 表达式 备注 Linear Kernel线性核 $k(x,y)=x^{t}y+c$ Polynomial Kernel多项式核 $k(x,y)=(ax^{t}y+c)^{d}$ $d\\geqslant1$为多项式的次数 Exponential Kernel指数核 $k(x,y)=exp(-\\frac{\\left |x-y \\right |}{2\\sigma ^{2}})$ $\\sigma>0$ Gaussian Kernel高斯核 $k(x,y)=exp(-\\frac{\\left |x-y \\right |^{2}}{2\\sigma ^{2}})$ $\\sigma$为高斯核的带宽,$\\sigma>0$, Laplacian Kernel拉普拉斯核 $k(x,y)=exp(-\\frac{\\left |x-y \\right |}{\\sigma})$ $\\sigma>0$ ANOVA Kernel $k(x,y)=exp(-\\sigma(x^{k}-y^{k})^{2})^{d}$ Sigmoid Kernel $k(x,y)=tanh(ax^{t}y+c)$ $tanh$为双曲正切函数,$a>0,c<0$ 1.3.3 总结不准确的说,SVM它本质上即是一个分类方法,用 w^T+b 定义分类函数,于是求w、b,为寻最大间隔,引出1/2||w||^2,继而引入拉格朗日因子,化为对拉格朗日乘子a的求解(求解过程中会涉及到一系列最优化或凸二次规划等问题),如此,求w.b与求a等价,而a的求解可以用一种快速学习算法SMO,至于核函数,是为处理非线性情况,若直接映射到高维计算恐维度爆炸,故在低维计算,等效高维表现。 OK,理解到这第二层,已经能满足绝大部分人一窥SVM原理的好奇心,针对于面试来说已经足够了。 1.4 SVM的应用SVM在很多诸如文本分类,图像分类,生物序列分析和生物数据挖掘,手写字符识别等领域有很多的应用,但或许你并没强烈的意识到,SVM可以成功应用的领域远远超出现在已经在开发应用了的领域。 2. SVM的一些问题 是否存在一组参数使SVM训练误差为0? 答:存在 训练误差为0的SVM分类器一定存在吗? 答:一定存在 加入松弛变量的SVM的训练误差可以为0吗? 答:使用SMO算法训练的线性分类器并不一定能得到训练误差为0的模型。这是由于我们的优化目标改变了,并不再是使训练误差最小。 *带核的SVM为什么能分类非线性问题? * 答:核函数的本质是两个函数的內积,通过核函数将其隐射到高维空间,在高维空间非线性问题转化为线性问题, SVM得到超平面是高维空间的线性分类平面。其分类结果也视为低维空间的非线性分类结果, 因而带核的SVM就能分类非线性问题。 如何选择核函数? 如果特征的数量大到和样本数量差不多,则选用LR或者线性核的SVM; 如果特征的数量小,样本的数量正常,则选用SVM+高斯核函数; 如果特征的数量小,而样本的数量很大,则需要手工添加一些特征从而变成第一种情况。 3. LR和SVM的联系与区别3.1 相同点 都是线性分类器。本质上都是求一个最佳分类超平面。 都是监督学习算法。 都是判别模型。判别模型不关心数据是怎么生成的,它只关心信号之间的差别,然后用差别来简单对给定的一个信号进行分类。常见的判别模型有:KNN、SVM、LR,常见的生成模型有:朴素贝叶斯,隐马尔可夫模型。 3.2 不同点 LR是参数模型,svm是非参数模型,linear和rbf则是针对数据线性可分和不可分的区别; 从目标函数来看,区别在于逻辑回归采用的是logistical loss,SVM采用的是hinge loss,这两个损失函数的目的都是增加对分类影响较大的数据点的权重,减少与分类关系较小的数据点的权重。 SVM的处理方法是只考虑support vectors,也就是和分类最相关的少数点,去学习分类器。而逻辑回归通过非线性映射,大大减小了离分类平面较远的点的权重,相对提升了与分类最相关的数据点的权重。 逻辑回归相对来说模型更简单,好理解,特别是大规模线性分类时比较方便。而SVM的理解和优化相对来说复杂一些,SVM转化为对偶问题后,分类只需要计算与少数几个支持向量的距离,这个在进行复杂核函数计算时优势很明显,能够大大简化模型和计算。 logic 能做的 svm能做,但可能在准确率上有问题,svm能做的logic有的做不了。 4. 线性分类器与非线性分类器的区别以及优劣线性和非线性是针对模型参数和输入特征来讲的;比如输入x,模型y=ax+ax^2 那么就是非线性模型,如果输入是x和X^2则模型是线性的。 线性分类器可解释性好,计算复杂度较低,不足之处是模型的拟合效果相对弱些。 LR,贝叶斯分类,单层感知机、线性回归 非线性分类器效果拟合能力较强,不足之处是数据量不足容易过拟合、计算复杂度高、可解释性不好。 决策树、RF、GBDT、多层感知机 SVM两种都有(看线性核还是高斯核) 5. 代码实现新闻分类 GitHub:点击进入 6. 参考文献支持向量机通俗导论(理解SVM的三层境界) 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】LightGBM","slug":"ML/LightGBM","date":"2019-07-09T16:00:00.000Z","updated":"2019-12-25T06:18:12.518Z","comments":true,"path":"2019/07/10/ML/LightGBM/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/10/ML/LightGBM/","excerpt":"LightGBM是什么东东 不久前微软DMTK(分布式机器学习工具包)团队在GitHub上开源了性能超越其他boosting工具的LightGBM,在三天之内GitHub上被star了1000次,fork了200次。知乎上有近千人关注“如何看待微软开源的LightGBM?…","text":"LightGBM是什么东东 不久前微软DMTK(分布式机器学习工具包)团队在GitHub上开源了性能超越其他boosting工具的LightGBM,在三天之内GitHub上被star了1000次,fork了200次。知乎上有近千人关注“如何看待微软开源的LightGBM?… 1. LightGBM是什么东东不久前微软DMTK(分布式机器学习工具包)团队在GitHub上开源了性能超越其他boosting工具的LightGBM,在三天之内GitHub上被star了1000次,fork了200次。知乎上有近千人关注“如何看待微软开源的LightGBM?”问题,被评价为“速度惊人”,“非常有启发”,“支持分布式”,“代码清晰易懂”,“占用内存小”等。 LightGBM (Light Gradient Boosting Machine)(请点击https://github.com/Microsoft/LightGBM)是一个实现GBDT算法的框架,支持高效率的并行训练。 LightGBM在Higgs数据集上LightGBM比XGBoost快将近10倍,内存占用率大约为XGBoost的1/6,并且准确率也有提升。GBDT在每一次迭代的时候,都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小;如果不装进内存,反复地读写训练数据又会消耗非常大的时间。尤其面对工业级海量的数据,普通的GBDT算法是不能满足其需求的。 LightGBM提出的主要原因就是为了解决GBDT在海量数据遇到的问题,让GBDT可以更好更快地用于工业实践。 1.1 LightGBM在哪些地方进行了优化 (区别XGBoost)? 基于Histogram的决策树算法 带深度限制的Leaf-wise的叶子生长策略 直方图做差加速直接 支持类别特征(Categorical Feature) Cache命中率优化 基于直方图的稀疏特征优化多线程优化。 1.2 Histogram算法直方图算法的基本思想是先把连续的浮点特征值离散化成k个整数(其实又是分桶的思想,而这些桶称为bin,比如[0,0.1)→0, [0.1,0.3)→1),同时构造一个宽度为k的直方图。 在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。 使用直方图算法有很多优点。首先,最明显就是内存消耗的降低,直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用8位整型存储就足够了,内存消耗可以降低为原来的1/8。然后在计算上的代价也大幅降低,预排序算法每遍历一个特征值就需要计算一次分裂的增益,而直方图算法只需要计算k次(k可以认为是常数),时间复杂度从O(#data#feature)优化到O(k#features)。 1.3 带深度限制的Leaf-wise的叶子生长策略在XGBoost中,树是按层生长的,称为Level-wise tree growth,同一层的所有节点都做分裂,最后剪枝,如下图所示: Level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。 在Histogram算法之上,LightGBM进行进一步的优化。首先它抛弃了大多数GBDT工具使用的按层生长 (level-wise)的决策树生长策略,而使用了带有深度限制的按叶子生长 (leaf-wise)算法。 Leaf-wise则是一种更为高效的策略,每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。 1.4 直方图差加速LightGBM另一个优化是Histogram(直方图)做差加速。一个容易观察到的现象:一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到。通常构造直方图,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶。 利用这个方法,LightGBM可以在构造一个叶子的直方图后,可以用非常微小的代价得到它兄弟叶子的直方图,在速度上可以提升一倍。 1.5 直接支持类别特征实际上大多数机器学习工具都无法直接支持类别特征,一般需要把类别特征,转化到多维的0/1特征,降低了空间和时间的效率。而类别特征的使用是在实践中很常用的。基于这个考虑,LightGBM优化了对类别特征的支持,可以直接输入类别特征,不需要额外的0/1展开。并在决策树算法上增加了类别特征的决策规则。在Expo数据集上的实验,相比0/1展开的方法,训练速度可以加速8倍,并且精度一致。据我们所知,LightGBM是第一个直接支持类别特征的GBDT工具。 2. LightGBM优点LightGBM (Light Gradient Boosting Machine)(请点击https://github.com/Microsoft/LightGBM)是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有以下优点: 更快的训练速度 更低的内存消耗 更好的准确率 分布式支持,可以快速处理海量数据 3. 代码实现为了演示LightGBM在Python中的用法,本代码以sklearn包中自带的鸢尾花数据集为例,用lightgbm算法实现鸢尾花种类的分类任务。 GitHub:点击进入 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】XGBoost","slug":"ML/XGBoost","date":"2019-07-09T16:00:00.000Z","updated":"2019-12-25T05:30:56.559Z","comments":true,"path":"2019/07/10/ML/XGBoost/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/10/ML/XGBoost/","excerpt":"XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学习竞赛中并取得了不错的成绩。 说到XGBoost,不得不提GBDT(Gradient Boosting Decision Tree)。因为XGB…","text":"XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学习竞赛中并取得了不错的成绩。 说到XGBoost,不得不提GBDT(Gradient Boosting Decision Tree)。因为XGB… 1. 什么是XGBoostXGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学习竞赛中并取得了不错的成绩。 说到XGBoost,不得不提GBDT(Gradient Boosting Decision Tree)。因为XGBoost本质上还是一个GBDT,但是力争把速度和效率发挥到极致,所以叫X (Extreme) GBoosted。包括前面说过,两者都是boosting方法。 关于GBDT,这里不再提,可以查看我前一篇的介绍,点此跳转。 1.1 XGBoost树的定义先来举个例子,我们要预测一家人对电子游戏的喜好程度,考虑到年轻和年老相比,年轻更可能喜欢电子游戏,以及男性和女性相比,男性更喜欢电子游戏,故先根据年龄大小区分小孩和大人,然后再通过性别区分开是男是女,逐一给各人在电子游戏喜好程度上打分,如下图所示。 就这样,训练出了2棵树tree1和tree2,类似之前gbdt的原理,两棵树的结论累加起来便是最终的结论,所以小孩的预测分数就是两棵树中小孩所落到的结点的分数相加:2 + 0.9 = 2.9。爷爷的预测分数同理:-1 + (-0.9)= -1.9。具体如下图所示: 恩,你可能要拍案而起了,惊呼,这不是跟上文介绍的GBDT乃异曲同工么? 事实上,如果不考虑工程实现、解决问题上的一些差异,XGBoost与GBDT比较大的不同就是目标函数的定义。XGBoost的目标函数如下图所示: 其中: 红色箭头所指向的L 即为损失函数(比如平方损失函数:$l(y_i,y^i)=(y_i-y^i)^2$) 红色方框所框起来的是正则项(包括L1正则、L2正则) 红色圆圈所圈起来的为常数项 对于f(x),XGBoost利用泰勒展开三项,做一个近似。f(x)表示的是其中一颗回归树。 看到这里可能有些读者会头晕了,这么多公式,我在这里只做一个简要式的讲解,具体的算法细节和公式求解请查看这篇博文,讲得很仔细:通俗理解kaggle比赛大杀器xgboost XGBoost的核心算法思想不难,基本就是: 不断地添加树,不断地进行特征分裂来生长一棵树,每次添加一个树,其实是学习一个新函数f(x),去拟合上次预测的残差。 当我们训练完成得到k棵树,我们要预测一个样本的分数,其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点就对应一个分数 最后只需要将每棵树对应的分数加起来就是该样本的预测值。 显然,我们的目标是要使得树群的预测值$y_i^{‘}$尽量接近真实值$y_i$,而且有尽量大的泛化能力。类似之前GBDT的套路,XGBoost也是需要将多棵树的得分累加得到最终的预测得分(每一次迭代,都在现有树的基础上,增加一棵树去拟合前面树的预测结果与真实值之间的残差)。 那接下来,我们如何选择每一轮加入什么 f 呢?答案是非常直接的,选取一个 f 来使得我们的目标函数尽量最大地降低。这里 f 可以使用泰勒展开公式近似。 实质是把样本分配到叶子结点会对应一个obj,优化过程就是obj优化。也就是分裂节点到叶子不同的组合,不同的组合对应不同obj,所有的优化围绕这个思想展开。到目前为止我们讨论了目标函数中的第一个部分:训练误差。接下来我们讨论目标函数的第二个部分:正则项,即如何定义树的复杂度。 1.2 正则项:树的复杂度XGBoost对树的复杂度包含了两个部分: 一个是树里面叶子节点的个数T 一个是树上叶子节点的得分w的L2模平方(对w进行L2正则化,相当于针对每个叶结点的得分增加L2平滑,目的是为了避免过拟合) 我们再来看一下XGBoost的目标函数(损失函数揭示训练误差 + 正则化定义复杂度): $$L(\\phi)=\\sum_{i}l(y_i^{‘}-y_i)+\\sum_k\\Omega(f_t)$$ 正则化公式也就是目标函数的后半部分,对于上式而言,$y_i^{‘}$是整个累加模型的输出,正则化项∑kΩ(ft)是则表示树的复杂度的函数,值越小复杂度越低,泛化能力越强。 1.3 树该怎么长很有意思的一个事是,我们从头到尾了解了xgboost如何优化、如何计算,但树到底长啥样,我们却一直没看到。很显然,一棵树的生成是由一个节点一分为二,然后不断分裂最终形成为整棵树。那么树怎么分裂的就成为了接下来我们要探讨的关键。对于一个叶子节点如何进行分裂,XGBoost作者在其原始论文中给出了一种分裂节点的方法:枚举所有不同树结构的贪心法 不断地枚举不同树的结构,然后利用打分函数来寻找出一个最优结构的树,接着加入到模型中,不断重复这样的操作。这个寻找的过程使用的就是贪心算法。选择一个feature分裂,计算loss function最小值,然后再选一个feature分裂,又得到一个loss function最小值,你枚举完,找一个效果最好的,把树给分裂,就得到了小树苗。 总而言之,XGBoost使用了和CART回归树一样的想法,利用贪婪算法,遍历所有特征的所有特征划分点,不同的是使用的目标函数不一样。具体做法就是分裂后的目标函数值比单子叶子节点的目标函数的增益,同时为了限制树生长过深,还加了个阈值,只有当增益大于该阈值才进行分裂。从而继续分裂,形成一棵树,再形成一棵树,每次在上一次的预测基础上取最优进一步分裂/建树。 1.4 如何停止树的循环生成凡是这种循环迭代的方式必定有停止条件,什么时候停止呢?简言之,设置树的最大深度、当样本权重和小于设定阈值时停止生长以防止过拟合。具体而言,则 当引入的分裂带来的增益小于设定阀值的时候,我们可以忽略掉这个分裂,所以并不是每一次分裂loss function整体都会增加的,有点预剪枝的意思,阈值参数为(即正则项里叶子节点数T的系数); 当树达到最大深度时则停止建立决策树,设置一个超参数max_depth,避免树太深导致学习局部样本,从而防止过拟合; 样本权重和小于设定阈值时则停止建树。什么意思呢,即涉及到一个超参数-最小的样本权重和min_child_weight,和GBM的 min_child_leaf 参数类似,但不完全一样。大意就是一个叶子节点样本太少了,也终止同样是防止过拟合; 2. XGBoost与GBDT有什么不同除了算法上与传统的GBDT有一些不同外,XGBoost还在工程实现上做了大量的优化。总的来说,两者之间的区别和联系可以总结成以下几个方面。 GBDT是机器学习算法,XGBoost是该算法的工程实现。 在使用CART作为基分类器时,XGBoost显式地加入了正则项来控制模型的复杂度,有利于防止过拟合,从而提高模型的泛化能力。 GBDT在模型训练时只使用了代价函数的一阶导数信息,XGBoost对代价函数进行二阶泰勒展开,可以同时使用一阶和二阶导数。 传统的GBDT采用CART作为基分类器,XGBoost支持多种类型的基分类器,比如线性分类器。 传统的GBDT在每轮迭代时使用全部的数据,XGBoost则采用了与随机森林相似的策略,支持对数据进行采样。 传统的GBDT没有设计对缺失值进行处理,XGBoost能够自动学习出缺失值的处理策略。 3. 为什么XGBoost要用泰勒展开,优势在哪里?XGBoost使用了一阶和二阶偏导, 二阶导数有利于梯度下降的更快更准. 使用泰勒展开取得函数做自变量的二阶导数形式, 可以在不选定损失函数具体形式的情况下, 仅仅依靠输入数据的值就可以进行叶子分裂优化计算, 本质上也就把损失函数的选取和模型算法优化/参数选择分开了. 这种去耦合增加了XGBoost的适用性, 使得它按需选取损失函数, 可以用于分类, 也可以用于回归。 4. 代码实现GitHub:点击进入 5. 参考文献通俗理解kaggle比赛大杀器xgboost 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】GBDT","slug":"ML/GBDT","date":"2019-07-08T16:00:00.000Z","updated":"2019-12-25T06:18:21.698Z","comments":true,"path":"2019/07/09/ML/GBDT/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/09/ML/GBDT/","excerpt":"解释一下GBDT算法的过程 GBDT(Gradient Boosting Decision Tree),全名叫梯度提升决策树,使用的是Boosting的思想。 Boosting方法训练基分类器时采用串行的方式,各个基分类器之间有依赖。它的基本思路是将基分类器层层叠加,每一…","text":"解释一下GBDT算法的过程 GBDT(Gradient Boosting Decision Tree),全名叫梯度提升决策树,使用的是Boosting的思想。 Boosting方法训练基分类器时采用串行的方式,各个基分类器之间有依赖。它的基本思路是将基分类器层层叠加,每一… 1. 解释一下GBDT算法的过程GBDT(Gradient Boosting Decision Tree),全名叫梯度提升决策树,使用的是Boosting的思想。 1.1 Boosting思想Boosting方法训练基分类器时采用串行的方式,各个基分类器之间有依赖。它的基本思路是将基分类器层层叠加,每一层在训练的时候,对前一层基分类器分错的样本,给予更高的权重。测试时,根据各层分类器的结果的加权得到最终结果。 Bagging与Boosting的串行训练方式不同,Bagging方法在训练过程中,各基分类器之间无强依赖,可以进行并行训练。 1.2 GBDT原来是这么回事GBDT的原理很简单,就是所有弱分类器的结果相加等于预测值,然后下一个弱分类器去拟合误差函数对预测值的残差(这个残差就是预测值与真实值之间的误差)。当然了,它里面的弱分类器的表现形式就是各棵树。 举一个非常简单的例子,比如我今年30岁了,但计算机或者模型GBDT并不知道我今年多少岁,那GBDT咋办呢? 它会在第一个弱分类器(或第一棵树中)随便用一个年龄比如20岁来拟合,然后发现误差有10岁; 接下来在第二棵树中,用6岁去拟合剩下的损失,发现差距还有4岁; 接着在第三棵树中用3岁拟合剩下的差距,发现差距只有1岁了; 最后在第四课树中用1岁拟合剩下的残差,完美。 最终,四棵树的结论加起来,就是真实年龄30岁(实际工程中,gbdt是计算负梯度,用负梯度近似残差)。 为何gbdt可以用用负梯度近似残差呢? 回归任务下,GBDT 在每一轮的迭代时对每个样本都会有一个预测值,此时的损失函数为均方差损失函数, $$l(y_i,y^i)=\\frac{1}{2}(y_i-y^i)^2$$ 那此时的负梯度是这样计算的 $$-[\\frac{\\partial l(y_i,y^i)}{\\partial y^i}]=(y_i-y^i)$$ 所以,当损失函数选用均方损失函数是时,每一次拟合的值就是(真实值 - 当前模型预测的值),即残差。此时的变量是$y^i$,即“当前预测模型的值”,也就是对它求负梯度。 训练过程 简单起见,假定训练集只有4个人:A,B,C,D,他们的年龄分别是14,16,24,26。其中A、B分别是高一和高三学生;C,D分别是应届毕业生和工作两年的员工。如果是用一棵传统的回归决策树来训练,会得到如下图所示结果: 现在我们使用GBDT来做这件事,由于数据太少,我们限定叶子节点做多有两个,即每棵树都只有一个分枝,并且限定只学两棵树。我们会得到如下图所示结果: 在第一棵树分枝和图1一样,由于A,B年龄较为相近,C,D年龄较为相近,他们被分为左右两拨,每拨用平均年龄作为预测值。 此时计算残差(残差的意思就是:A的实际值 - A的预测值 = A的残差),所以A的残差就是实际值14 - 预测值15 = 残差值-1。 注意,A的预测值是指前面所有树累加的和,这里前面只有一棵树所以直接是15,如果还有树则需要都累加起来作为A的预测值。 然后拿它们的残差-1、1、-1、1代替A B C D的原值,到第二棵树去学习,第二棵树只有两个值1和-1,直接分成两个节点,即A和C分在左边,B和D分在右边,经过计算(比如A,实际值-1 - 预测值-1 = 残差0,比如C,实际值-1 - 预测值-1 = 0),此时所有人的残差都是0。残差值都为0,相当于第二棵树的预测值和它们的实际值相等,则只需把第二棵树的结论累加到第一棵树上就能得到真实年龄了,即每个人都得到了真实的预测值。 换句话说,现在A,B,C,D的预测值都和真实年龄一致了。Perfect! A: 14岁高一学生,购物较少,经常问学长问题,预测年龄A = 15 – 1 = 14 B: 16岁高三学生,购物较少,经常被学弟问问题,预测年龄B = 15 + 1 = 16 C: 24岁应届毕业生,购物较多,经常问师兄问题,预测年龄C = 25 – 1 = 24 D: 26岁工作两年员工,购物较多,经常被师弟问问题,预测年龄D = 25 + 1 = 26 所以,GBDT需要将多棵树的得分累加得到最终的预测得分,且每一次迭代,都在现有树的基础上,增加一棵树去拟合前面树的预测结果与真实值之间的残差。 2. 梯度提升和梯度下降的区别和联系是什么?下表是梯度提升算法和梯度下降算法的对比情况。可以发现,两者都是在每 一轮迭代中,利用损失函数相对于模型的负梯度方向的信息来对当前模型进行更新,只不过在梯度下降中,模型是以参数化形式表示,从而模型的更新等价于参数的更新。而在梯度提升中,模型并不需要进行参数化表示,而是直接定义在函数空间中,从而大大扩展了可以使用的模型种类。 3. GBDT的优点和局限性有哪些?3.1 优点 预测阶段的计算速度快,树与树之间可并行化计算。 在分布稠密的数据集上,泛化能力和表达能力都很好,这使得GBDT在Kaggle的众多竞赛中,经常名列榜首。 采用决策树作为弱分类器使得GBDT模型具有较好的解释性和鲁棒性,能够自动发现特征间的高阶关系。 3.2 局限性 GBDT在高维稀疏的数据集上,表现不如支持向量机或者神经网络。 GBDT在处理文本分类特征问题上,相对其他模型的优势不如它在处理数值特征时明显。 训练过程需要串行训练,只能在决策树内部采用一些局部并行的手段提高训练速度。 4. RF(随机森林)与GBDT之间的区别与联系相同点: 都是由多棵树组成,最终的结果都是由多棵树一起决定。 RF和GBDT在使用CART树时,可以是分类树或者回归树。 不同点: 组成随机森林的树可以分类树也可以是回归树,而GBDT只由回归树组成 组成随机森林的树可以并行生成,而GBDT是串行生成 随机森林的结果是多数表决表决的,而GBDT则是多棵树累加之和 随机森林对异常值不敏感,而GBDT对异常值比较敏感 随机森林是减少模型的方差,而GBDT是减少模型的偏差 随机森林不需要进行特征归一化。而GBDT则需要进行特征归一化 5. 代码实现GitHub:https://github.com/NLP-LOVE/ML-NLP/blob/master/Machine%20Learning/3.2%20GBDT/GBDT_demo.ipynb 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!qq群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】随机森林","slug":"ML/Random Forest","date":"2019-07-06T16:00:00.000Z","updated":"2019-12-25T04:38:18.182Z","comments":true,"path":"2019/07/07/ML/Random Forest/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/07/ML/Random%20Forest/","excerpt":"Bagging是bootstrap aggregating。思想就是从总体样本当中随机取一部分样本进行训练,通过多次这样的结果,进行投票获取平均值作为结果输出,这就极大可能的避免了不好的样本数据,从而提高准确度。因为有些是不好的样本,相当于噪声,模型学入噪声后会使准确度不高。 假设有1000个样本…","text":"Bagging是bootstrap aggregating。思想就是从总体样本当中随机取一部分样本进行训练,通过多次这样的结果,进行投票获取平均值作为结果输出,这就极大可能的避免了不好的样本数据,从而提高准确度。因为有些是不好的样本,相当于噪声,模型学入噪声后会使准确度不高。 假设有1000个样本… 1.什么是随机森林1.1 Bagging思想Bagging是bootstrap aggregating。思想就是从总体样本当中随机取一部分样本进行训练,通过多次这样的结果,进行投票获取平均值作为结果输出,这就极大可能的避免了不好的样本数据,从而提高准确度。因为有些是不好的样本,相当于噪声,模型学入噪声后会使准确度不高。 举个例子: 假设有1000个样本,如果按照以前的思维,是直接把这1000个样本拿来训练,但现在不一样,先抽取800个样本来进行训练,假如噪声点是这800个样本以外的样本点,就很有效的避开了。重复以上操作,提高模型输出的平均值。 1.2 随机森林Random Forest(随机森林)是一种基于树模型的Bagging的优化版本,一棵树的生成肯定还是不如多棵树,因此就有了随机森林,解决决策树泛化能力弱的特点。(可以理解成三个臭皮匠顶过诸葛亮) 而同一批数据,用同样的算法只能产生一棵树,这时Bagging策略可以帮助我们产生不同的数据集。Bagging策略来源于bootstrap aggregation:从样本集(假设样本集N个数据点)中重采样选出Nb个样本(有放回的采样,样本数据点个数仍然不变为N),在所有样本上,对这n个样本建立分类器(ID3\\C4.5\\CART\\SVM\\LOGISTIC),重复以上两步m次,获得m个分类器,最后根据这m个分类器的投票结果,决定数据属于哪一类。 每棵树的按照如下规则生成: 如果训练集大小为N,对于每棵树而言,随机且有放回地从训练集中的抽取N个训练样本,作为该树的训练集; 如果每个样本的特征维度为M,指定一个常数m<<M,随机地从M个特征中选取m个特征子集,每次树进行分裂时,从这m个特征中选择最优的; 每棵树都尽最大程度的生长,并且没有剪枝过程。 一开始我们提到的随机森林中的“随机”就是指的这里的两个随机性。两个随机性的引入对随机森林的分类性能至关重要。由于它们的引入,使得随机森林不容易陷入过拟合,并且具有很好得抗噪能力(比如:对缺省值不敏感)。 总的来说就是随机选择样本数,随机选取特征,随机选择分类器,建立多颗这样的决策树,然后通过这几课决策树来投票,决定数据属于哪一类(投票机制有一票否决制、少数服从多数、加权多数) 2. 随机森林分类效果的影响因素 森林中任意两棵树的相关性:相关性越大,错误率越大; 森林中每棵树的分类能力:每棵树的分类能力越强,整个森林的错误率越低。 减小特征选择个数m,树的相关性和分类能力也会相应的降低;增大m,两者也会随之增大。所以关键问题是如何选择最优的m(或者是范围),这也是随机森林唯一的一个参数。 3. 随机森林有什么优缺点优点: 在当前的很多数据集上,相对其他算法有着很大的优势,表现良好。 它能够处理很高维度(feature很多)的数据,并且不用做特征选择(因为特征子集是随机选择的)。 在训练完后,它能够给出哪些feature比较重要。 训练速度快,容易做成并行化方法(训练时树与树之间是相互独立的)。 在训练过程中,能够检测到feature间的互相影响。 对于不平衡的数据集来说,它可以平衡误差。 如果有很大一部分的特征遗失,仍可以维持准确度。 缺点: 随机森林已经被证明在某些噪音较大的分类或回归问题上会过拟合。 对于有不同取值的属性的数据,取值划分较多的属性会对随机森林产生更大的影响,所以随机森林在这种数据上产出的属性权值是不可信的。 4. 随机森林如何处理缺失值?根据随机森林创建和训练的特点,随机森林对缺失值的处理还是比较特殊的。 首先,给缺失值预设一些估计值,比如数值型特征,选择其余数据的中位数或众数作为当前的估计值 然后,根据估计的数值,建立随机森林,把所有的数据放进随机森林里面跑一遍。记录每一组数据在决策树中一步一步分类的路径. 判断哪组数据和缺失数据路径最相似,引入一个相似度矩阵,来记录数据之间的相似度,比如有N组数据,相似度矩阵大小就是N*N 如果缺失值是类别变量,通过权重投票得到新估计值,如果是数值型变量,通过加权平均得到新的估计值,如此迭代,直到得到稳定的估计值。 其实,该缺失值填补过程类似于推荐系统中采用协同过滤进行评分预测,先计算缺失特征与其他特征的相似度,再加权得到缺失值的估计,而随机森林中计算相似度的方法(数据在决策树中一步一步分类的路径)乃其独特之处。 5. 什么是OOB?随机森林中OOB是如何计算的,它有什么优缺点?OOB: 上面我们提到,构建随机森林的关键问题就是如何选择最优的m,要解决这个问题主要依据计算袋外错误率oob error(out-of-bag error)。 bagging方法中Bootstrap每次约有1/3的样本不会出现在Bootstrap所采集的样本集合中,当然也就没有参加决策树的建立,把这1/3的数据称为袋外数据oob(out of bag),它可以用于取代测试集误差估计方法。 袋外数据(oob)误差的计算方法如下: 对于已经生成的随机森林,用袋外数据测试其性能,假设袋外数据总数为O,用这O个袋外数据作为输入,带进之前已经生成的随机森林分类器,分类器会给出O个数据相应的分类 因为这O条数据的类型是已知的,则用正确的分类与随机森林分类器的结果进行比较,统计随机森林分类器分类错误的数目,设为X,则袋外数据误差大小=X/O 优缺点: 这已经经过证明是无偏估计的,所以在随机森林算法中不需要再进行交叉验证或者单独的测试集来获取测试集误差的无偏估计。 6. 随机森林的过拟合问题 你已经建了一个有10000棵树的随机森林模型。在得到0.00的训练误差后,你非常高兴。但是,验证错误是34.23。到底是怎么回事?你还没有训练好你的模型吗? 答:该模型过度拟合,因此,为了避免这些情况,我们要用交叉验证来调整树的数量。 7. 代码实现GitHub:https://github.com/NLP-LOVE/ML-NLP/blob/master/Machine%20Learning/3.1%20Random%20Forest/RandomForestRegression.ipynb 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!qq群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】决策树","slug":"ML/Desition Tree","date":"2019-07-05T16:00:00.000Z","updated":"2019-12-25T04:38:42.028Z","comments":true,"path":"2019/07/06/ML/Desition Tree/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/06/ML/Desition%20Tree/","excerpt":"其实用一下图片能更好的理解LR模型和决策树模型算法的根本区别,我们可以思考一下一个决策问题:是否去相亲,一个女孩的母亲要给这个女海介绍对象。 大家都看得很明白了吧!LR模型是一股脑儿的把所有特征塞入学习,而决策树更像是编程语言中的if-else一样,去做条件判断,这就是根本性的区别。 决策树基于“…","text":"其实用一下图片能更好的理解LR模型和决策树模型算法的根本区别,我们可以思考一下一个决策问题:是否去相亲,一个女孩的母亲要给这个女海介绍对象。 大家都看得很明白了吧!LR模型是一股脑儿的把所有特征塞入学习,而决策树更像是编程语言中的if-else一样,去做条件判断,这就是根本性的区别。 决策树基于“… 1. 什么是决策树1.1 决策树的基本思想其实用一下图片能更好的理解LR模型和决策树模型算法的根本区别,我们可以思考一下一个决策问题:是否去相亲,一个女孩的母亲要给这个女海介绍对象。 大家都看得很明白了吧!LR模型是一股脑儿的把所有特征塞入学习,而决策树更像是编程语言中的if-else一样,去做条件判断,这就是根本性的区别。 1.2 “树”的成长过程决策树基于“树”结构进行决策的,这时我们就要面临两个问题 : “树”怎么长。 这颗“树”长到什么时候停。 弄懂了这两个问题,那么这个模型就已经建立起来了,决策树的总体流程是“分而治之”的思想,一是自根至叶的递归过程,一是在每个中间节点寻找一个“划分”属性,相当于就是一个特征属性了。接下来我们来逐个解决以上两个问题。 这颗“树”长到什么时候停 当前结点包含的样本全属于同一类别,无需划分;例如:样本当中都是决定去相亲的,属于同一类别,就是不管特征如何改变都不会影响结果,这种就不需要划分了。 当前属性集为空,或是所有样本在所有属性上取值相同,无法划分;例如:所有的样本特征都是一样的,就造成无法划分了,训练集太单一。 当前结点包含的样本集合为空,不能划分。 1.3 “树”怎么长在生活当中,我们都会碰到很多需要做出决策的地方,例如:吃饭地点、数码产品购买、旅游地区等,你会发现在这些选择当中都是依赖于大部分人做出的选择,也就是跟随大众的选择。其实在决策树当中也是一样的,当大部分的样本都是同一类的时候,那么就已经做出了决策。 我们可以把大众的选择抽象化,这就引入了一个概念就是纯度,想想也是如此,大众选择就意味着纯度越高。好,在深入一点,就涉及到一句话:信息熵越低,纯度越高。我相信大家或多或少都听说过“熵”这个概念,信息熵通俗来说就是用来度量包含的“信息量”,如果样本的属性都是一样的,就会让人觉得这包含的信息很单一,没有差异化,相反样本的属性都不一样,那么包含的信息量就很多了。 一到这里就头疼了,因为马上要引入信息熵的公式,其实也很简单: $$Ent(D)=-\\sum_{k=1}^{|y|}p_klog_2p_k$$ Pk表示的是:当前样本集合D中第k类样本所占的比例为Pk。 信息增益 废话不多说直接上公式: 看不懂的先不管,简单一句话就是:划分前的信息熵–划分后的信息熵。表示的是向纯度方向迈出的“步长”。 好了,有了前面的知识,我们就可以开始“树”的生长了。 1.3.1 ID3算法解释:在根节点处计算信息熵,然后根据属性依次划分并计算其节点的信息熵,用根节点信息熵–属性节点的信息熵=信息增益,根据信息增益进行降序排列,排在前面的就是第一个划分属性,其后依次类推,这就得到了决策树的形状,也就是怎么“长”了。 如果不理解的,可以查看我分享的图片示例,结合我说的,包你看懂: 第一张图.jpg 第二张图.jpg 第三张图.jpg 第四张图.jpg 不过,信息增益有一个问题:对可取值数目较多的属性有所偏好,例如:考虑将“编号”作为一个属性。为了解决这个问题,引出了另一个 算法C4.5。 1.3.2 C4.5为了解决信息增益的问题,引入一个信息增益率: $$Gain_ratio(D,a)=\\frac{Gain(D,a)}{IV(a)}$$ 其中: $$IV(a)=-\\sum_{v=1}^{V}\\frac{|D^v|}{|D|}log_2\\frac{|D^v|}{|D|}$$ 属性a的可能取值数目越多(即V越大),则IV(a)的值通常就越大。信息增益比本质: 是在信息增益的基础之上乘上一个惩罚参数。特征个数较多时,惩罚参数较小;特征个数较少时,惩罚参数较大。不过有一个缺点: 缺点:信息增益率偏向取值较少的特征。 使用信息增益率:基于以上缺点,并不是直接选择信息增益率最大的特征,而是现在候选特征中找出信息增益高于平均水平的特征,然后在这些特征中再选择信息增益率最高的特征。 1.3.3 CART算法数学家真是聪明,想到了另外一个表示纯度的方法,叫做基尼指数(讨厌的公式): $$Gini(D)=\\sum_{k=1}^{|y|}\\sum_{k_{‘}\\neq k}p_{k}p_{k^{‘}}=1-\\sum_{k=1}^{|y|}{p_k}^2$$ 表示在样本集合中一个随机选中的样本被分错的概率。举例来说,现在一个袋子里有3种颜色的球若干个,伸手进去掏出2个球,颜色不一样的概率,这下明白了吧。Gini(D)越小,数据集D的纯度越高。 举个例子假设现在有特征 “学历”,此特征有三个特征取值: “本科”,“硕士”, “博士”, 当使用“学历”这个特征对样本集合D进行划分时,划分值分别有三个,因而有三种划分的可能集合,划分后的子集如下: 1.划分点: “本科”,划分后的子集合 : {本科},{硕士,博士} 2.划分点: “硕士”,划分后的子集合 : {硕士},{本科,博士} 3.划分点: “硕士”,划分后的子集合 : {博士},{本科,硕士}} 对于上述的每一种划分,都可以计算出基于 划分特征= 某个特征值 将样本集合D划分为两个子集的纯度: $$Gini(D,A)=\\frac{|D_1|}{|D|}Gini(D_1)+\\frac{|D_2|}{|D|}Gini(D_2)$$ 因而对于一个具有多个取值(超过2个)的特征,需要计算以每一个取值作为划分点,对样本D划分之后子集的纯度Gini(D,Ai),(其中Ai 表示特征A的可能取值) 然后从所有的可能划分的Gini(D,Ai)中找出Gini指数最小的划分,这个划分的划分点,便是使用特征A对样本集合D进行划分的最佳划分点。到此就可以长成一棵“大树”了。 1.3.4 三种不同的决策树 ID3:取值多的属性,更容易使数据更纯,其信息增益更大。 训练得到的是一棵庞大且深度浅的树:不合理。 C4.5:采用信息增益率替代信息增益。 CART:以基尼系数替代熵,最小化不纯度,而不是最大化信息增益。 2. 树形结构为什么不需要归一化?因为数值缩放不影响分裂点位置,对树模型的结构不造成影响。按照特征值进行排序的,排序的顺序不变,那么所属的分支以及分裂点就不会有不同。而且,树模型是不能进行梯度下降的,因为构建树模型(回归树)寻找最优点时是通过寻找最优分裂点完成的,因此树模型是阶跃的,阶跃点是不可导的,并且求导没意义,也就不需要归一化。 既然树形结构(如决策树、RF)不需要归一化,那为何非树形结构比如Adaboost、SVM、LR、Knn、KMeans之类则需要归一化。 对于线性模型,特征值差别很大时,运用梯度下降的时候,损失等高线是椭圆形,需要进行多次迭代才能到达最优点。但是如果进行了归一化,那么等高线就是圆形的,促使随机梯度下降(SGD)往原点迭代,从而导致需要的迭代次数较少。 3. 分类决策树和回归决策树的区别Classification And Regression Tree(CART)是决策树的一种,CART算法既可以用于创建分类树(Classification Tree),也可以用于创建回归树(Regression Tree),两者在建树的过程稍有差异。 回归树: CART回归树是假设树为二叉树,通过不断将特征进行分裂。比如当前树结点是基于第j个特征值进行分裂的,设该特征值小于s的样本划分为左子树,大于s的样本划分为右子树。 $$R_1(j,s)={x|x^{(j)}\\leq s} and R_2(j,s)={x|x^{(j)}>s}$$ 而CART回归树实质上就是在该特征维度对样本空间进行划分,而这种空间划分的优化是一种NP难问题,因此,在决策树模型中是使用启发式方法解决。典型CART回归树产生的目标函数为: $$\\sum_{x_i\\in R_m}(y_i-f(x_i))^2$$ 因此,当我们为了求解最优的切分特征j和最优的切分点s,就转化为求解这么一个目标函数: $$min_{j,s}[min_{c_1}\\sum_{x_i\\in R_1(j,s)}(y_i-c_1)^2+min_{c_2}\\sum_{x_i\\in R_2(j,s)}(y_i-c_2)^2]$$ 所以我们只要遍历所有特征的的所有切分点,就能找到最优的切分特征和切分点。最终得到一棵回归树。 参考文章:经典算法详解–CART分类决策树、回归树和模型树 4. 决策树如何剪枝决策树的剪枝基本策略有 预剪枝 (Pre-Pruning) 和 后剪枝 (Post-Pruning)。 预剪枝:其中的核心思想就是,在每一次实际对结点进行进一步划分之前,先采用验证集的数据来验证如果划分是否能提高划分的准确性。如果不能,就把结点标记为叶结点并退出进一步划分;如果可以就继续递归生成节点。 后剪枝:后剪枝则是先从训练集生成一颗完整的决策树,然后自底向上地对非叶结点进行考察,若将该结点对应的子树替换为叶结点能带来泛化性能提升,则将该子树替换为叶结点。 参考文章:决策树及决策树生成与剪枝 5. 决策树的特征重要度怎么算?5. 代码实现GitHub:https://github.com/NLP-LOVE/ML-NLP/blob/master/Machine%20Learning/3.Desition%20Tree/DecisionTree.ipynb 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】逻辑回归","slug":"ML/Logistics Regression","date":"2019-07-05T16:00:00.000Z","updated":"2019-12-25T04:39:06.920Z","comments":true,"path":"2019/07/06/ML/Logistics Regression/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/06/ML/Logistics%20Regression/","excerpt":"逻辑回归是用来做分类算法的,大家都熟悉线性回归,一般形式是Y=aX+b,y的取值范围是[-∞, +∞],有这么多取值,怎么进行分类呢?不用担心,伟大的数学家已经为我们找到了一个方法。 也就是把Y的结果带入一个非线性变换的SIGMOID函数中,即可得到[0,1]之间取值范围的数S,S可以把它看成是一…","text":"逻辑回归是用来做分类算法的,大家都熟悉线性回归,一般形式是Y=aX+b,y的取值范围是[-∞, +∞],有这么多取值,怎么进行分类呢?不用担心,伟大的数学家已经为我们找到了一个方法。 也就是把Y的结果带入一个非线性变换的SIGMOID函数中,即可得到[0,1]之间取值范围的数S,S可以把它看成是一… 1. 什么是逻辑回归逻辑回归是用来做分类算法的,大家都熟悉线性回归,一般形式是Y=aX+b,y的取值范围是[-∞, +∞],有这么多取值,怎么进行分类呢?不用担心,伟大的数学家已经为我们找到了一个方法。 也就是把Y的结果带入一个非线性变换的Sigmoid函数中,即可得到[0,1]之间取值范围的数S,S可以把它看成是一个概率值,如果我们设置概率阈值为0.5,那么S大于0.5可以看成是正样本,小于0.5看成是负样本,就可以进行分类了。 2. 什么是Sigmoid函数函数公式如下: 函数中t无论取什么值,其结果都在[0,-1]的区间内,回想一下,一个分类问题就有两种答案,一种是“是”,一种是“否”,那0对应着“否”,1对应着“是”,那又有人问了,你这不是[0,1]的区间吗,怎么会只有0和1呢?这个问题问得好,我们假设分类的阈值是0.5,那么超过0.5的归为1分类,低于0.5的归为0分类,阈值是可以自己设定的。 好了,接下来我们把aX+b带入t中就得到了我们的逻辑回归的一般模型方程: $$H(a,b)=\\frac{1}{1+e^{(aX+b)}}$$ 结果P也可以理解为概率,换句话说概率大于0.5的属于1分类,概率小于0.5的属于0分类,这就达到了分类的目的。 3. 损失函数是什么逻辑回归的损失函数是 log loss,也就是对数似然函数,函数公式如下: 公式中的 y=1 表示的是真实值为1时用第一个公式,真实 y=0 用第二个公式计算损失。为什么要加上log函数呢?可以试想一下,当真实样本为1是,但h=0概率,那么log0=∞,这就对模型最大的惩罚力度;当h=1时,那么log1=0,相当于没有惩罚,也就是没有损失,达到最优结果。所以数学家就想出了用log函数来表示损失函数。 最后按照梯度下降法一样,求解极小值点,得到想要的模型效果。 4.可以进行多分类吗?可以的,其实我们可以从二分类问题过度到多分类问题(one vs rest),思路步骤如下: 1.将类型class1看作正样本,其他类型全部看作负样本,然后我们就可以得到样本标记类型为该类型的概率p1。 2.然后再将另外类型class2看作正样本,其他类型全部看作负样本,同理得到p2。 3.以此循环,我们可以得到该待预测样本的标记类型分别为类型class i时的概率pi,最后我们取pi中最大的那个概率对应的样本标记类型作为我们的待预测样本类型。 总之还是以二分类来依次划分,并求出最大概率结果。 5.逻辑回归有什么优点 LR能以概率的形式输出结果,而非只是0,1判定。 LR的可解释性强,可控度高(你要给老板讲的嘛…)。 训练快,feature engineering之后效果赞。 因为结果是概率,可以做ranking model。 6. 逻辑回归有哪些应用 CTR预估/推荐系统的learning to rank/各种分类场景。 某搜索引擎厂的广告CTR预估基线版是LR。 某电商搜索排序/广告CTR预估基线版是LR。 某电商的购物搭配推荐用了大量LR。 某现在一天广告赚1000w+的新闻app排序基线是LR。 7. 逻辑回归常用的优化方法有哪些7.1 一阶方法梯度下降、随机梯度下降、mini 随机梯度下降降法。随机梯度下降不但速度上比原始梯度下降要快,局部最优化问题时可以一定程度上抑制局部最优解的发生。 7.2 二阶方法:牛顿法、拟牛顿法:这里详细说一下牛顿法的基本原理和牛顿法的应用方式。牛顿法其实就是通过切线与x轴的交点不断更新切线的位置,直到达到曲线与x轴的交点得到方程解。在实际应用中我们因为常常要求解凸优化问题,也就是要求解函数一阶导数为0的位置,而牛顿法恰好可以给这种问题提供解决方法。实际应用中牛顿法首先选择一个点作为起始点,并进行一次二阶泰勒展开得到导数为0的点进行一个更新,直到达到要求,这时牛顿法也就成了二阶求解问题,比一阶方法更快。我们常常看到的x通常为一个多维向量,这也就引出了Hessian矩阵的概念(就是x的二阶导数矩阵)。 缺点:牛顿法是定长迭代,没有步长因子,所以不能保证函数值稳定的下降,严重时甚至会失败。还有就是牛顿法要求函数一定是二阶可导的。而且计算Hessian矩阵的逆复杂度很大。 拟牛顿法: 不用二阶偏导而是构造出Hessian矩阵的近似正定对称矩阵的方法称为拟牛顿法。拟牛顿法的思路就是用一个特别的表达形式来模拟Hessian矩阵或者是他的逆使得表达式满足拟牛顿条件。主要有DFP法(逼近Hession的逆)、BFGS(直接逼近Hession矩阵)、 L-BFGS(可以减少BFGS所需的存储空间)。 8. 逻辑斯特回归为什么要对特征进行离散化。 非线性!非线性!非线性!逻辑回归属于广义线性模型,表达能力受限;单变量离散化为N个后,每个变量有单独的权重,相当于为模型引入了非线性,能够提升模型表达能力,加大拟合; 离散特征的增加和减少都很容易,易于模型的快速迭代; 速度快!速度快!速度快!稀疏向量内积乘法运算速度快,计算结果方便存储,容易扩展; 鲁棒性!鲁棒性!鲁棒性!离散化后的特征对异常数据有很强的鲁棒性:比如一个特征是年龄>30是1,否则0。如果特征没有离散化,一个异常数据“年龄300岁”会给模型造成很大的干扰; 方便交叉与特征组合:离散化后可以进行特征交叉,由M+N个变量变为M*N个变量,进一步引入非线性,提升表达能力; 稳定性:特征离散化后,模型会更稳定,比如如果对用户年龄离散化,20-30作为一个区间,不会因为一个用户年龄长了一岁就变成一个完全不同的人。当然处于区间相邻处的样本会刚好相反,所以怎么划分区间是门学问; 简化模型:特征离散化以后,起到了简化了逻辑回归模型的作用,降低了模型过拟合的风险。 9. 逻辑回归的目标函数中增大L1正则化会是什么结果。所有的参数w都会变成0。 10. 代码实现GitHub:https://github.com/NLP-LOVE/ML-NLP/blob/master/Machine%20Learning/2.Logistics%20Regression/demo/CreditScoring.ipynb 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP 欢迎大家加入讨论!共同完善此项目!群号:【541954936】","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]},{"title":"【机器学习】线性回归","slug":"ML/Linner Regression","date":"2019-07-04T16:00:00.000Z","updated":"2019-12-25T04:39:31.028Z","comments":true,"path":"2019/07/05/ML/Linner Regression/","link":"","permalink":"http://reverent-montalcini-17e4bf.netlify.com/2019/07/05/ML/Linner%20Regression/","excerpt":"线性回归对大量的观测数据进行处理,从而得到比较符合事物内部规律的数学表达式。也就是说寻找到数据与数据之间的规律所在,从而就可以模拟出结果,也就是对结果进行预测。解决的就是通过已知的数据得到未知的结果。例如:对房价的预测、判断信用评价、电影票房预估等。","text":"线性回归对大量的观测数据进行处理,从而得到比较符合事物内部规律的数学表达式。也就是说寻找到数据与数据之间的规律所在,从而就可以模拟出结果,也就是对结果进行预测。解决的就是通过已知的数据得到未知的结果。例如:对房价的预测、判断信用评价、电影票房预估等。 1.什么是线性回归 线性:两个变量之间的关系是一次函数关系的——图象是直线,叫做线性。 非线性:两个变量之间的关系不是一次函数关系的——图象不是直线,叫做非线性。 回归:人们在测量事物的时候因为客观条件所限,求得的都是测量值,而不是事物真实的值,为了能够得到真实值,无限次的进行测量,最后通过这些测量数据计算回归到真实值,这就是回归的由来。 2. 能够解决什么样的问题对大量的观测数据进行处理,从而得到比较符合事物内部规律的数学表达式。也就是说寻找到数据与数据之间的规律所在,从而就可以模拟出结果,也就是对结果进行预测。解决的就是通过已知的数据得到未知的结果。例如:对房价的预测、判断信用评价、电影票房预估等。 3. 一般表达式是什么$$Y=wx+b$$ w叫做x的系数,b叫做偏置项。 4. 如何计算4.1 Loss Function–MSE$$J=\\frac{1}{2m}\\sum^{i=1}_{m}(y^{‘}-y)^2$$ 利用梯度下降法找到最小值点,也就是最小误差,最后把 w 和 b 给求出来。 5. 过拟合、欠拟合如何解决使用正则化项,也就是给loss function加上一个参数项,正则化项有L1正则化、L2正则化、ElasticNet。加入这个正则化项好处: 控制参数幅度,不让模型“无法无天”。 限制参数搜索空间 解决欠拟合与过拟合的问题。 5.1 什么是L2正则化(岭回归)方程: $$J=J_0+\\lambda\\sum_{w}w^2$$ $J_0$ 表示上面的 loss function ,在loss function的基础上加入w参数的平方和乘以 $\\lambda$ ,假设: $$L=\\lambda({w_1}^2+{w_2}^2)$$ 回忆以前学过的单位元的方程: $$x^2+y^2=1$$ 正和L2正则化项一样,此时我们的任务变成在L约束下求出J取最小值的解。求解J0的过程可以画出等值线。同时L2正则化的函数L也可以在w1w2的二维平面上画出来。如下图: L表示为图中的黑色圆形,随着梯度下降法的不断逼近,与圆第一次产生交点,而这个交点很难出现在坐标轴上。这就说明了L2正则化不容易得到稀疏矩阵,同时为了求出损失函数的最小值,使得w1和w2无限接近于0,达到防止过拟合的问题。 5.2 什么场景下用L2正则化只要数据线性相关,用LinearRegression拟合的不是很好,需要正则化,可以考虑使用岭回归(L2), 如何输入特征的维度很高,而且是稀疏线性关系的话, 岭回归就不太合适,考虑使用Lasso回归。 5.3 什么是L1正则化(Lasso回归)L1正则化与L2正则化的区别在于惩罚项的不同: $$J=J_0+\\lambda(|w_1|+|w_2|)$$ 求解J0的过程可以画出等值线。同时L1正则化的函数也可以在w1w2的二维平面上画出来。如下图: 惩罚项表示为图中的黑色棱形,随着梯度下降法的不断逼近,与棱形第一次产生交点,而这个交点很容易出现在坐标轴上。这就说明了L1正则化容易得到稀疏矩阵。 5.4 什么场景下使用L1正则化L1正则化(Lasso回归)可以使得一些特征的系数变小,甚至还使一些绝对值较小的系数直接变为0,从而增强模型的泛化能力 。对于高的特征数据,尤其是线性关系是稀疏的,就采用L1正则化(Lasso回归),或者是要在一堆特征里面找出主要的特征,那么L1正则化(Lasso回归)更是首选了。 5.5 什么是ElasticNet回归ElasticNet综合了L1正则化项和L2正则化项,以下是它的公式: $$min(\\frac{1}{2m}[\\sum_{i=1}^{m}({y_i}^{‘}-y_i)^2+\\lambda\\sum_{j=1}^{n}\\theta_j^2]+\\lambda\\sum_{j=1}^{n}|\\theta|$$ 5.6 ElasticNet回归的使用场景ElasticNet在我们发现用Lasso回归太过(太多特征被稀疏为0),而岭回归也正则化的不够(回归系数衰减太慢)的时候,可以考虑使用ElasticNet回归来综合,得到比较好的结果。 6. 线性回归要求因变量服从正态分布?我们假设线性回归的噪声服从均值为0的正态分布。 当噪声符合正态分布N(0,delta^2)时,因变量则符合正态分布N(ax(i)+b,delta^2),其中预测函数y=ax(i)+b。这个结论可以由正态分布的概率密度函数得到。也就是说当噪声符合正态分布时,其因变量必然也符合正态分布。 在用线性回归模型拟合数据之前,首先要求数据应符合或近似符合正态分布,否则得到的拟合函数不正确。 7. 代码实现GitHub:房价预测 8. 什么叫广义线性模型广义线性模型相对于经典的线性模型(y=wx+b),核心在于引入了连接函数g(.),形式变为:y=g−1(wx+b)。 作者:@mantchs GitHub:https://github.com/NLP-LOVE/ML-NLP","categories":[{"name":"机器学习","slug":"机器学习","permalink":"http://reverent-montalcini-17e4bf.netlify.com/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"}],"tags":[]}]}