现在,像达内、华清远见、国嵌、北大青鸟、传播智客等等IT培训机构很多,为尚未毕业的大学生、毕业了一时找不到工作的大学生、工作后想转行的再就业者提供了一个掌握新技能的机会,通过三个月或半年或更久的培训,你就可以掌握某一种技能,比如Android开发、Java Web开发、iOS开发、嵌入式Linux开发,然后,没然后了吗……

Sorry,然后还是有的,只不过,“然后”并不是像培训机构的销售代表频频给你通电话时宣传的那样光明罢了。有的机构会推荐你就业直到你彻底失望他们推荐的单位,有的机构会放你出去闯荡江湖四处碰壁……形式不一,但,一段痛苦的旅程从此开始了,这倒是真的。

很多单位歧视培训机构毕业的学员,你所在的单位是这样吗?或者你从IT培训机构毕业后,找工作时被鄙视了吗?

为了弄明白为什么IT培训机构出来的程序员在找工作时经常遭遇不平等对待,我们需要弄明白“教育”和“培训”的差别。

教育和培训

大致上讲,我们所说的“教育”,指的是掌握一般性的原理与技巧的过程;而我们所说的“培训”,不过是学会某种特定技能的过程。

上面是温伯格在《程序开发心理学》中说到的,符合大多数人对“教育”和“培训”的理解。

你可以通过培训机构学会理发、做饭、修汽车、写代码、做蛋糕,这没什么稀奇的,当我们接受培训时,就是为了某项技能而去的,不是吗?我去蓝翔,难道不是为了开挖掘机吗?

通常我们认为培训机构(学校)是学习某种不太复杂的谋生技能的摇篮。这种技能还有一个特点,就是相对稳定、变化不是特别频繁,能够在相当长一段时间内保持基本的稳定性。所以,一旦你获得了这项技能,就可以靠它吃饭吃上一阵子,一年半载,三年五年,十年八年,都有可能。

而教育,我们通常认为是一项基础性的工作,重知识,重原理,周期长,见效慢,与社会脱节,有时还能把人变傻(注意我不是讽刺现行教育制度,也不是诋毁我们伟大的大学教育)。虽然如此,很多IT公司的基础部门还是被受过正规大学教育的朋友们占据了重要岗位。因为大家普遍认为,虽然学校教育严重脱离社会现实,但名牌大学的学生的智力水平、学习能力,平均来看还是高于未能考上大学的中学生,更适合于从事某种对智力、学习能力有些特别要求的技术岗位。

没错,程序员正是这样的岗位。程序员的平均智力水平和学习能力高于大部分的其它行业从业者。

然而,教育和培训的差别,并不是关键。关键是,出于某种原因,面试官或公司主管对出身“培训机构”的人有偏见。为了说明这一点,我们先要看看程序员需要的特殊能力。

程序员需要的特殊能力

成为一个合格的程序员,需要以下“特殊”能力:

  • 自知之明
  • 自我学习
  • 努力

看起来没什么出奇之处,也许你会觉得一个程序员最重要的能力不是上面三项,没关系,知否知否,应是绿肥红瘦,随便怎么看,横看成岭侧成峰,一千个观众就有一千个哈姆雷特,嗯,开启口水模式……这里省略500字……

大家公认程序员从事的是烧脑性工作,行业发展日新月异,各种新语言新技术新框架新概念层出不穷,需要程序员时刻保持归零的学习心态,持续不断地保持学习维持竞争能力和价值。所以,我也是从这个角度出发,选择了前面提到的三点,实际上这三点指向的是“[学习之道]”。

自知之明

我们要了解自己拥有什么、缺乏什么,然后才能开始学习。

通过不断地总结、回顾自己做过的事情,我们就可以慢慢了解自己的能力边界。哪些事情做好了,好在哪里,为什么好在那里而不是别处,是由你自身的哪种行为、才干、能力决定的?哪些事情做得不好,坏在哪里,为什么坏在那个点而不是其它的点,改善你自身的哪种行为或能力可以改变事情的走向,还是说你没什么能改变的那就是你的局限?

当你了解了自己,就能发现自己应该做什么,就能决定自己的学习方向,而不是盲目地把自己交付给别人(学校、老师、家长、培训机构),因为,没有什么人真的可以为你负责,能为你负责的,只有你自己。

当然,自知是最难的事,也不是一朝一夕的事,需要不断的自省和内视才可以做到。

自我学习

知名的教育专家林格有两本非常著名的书,《教育是没有用的》和《学习是不需要教的》。林格有一个非常核心的观点:学习能力是人与生俱来的能力,是人之天赋,是不需要教的,但这种能力会随着年龄的增长和家庭教育、学校教育的误导而萎缩或消失,所以,教育的方向就是营造一个环境,让人自己发现自己的学习能力。

六祖慧能一朝顿悟传承衣钵,佛性自在每人心中。只不过,世人多如神秀,认为“身是菩提树,心如明镜台,时时勤拂拭,勿使惹尘埃”,一定要借助外力和各种各样的清规戒律,方可保持灵台清明,最终获得某种修行。这种扭曲了教育本质的说法、做法大行其道,导致中学教育(大学相对自由)重知识、重规矩、重技能而轻发现、轻唤醒、轻因材施教、轻有教无类,最终扼杀了学生的自我学习能力。所以,很多人不是天生不会学习,而是在成长过程中在家庭、学校、社会的各种外力撕扯中慢慢丧失了自我学习能力。更甚之,多数人不自知这种能力的丧失。

