拒绝成为一个老好人

(一)珍惜自己的时间和精力

当年在国外留学,有一次挂着QQ开始自习,突然QQ发出提示,结果定睛一看,是一位长久不联系的同学发来了消息。于是开始一阵寒暄之后,同学就开始问“你什么时候回国啊?帮我带一个iPhone好不好?听说国外比较便宜”之类的话。对于这种场景,想必各位留学生都不陌生。由于汇率差等一些因素,香港和新加坡的电子产品一般来说比国内会便宜一些,总会有国内各种各样的同学联系国外的同学,求帮忙带各种各样的物品。小到 iPod,大到 Mac Pro,甚至会有衣服和化妆品。

能够提出这种要求的人认为留学生在国外学习生活,平时闲着无事可做,顺便去商场买一个 iPhone 或者化妆品轻而易举。再说,反正这个留学生会回国,回国的时候顺便塞在箱子里面就可以带回来了,也不用国际邮递的费用,举手之劳而已。这种时候,不同的留学生就会有不同的处理方案,有一种是有求必应,导致自己回国的箱子塞满了其他人的行李。另外一种是置之不理,只带着自己应该携带的行李。

第一种人呢,就是传统意义上的老好人。这种人对其他人的要求都是有求必应,别人随便说的一句话,顺口提的一个要求都会极大可能地去满足对方,哪怕自己亏本。其实,对于一个留学生而言,时间就是金钱,无论是去商场买东西还是在网上下单购物都会耗费大量的时间。曾经见过一位留学生花了很多时间去商场帮忙代购奢侈品,回国的时候却因为颜色略有不同,对方拒不买单的情况。导致这些结果,都是因为一些留学生在无形之中当了一次老好人,认为别人只是提了一个要求,自己应该完成。不过请别忘记,求别人帮忙是需要人情的,国内的朋友求留学生带iPhone,就已经欠了留学生一个人情。而且在这个过程中,留学生的时间成本被无限度的降低,代购在对方的眼里就只是一个不需要成本的事情。而真正的朋友,会尊重对方的付出,会时刻维持着这一份友谊。

(二)不要有求必应

博士生一般都会承担每周6小时甚至更多的助教任务,在这几个小时内,需要给本科生开设课程,讲解习题,有的时候还需要给本科生批改作业。在考试前夕,就有学生有问题需要来咨询博士生。本来,博士生作为助教,是有义务给本科生讲解习题的。但是,总有一些本科生,会在考试前提出各种各样无理的要求,比如“再把这门课从头到尾给我讲解一遍,把这套试卷给我讲解一下”之类的。在我眼里,能提出这种要求的学生,基本上考试也就这样了,讲不讲已经基本上不重要了。作为一个大学生,自己需要为自己的选择买单,平时不花时间学习,一天晚上就想搞定高分几乎是一件不可能的事情。对于这些学生,自己的选择一般都是提出建议:“你可以去数学系五楼的答疑教室,那里会有助教给你详细地讲解问题”。

但是,也有一些助教,不会拒绝学生,为了满足学生的这些需求,在考试前不吃饭不睡觉,时刻保持email在线,随时准备回答学生提出的各种各样的问题。对于学生提出了需要当面答疑的要求也从不拒绝,从早上9点一直干到晚上11点,每两个小时就安排一批学生答疑。当然这种对工作负责任的精神值得大家学习,不过这种方式实在是不可取。作为一个PHD,首要任务就是科研,教学只是不那么重要的一件事情,只要不出教学事故,不收到学生投诉即可。就目前的就业情况来看,科研论文才是王道,为了学生付出太多实在是舍本逐末。退一万步讲,能够提出让助教花费整个晚上为他答疑这种要求的本科生,只是把助教当成了一个可以有求必应的人,只是把这个职业当成了服务性的职业,认为交了学费就应该享受到这些服务。对于这些学生,实在是不值得花费博士生过多的精力。数学系本来就给本科生开设了 Consultation Room,在非助教工作时间完全可以把答疑的工作推给这些地方,因为只有这些地方才是专门为了学生答疑而设置的机构,而不是私底下给学生们答疑。学会对一些不合理的要求说“不”是一个非常重要的能力。

(三)不要成为别人情绪的垃圾桶

想必大家都在玩腾讯的两大产品,微信和QQ。在微信或者QQ上面,总会有人时刻传递着各种负能量,随便抓住一个朋友就开始抱怨自己的生活多么不如意,自己的人生有多么的艰难。偶尔一两次当然无所谓,就当是开导朋友,帮朋友一把也是一种义务。但是,如果天天抱怨这些事情而没有任何正能量,就会让人产生一种厌恶。使用微信或者QQ是为了达成一种信息的交换,如果一方一直产生负能量,就会在无形之中把这种负能量传递给其他人,从而影响到其他人的生活。

在读本科的时候,大家或许还会互相关心一下对方在做什么。到了工作岗位之后,其他人做什么样的事情其实已经和自己没有太大关系了,尤其是不在同一个公司,同一个城市,甚至同一个行业的人。一些整天抱怨行业或者运气不好的人,何必不鼓起勇气跳出圈子,去寻找想要的东西。在微信或者QQ上抱怨并不能够解决任何问题,能够摆脱这种现状只有靠自己的努力,而不是当一个键盘侠。对于一些整天传播负能量的人,最好的办法就是屏蔽他们,避免他们的情绪影响到自己的生活。

每个人都在一天天地成长,在帮助别人的同时也在接受着其他人的帮助。对于别人小小的帮助,要学会感恩。在帮助他人的时候,也要学会明辨是非,拒绝成为一个老好人。

Advertisement

消耗时间的微信

最近和朋友们探讨app的话题,不约而同的都说到微信。无论是在工作日还是在周末,大家最常做的事情就是翻看聊天记录或者去看朋友圈。但是就现在的社会发展而言,不看微信又是一件特别不现实的事情,那么如何减少对微信的依赖就成为了一个关键的问题。

(一)避免实时响应消息

不少的人在使用微信的时候,已经养成了实时回复朋友消息,时刻关注朋友圈的习惯。如果在周末实时回复朋友消息,可能还好,毕竟周末只是一个休息的时刻。如果是在工作日要做到实时回复朋友的消息,那可能就有大麻烦了。对于一些脑力工作者而言,最害怕的就是在工作期间被打断。因为一旦被打断了工作,各种思路就必须要重新捡起来,耗时耗力。但是有的人在使用微信的时候,就已经形成了强迫症,不点开微信的红点消息,不查看朋友圈的消息提示就会觉得全身不舒服。这种时候,一定要想尽办法中断自己的这种条件反射。解决办法就是关闭微信消息的提示。这种时候就肯定会有人纠结一个问题,如果有人有急事找我,那该怎么办?其实,就个人的经验而言,如果真的有急事,那个人一定会直接打电话给你,而不是在手机边等着你慢慢地回复微信。通过微信聊天的,一般来说要么是暂时闲着无聊或者无事可做,要么就是说一些重要但是不那么紧急的事情,并不需要立刻做出回复。如果关闭了微信的消息提示,那么只要把手机放在一边即可,反正不会有新的消息提示,也就减少了触碰手机的频率,也就可以减少这种实时响应消息的条件反射行为。