然而,程序员尤其需要自我学习能力。

学校会教你操作系统原理,会教你计算机组成原理,会教你算法,会教你C语言,会教你Java,各种知识都会教你。然而你到工作中,能不能用你学到的知识解决问题,实在是个未知数。

培训机构会教你怎么写Java代码,怎么安装某个IDE,怎么完成一个个人博客或购物车之类的小项目。然而,你是在框好的架子下被动地按照老师的要求“完成”了这些事。到了工作中,面对巨大的未知和陌生的项目,你能不能举一反三灵活运用,充满了未知。

[一个程序员能不能自己学会一门技术、能不能自己解决一个问题特别重要]。因为,很少有主管会手把手的教会你编程和设计的实际技巧,也很少有主管会大发慈悲把你送去研习班学习工作需要的技能,在一个现实的环境里,一切都要靠你自己。假如你自己不能独立习得某项必须的技术,真没有人能帮得上你。假如你自己不能独立解决问题,真没有人能始终拉扯着你。这也正合梁漱溟说的话:“任何一个人的学问成就,都是出于自学。学校教育不过给学生一个开端,使他更容易自学而已。青年于此,不可不勉。”

很多人轻视培训机构,是认为培训机构的老师,多数脱产,没有丰富的一线工程实践,是业余选手,而这些“业余选手”却要通过短短的一期培训来为社会培养“专业选手”,这基本是一个笑话。即便我们能举出不少从培训机构出来的优秀选手,那也只能说明,这个选手本身具有很好的学习能力。

如果一个人意识到了自己还具备自我学习能力,那他完全没必要去培训机构浪费动辄六七千一两万的学费——他完全可以自己学到必须的知识和技能,假如他真有兴趣的话。

而要检验你是否还有自我学习能力,先不要去培训机构,自己找本讲编程的书、找台电脑、连上网,花一两个月时间就能搞明白你是否适合做一个程序员。一旦你通过了这种自我学习实验,那时再挑一个培训机构系统地学习某条技术栈不迟。

言而总之,你能不能成为合格的或优秀的程序员,取决于自我学习能力,而不是参加过专业培训。所以,很多公司在招募程序员时,不太愿意考虑培训机构毕业的学员,因为在面试官的心里,觉得如果你有能力,自己就可以学会,完全没必要去培训机构,你接受了培训,他反倒认为你可能缺乏自我学习能力(以及对技术的兴趣),担心你不能胜任将来的工作,他太了解了,你学的那点东西根本不够用,还有很多新东西等着你学,所以,他不愿意考虑你。

而对于知名大学的毕业生,虽然可能和你一样是一张白纸,但别人会以为,能进得了大学当得了学霸,起码学习能力没问题的概率高一些。

努力

有一句话是这么说的,“以大多数人的努力程度之低,根本还轮不到拼天赋”。其实,努力也是一种天赋。为什么有的人明知努力可以改变生活,可他还是不努力呢?因为,臣妾做不到啊!为什么做不到,因为他缺乏“勤奋”、“努力”之类的天赋和才干。真的,勤奋、努力的人,多数是生就的,少数是被后妈(生活)逼的。

程序员白天要上班,晚上偶尔还要加个班,自由时间少,而新技术很多,什么时候去学呢?你以为实际的项目一定可以让你锻炼新技术吗?要知道,大部分的项目在技术选型时,会考虑技术的成熟度和团队的技术储备,很少有冒险采用大家都不熟悉的技术的,不可控因素太多,风险太大,项目失败的概率很高。那这样的话,你什么时间丰富自己呢?

八小时之内是现在,八小时之外是将来。你可以用的,就是你的业余时间了。你看,人家都在打游戏、看电视、挎着女伴的胳膊去速8,你还要苦哈哈的学习,如果你没有“努力”这种天赋,是很难做到的。

所以,很多面试官在面对培训机构毕业的人选时,也会有诸如“如果你有自我学习能力并且努力,其实没必要上什么培训班,完全可以自己搞定”之类的想法,而你上了培训班,是不是反过来证明你不够努力咧……然后,他又会想,是不是因为你没自知之明不知道自己要干啥才被忽悠到培训机构去交学费了呢……也许,他还会想,是不是因为你对技术其实不感兴趣只是想谋个事儿干呢……

额,你看,面无表情之下,其实各种想法如同暗流漩涡,澎湃不息……所以,最后,你可能就只好“回去等消息”了……


不知道说了这么多,你是否明白了个中原因——面试官会觉得培训出来的学员,可能对技术没有那么浓厚的兴趣、缺乏足够强的自我学习能力也不能很好的自律和努力。但在我的观念里,其实应该这么看待IT培训机构的学员:他只是找了一个类似学校的地方系统学了一些东西,和别人并无什么不同,如果他对技术有兴趣,有自我学习能力,一样可以做一个优秀的程序员。

文/foruok


一、写在之前的题外话

缘起。

想起要写这篇文章,一方面是昨天终于把项亮写的《推荐系统实践》给看完了,另一方面是自己负责的推荐系统项目已经处于一个多版本迭代的阶段了,并且从最近的AB测试效果来看,新提交的算法模型还是有一定的进步的,如今已经把流量全部切换到了新算法中。

所以,结合看书的一些思考,以及实际操作的一些感想,总是有一些想要表达、分享的东西,不吐不快啊~~ 哈哈!

不过在说个性化推荐之前,说两个题外话。

首先就是关于看书这个话题,我在《这些年,这些挖掘机算法,这些反思》一文中,曾经说到。看书是提升自我的一个最佳途径,我说过曾给自己定了一个每月看完一本书的目标,说来惭愧,至今只能算面面强强完成任务。不过关于看书这个观点,个人还是坚持自己的看法的。

首先是如何给自己挤出看书的时间,一是上下班地铁的零碎时间,二是睡觉前,三是敲代码搬砖搬累的时候。我想说的是,想要提升自己,书是一定要找时间看的。记住,这个时间不是为别人挤的,是为了未来你的薪水能够提上那么个一两档而挤的!

其次,关于看书的方法。以前,我看书只是试图理解作者的意图,然后从中吸取能够吸取的知识。现在,我看书喜欢拿着一支笔,边看边涂涂画画。我试图去理解作者说的话,然后结合自己的认知,写下自己的感想,甚至是依据自己的认识反驳作者的观点,然后事后去求证。

对于我不熟悉的领域,我会写下看完后的一些体会。然后就是对于部分章节,如果我认为其价值量并不值得我去细究,我会迅速的跳过,毕竟时间还是挺值钱的。所以,后期以来,只要是我看过的书,一些章节要么是涂涂画画了很多东西,要么是崭新的页面。总结起来就是,看书不能看死书,要有一定的效率和方法,找到适合自己的,然后从中获益!

OK,说了不少题外话,言归正传。

二、由这本书想到的一些东西

先来对这本书(《推荐系统实践》)来个整体评价吧。

个人对这本书的定位就是:它不是一本推荐系统的工具书,所以他不会详细的介绍推荐系统的一些算法,更多的笔墨在于讲述在设计个性化推荐系统中的一些衡量点、一些思维方式(这个我认为更重要,原因后面细说,甚至于书中的一些实验参考个人认为可看可不看)。

所以,感觉这本书的题目取的有点稍稍不合理~~

好吧,咱不纠结他的书名了,说一说一些书中个人认为值得一起分享的东西吧。这些东西都是看书之后,结合实践操作的一些感想。

并且,你会发现这章的内容,绝对不会是书中内容的重复,对于开挖掘机特别是开推荐系统挖掘机的人来说,相信我,我的观点会有用的!

(1) 首先谈一谈关于推荐系统评测

我先列一下作者列举的评测指标:用户满意度、预测准确度、覆盖率、多样性、新颖度、惊喜度、信任度、实时性、健壮性、商业目标。然后作者说,在设计推荐系统的时候,要尽量的考虑这些指标,特别是推荐的结果尽量满足多样性、新颖、能够惊喜就更好了。

关于这一点,其实个人观点有点不一样,我认为评测推荐结果只有一个指标就够了,那就是商业价值,能够提升商业价值,给业务带来更多利益的推荐系统,就是好的推荐系统。

至于说推荐的多样性、新颖度,如果多样化的推荐结果能够提升价值转换,那我们就在设计推荐系统的时候适当的提高多样性的权重,同样,如果新颖的东西能够提升价值转换,那么我们就提升新颖的权重。这才是回归推荐系统的本质!

在这一点上,在个人的实际操作中也是这样做的。我们会首先定好我们需要达到的目标,比如转化率或者是收益转换,我们调整算法的唯一依据就是:转化率提升了?如果是,那么我们的算法改进就是有效;如果不是,那么这次改进就是一个失败的改进。

至于说书中的每次实验,都评估覆盖率、多样性以及其他等几个指标,在我看来,其实是没有必要的。结合实践来说,因为你不敢保证提升你的推荐覆盖度就一定能够提升转化率,换言之,如果挖掘长尾能够提升转化率,那么,我们就适当提高覆盖度,并且尽量支持多样性。然而实际的业务场景是很复杂,这种保证并不是绝对的,需要依据于实际的情况而定,说白,那就是实际操作。

既然说到了实际操作,那我们说一说评测方法相关的东西吧。

书中列举了三种方式:离线实验、用户调查、在线实验。

首先说一下离线实验,个人认为在推荐系统中,利用已经现成的用户行为轨迹(即推荐之后是否点击之类的数据),来预测一个推荐系统并不是很靠谱,只能做为一个参考。因为,例如推荐这种场景,并不是如分类这种的模型,没有一个绝对值,对就是对,错就是错,它只是一个预测程度的提升。

其次,用户调查这种方式,有一定参考性,但是前提是调查的量要足够,如果取的量不够,其意义是不大的。所以,这是一个耗费巨大成本的工程,在实际的操作中并不可取。

所以,个人认为其重点应该是在在线实验,而且严格来说是AB测试。说白点就是,我们把数据分流,一部分数据走A推荐算法,一部分走B推荐算法,然后收集AB算法的推荐结果导致的用户行为,根据核心价值一对比结果,一目了然。

但这样,或许就有人有意见了:在线系统是一个很严肃的事情,怎么能在线上进行未知效果的算法实验呢?

关于这个问题,首先,算法上线之前对于新算法肯定是需要进行一定的评估的,比如离线实验,虽然说不能绝对依靠它,但是作为一个参考完全是可以的。其他的一些诸如统计调研工作也是不可缺少的,在数据量较大的情况下,是能反映一些问题的,然后算法的设计总是有依据的,这些就是依据。换言之,这些前提工作能够保证,即使你的新算法不会比现成的算法好,但也不会出现大幅度下降的情形。如果出现了这种情况,只能说明你们的初期工作做的太烂,你们的算法设计方案是瞎搞的。