在微信上的沟通经常都是有上句没有下句,本来打电话两分钟就可以说清楚的事情,在微信上面真的就需要沟通半小时甚至更长的时间。如果是在电车上闲着无聊,玩玩微信来 kill time 确实是一个不错的选择。但是如果在办公室或者工作岗位上,时刻通过微信沟通业务其实是一种效率不高的做法。

(二)慎重对待朋友圈

大家或多或少的都会在朋友圈发送一些图片,转载一些文章,这些事情本来也是正常的,都是正常的社交途径。但是如果在工作的时候时刻关注朋友圈,那也会造成很多时间的浪费。如果有朋友发送了朋友圈,那么朋友圈的位置就会出现一个小红点,时刻提醒着大家去看朋友圈。如果有朋友回复了朋友圈,那么就会直接出现消息的提示。很常见的一种情况就是:本来只打算看一下有没有新的消息,却一不小心打开了朋友圈,反而耗费了更多的时间在微信上。这个时候,可以关闭朋友圈的新消息提示,然后就再也不会出现小红点强迫大家去看朋友圈。这样的话,在忙碌的时候就不会时刻关注朋友圈,在休息的时候可以批量处理朋友圈消息。有人肯定会纠结:如果错过了朋友圈一些重要的消息怎么办?其实,说句实在话,朋友圈里面没有任何一条消息是必须需要处理了,完全可以忽略。目前朋友圈最多的无非就是旅游照片,自拍,转发的文章甚至微商。信息量很大,但是有用的信息却不多。能够获取有效知识的途径是通过书籍或者一些有质量的博客,而不是通过朋友圈。

(三)如何处理群聊

想必大家都用过微信群,随着时间的推移,微信群里面的成员就会越来越多,同时每个人也在不停地加入新的微信群。如果不把这些微信群的消息提示关掉,那么手机很快就会没电了,因为时刻都会有各种各样的群消息弹出来,并且群消息里面有很多是根本不需要关心和和回复的消息。也正是这些消息时刻转移着每个人的注意力。除此之外,红包本身是一个很优秀的产品设计,但是如果在工作的时候不停地关注红包,那可能就会酿成惨剧。几个月前不就有公交司机在车辆行驶的途中抢红包导致车祸的事情么。因此,为了不浪费自己的时间,关闭一些闲聊群的消息提示就是一件非常有必要的事情。至于红包,反正也没多少,喝一杯星巴克几十块钱都不眨眼的人,还会在乎那几块钱么。所以开启群消息免打扰就是一件必须要做的事情。

(四)工作和生活尽量分开

在一些大的公司里面,有着自行研发的实时聊天系统,因此在微信里面一般不会探讨工作的事情,但是对于没有这类系统的公司或者企业而言,上级通过微信来给下级布置任务就是一件特别常见的事情。经常出现的情况就是,本来是在聊工作的话题,突然有一个生活群冒出一个新的消息,同时自己又特别感兴趣,于是就会打开消息框,在里面和群友们谈笑风生。而且使用微信的时候,总会有朋友时不时寒暄几句,然后又不由自主的忘记了本来就应该完成的工作。你一句我一句,高效的工作模式就会被硬生生的切换成散漫的闲聊模式,导致工作没有办法按时完成,甚至只能够靠加班来完成任务。其实现在发现,随着大家步入了工作岗位,频繁的使用着微信,QQ的消息数反而减少了不少。经常发现登陆了一天的QQ,然后1对1的消息数几乎是零,除了群里面会有着各种各样的消息。这个时候,使用QQ来进行工作上的沟通或者是任务的布置或许真的就是一个不错的选择。

随着微信的发展,总会不由自主的时刻关注着微信消息,朋友圈,各种公众号。一旦有半分钟的闲暇时间,就会立刻掏出手机,查看各种各样的消息。在工作中,也总会时刻关注着手机的消息提示。也就是说,微信不仅占据着大量的碎片时间,甚至还在工作的时间中切割着每个人的大块时间。对于一个程序员或者其他脑力工作者而言,保证整块的工作时间是非常有必要的,这样可以保证工作的效率和质量。

最后,上面写了那么多,也说了一些解决的方法,当然也不一定很有效。不过,微信也要继续用,聊天也要继续聊,朋友圈也要继续发,红包当然也要继续抢。要做的只是选择一个合适的时间,合适的地点,合适的一群人,做合适的事情。

读博驱动力的五个阶段:过山车曲线

读博时的驱动力并非一成不变,它也经历了类似于创业者们都体验过的阶段。蒂姆·费里斯(Tim Ferriss)在他的博客中提到这些阶段:(充分)利用创业时的狂躁抑郁症:让过山车(曲线)服务于你。蒂姆·费里斯为创业者们提供了有用的建议,而这些建议同样适用于研究与读博历程。

第一阶段:不知情时的乐观

当你开始读博,一切都是新鲜的,你觉得你的研究项目很酷。那种感觉就像是你将要去解决一个大问题,如果你还有抱负并且表现良好,说不定还能获得很大的回报,也许是一个专利,或者一篇被刊登在颇具影响力的杂志上的论文。是不是听上去很耳熟?(其实,)它类似于(你)刚开始接触一份新的工作,所有人都对你比以前(的同事对你)好,以及一切顺利。好吧,再过几个月(让激情再飞一会),你将意识到这并不是(想象中的)那么振奋人心。

第二阶段:知情后的悲观

你已经在你的研究项目上耕耘有一段时日,也更理解这个领域了,但不幸的是,你依然迷惘。你(似乎)无法在不远的将来看到任何好的成果,并开始疑惑这个研究项目对你而言是不是太大。如果你的博士研究不是延续于前人的工作,比如你更换了研究领域,这个阶段的(悲观)体验将更强烈。

第三阶段:信念危机(读博意义的危机)

你正处于读博历程的中段,却有着如四十岁男人一般的(中年)危机感:你既然没钱给自己买辆保时捷(Porsche),就只能躲在一个角落默默地垂泪。你在想:“结束了吗?我是个失败者?!” 研究项目也不再是你想象中的那么秀色可餐(pinkful),事实上,你不得不为完成一部分很难称得上优雅的研究工作而奋斗。你觉得已经浪费了大量的时间,而且做了很多毫无意义的小事。(但是,)虽然这些小事现在看起来毫无用处,但你永远不知道,也许就在未来的某个时刻,你为它们串起了线索(connect the dots),它们便有可能成为某项伟大事业的出发点。

第四阶段:崩溃与浴火重生(可选)

如果你在第三阶段没有快步地走出那些阴霾的负面感觉,你将面临崩溃。消极的情绪可能掌控了一切,使你染上一场迷你抑郁症。在这个阶段,很多人认为他们已经浪费了太多的时间以致于决定放弃。他们携一份未竟的读博事业黯然离去。无论如何,我们想避免这样的情形。

第五阶段:知情后的乐观

慢慢地,你开始意识到你的博士论文将不会像你想象中的让人击节称赞或叹为观止(awesome)。不管了(Whatever)。至少你会有几篇刊文,足够毕业。也许,《自然(Nature)》(就算想要你的文章也)不得不等你读上了博士后。但有谁会关心(Who cares)。你最好(至少)能读出个半吊子的博士来,这比什么都强。(当前,)你正紧挨着研究领域的前沿,可以为先进的科技文化做出(或多或少的)贡献。于愿足矣。这就足够了,你并不需要成就完美。

这条(过山车)曲线也吻合这几年收集的读博数据。它意味着每个人都经历着某种程度的(读博)价值预期的偏离。(因人而异,)某些阶段会缓和些,某些阶段可能很剧烈。在任何阶段,请不要因过度的乐观或悲观而失去常态(不以物喜,不以己悲)。沉静若水,我的朋友(Stay cool, be water my friend)。

 

英文原文如下:

Transition Curve
The motivation during your PhD is not constant, and it resembles the phases that entrepreneurs experience and that Tim Ferriss describes in his post Harnessing Entrepreneurial Manic Depression: Making The Rollercoaster Work for You. Tim provides great advice for entrepreneurs, but this can easily be adapted to research and PhD life.

Phase 1: Uninformed optimism

You start your PhD, everything is new and you find your project really cool. It feels like you are going to solve a big problem and you might get a big prize if you are ambitious and work well, maybe a patent, maybe a paper in a high impact journal. Sounds familiar? It is a similar feeling to starting in a new job, everybody is nicer than in the previous job and it is by far better organized. Well, give it some months, you’ll realize it is not that great.

Phase 2: Informed Pessimism

You have been working for some time on your project, you understand the field better, but unfortunately you are still lost. You don’t see any good results in the near future and you start to realize that this project might be a bit too big for you. This phase is more severe if the content of your PhD is not a continuation from a previous work, if you switched fields.

Phase 3: Crisis of Meaning

You are more or less in the middle of your PhD and you have a crisis like 40 year old guys have. Since you don’t have money to buy you a Porsche, you just cry in silence in a corner. You think “Is this all? Am I a failure?” The project is not as pinkful as you dreamt it, in fact, you are going to struggle and work your ass off to finish a minimally decent body of work. You feel that you have wasted a lot of time, that you did a lot of useless little projects. Now they seem useless, but you never know, maybe sometime later you connect the dots and they were the starting points of something great.

Phase 4: Crash and Burn (optional)

While at Phase 3, if you don’t step aside fast from your negative feelings you are going to be screwed. Negativity might take over, leading you a mini depression. At this stage, many people think they have been wasting their time and they give up. They walk away with an unfinished PhD. Needless to say, we want to avoid this.

Phase 5: Informed Optimism

Slowly you start to realize that your PhD thesis is not going to be as awesome as you thought. Whatever. At least you’ll get some publications, enough to graduate. Maybe the Nature paper has to wait for your post-doc. Who cares. You’d better finish a half-ass Phd than nothing. You are getting the grip of your field, you can contribute (something) to the state of the art. It should be enough. Good enough, you don’t need perfect.

This curve is fitted to PhD data collected during many years. This means everybody will experience a certain deviation from the values here predicted. Some phases will be mild while others can be extreme. At any stage, don’t be carried away by over-optimism/pessimism. Stay cool, be water my friend.

Interested in becoming a Scientist 2.0? Then visit my blog: http://juliopeironcely.com/

开公众号之后的一些感想

从2015年11月左右开始写订阅号的文章,至今也有大半年的时光了。其中得到了很多朋友的帮助和建议,也有朋友在后台留言,在此感谢大家。不过在看到一些问题的时候,有一些想法,在此写出来和大家一起分享。

PS:自己踏入社会也没多长的时间,可能其中也会有一些偏见,希望大家多多指教。

1. 范例思维

在写《博士生涯》系列文章的时候,有的朋友会在后台留言咨询这类问题:“在NUS读完PHD之后能否去美国或者欧洲做博士后?能否回国去985,211高校?”

关于这一类的问题,可能和大家在中学,大学所受到的教育有关系。在中学的时候,大家只有一个目标,那就是高考,所有事情和所有人都必须围绕着这件事情转,沿着这条路走下去。但是到了大学之后,就会明显的发现身边的同学不再只围绕着学习这一件事情,比方说有很多同学会去参加社团活动,有不少同学会去做社会实践,当然也有一批同学依旧以学习为主业,持续着中学的生活。其实,这几种生活方式都是可以接受的,毕竟在18岁之后,很多事情就需要自己亲自做决定。这个时候就会带来一个问题,如果学生明确知道自己想做什么事情,那就不会产生迷茫,肯定就一股脑的做下去了。但是,很多学生是不清楚自己该做什么,不该做什么的。那么在大学里面就会有老师,辅导员甚至学长学姐来给大家提供经验,告诉大家应该做什么,只有做什么能够带来最大的收益。

到了国外攻读博士学位的阶段,这种环境就会产生巨大的变化。不再有老师的就业辅导,不再有辅导员这个职位,甚至没有学长学姐的经验总结。用常见的话说就是:一切皆有可能。比如,在NUS读PHD的过程中,自己亲眼见过自己的朋友遇到过各种各样的悲剧。有的是导师辞职离开学校,把学生留在学校不闻不问的;有的是即使导师在学校,也对学生的科研不关心的;有的是拖着学生长期不给毕业的。身边的朋友也做过各种各样的选择,包括读博期间换导师的,转专业的,甚至退学的。至于毕业的去向,不仅有去欧美做博士后的,有去大学做助理教授的,也有去投行的,甚至有去互联网公司的。每个人都有着自己的生活,除了特别亲密的朋友,你不再会去关心别人做什么样的工作,过什么样的生活了。每个人根据自己的情况,走着完全不同的路,根本就没有模板一样的人可以模仿。每个人都需要为自己的选择负责,为自己的未来做着准备。

2. 线性思维

还有一些经常碰到的问题就是:“在NUS读完PHD,能够去投行工作吗?”,“在读博士期间需要去考CFA吗?”,“博士毕业工资能够拿多少?”,“这个硕士生或者博士生的项目竞争力如何,值得去读么?”

这些就是典型的线性思维,就是做了事件A,必然会导致事件B的发生。在现实生活中,人的发展不仅要考虑自身的情况,还需要考虑历史的进程。也就是说,很多时候并不是因果关系而是某种相关性导致了事件的发生。首先,读PHD,没有人能够保证博士生一定能毕业。其次,学生也不知道自己要读几年才能够毕业,只能够根据师兄师姐的毕业年限计算一个期望值。再次,导师给学生的推荐信质量也是不同的,师兄能够去985,说不定由于导师不喜欢某学生导致该学生只能够去二本教书,即使这个学生的论文发的水平远远高于师兄。并且跟一些厉害老板的学生的出路也不见得比一些普通老板的学生出路好。最后,能不能够去投行,能拿到多少工资基本上都是因人而异。曾经见过纯数学的同学去投行做quant,去互联网公司写代码,做着和博士论文基本上没有关系的工作。真正厉害的人,不在于多读了一个学位或者考了一个CFA,而在于那些让他们厉害的背后因素,一些其他人根本不具备的素质,比如性格,意志力等。

3. 学生思维

之前某天写过一篇转行的文章,有人在后台留言:“这些技术能不能进了企业再开始学?”,“转行到底要花多少时间?”,“在公司有没有人带着干活?”

在学校的时候,无论是本科,硕士,还是博士阶段,学生都可以告诉老师,虽然我不会,但是我愿意学。但是按照普通企业的招聘标准,一般都是观察这个人能否胜任该岗位的需求(或者说有潜力胜任这个岗位),而不是看这个人愿不愿意学。在企业工作,是需要时刻有产出的,无论是成功的项目还是失败的项目,都需要给出一个交代。企业是一个商业机构,需要员工有产出,然后从中获取利润的,而不是像学校一样的培训机构。