其次,我们设计的AB测试机制,必然是可以调节流量分配的,如果不是,那么设计者去面壁吧。在AB测试分流中,我们完全可以控制新算法的流量,达到一个可以观察到效果,又能保证失误在可控的范围内。

(2) 冷启动,这是一个很严肃的问题

关于推荐系统的冷启动,作者专门看了一个单章来说这个问题,But,在书的最后又提出了一个观点:忽略推荐系统冷启动的问题,因为,只要你的推荐系统设计的足够好,是不担心数据问题的。

但在我认为,冷启动是个大问题,特别是对于初入此道的人来说,是绕不开的一个问题。对于冷启动,有一个好的机制进行解决,那么,我们的推荐系统才有一个好的开端。

诸如推荐系统中的最经典的协同推荐算法,其核心依赖就是用户行为数据,在一个推荐系统初期,用户行为是很少的,那么这就是我们急需解决的问题。

辣么,如何累积用户行为数据呢?并且,请注意,在累积用户行为数据的前提下,我们需要尽可能的保证推荐的有效性,也就是说,让用户更有可能去点击你的推荐,对于公司来说,你尽可能的创造价值,对于你本身业务来说,你也可以尽快的收集到更多的数据嘛!

举个简单的栗子。我要做一个类似于今日头条这种APP,进行各种新闻头条个性化推送。一句话,咋整?

这就是冷启动中的冷启动了,因为整个系统都是新的,文章是新的,用户是新的,没有任何用户数据,没有观看记录,没有顶踩行为。无法体现用户偏好,甚至于连文章是否是热点我们都不知道。

这个时候,怎么办?按照书中所说,利用用户的注册信息,然后结合商品信息,进行推荐,这个基本思路是没有问题的。在这里,商品其实就是各种新闻头条。

但是,这种方式局限性也很大,一方面,在注册时信息有限,并且很多时候这种信息是带有欺诈性质的,所以我们不能过度依赖于其。

这个时候,怎么办?请忽略针对于用户个性化的推荐,我们只要掌握大体趋势就好了。那么,如何掌握大体趋势。借助外力!

刚才说了嘛,类似今日头条。今日头条肯定做了类似的工作,例如在你没有登陆的情况下,肯定同样提供了推荐列表。并且可以肯定的是,这个推荐列表是有数据支撑的,并不是胡乱推送的。也就是意味着,这批推荐名单是比较容易被普通大众所接受的,换言之,是能够提升点击率的。

那我们如何利用它呢?我们复刻一个推荐列表出来。当然,并不是要你直接把人家的文章拿过来直接放上,要是这样,人家就该告你了。

我们可以通过计算相似度的方式,针对于今日头条的每一个推荐,在自己的文章库里计算一个最相似的文章出来,顶上去。不依赖于任何己方的数据,一个推荐列表就出来了。

至于说效率问题,其实类似这种新闻头条的推荐列表,其变化并不是实时的,所以,计算的代价完全是可以承受的。

至于说如何计算相似度,那就是另外一个范畴了,这里只是提供一个思路。

说到思路,那么,通过这个栗子,我想要表达的意思也差不多了,那就是处理这种冷启动的问题,我们的处理思路是:借助类似产品的现有成果,并以此为依据。

虽然有点无赖,但是能解决问题,无赖就无赖吧~~

在收集到第一手行为轨迹之后,往后的事就方便多了,该怎么滴怎么滴吧~~

(3) 上下文信息与规则打分模型的关系

书中有提到,所谓上下文信息,主要两方面:时间上下文,地点上下文。

在我认为,其实是远远不够的,一切可能对于结果有影响的第三方因素都是可以参考的。所谓第三方因素,个人认为可以定义为:与用户个性化没有显性关联的因子。比如前文说到的时间、地点,又如季节、天气等等诸如此类。

说到这些,不得不说到规则打分模型。

说到规则打分模型,简单解释一下吧。所谓规则,即我们自己定义的一系列操作规范;至于打分,则意味着有某项操作,我们就给某项操作加分。最后看看谁的分多,我们就选择谁。换个专业点的术语就是规则权重模型,好吧,其实就是权重计算。

很简单是吧,但是别忽略它的重要性。个人从来就不认为推荐系统就是协同推荐之类的算法作为代表。

推荐系统,这是一个浩大的工程,以协同推荐为代表的算法只是其中的一个因子,它必然是综合了各种各样的东西的。而权重模型是一个很简单,很原始又很有效的方式。

如何定义不同外在因子对于推荐结果的影响,也就是如何针对于不同外在因子赋予其应有的权重比。这需要数据的统计!

特别是在当期大数据的背景下,这种基于统计的规则权重模型愈显有效。大规模的数据统计是能够体现数据趋势的,这点毋庸置疑!好吧,我承认,这也是为何我把题目中数据加了个“字”的直接原因。

并且在实际的操作中,很多推荐系统的结果都是通过规则权重模型呈现的;还有就是多种推荐方式时,是通过规则权重模型把多种方式结果整合,以达到结果最优化。

所以,在你的推荐系统算法没有丝毫思路的时候,何不尝试尝试走规则权重模型的路子?通过权重模型去修正你的推荐结果,你会有惊喜的!

(4) 无处不在的长尾以及马太效应

长尾分布或者说长尾效应,这个名词解释应该不用我多说了吧。实际上,在现实生活中,这是一个很常见的现象。

然后长尾分布导致的直接结果就是马太效应,即通俗点说就是强者愈强,弱者愈弱。

即,比如一些热点物品,其附带的行为数据越多,其得到的推荐机会就越大,然后被展现的机会越多,然后再次被推荐的机会越多,然后…陷入死循环了,其他物品还有存在的必要吗?!

所以,作者在实验结果中除了准确率,另外一直很强调的一个指标就是:覆盖率或者说多样性(这也是为何我我一直跳过他实验描述部分的原因,感觉参考意义不大)。

对于说我们是否需要挖掘长尾,我的观点跟我之前提到的依然一致:如果挖掘长尾有益提升我们的商业价值,那我们就想方法提高覆盖度,换言之就是降低热点物品的权重;如果挖掘长尾对于我们提升价值转换并没有益处,那我们为何要这么做。

极端点的栗子就是:假如我每天推荐的是固定这几个物品,从不改变,但是,它创造的价值比其他任何流弊推荐系统产生的价值都高,那么,它就是一个好的推荐!

这又回归到了我之前的观点:衡量推荐系统好坏的唯一标准就是,它是否能够提升价值转换!

那么,我到底该不该挖掘长尾呢,大家都挖?还问这个问题的人一定是个死脑筋。是否挖掘长尾,看业务场景,然后进行充分的AB测试,来决定是否提升覆盖度、多样性,提升多少,这一切的标准唯一衡量就是,它能给我带来更多的money吗?

如果它能给我带来更多的money,长尾就长尾吧,马太就马太吧,又何妨?

三、我那悲惨的推荐系统实践经历

写这个之前,我仔细的反思一下,我策划并且实施的那个推荐系统算是推荐系统吗?然后我想了想,感觉应该还算是,只不过不是典型推荐系统,但是在整个实施的过程中,思考的方式还是可以借鉴的。

并且,可以预见的是,实际的工程操作哪有像教科书似得,都是特定场景,特定条件下的产物。也就是说,没有通用的推荐系统,即使有,肯定也是不好用的!

我想,在整个过程中,一些思考,一些处理问题的方式,对大家在以后类似工程的实施中还是有一些参考意义的。

所以,我还是决定把它写下来~~

(1) 业务场景是这样滴

还记得那会儿是三月份还是二月份来着,我所在的A公司上线了在线教育频道,一段时间后,主持运营在线教育的B君突发感想,博客频道辣么多流量,随随便便不就可以引一大坨流量过来了吗?于是乎,任务跑到了我所在的数据部。

需要说明的是,A公司主要是做IT技术论坛社区博客的,而在线教育客户也是程序猿,所以业务上并不冲突,这个引流思路也是对的。

言归正传。

我当时一看,这不是推荐系统么!然后再仔细一看,这是推荐系统吗?好吧,我承认,有点绕口了。

我们首先来回顾一遍,我们正经的推荐系统是什么样的。吃个栗子,啊不,举个栗子:我们在一个视频网站上看视频,然后下面给你推荐了一坨视频,可能是根据你的偏好,也可能是根据网站用户的数据给你推,反正不管,这是正经的推荐系统;你在某宝买东西,然后浏览物品的时候,下面列出一坨东西,这是正经的推荐系统;等等诸如此类。

然后再回到我们的场景,我在浏览一片IT技术博文,然后下面你给我推荐一坨在线教育视频。这叫啥事儿!

对比一下发现了没有,上述的场景跟我们的场景哪里不一样?是的,他们推的东西都是一类,而我们的东西完全是两套东西,一个是IT技术博文,一个IT在线培训视频,他们有着不同的属性。

如果运营在线教育B君说,blogchong sir,我想在我们在线教育频道做视频的推荐,来给整一套吧。

那我会很愉快地按照行业标准,迅速的整一个推荐系统出来,然后按部就班的调算法,优化效果,从此过上快乐的生活!

But,事实摆在眼前,需要面对就是这么一个业务场景。我仔细想了想,这是一个推荐系统,只不过是一个不那么正儿八经的推荐系统。

然后设计方案、组织人手、推动项目进行等这个活落到我头上了。这是上天的安排,对我的考验吗?事实上是组织给我的安排,对我的考验。顿时泪牛满面~~

好吧,那就干吧!

(2) JUST DO IT

在那之前,虽然对于数据挖掘领域有所涉猎,但是在推荐这一块,还是处于基本理论了解到水平,并且当前部门里并没有其他太多的可参考的东西。

我开始着手调研这个业务场景,然后很杯具的发现,业内基本没有出现类似的这种业务场景。是的,有谁能够想到要从X事物关联到Y事物啊,但事实就是如此。

然后我开始分析,在博客与视频之间到底有什么样的联系。我挨个梳理两者的属性列表,然后发现他们其实还是有共同点的,比如:他们主要IT方向的,他们都有中文Title,都有tag,都有des也就是详细地中文描述。

是的,我们无法从业界进行参考,我们无法通过用户行为进行参考(相当冷的启动),那么他们两唯一的关联就是主题了。

抛开用户行为,推荐相同或者相似主题的内容,这是不会错的,这是推荐系统的常规方式之一。

于是按照这个思路,我开始做设计。一开始,对于很多方面的思考都不成熟,所以映射也比较简单,直接通过博客的tag去找视频。