至于转行的时间肯定是因人而异的,不同的人有着不同的思维方式,不同的知识结构,所能够做的事情也会有所不同。不过如果想好了要转行的话,早准备肯定胜过不准备。还有的人会问如何快速的学习HIVE,C++之类的,这一类问题实在是不知道怎么回答。不过如果有一个人问我,如何在十天内快速学会实变函数,我一定会告诉他这是一件不可能的事情。

刚进公司的时候,一般来说会企业都会指定一位导师,给新人划定工作的范围,甚至有明确的deadline,看上去其实和学生时代没有什么两样。但是如果只是抱着完成任务的心态来工作,那这个项目基本上就完蛋了。上级一般来说会希望员工主动去思考一些问题,主动做一些事情,甚至有一个较为长远的规划。做这些事情都是希望员工能够成长起来,能够在工作中独当一面,能够和别的团队甚至和其它公司竞争。在学校中,一般来说老师都会主动教学生很多知识,希望学生学会这些技能。但是在工作中,有人主动传授知识和技能,绝对一种可遇而不可求的事情,很多技能都需要自己主动地去学习。别人出于援手帮助是由于他们的好心,如果没有出手也不必苛责。每个人在公司里面都有着做不完的业务,忙不完的事情,实在是没有多余的时间去指导其他人。既然在别人都可以自学成才,为何不自己动手主动学习,丰衣足食?在大多数情况下,一定要放弃“老师教才会学”的学习方法,企业雇佣一个人是用来产生价值的,而不是不是消耗公司资源的。

4. 不独立的思维

在学校的生活中,除了读PHD期间课题的未知性,在中学,本科,硕士的作业甚至论文几乎都有标准答案,考试也有规定的范围。在学生生涯中,除了读博士阶段,一般来说老师都会告诉学生该怎么做,不该怎么做。但是到了工作中,处处都是未知,每一天都是一种“考试”,没有固定的答案可以参考,没有现成的模版可以参考。学生思维的人一般都会以一种被动的方式去接受任务并完成任务,当然这并没有错。不过以职场的角度来说,这样就会处于一种非常被动的方式,一般都会在做一些繁重而没有多少技术含量的任务。在职场混,不但要学习,还需要主动给业务方甚至自己的团队出谋划策,想各种方案应对当前的问题。

在实际工作中,不仅需要提升自己的技能点,亲自动手做调研的工作,还需要学会和业务方沟通,想办法从其它地方获取资源供自己调用,甚至知道如何管理项目。如果独立负责一个小项目的话,不仅需要自己把控项目的进度,积极反馈产品的不足之处,还要推动项目其余成员去做该做的事情,一起把项目做好做大。在项目的进展中,不仅需要把具体的任务落实到每一个人身上,还需要实时地与大家沟通,了解项目的困难点和关键时间点,更好的完成项目。

异常点检测算法(二)

前面一篇文章《异常点检测算法(一)》简要的介绍了如何使用概率统计的方法来计算异常点,本文将会介绍一种基于矩阵分解的异常点检测方法。在介绍这种方法之前,先回顾一下主成分分析(Principle Component Analysis)这一基本的降维方法。

(一)主成分分析(Principle Component Analysis)

对高维数据集合的简化有各种各样的原因,例如:

(1)使得数据集合更容易使用;

(2)降低很多算法的计算开销;

(3)去除噪声;

(4)更加容易的描述结果。

在主成分分析(PCA)这种降维方法中,数据从原来的坐标系转换到新的坐标系,新坐标系的选择是由数据集本身所决定的。第一个新坐标轴的方向选择的是原始数据集中方差最大的方向,第二个新坐标轴的选择是和第一个坐标轴正交并且具有最大方差的方向。该过程一直重复,重复的次数就是原始数据中特征的数目。如此操作下去,将会发现,大部分方差都包含在最前面的几个新坐标轴之中。因此,我们可以忽略余下的坐标轴,也就是对数据进行了降维的处理。

为了提取到第一个主成分(数据差异性最大)的方向,进而提取到第二个主成分(数据差异性次大)的方向,并且该方向需要和第一个主成分方向正交,那么我们就需要对数据集的协方差矩阵进行特征值的分析,从而获得这些主成分的方向。一旦我们计算出了协方差矩阵的特征向量,我们就可以保留最大的 N 个值。正是这 N 个值反映了 N 个最重要特征的真实信息,可以把原始数据集合映射到 N 维的低维空间。

提取 N 个主成分的伪代码如下:

去除平均值

计算协方差矩阵

计算协方差矩阵的特征值和特征向量

将特征值从大到小排序

保留最大的N个特征值以及它们的特征向量

将数据映射到上述N个特征向量构造的新空间中

通过 Python 的 numpy 库和 matplotlib 库可以计算出某个二维数据集合的第一主成分如下:原始数据集使用蓝色的三角形表示,第一主成分使用黄色的圆点表示。

PCA

Principle Component Analysis 的基本性质:

Principle component analysis provides a set of eigenvectors satisfying the following properties:

(1)If the top-k eigenvectors are picked (by largest eigenvalue), then the k-dimensional hyperplane defined by these eigenvectors, and passing through the mean of the data, is a plane for which the mean square distance of all data points to it is as small as possible among all hyperplanes of dimensionality k.

(2)If the data is transformed to the axis-system corresponding to the orthogonal eigenvectors, the variance of the transformed data along each eigenvector dimension is equal to the corresponding eigenvalue. The covariances of the transformed data in this new representation are 0.

(3)Since the variances of the transformed data along the eigenvectors with small eigenvalues are low, significant deviations of the transformed data from the mean values along these directions may represent outliers.

(二)基于矩阵分解的异常点检测方法

基于矩阵分解的异常点检测方法的关键思想是利用主成分分析去寻找那些违背了数据之间相关性的异常点。为了发现这些异常点,基于主成分分析(PCA)的算法会把原始数据从原始的空间投影到主成分空间,然后再把投影拉回到原始的空间。如果只使用第一主成分来进行投影和重构,对于大多数的数据而言,重构之后的误差是小的;但是对于异常点而言,重构之后的误差依然相对大。这是因为第一主成分反映了正常值的方差,最后一个主成分反映了异常点的方差。

假设 dataMat 是一个 p 维的数据集合,有 N 个样本,它的协方差矩阵是 X。那么协方差矩阵就通过奇异值分解写成:

X=PDP^{T},

其中 P 是一个 (p,p) 维的正交矩阵,它的每一列都是 X 的特征向量。D 是一个 (p,p) 维的对角矩阵,包含了特征值 \lambda_{1},...,\lambda_{p}。从图像上看,一个特征向量可以看成 2 维平面上面的一条线,或者高维空间里面的一个超平面。特征向量所对应的特征值反映了这批数据在这个方向上的拉伸程度。通常情况下,可以把对角矩阵 D 中的特征值进行从大到小的排序,矩阵 P 的每一列也进行相应的调整,保证 P 的第 i 列对应的是 D 的第 i 个对角值。

这个数据集 dataMat 在主成分空间的投影可以写成

Y=dataMat\times P.

需要注意的是做投影可以只在部分的维度上进行,如果使用 top-j 的主成分的话,那么投影之后的数据集是

Y^{j}=dataMat \times P^{j},

其中 P^{j} 是矩阵 P 的前 j 列,也就是说 P^{j} 是一个 (p,j) 维的矩阵,Y^{j} 是一个 (N,j) 维的矩阵。如果考虑拉回映射的话(也就是从主成分空间映射到原始空间),重构之后的数据集合是

R^{j}=(P^{j}\times (Y^{j})^{T})^{T}=Y^{j}\times (P^{j})^{T},

其中 R^{j} 是使用 top-j 的主成分进行重构之后形成的数据集,是一个 (N,p) 维的矩阵。

下面可以定义数据 dataMat_{i}=(dataMat_{i,1},...,dataMat_{i,p}) 的异常值分数(outlier score)如下:

score(dataMat_{i})=\sum_{j=1}^{p}(|dataMat_{i}-R_{i}^{j}|)\times ev(j)

ev(j)=\sum_{k=1}^{j}\lambda_{k}/\sum_{k=1}^{p}\lambda_{k}

注意到 |dataMat_{i}-R_{i}^{j}| 指的是 Euclidean 范数, ev(j) 表示的是 top-j 的主成分在所有主成分中所占的比例,并且特征值是按照从大到小的顺序排列的。因此,ev(j) 是递增的序列,这就表示 j 越高,越多的方差就会被考虑在 ev(j) 中,因为是从 1 到 j 的求和。在这个定义下,偏差最大的第一个主成分获得最小的权重,偏差最小的最后一个主成分获得了最大的权重 1。根据 PCA 的性质,异常点在最后一个主成分上有着较大的偏差,因此可以获得更高的分数。

整个算法的结构如图所示:

PCC

 

(三)效果展示

下面两幅图使用了同一批数据集,分别采用了基于矩阵分解的异常点检测算法和基于高斯分布的概率模型的异常点算法。

PCC2

基于矩阵分解的异常点检测

 

Gauss

基于高斯分布的概率模型的异常点检测

根据图像可以看出,如果使用基于矩阵分解的异常点检测算法的话,偏离第一主成分较多的点都被标记为异常点,其中包括部分左下角的点。需要注意的是如果使用基于高斯分布的概率模型的话,是不太可能标记出左下角的点的,两者形成鲜明对比。

异常点检测算法(一)

异常点检测(又称为离群点检测)是找出其行为很不同于预期对象的一个检测过程。这些对象被称为异常点或者离群点。异常点检测在很多实际的生产生活中都有着具体的应用,比如信用卡欺诈,工业损毁检测,图像检测等。

异常点(outlier)是一个数据对象,它明显不同于其他的数据对象,就好像它是被不同的机制产生的一样。例如下图红色的点,就明显区别于蓝色的点。相对于蓝色的点而言,红色的点就是异常点。

outlier

一般来说,进行异常点检测的方法有很多,最常见的就是基于统计学的方法。

(一)基于正态分布的一元离群点检测方法

假设有 n 个点 (x_{1},...,x_{n}),那么可以计算出这 n 个点的均值 \mu 和方差 \sigma。均值和方差分别被定义为:

\mu=\sum_{i=1}^{n}x_{i}/n,

\sigma^{2}=\sum_{i=1}^{n}(x_{i}-\mu)^{2}/n.

在正态分布的假设下,区域 \mu\pm 3\sigma 包含了99.7% 的数据,如果某个值距离分布的均值 \mu 超过了 3\sigma,那么这个值就可以被简单的标记为一个异常点(outlier)。

(二)多元离群点的检测方法

涉及两个或者两个以上变量的数据称为多元数据,很多一元离群点的检测方法都可以扩展到高维空间中,从而处理多元数据。

(1)基于一元正态分布的离群点检测方法

假设 n 维的数据集合形如 \vec{x}_{i}=(x_{i,1},...,x_{i,n}), i\in \{1,...,m\},那么可以计算每个维度的均值和方差 \mu_{j},\sigma_{j}, j\in\{1,...,n\}. 具体来说,对于 j\in \{1,...,n\},可以计算

\mu_{j}=\sum_{i=1}^{m}x_{i,j}/m

\sigma_{j}^{2}=\sum_{i=1}^{m}(x_{i,j}-\mu_{j})^{2}/m

在正态分布的假设下,如果有一个新的数据 \vec{x},可以计算概率 p(\vec{x}) 如下:

p(\vec{x})=\prod_{j=1}^{n} p(x_{j};\mu_{j},\sigma_{j}^{2})=\prod_{j=1}^{n}\frac{1}{\sqrt{2\pi}\sigma_{j}}\exp(-\frac{(x_{j}-\mu_{j})^{2}}{2\sigma_{j}^{2}})

根据概率值的大小就可以判断 x 是否属于异常值。运用该方法检测到的异常点如图,红色标记为异常点,蓝色表示原始的数据点。

Gauss

(2)多元高斯分布的异常点检测

假设 n 维的数据集合 \vec{x}=(x_{1},...,x_{n}), ,可以计算 n 维的均值向量

\vec{\mu}=(E(x_{1}),...,E(x_{n}))

n\times n 的协方差矩阵:

\Sigma=[Cov(x_{i},x_{j})], i,j \in \{1,...,n\}

如果有一个新的数据 \vec{x},可以计算

p(\vec{x})=\frac{1}{(2\pi)^{\frac{n}{2}}|\Sigma|^{\frac{1}{2}}} \exp(-\frac{1}{2}(\vec{x}-\vec{\mu})^{T}\Sigma^{-1}(\vec{x}-\vec{\mu}))

根据概率值的大小就可以判断 \vec{x} 是否属于异常值。

(3)使用 Mahalanobis 距离检测多元离群点

对于一个多维的数据集合 D,假设 \overline{a} 是均值向量,那么对于数据集 D 中的其他对象 a,从 a\overline{a} 的 Mahalanobis 距离是

MDist(a,\overline{a})=\sqrt{(a-\overline{a})^{T}S^{-1}(a-\overline{a})},

其中 S 是协方差矩阵。

在这里,MDist(a,\overline{a}) 是数值,可以对这个数值进行排序,如果数值过大,那么就可以认为点 a 是离群点。或者对一元实数集合 \{MDist(a,\overline{a})|a\in D\} 进行离群点检测,如果 MDist(a,\overline{a}) 被检测为异常点,那么就认为 a 在多维的数据集合 D 中就是离群点。

运用 Mahalanobis 距离方法检测到的异常点如图,红色标记为异常点,蓝色表示原始的数据点。

Mahalanobis

(4)使用 \chi^{2} 统计量检测多元离群点

在正态分布的假设下,\chi^{2} 统计量可以用来检测多元离群点。对于某个对象 \bold{a}\chi^{2} 统计量是

\chi^{2}=\sum_{i=1}^{n}(a_{i}-E_{i})^{2}/E_{i}.

其中,a_{i}\bold{a} 在第 i 维上的取值,E_{i} 是所有对象在第 i 维的均值,n 是维度。如果对象 \bold{a}\chi^{2} 统计量很大,那么该对象就可以认为是离群点。

运用 \chi^{2} 统计量检测到的异常点如图,红色标记为异常点,蓝色表示原始的数据点。

ChiSquare

 

异常点检测算法(三)Replicator Neural Networks

异常值检测算法在数据挖掘的诸多领域有着应用场景,例如金融领域,信息传输领域,图像领域等。在研究过程中,有学者给出了异常点的一个定义:

An outlier is an observation that deviates so much from other observations as as to arouse suspicion that it was generated by a different mechanism.

RNN 算法的主要思想