方案开始实施,考虑到后期视频内容量的增长,我使用博文tag通过搜索引擎的方式聚合出视频,于是推荐列表有了。

产品经理C君说,光通过博文进行推荐不行啊,我们需要考虑那些热点视频。好吧,那就加上吧,于是,我在推荐列表中加了一部分观看次数TopN的视频。

C君又说,光有博文推荐出来以及最热视频也不行啊,我们得考虑用户。于是,我和擅长数据批量处理D君把公司里所有活跃用户近一个月的博文浏览行为跑了一遍,其实就是看用户看了写了那些博文,并且对所有博文tag根据读写不同权重进行排序,选择前N作为用户的核心技能。而且,我们在调度中心做成了定时任务,定时更新用户画像中技能字段。

好吧,用户的tag也有了,剩下的过程与博文没啥区别了。

接着需要考虑的问题就是,三种方式得来的列表,我们该怎么分配,因为推荐位就那么几个,总的分一分吧。

然后C君说,拍脑袋吧,于是,我们拍脑袋给他们定了个权重。

只怪我当初太年轻,太好骗,啥也不懂~~

好吧,不管怎么样,我们的第一版推荐系统正式上线了(没法离线评测),然后我让BI小组的G君给网页上埋了点,进行结果收集。

BI报表出来了,结果差强人意,这是显然的。

(3) 工作还得继续

我和数据分析小组的E妹一起跟踪行为历史log,发现了其实很多博文很多用户根本就没有tag,这样会导致我们都给人家推的是Hot数据。换言之,很多根本是毫不相干的。

于是,我开始着手解决这个问题。没有tag,那我就给造tag。在推荐的时候,我通过博文的Title,进行分词,并且把停用词去掉,把分出来的词填充到临时tag中,用于视频的聚合,并且通过直觉略微调整了下三种方式的权重。

结果又好了辣么一点点。

这事被F君知道了,他说,如果要获取一个比较客观的博文主题,为何不从整个博文中进行抽取呢?有道理!

我跟D君开始进行主题抽取的研究,并且最终又把800G的较新博文跑了一遍,在数据中心为它填充了一个新的主题词描述字段。妈妈再也不用担心我的tag了!

于是乎,我们的结果又好了辣么一点点。

又过了一段时间,数据分析小组的G妹通过分析发现,其实很多视频课程跟我们的博文相关度并不是很大的。我说不对啊,我们抽取tag词中,虽然有些不相关的词,但是基本上对应的技能大部分还是比较靠谱的呀。

然后我再梳理了一遍通过tag词聚合视频课程的过程,确实存在课程不是很匹配的情况。原因在于主题词抽取虽然大部分情况下都把对应的技能词给提取出来了,但是权重排序很难做到很准确,而我们的检索引擎匹配又是匹配更多的词的结果,权重会较高。

于是,我认为应该把主题词分主次。举个简单栗子,假如主题词有三个:hadoop、应用、开发。那么,我完全可以认为,hadoop其实才是最主要的词,其他两个都是次要的。

就比如,我希望匹配到是hadoop视频课程,而目前结果恰巧那种“XX应用开发视频教程”会排在前面。当然,如果能完全命中“hadoop应用开发教程”,那就更好了。

我跟G妹开始梳理在线视频教育的技术点,把认为能够体现技术特征的词整理成了一份数百词的核心词字典。

于是,在聚合逻辑上,我会优先考虑核心词的命中,然后才考虑次要的词。这样,我们的结果似乎又好了一点点。

后续,我们又做了一些小的修改,但发现,结果提升的幅度越来越小。

如果按照这个路子下去,估计我们的结果也就这样了。

里程碑式的跨越,是在我跟F君进行的一次深度的讨论。

(4) 里程碑式的跨越

在讨论之中,我们在深刻反思,我们的路子走的对不对。假设在主题词提取的足够正确的前提下,我们是否全盘考虑了所有词对于视频匹配的贡献呢?然后关于视频属性的命中,我们又在考虑,命中位置对于匹配度的贡献是一样的吗?除了视频中文相关的一些中文描述,难道没有其他的一些属性能够给我们的推荐建议带来一丝贡献吗?

于是,我一方面让D君继续优化主题提取的准确率,一方面思考新的设计方案,推翻原来的方案基础上进行思考。

常规的协同推荐路子走不通,那我们就走规则权重模型。在这个方向偷摸滚打这么久,总是需要长点记性的。

于是我列举了一些可能为模型带来贡献的属性,并且初步设计了一个嵌套了两层的规则权重模型。通过几次的小组会议,增删了一些属性,并且稍微的修改了一下模型。

其中需要说明的就是,我添加了不少视频中与博文没有任何关系的属性,我们的目的在于,这些属性或多或少都是有影响的。

于是我着手开始进行视频相同统计属性的量化操作,诸如发布时间无穷增长的值,诸如是否收费这样的二值属性,进行0到1之间的量化。

有了量化,我们的E妹就可以根据数据分析,那些指标跟点击率是正相关的,那些是无相关的。我们进一步刨除了一些无相关的统计属性。

对于初始阶段,我们没有任何数据可以参考进行权重设计,于是在慎重考虑之后,我为嵌套的两层规则模型设计了一个看起来比较合理的权重比。

然后在数据初筛的阶段,使用每一个主题词进行视频N值提取,然后在N*M个初筛的视频中,根据规则模型对N*M个视频进行打分(这会牺牲一部分性能,但是这种思路为部门内部搜索优化项目提供了参考)。然后按照要求的个数进行截取就OK了。