在这篇文章中,我们将会介绍一个多层的前馈神经网络,该神经网络可以用来进行异常值的检测。这个神经网络模拟的是一个恒等映射,输入层的神经元个数和输出层的神经元个数是一样的。这类的神经网络被称为 Replicator Neural Networks (RNNs),请注意这里的 RNN 算法指的并不是 Recurrent Neural Networks(RNNs),而是 Replicator Neural Networks,尽管它们拥有着同样的缩写名字 RNNs。具体来说, Replicator Neural Networks (RNNs),或者说自编码器,是一个多层前馈的神经网络 (multi-layer feed-forward neural networks)。在 Replicator Neural Networks 中,输入的变量也是输出的变量,模型中间层节点的个数少于输入层和输出层节点的个数。这样的话,模型就起到了压缩数据和恢复数据的作用。

rnn1

如图所示,这里的 RNNs 有三个隐藏层,输入层和输出层的节点个数都是6,第一个隐藏层和第三个隐藏层的节点个数(图中是4个节点)少于输入层,第二个隐藏层的节点个数是最少的(图中是2个节点)。在神经网络传输的时候,中间使用了 tanh 函数和 sigmoid 函数。这个神经网络是训练一个从输入层到输出层的恒等函数(identity mapping),传输的时候从输入层开始压缩数据,然后到了第二个隐藏层的时候开始解压数据。训练的目标就是使得整体的输出误差足够小,整体的误差是由所有的样本误差之和除以样本的个数得到的。由于图中只画出了6个特征,因此第 i 个样本的误差是

e_{i}=\sum_{j=1}^{6}(x_{i j}-r_{i j})^{2}/6

如果使用已经训练好的 RNN 模型,异常值的分数就可以定义为重构误差(reconstruction error)。

下面简要介绍一下 RNN 模型是如何构建的:

rnn2

根据上图所示,左边的是输入层,右边的输出层。假设第 k 层中第 i 个神经元的输出是 S_{k}(I_{ki}),其中 I_{ki} 表示第 k 层中第 i 个神经元的输入,S_{k} 表示第 k 层使用的激活函数。那么

\theta=I_{ki}=\sum_{j=0}^{L_{k-1}}w_{kij}Z_{(k-1)j}

其中 Z_{kj} 是第 k 层中第 j 个神经元的输出,L_{k} 是第 k 层神经元的个数。对于第二层和第四层而言 (k=2,4),激活函数选择为

S_{k}(\theta)=tanh(a_{k}\theta)  \text{ for } k=2 \text{ or } 4,

这里的 a_{k} 是一个参数,通常假设为1。对于中间层 (k=3) 而言,激活函数是一个类阶梯 (step-like) 函数。有两个参数 N 和 a_{3},N 表示阶梯的个数,a_{3} 表示从这一层到下一层的提升率 (transition rate):

S_{3}(\theta)=\frac{1}{2}+\frac{1}{4}\sum_{j=1}^{N-1}tanh(a_{3}(\theta-\frac{j}{N})).

在这里可以假设 a_{3}=100N=4. 那么 S_{3}(\theta) 就如下图所示。

S3

第三层的激活函数的输出就变成了 N 个离散的变量:0, 1/(N-1), 2/(N-1),…,1。这个阶梯型的激活函数是把第三层的连续输入值变成了一批离散的值。也就意味着把样本映射到了 N 个簇,那么 RNN 就可以计算出单个的异常点和一小簇的异常点。

备注:

根据上面的分析,可以看出如果按照以上算法,则不能使用反向传播算法来训练模型,原因是 S_{3}(\theta) 的导数不能够通过它的取值来表示。这一点与 tanh 函数,\sigma 函数是不一致的,因为 tanh^{'}(x) = 1-tanh^{2}(x)\sigma^{'}(x)=\sigma(x)(1-\sigma(x))。因此有学者指出 [1],使用三个隐藏层是没有必要的,使用1个或者2个隐藏层的神经网络也能够得到类似的结果;同样,没有必要使用 S_{3}(\theta) 这样类型的阶梯函数,使用传统的 \sigma 激活函数也能够得到类似的结果。并且 S_{3}(\theta) 是一个 step-like 函数,很多地方的导数取值都是接近于零的。

后向传播算法:

一般来说,为了训练神经网络模型,需要使用后向传播算法(back propagation),也简称为 BP 算法,或者误差逆传播算法(error back propagation)。在本文中,仅针对最简单的 RNN 模型介绍如何使用 BP 算法进行模型训练,至于多层的神经网络模型或者其他的神经网络模型,方法则是完全类似的。

rnn3

给定训练集合 D=\{(\bold{x}_{1},\bold{y}_{1}),...,(\bold{x}_{m},\bold{y}_{m})\},其中有 m 个样本,并且输入和输出是一样的值。换句话说,也就是 n 维向量

\bold{x}_{i}=\bold{y}_{i}\in\mathbb{R}^{n} \text{ for all } 1\leq i\leq m.

换句话说,输入样例是由 n 个属性描述,输出的结果也是 n 个属性。隐藏层只有一个,隐藏层的神经元个数是 q=[(n+1)/2],这里的 [] 表示 Gauss 取整函数。输出层第 j 个神经元的阈值使用 \theta_{j} 表示,隐藏层第 h 个神经元的阈值使用 \gamma_{h} 表示。输入层第 i 个神经元与隐藏层第 h 个神经元之间的连接权重是 v_{i h}, 隐藏层第 h 个神经元与输出层第 j 个神经元之间的连接权重是 w_{h j}, 其中 1\leq i \leq n, 1\leq h \leq q, 1\leq j \leq n.

记隐藏层第 h 个神经元接收到的输入为

\alpha_{h} = \sum_{i=1}^{n}v_{i h}x_{i} \text{ for all } 1\leq h \leq q.

写成矩阵形式就是:

(\alpha_{1},\cdot\cdot\cdot,\alpha_{q})=(x_{1},\cdot\cdot\cdot,x_{n})\begin{bmatrix} v_{11} & ... & v_{1q} \\ ... & ... & ... \\ v_{n1} & ... & v_{nq} \end{bmatrix}.

记输出层第 j 个神经元接收到的输入为

\beta_{j}=\sum_{h=1}^{q}w_{h j}b_{h} \text{ for all } 1\leq j\leq n,

其中 b_{h} 是隐藏层第 h 个神经元的输出,b_{h} = f(\alpha_{h}-\gamma_{h}) \text{ for all } 1\leq h \leq q, f 是激活函数。写成矩阵形式就是:

(\beta_{1},\cdot\cdot\cdot,\beta_{n})=(b_{1},\cdot\cdot\cdot,b_{q})\begin{bmatrix} w_{11} & ... & w_{1n} \\ ... & ... & ... \\ w_{q1} & ... & w_{qn} \end{bmatrix}.

输出层第 j 个神经元的输出是 f(\beta_{j}-\theta_{j}), 其中 1\leq j \leq n.

下面可以假定激活函数都使用 f(x)=1/(1+\exp(-x)), 那么直接通过导数计算可以得到 f^{'}(x)=f(x)(1-f(x)).

对于训练集 (\bold{x}_{k},\bold{y}_{k}), 通过神经网络得到的输出是 \hat{\bold{y}}_{k}=(\hat{y}_{k1},...,\hat{y}_{kn}), 并且 \hat{y}_{kj} = f(\beta_{j}-\theta_{j}) 对于 1\leq j \leq n 都成立。那么神经网络在训练集 (\bold{x}_{k},\bold{y}_{k}) 的均方误差是

E_{k} =\frac{1}{2}\sum_{j=1}^{n}(\hat{y}_{kj}-y_{kj})^{2},

其中 \bold{y}_{k}=(y_{k1},...,y_{kn}). 整体的误差是

E = \frac{1}{m}\sum_{k=1}^{m}E_{k} = \frac{1}{2m}\sum_{k=1}^{m}\sum_{j=1}^{n}(\hat{y}_{kj}-y_{kj})^{2}

标准 BP 算法:

网络中有 个参数需要确定:输入层到隐藏层的 n*q 个权重值,隐藏层到输出层的 n*q 个权重值,q个隐层神经元的阈值,n 个输出层神经元的阈值。BP 算法是一个迭代学习算法,在迭代的每一轮采用了梯度下降法来进行参数的更新。任意参数的更新规则是

v \leftarrow v+\Delta v.

标准 BP 算法是根据每一个 E_{k} 来获得更新规则,下面来推导每一个参数的更新规则。对于 1\leq h \leq q, 1\leq j \leq n, 计算梯度

\Delta w_{hj} = -\eta \frac{\partial E_{k}}{\partial w_{hj}},

注意到 w_{hj} 先影响到第 j 个输出层神经元的输入值 \beta_{j}, 再影响到第 j 个输出层神经元的输出值 \hat{y}_{kj},最后影响到 E_{k},根据高等数学的链式法则可以得到

\frac{\partial E_{k}}{\partial w_{hj}} = \frac{\partial E_{k}}{\partial \hat{y}_{kj}} \cdot \frac{\partial \hat{y}_{kj}}{\partial \beta_{j}} \cdot \frac{\partial \beta_{j}}{\partial w_{hj}}

根据定义 \beta_{j}=\sum_{h=1}^{q}w_{hj}b_{h} 可以得到 \frac{\partial \beta_{j}}{\partial w_{hj}}=b_{h} 对于 1\leq j \leq n 都成立。

根据定义 E_{k}=\frac{1}{2}\sum_{j=1}^{n}(\hat{y}_{kj}-y_{kj})^{2} 可以得到 \frac{\partial E_{k}}{\partial \hat{y}_{kj}}=(\hat{y}_{kj}-y_{kj}).

根据定义 \hat{y}_{kj}=f(\beta_{j}-\theta_{j})f^{'}(x)=f(x)\cdot(1-f(x)) 可以得到 \frac{\partial \hat{y}_{kj}}{\partial \beta_{j}}=f^{'}(\beta_{j}-\theta_{j})=f(\beta_{j}-\theta_{j})\cdot(1-f(\beta_{j}-\theta_{j}))=\hat{y}_{kj}\cdot (1-\hat{y}_{kj}).

所以可以计算出对于 1\leq h \leq q, 1\leq j \leq n,

\frac{\partial E_{k}}{\partial w_{hj}} = (\hat{y}_{kj}-y_{kj})\cdot\hat{y}_{kj}\cdot(1-\hat{y}_{kj})\cdot b_{h}

如果假设

g_{j}=-\frac{\partial E_{k}}{\partial \beta_{j}}=-\frac{\partial E_{k}}{\partial \hat{y}_{kj}}\cdot \frac{\hat{y}_{kj}}{\partial \beta_{j}}

那么可以得到

g_{j}=\hat{y}_{kj}\cdot(1-\hat{y}_{kj})\cdot(y_{kj}-\hat{y}_{kj})

因此对于 1\leq h \leq q, 1\leq j \leq n, 可以得到\Delta w_{hj}=\eta g_{j}b_{h}.

根据类似的想法,有

\Delta \theta_{j}=-\eta\cdot\frac{\partial E_{k}}{\partial \theta_{j}}, \Delta v_{ih}=-\eta\cdot\frac{\partial E_{k}}{\partial v_{ih}}, \Delta \gamma_{h}=-\eta\cdot\frac{\partial E_{k}}{\partial \gamma_{h}}.

逐个计算:

\frac{\partial E_{k}}{\partial \theta_{j}}=\frac{\partial E_{k}}{\partial \hat{y}_{kj}}\cdot\frac{\partial\hat{y}_{kj}}{\partial\theta_{j}}=(\hat{y}_{kj}-y_{kj})\cdot(-1)\cdot f^{'}(\beta_{j}-\theta_{j})=(y_{kj}-\hat{y}_{kj})\cdot\hat{y}_{kj}\cdot(1-\hat{y}_{kj})=g_{j}

\frac{\partial E_{k}}{\partial v_{ih}}=\frac{\partial E_{k}}{\partial\alpha_{h}}\cdot\frac{\partial\alpha_{h}}{\partial v_{ih}}=\frac{\partial E_{k}}{\partial b_{h}}\cdot\frac{\partial b_{h}}{\partial \alpha_{h}}\cdot\frac{\partial\alpha_{h}}{\partial v_{ih}}

由于

\frac{\partial \alpha_{h}}{\partial v_{ih}}=x_{ki}

\frac{\partial b_{h}}{\partial\alpha_{h}}=f^{'}(\alpha_{h}-\gamma_{h})=f(\alpha_{h}-\gamma_{h})\cdot(1-f(\alpha_{h}-\gamma_{h}))=b_{h}\cdot(1-b_{h})

\frac{\partial E_{k}}{\partial b_{h}}=\sum_{j=1}^{n}\frac{\partial E_{k}}{\partial \beta_{j}}\cdot\frac{\partial \beta_{j}}{\partial b_{h}}=\sum_{j=1}^{n}(-g_{j})\cdot w_{hj}

所以,

\Delta v_{ih}=\eta(\sum_{j=1}^{n}g_{j}w_{hj})\cdot b_{h}\cdot (1-b_{h})x_{ki} = \eta e_{h}x_{ki}, 其中 e_{h}=-\partial E_{k}/\partial\alpha_{h}=(\sum_{j=1}^{n}g_{j}w_{hj})\cdot b_{h}\cdot(1-b_{h}).

\Delta \gamma_{h}=(-\eta)\cdot\frac{\partial E_{k}}{\partial\gamma_{h}}=(-\eta)\cdot\frac{\partial E_{k}}{\partial b_{h}}\cdot\frac{\partial b_{h}}{\partial\gamma_{h}}=\eta\cdot(\sum_{j=1}^{n}g_{j}w_{hj})\cdot(-1)\cdot f^{'}(\alpha_{h}-\gamma_{h})=(-\eta)\cdot(\sum_{j=1}^{n}g_{j}w_{hj})\cdot b_{h}\cdot(1-b_{h})=(-\eta)\cdot e_{h} .

整理之后,任意参数 v 的更新式子是 v\leftarrow v+\Delta v, 并且更新的规则如下:

\Delta w_{hj}=\eta g_{j}b_{h} \text{ for all } 1\leq j\leq n, 1\leq h \leq q,

\Delta \theta_{j}=-\eta g_{j} \text{ for all } 1\leq j\leq n,

\Delta v_{ih}=\eta e_{h}x_{ki} \text{ for all } 1\leq i\leq n, 1\leq h\leq q,

\Delta \gamma_{h}=-\eta e_{h} \text{ for all } 1\leq h\leq q,

其中学习率 \eta\in(0,1) 控制着算法每一轮迭代中的更新步长,若步长太大则容易振荡,太小则收敛速度过慢,需要人工调整学习率。 对每个训练样例,BP 算法执行下面的步骤:先把输入样例提供给输入层神经元,然后逐层将信号往前传,直到计算出输出层的结果;然后根据输出层的误差,再将误差逆向传播至隐藏层的神经元,根据隐藏层的神经元误差来对连接权和阈值进行迭代(梯度下降法)。该迭代过程循环进行,直到达到某个停止条件为止。

标准 BP 算法的训练流程:
输入:训练集合 D={(\bold{x}_{k},\bold{y}_{k})}_{k=1}^{m} 和学习率 \eta.
过程:
1. 在 (0,1) 范围内随机神经网络中的所有连接权重和阈值
2. repeat
for all (\bold{x}_{k},\bold{y}_{k}) do
根据当前参数,计算出当前的样本输出 \bold{y}_{k}
计算输出层神经元的梯度项 g_{j}
计算隐藏层神经元的梯度项 e_{h}
更新连接权重 w_{hj}, v_{ih} 与阈值 \theta_{j},\gamma_{h}
end for
3. 达到停止条件
输出:链接权与阈值都确定的神经网络模型

累积 BP 算法:

BP 算法的目的是最小化训练集上的累计误差 E=\sum_{k=1}^{m}E_{k}/m, 其中 m 是训练集合中样本的个数。不过,标准的 BP 算法每次仅针对一个训练样例更新连接权重和阈值,也就是说,标准 BP 算法的更新规则是基于单个的 E_{k} 推导而得到的。通过类似的计算方法可以推导出累计误差的最小化更新规则,那就得到了累计误差逆传播(accumulate error backpropagation)算法。标准 BP 算法需要进行更多次的迭代,并且参数的更新速度快,累积 BP 算法必须扫描一次训练集合才会进行一次参数的更新,而且累计误差下降到一定的程度以后 ,进一步下降就会明显变慢,此时标准 BP 算法往往会更快的得到较好的解,尤其是训练集合大的时候。

训练方法:

(1)把数据集合的每一列都进行归一化;

(2)选择 70% 的数据集合作为训练集合,30% 的数据集合作为验证集合。或者 训练集合 : 验证集合 = 8 : 2,这个需要根据情况而定。

(3)随机生成一个三层的神经网络结构,里面的权重都是随机生成,范围在 [0,1] 内。输入层的数据和输出层的数据保持一致,并且神经网络中间层的节点个数是输入层的一半。

(4)使用后向传播算法(back-propagation)来训练模型。为了防止神经网络的过拟合,通常有两种策略来防止这个问题。(i)第一种策略是“早停”(early stopping):当训练集合的误差降低,但是验证集合的误差增加时,则停止训练,同时返回具有最小验证集合误差的神经网络;(ii)第二种策略是“正则化”(regularization):基本思想是在误差目标函数中增加一个用于描述网络复杂度的部分,例如链接权和阀值的平方和。

测试效果:

其中蓝色的点表示正常点,红色的点表示被 RNN 算法标记的异常点。

rnn_result1

rnn_result2

参考文献:

[1] Anomaly Detection Using Replicator Neural Networks Trained on Examples of One Class, Hoang Anh Dau, Vic Ciesielski, Andy Song

[2] Replicator Neural Networks for Outlier Modeling in Segmental Speech Recognition, Laszlo Toth and Gabor Gosztolya

[3] Outlier Detection Using Replicator Neural Networks, Simon Hawkins, Honxing He, Graham Williams and Rohan Baxter

 

聚类算法(一)

聚类是一种无监督学习(无监督学习是指事先并不知道要寻找的内容,没有固定的目标变量)的算法,它将相似的一批对象划归到一个簇,簇里面的对象越相似,聚类的效果越好。聚类的目标是在保持簇数目不变的情况下提高簇的质量。给定一个 n 个对象的集合。把这 n 个对象划分到 K 个区域,每个对象只属于一个区域。所遵守的一般准则是:同一个簇的对象尽可能的相互接近或者相关,而不同簇的对象尽可能的区分开。最常见的一种聚类算法则是 K-均值 算法。

K-均值(K-Means)聚类算法

K 均值聚类算法是用来发现给定数据集的 K 个簇的一种无监督学习算法,簇的个数是由人工给定的,每个簇使用质心(Centroid)和相应的半径(Radius)来描述。需要量化的误差指标有误差平方和(sum of squared error)等。

K-均值算法是一种启发式的算法。它会渐近地提高聚类的质量,达到局部的最优解,但是就是因为这样,才容易陷入局部最优解,而没有达到全局最优解,所有有人提出了二分 K-均值算法。启发式的聚类算法很适合发现中小规模的簇,对于大数据集合,从计算量来说成本则会很高。K-均值算法也有着自己的不足之处,通过下面算法可以发现 K-均值算法对离群点特别敏感,离群点的存在会直接影响着 K-均值算法的效果。

K 均值算法的流程是这样的。首先,随机确定 K 个初始点作为质心。然后将数据集中的每个点分配到每一个簇中,具体来讲,为每一个数据点找距离其最近的质心,并将其分配给该质心所对应的簇。这一步完成之后,每个簇的质心更新为该簇所有点的平均值。

K-Means 的伪代码:

创建K个点作为初始的质心(经常是随机选择数据点中的K个点,而不是平面上随机的K个点)

当任意一个点的簇分配结果发生变化时:

    对数据集中每个数据点

        对每个质心,计算质心与数据点之间的距离

        将数据点分配到距离其最近的簇

    对每一个簇,计算簇中所有点的均值并将均值作为质心

注:K 均值算法在某些时候容易收敛到局部最小值。

使用一批二维数据集合,进行 4 均值聚类算法可以得到下图:’+’ 表示的是质心的位置,其余就是数据点的位置。

聚类1

 

效果评估:

SSE 指的是 Sum of Squared Error(误差平方和)越小表示数据点越接近它们的质心,聚类的效果也就越好。质心使用 c[i] 表示,质心 c[i] 所包含的对象集合使用 C[i] 表示。如果用 p 表示 C[i] 中的某个对象,dist(p,c[i]) 表示的就是对象和质心 c[i] 的距离。那么误差平方和则定义为

E=\sum_{i=1}^{K}\sum_{p \in C[i]} dist(p, c[i])^{2}

 

二分 K 均值聚类(Bisecting K-Means)

为了解决 K 均值算法可能会收敛到局部最小值的情况,有人提出了二分 K 均值算法(bisecting K-means)。该算法首先将所有点作为一个簇,然后将该簇一分为二,之后选择其中的一个簇继续进行划分,选择哪一个簇进行划分取决于对其划分是否可以最大程度降低 SSE 的值。上述基于SSE的划分过程不断重复,直到得到用户指定的簇的数目为止。

二分 K-Means 的伪代码如下:

将所有的点看成一个簇

当簇的数量小于K时

    对于每一个簇

        计算总误差

        在给定的簇上面进行2均值聚类

        计算将该簇一分为二之后的总误差(指的是这两个簇的误差与其他剩余集的误差之和)

    选择使得总误差最小的那个簇进行划分操作

另一种做法就是:每次进行下一步划分的时候,选择误差平方和最大的簇进行划分,直到簇的数目达到用户指定的数目为止。这样的启发式算法就使得整体的误差平方和尽可能的小,也就是簇的划分更加精确。

使用一批二维数据集合,进行 3 均值聚类算法可以得到下图:’+’ 表示的是质心的位置,其余就是数据点的位置。

聚类2