其中有一点需要说明的就是,在我们的场景中,登陆用户的比重与游客的比重是1/60,所以,我们的重心一直不在用户身上,这个就不多说了。

还有一个跨越式的进展就是,我设计了AB分流测试机制。当时回想一下,冷汗淋淋啊,之前辣么多的版本,我们就这样闷头直上了,那可是线上的系统啊。之所以没有出问题,一大部分原因就是,在新版本中,我们进行了足够的思考。

好了,如今,有了AB分流机制,我在保证系统不受大影响的情形下,在转化率可能下降并且可接受的范围内,为新模型分了1/4的流量。别小看这四分之一的流量,那可是上百万的流量啊。

不用等多久,因为我提前让G君埋好了点,第二天我们就看到了效果,具体的数值俺就不多说了。我们果断的把流量全部切到了新模型中。

此后,我们的工作重点在于如何有效优化权重比例。这一点,我跟E妹进行讨论分析,最后E妹的敏捷思维还是说服了我。

E妹说,我们是在有数据倾向的前提下来预测权重值,这不就是逻辑回归嘛,跟计算逻辑回归的参数有何区别呢?啊不,区别还是有的,区别就是我们需要的是正参数。

好吧,后续的我就不多说了,再说这就是一篇小说了。

后续我们又做了一些其他思考,比如我们认为技术应该是分层级,加入一个技术水平分高中低三级,如果博文体现出来的技术水平是初级的,那我们是不是应该适当的给人家推荐对应中级的技术视频。

又诸如,技术之间是有关联的,人家看hadoop的博文,是不是可以适当的给人家推荐spark的视频课程?这种关系如何提取?

其中涉及到的技术以及其他种种,我就不多说了,再说下去,我就得写到凌晨两点了。

(5) 做一个象征性的总结吧

也不算是总结吧,整个过程反倒像是我在记流水账了。但不管怎么样,有些观点我认为还是有意义的。

首先对于我们不熟悉的领域,我们需要果断的去做,有些东西是需要吃过一点亏才明白的,毕竟书上的东西只是书上的东西,这句话可明白?

其次,在做新算法改进,乃至于其他改进,或者诸如其他项目时,我们需要经过慎重的思考,然后再做方案,然后再实施。这也是为何我们在AB测试机制出来之前,无数次“勇敢”上线,覆盖线上版本,而没有出问题,效果没有下跌的直接原因。

针对于推荐系统的设计,我想说的就是,我们需要解决的是主要矛盾。针对于我们的这个项目实践来说就是,我们的一切努力方向就是提升流量从博客频道到在线教育频道的转化率。至于说试图挖掘长尾,我们尝试过,呈现推荐的多样性我们也尝试过,但是,这不是我们的目标,我们只会在转化率最合适的地方挺住脚步,而不是一味的提升多样性。还是那句话:能给你带来更多money的推荐系统,才是好的推荐系统,其他的管他呢!

关于推荐系统另外一个建议就是,我们不要拘泥于某种形式,我们需要切实地参考业务场景,提出最适合自己的设计方案。很多方案,只有你想不到,没有做不到的,结果如何,试一下就知道了。

作为项目的推动者组织者,我们需要承担更多的责任,例如任何让各个方面的人进入到其位置中,并且及时协调各个方面的进度,这很重要。团队的力量很强大,一个重要体现就是,初始方案可以你来做,但是通过小组讨论,你会发现众人的智慧是很强大的,自己认为再完美的方案也是有改进之处的。多多与他人讨论沟通交流,每个人都有其强大之处,我们需要虚心学习。他山之石可以攻玉,这句话永远都是对的!

文/博客虫

1.环境
 
阿里云 
操作系统: Aliyun Linux 5.4 64位
 
2.安装svn
 
yum -y install subversion

注:到此为止,svn服务器端已经安装完成

3.配置
 
建立版本库目录
 
mkdir /alidata/www/svndata
svnserve -d -r /alidata/www/svndata

4.建立版本库
 
创建一个新的Subversion项目
 
svnadmin create /alidata/www/svndata/myproject
配置允许用户rsync访问
 
cd /alidata/www/svndata/myproject/conf
vi svnserve.conf
anon-access=none
auth-access=write
password-db=passwd
注:修改的文件前面不能有空格,否则启动svn server出错
 
vi passwd
[users]
#<用户1> = <密码1>
#<用户2> = <密码2>
myname=mysercert

5、测试svn服务器是否可以使用
svn服务器默认的端口是3690
你可以在linux中用命令 netstat -ant 查看此端口服务是否启动
也可以使用本地电脑通过telnet远程访问:telnet 192.168.1.8 3690
如果可以访问,证明svn服务器已经可以对外网提供服务了

注:至此服务器端代码仓库已经创建完毕,你可以通过用户名/密码 myname/mysercert 访问了。

6、安装本地客户端
我用的是eclipse的subclipse作为svn的客户端
打开eclipse -> Help ->Install New Software选项, 点击Add按钮

根据需要,添加自己需要的版本svn控制器的版本,填写name和url,点击ok。
Name: Subclipse 1.8.x (Eclipse 3.2+)
URL: http://subclipse.tigris.org/update_1.8.x

7、通过eclipse的svn客户端将代码提交
选中项目,右键,team-》share Project…

8、在弹出的对话框中选择SVN,选择创建新的资源库
在URL输入框中输入:svn://192.168.1.8/myproject
注:这个ip地址需要根据你实际情况进行替换,看你放到哪个机器上了

9、这个时候进入了同步的视图。选择提交本地代码就完成了代码仓库的第一个项目的管理。

ModelBuilder 是 ArcGIS for Desktop 产品中最可爱的功能之一,它可以尽可能免代码地将我们从重复劳动中解放出来。使用 ModelBuilder 的过程常常被比喻为“搭积木”,我们只需要拿着 ArcGIS for Desktop 中为我们提供的“积木”去搭建满足于自己的特定工作流模型。

再打个比方,我们要实现的某个功能比作是自己做面包。首先要准备食材,例如面粉、牛奶、鸡蛋、黄油、糖、盐、酵母,类比为 地理数据; 食材齐备了,就可以顺序开始和面、发酵、烘焙,这些工作由特定的器具承担,例如各种烘焙工具、烤箱,就好比ArcGIS提供的 工具,例如 ArcToolbox中的工具们; 面包制作过程中可以根据自己口味,规定发酵时间、控制糖和盐的多少等,这就类比为工具的自定义 参数

如果自己享受整个烘焙的过程,不厌其烦地面面俱到,那大可维持现状;可是如果你觉得做面包是个体力活,你只是想吃到自家面包,而希望把做面包的过程“外包”出去,那么面包机的市场就来了。这篇blog就和大家说说如何制作“面包机”。

1 明确需求

我们从一个简单常见的实例开始……

需求:现有一些表示各种研究对象的地理数据,小明希望把所有研究数据变换到需要的坐标系统,并且全部裁剪至研究范围。

如果只有一份数据,小明会不假思索的找到 ArcToolbox中的 Project和Clip工具,顺序执行即可解决问题;如果是3+份数据,小明可能会想,该做个工具了。

2 构建工作流

从【地理处理】菜单,打开 这里写图片描述 ModelBuilder,依次拖拽和连接 Project 和 Clip 两个工具。Project 工具的输出作为 Clip 工具的输入。

这里写图片描述

双击工具可以打开工具继续填补工具需要的参数,直至Model因参数完全而变成彩色。

这里写图片描述

3 使用迭代器

前一步的工具已经满足一次任务的需要了,接着就是解决批量处理的问题。ModelBuilder提供了一些额外的自带工具来满足我们的一些高级需求,其中一类就是 迭代器,它用来实现循环。

在这个例子中,需要遍历的对象是表示各种研究对象的要素类,因此选择 迭代要素类 / Iterate Feature Classes。当然也可以根据自己的实际需求选择其他迭代器。

这里写图片描述

接下来就是把迭代器与工具串联起来。首先,双击迭代器的六边形为迭代器设置工作空间,即地理数据库/GDB,或者文件夹目录(例如shapefile所在的目录)。这样,迭代器会在指定的工作空间遍历要素类。删除现有Project工具的输入数据,将迭代器的输出数据连接到Project工具。

这里写图片描述

这里写图片描述

工具基本准备完毕,但是还差了重要的一步。目前,最后的输出数据是常量,也就是说,即使前面的工具执行了N次,那结果都将被同名覆盖。那么,行内变量 就显出用武之地了。

迭代器每次遍历到一个要素类,会返回一个 Name,内容是当前要素类的名称,这个Name就是行内变量。引用的方法就是使用百分号括起来,即 %Name%

输出数据设置示例:

这里写图片描述

至此我们就完成了一次批量任务。

4 复用工具

如果我们以后想按照这个相同的需求处理数据,完全可以将其做成模型工具。将输入数据和输出数据设置为模型变量,我们就可以在“运行”状态下使用。

设置方法,在需要作为参数方便后续修改的项目上右键,勾选 “模型参数”即可,然后项目的头上顶了个“P”,( ̄▽ ̄)”。

这里写图片描述

将模型保存至工具箱后,双击运行工具。现在就可以把它当成“面包机”,放入食材,等面包即可。

这里写图片描述

5 注意事项

下面是些有用的提示,FYI:

  • 每个模型仅可使用唯一一个迭代器。如果模型中已经存在一个迭代器,那么用于添加迭代器的菜单就不可用了。这是限制之一。

  • 如果将含有迭代器的模型导出为 Python 脚本,则导出的脚本中将不会包括迭代逻辑。这是限制之二。Python中有list函数,也可以实现类似的需求,但是需要重写。

  • 尽管Model可以嵌套调用,但是迭代器的嵌套循环逻辑不佳,不建议使用。如果需要实现嵌套循环,强烈建议使用python脚本。例如,实现遍历工作空间内每个要素类中的每个要素(记录)这样的需求,可以使用 ArcPy中的函数 ListFeatureClassesSearchCursor来实现。

一直想把CSDN上写的博客,搬家移植到自己的WordPress博客,网上介绍了一些方法,例如先把CSDN博客导入博客园,然后从博客园导出xml文件,最后用WordPress导入工具导入进WordPress博客,操作步骤太繁杂。

于是周末在家自己动手用Python写了爬虫脚本,利用WordPress自定义的投稿功能(wp_insert_post),导入进WordPress博客,步骤只有简单的两步:

步骤1:Python脚本爬取CSDN博客,包括博客标题,正文,发布日期,浏览数,标签

步骤2:利用WordPress投稿功能插入到WordPress,把所有CSDN博客导入WordPress

 

Python完整代码:

1