simplify

"The more stuff you own, the more stuff owns you"

就在这个假期,我忽然意识到为什么最近我不爱在家呆着干活了,因为“噪音”太多。卧室里的电视柜上没有电视,但是堆满了东西,床头柜上也是一样,书房的桌子上已经快要连笔记本电脑都要放不下了,而客厅了,全都是已经成碎片状的儿子的玩具或者小人书。基本上,每天回家除了往床上躲,快要没有下脚的地方了。事实上,我最近每天回家的心情都是非常低落的,也许这有一些工作上的压力的原因,但是,回到家也不能觉得这是一个安全和舒适的地方,也许才是最大的原因。

所以我开始打算收拾一下,于是,我才真正意识到了最近总觉得生活一团糟的原因,就是我把生活搞复杂了。我尝试去控制保留太多的东西在生活里,这个最终对我期望的生活没有帮助,反而让我摇摇摆摆地在无谓的事情上消耗了太多的精力。我从抽屉里找到了三台坏掉的手机,一台坏掉的无线路由,一台也许还好的Hub,50张刻了应该快有10年却再也没有看过的Discovery的DVD,以及各种各样“修一下我可以卖掉”或者“收藏起来以后可以用”的东西。

但是我从来没有再用过他们。事实上,每次我看到这些东西的时候,他们都会分散我的精力,我总是去想“啊,我应该修好/卖掉/修好然后卖掉”他们,然后有几小时或者几天惦记着这些事情,但是从来都没有真正做这些事情。因为这些事情根本不值得去做。大概三年前,在不夜城给老婆修N97的时候,我成功地把一台坏掉的BB 8310以50块钱的低价处理给了店老板,“咻”,这件事情就结束了。如果我真的需要去修理然后卖掉这些坏掉的,或者已经过时5-10年的玩意儿,我需要花上至少5个小时的时间,大概能够卖上120块钱?去掉来回的车费,我大概挣到了打扫卫生的小时工的薪水,嗯,真是一笔不少的钱呢~

也许是人类进化中的本性,也许是因为父辈都生活在贫乏年代,周围总是看到各种“收破烂”的习惯,我甚至怀疑大家买房子的目的就是为了囤积破烂。虽然最近一年一直秉持着“如非必要,勿增实体”的理念,但是因为不舍得扔垃圾,就像一个仓鼠一样,我存着各种乱七八糟的东西,想着“也许有一天要用”。它们包括笔记本电脑的散热器(自从08年摆脱了那台主板出问题的Compaq笔记本之后我就再也没有用过),震动手柄,外置刻录机(过去一年应该也没有用过一次),高中和大学时期的各种笔记,各种各样用了一点儿或者根本没用的笔记簿,使用胶片的傻瓜相机,300万像素的Cannon DC,等等等等等。

这是一个消费主义的时代,大众传媒告诉你去“买买买”,所以我们都去买,但是把一堆东西买回家其实并不会让我快乐,这些“玩意儿”不是我的资产而是负债,我的资产是我有限的时间和精力,我希望把他们花在阅读,写作,写程序,发现真和美的东西,而不是维护破烂。我买了刻录机于是花了很多时间下载了一堆东西刻成盘但是从来不看;老婆买了一堆鞋所以每隔一段时间你都得拿出来擦一遍不然会发霉;我的钱包里鼓鼓囊囊好几张各种会员卡但是平均使用频率小于一次每年。

我不是什么禅修人员,极端像 Steve Jobs 一样睡个床垫然后没有家具,但是我也喜欢简单干净的生活,更类似Simplify 中所说的“Rational Minimalist”。

我仍然会买我需要的东西,但是绝不因为“便宜实惠”去买东西,要么只买一次性用过扔掉的东西,要么就去买天天会用的好的工具。我并不希望“拥有”更多的东西,而是希望更丰富的人生体验,更多的创造。我喜欢我过去几年买的Macbook,Dell显示器和微软人体工学键盘,因为我每天都用他们而且他们的确很好用;我也打算咬咬牙买把舒服的椅子以缓解目前的背痛避免也走上腰间椎盘突出的道路;但是我不会再去买电脑包,或者笔记本散热器这种“装饰品”,是的,我非常讨厌各种没有含义的挂在墙上的画和桌子上的装饰品。

"Not What We Posses, But What We Pursue"

人生是一场旅程,我们需要的是更多的体验,我说过我希望追求的更多的是“真”和“美”,而不是“拥有”。很多我们尝试去“拥有”的东西都是没有意义的,它们更多的,是消遣我们的注意力。我并不拒绝去买东西,但是我期望它们是让我更好地体验这个旅程,或者更多地去创造一些东西或者解决一些问题,而不是为我自己带来问题。我仍然会在电脑坏了慢了的时候买一台好电脑因为这个是我创造和解决问题的工具,我希望摆脱的是“小饰品”和“收藏品”。“小饰品”就是各种小巧好看但是“无用”(一般他们被包装成很有用)的东西比如漂亮的铅笔盒(“嗯,我需要有个地方放文具”,可是其实直接放在桌子上的抽屉里就好了)。收藏品就是那些你虽然喜欢但是看完其实可以扔掉的东西(我有一套星球大战的漫画好变形金刚典藏版的DVD还是我要求老婆送我的生日礼物呢,其实我从来没有空看过超过一集!)。小饰品你压根就不该买,收藏品你应该看完就处理掉。

重新看了一下我书桌上的东西,对我来说,电脑,显示器,桌子,椅子,键盘,鼠标,耳机,手机,是工作必须品,Kindle是外出时候看书的利器之外,连iPad我都开始觉得多余(话说你们都多久没有用你的iPad了?)。

所以,无论如何,决定从今天开始,简化生活。

trust1_2

很多人都说在中国做生意靠的是关系,这个事情常常让做技术的人非常沮丧,觉得产品和技术上的努力,常常比不过关系,觉得自己做的事情没有价值。最近公司新进入了一个大客户,本来应该是个好事儿,可是我自己一度反而自我感觉很糟,觉得技术和产品上可能做出了各种努力,但是其实也许对于公司的商业价值来说也比不上可能各个老大的“关系”有价值。有时候想想如果真的是这样的话,做B2B的产品可能是毫无意义的,因为产品好坏拼不过“关系”。

不过今天陪家里领导逛街聊天的时候,被她一句话给点醒了,颇有拨云见日的感觉,大概意思是说,中国人做生意讲究的不是关系,而是信任,我觉得这个一下子讲清楚了全世界人民所谓的靠“关系”做生意的本质,然后觉得该做什么还是要继续做什么。

以前去理解做生意靠关系,总觉得有些道理但是味道不对。说有些道理是看工作生活中有很多东西的确是靠“关系”的,比如走后门找个重点学校,找医生插个队之类的,但是真用到做生意总觉得还不是那么回事儿。以前理解关系都是很表面化戏剧化的,比如最近在看The Mad Man,往坏里理解,我们觉得关系就是和客户去吃喝嫖赌,比如广告狂人里为了拿下捷豹让Joan去陪客户睡觉。往好里理解,就是人情往来请吃送礼什么的,比如几乎每个客户来到SCDP里每个客户来看提案都要安排点吃饭活动啥的。也许是我见识浅,但是真到生活中周围看,也没见到哪个客户是靠这个搞定的。其实这也容易理解,一是大家都不傻,又不是只有你会拉关系,竞争对手也会拉;二是客户也不傻,不可能你真得做得烂但还总是把生意给你做。

但是把“关系”这个词换成“信任”很多问题就很清楚了,很多情况下,生意给你做,是因为“信任”你这个人,觉得这个事情交给你你能够做好。客户在提要求的时候,拍胸脯保证这个事情谁都能做,但是客户信不信,不是信任不信任这个事情,而是信任面对的这个人。为什么很多“关系”常常是以前的同学同事,因为互相深入了解,知道你是能说到做到,不会拍胸脯保证,最后做不成就拍屁股走人;这也是为什么很多“关系”最后没有用,因为这个“关系”不是深入的信任,两人是很熟悉可是知道你这个人爱忽悠。同样的,即使之前不认识,不了解,气味相投也会有用,从小事开始合作做出成绩来也能够慢慢建立这种“信任”。

其实不只是销售面对客户的时候,面对自己老板,下属,其他部门的时候也是一样的,要做好事情,就要去赢得信任,就像我的第一个老板说的一样,你要去挣Credit。没有Credit,老板不会给你新活儿,反而会整天给你挑刺儿,下属觉得你安排的事情都不靠谱太扯淡,其他部门觉得你是SB在忽悠他们,这个不是靠请吃饭喝酒送礼能够解决的。挣Credit是个长期过程,而且是很靠做事情的结果的,所以光靠“关系”和“忽悠”帮你挣不了Credit,而且做得不好会把原来挣来的都赔出去。最佳策略反而是“日拱一卒,不期速成”。

想清楚了不是“关系”而是“信任”,做人做事也就不痛苦纠结了,所以接下来继续用原来的原则做事情——“但行好事,莫问前程”。

04. February 2013 · 1 comment · Categories: Book · Tags: , ,

程序员的思维修炼

今年的一个目标是多读书,于是前两天就花了点时间读完了这本 Pragmatic Thinking and Learning ,话说读之前的期待还是挺低的,读完之后觉得是值得5星推荐的一本书。之所以期待低,一是 Andy Hunt 之前的 The Pragamatic Programmer 已经读过,有个偏见觉得很可能是老调重弹;二是中文名容易让人觉得是神棍书,特别是看了目录的前几章关于L/R脑模型的标题之后。不过读了之后还是觉得这本书对我相当有帮助,觉得没有白费时间。这当中应该还要为电子版本的出版商多看记上一功(因为做笔记方便),不过这个是后话了,如果有空的话应该会再写一篇Blog专门写我对目前电子出版的一些看法。

想了想,一般我给出比较高评价的的非虚构类读物,大概分成三种。一种是叫做“与我心有戚戚焉”,就是人生观价值观的共鸣,比如读王小波就属于这一种;第二种则是让我“开眼看世界”,这种在看自己没有充足认识的领域和知识背景的图书最多,之前读 创新者的窘境 就是这种(这本也是值得好好写写Blog的),一本透彻讲清楚一个问题的产业经济学的图书,的确让人读完之后有“哇,原来是这么回事儿”的感觉;第三种最土了,比如这本,就是我认为有很多我认为可以直接实践的内容了。

说好话之前先说说批评意见,不知道为什么出版社和编辑把这本书的书名翻译成现在这个 <程序员的思维修炼——开发认知潜能的九堂课> ,因为英文名其实完全是不一样的,叫做 Pragmatic Thinking and Learning——Refactor Your Wetware ,如果土一点直接翻译过来应该叫做 <务实的思考和学习——重构你的“湿件”> 。这里面“WetWare”的确不太好翻译,也许可以叫做“思考模式”。但是从这个翻译和现在中文版名字的对比可以看到,原书想写的内容还是很务实的,基本就是一些作者觉得更有效的思考和学习的方法,翻译版则稍稍有点神棍了,不过不知道是不是现在中文出版界都比较喜欢神棍,比如以前 Scott Berkun (他的几本书也相当不错)的 Make Things Happen 愣是被翻译成了 项目管理之美 ,相当没有品味。而这帮相当没有品味和扯淡的人还一直异常推崇苹果和乔布斯而鄙视微软,至少从他们最后定的书名来看他们还是比较希望大胖子光头的推销模式

回到英文版的这个书名,基本上也把这本书想讲的内容说清楚了,就是告诉你作者认为应该如何学习如何思考会比较有效。

全书的结构也比较清楚,第一章是废话,完全可以略过。

第二章可以认为是一个能力阶段模型的大纲,基本上讲了,你在一个领域的不同阶段表现出来的水平是什么,虽然列了5个阶段,不过如果再简化一点,我觉得用三个阶段也就可以了,里面提到的新手到高级新手基本上是人都能很快做到的。高级新手到胜任者是第一道坎,主要的挑战在于胜任者开始理解上下文了,这个基本上可以称作猴子和人的区别,也就是说即使是猴子训练够了也能做高级新手,但是通常给他们换个context基本就完蛋了;然后胜任者到精通者是第二道坎,一个的区别在于是否已经学会快速自我反思和改进,这个我称之为人和牛人的区别,能学会养成不断反思的习惯,基本上随着时间最终能变成大家认为的牛人;另外一个他叫做全局思维,我理解为基本上你不能光想自己那点事儿,所谓“不谋万世者,不足谋一时,不谋全局者,不足谋一域”。

同时,在阶段模型建立了之后,建立了一个“积极的实践”的需求列表,分别是

  • 需要定义一个明确的任务
  • 任务需要有适当的难度——有挑战但是可行
  • 任务环境可以提供大量反馈,以便于你采取行动
  • 提供重复犯错和纠正错误的机会

我把这个模型和过去几年的工作经历印证了一下,觉得还是相当靠谱的,基本上成长最快的几个阶段,都是这样走过来的。无论是在TU,还是去年年初事故不断的阶段,都是四条都满足最后挺过来就胜利了,所以说所有经验都是要公司给你交学费的。

第三到第五章比较神棍,不过有些Practice在很多地方都读到过,值得实践一些,比如漫步,早晨写作,天天写,到处记笔记收集资料等等,基本上我叫做通过各种实践让你换换脑子,然后“好记性不如烂笔头”都把事情记录下来。

第六章我个人非常喜欢,主要讲作者觉得比较高效的学习方法的,我觉得比较值得尝试的是SQ3R法来做阅读,准备之后的几本书都这么做一下。事实上,我曾经一直觉得自己学习能力还是很强的,但是现在回过头反思和SQ3R对比觉得其实效率极其低下的。之前觉得自己学得还行,主要一是看书还算快,另外就是的确花得时间也多。但是缺陷一是很多东西的确没怎么记住,另一方面是很多需要静下心来看的东西就进展极其缓慢,之前做工程还算好,可以靠多写Code来实践,现在看点有数学推导的东西就和蜗牛一样。SQ3R基本上也就是传统的学习方法,先看大纲,然后列问题,然后带问题去读,然后复述,回顾,如果加上第七章的实践基本就齐了。不过不知道其他人怎么样,我自己是离开学校之后就没有再用这种方式学些过了。

第七章基本上就是讲在实践中如何学习,几个重点基本上一方面是设定环境能够安全地去探索、创造和应用,在学技术上,本质上叫做通过做点实际的东西来学习,把Code跑起来,改点东西,再跑跑,看看能否在其他的数据或者使用场景下使用。另一方面试一方面是寻找内在诀窍,我称之为想清楚问题的本质,这个过去两年在两个事情上特别有体会,一个是刘鹏老师讲Machine Learning和计算广告的很多东西,一个是看 Nathan MarzBig Data ,一旦触及到本质,很多问题就一下子清楚了。

第八章基本上是一些如何集中注意力的问题,这个在很多管理书籍上有很多类似的实践,比较有意思,我想尝试一下的是冥想,不知道是否会真实有用。

第九章就继续是扯淡的话了。

这本书我主要推荐的还是在6-8章,很适合大家觉得没什么好学的情况下去看看,然后就继续有动力看很多不同方面的东西,而且这里面的确有很多回到学习和思考的本质上的方法上的实践值得去做。Pragmatic系列在结合扯淡理论和实践上的确写得相当不错。很多别的书(不一定是特定领域)写得要么过于干瘪,比如之前看李航博士的<统计学习方法>;要么过于扯淡,这个就满大街都是了,讲一些具体实践的书很少,不知道什么原因。

01. January 2013 · 4 comments · Categories: Life · Tags: ,

世界末日已经过去了,现在又是人类的新纪元了,儿子和老婆都已经睡了,终于又在夜深人静中重新回顾过去的这一年。

过去的这一年算不上多精彩,多勤奋的一年。看了其他技术人的总结,感觉就是非常惭愧,觉得这一年做掉的事情太少。

如果说这一年比较值得高兴的事情的话,其实和去年一样,就是仍然在快速的变动和发展的过程中真心觉得个人有成长,虽然和自己曾经的各种设想多多少少不一样,但还是很高兴的。

工作上,角色基本完全转变为技术管理者,最后半年,基本没有机会再去写Production Code。对于这样的转变,过去一年半里,犹疑过,自我否定过,反复质问过自己,但是形势比人强,被实际的责任推着走,最后就成了这样。其实当真正把角色转换过来,放弃了一些的时候,得到的也是巨大的。基本上,现在敢觉得自己是个合格的技术管理者了,虽然有多好还不敢说。过去一年,虽然比自己期望的,做得仍然是更少的,但是一些重要的基础性功能都做完了,ETL的batch layer和index,Realtime Targeting,还有更Scalable的combination feature和exploration模块,都在世界末日之前完工了,希望明年能有更多的产出。比较遗憾的是,有些很重要牛B的队友离开了,只是不知道如果过去一年可以重来一次的话,他们是否会还在?另外比较值得一提的是,最近几个月,开始对广告行业本身开始感兴趣了,而之前,则完全是以工程上的挑战和乐趣作为工作的动力的,算是一个意料之外的变化。

技术上,年初曾经发宏愿要看完PRML,但是还是没有看完,但是零零碎碎看了不少Machine Learning的东西,对一些具体细节的问题有了更清楚的理解,但是因为角色的变化,的确没有机会真正能够对这些有着更深入的理解和insight。看了不少Machine Learning和系统结合的Paper,对于实际的工程实现和架构更有了点感觉,其他就没有太值得一提的东西了,基本上,继续处于18般武艺样样稀松的状态。

生活上,家里领导如愿去中欧读MBA了,结果就是两人都没什么时间陪徐蹬蹬同学,好在领导年前放了3周的假,母子去三亚呆了10天,然后赶在2012年的尾巴上,一家三口在大雪天去天目湖呆了两天,简直是体会了一把瑞士风光。

回顾一下过去两年,基本是被工作环境推着走,那么2013,希望能够比起日日焦虑的状态,走得更有目的性,更从容一些。

工作上,主要计划仍然是能够和团队一起,朝公司的共同目标前进,无论是产品上的支持开发工作,还是基础设施上的改进。给自己额外一点的目标,就是希望能够做到,让团队里的同事们在MediaV工作,能够比去TAB之类的公司成长得更快,得到得更多。这件事情,说起来简单,做起来,决不容易。对自己个人得期望,则是一年过去之后,能够觉得自己从一个合格的技术管理者,变成一个“好”的技术领导者,做到没做到,其实内心很容易给出答案。

虽然年前和老大做Review的时候,明确了不可能会再回头去做Individual Contributor的,不过内心对于技术总是有着各种好奇心的,所以还是希望在业余时间,继续折腾一下稀松的18般武艺,能看完8-10本技术书籍,不需要找新的,手上买来每看完的看完就可以了,不过更多地是要找零碎的业余时间看掉,基本上就是这几本:

这个计划比较简单,每列什么需要太多时间的书,而且大都看过一部分了。另外,2012年书看得少了,希望2013做到每月一书先吧,不算小说,并且能够记上笔记。

另外,就是在具体的Skills上,多用一些R和Ruby/Python/Bash,主要是可以快速做些新模块的探索性工作。

生活上,去年可以说是不及格,今年的目标更加具体,希望能够做到:

  • 每周一天全职陪娃儿,去年即使是放假之类也常常偷懒。
  • 家里领导顺利毕业,找到一份正常的工作。
  • 一家三口去一次香港,去一次厦门。
  • 每周运动一次,跑步也好,打球也好,至少让身体状况好一点,精力更旺盛一点。

每年计划都是想到哪里写到哪里,松松散散的,今年也是这样,就这样吧,希望能够多做掉一点,回头过来觉得一年没有白费就可以了。

17. December 2012 · Comments Off · Categories: Life, Work · Tags: , ,

过去一个月,采用了在<奇特的一生>中的时间记录法来记录所有的工作时间,今天晚上花了一个小时整理了数据,还是蛮恐怖的。

总有效工作时间,9980分钟,26个工作日,10个非工作日,考虑到周末需要陪孩子,基本除了偶尔看下报警,报表和邮件,基本上不工作,只考虑到均摊到工作日,平均每天有效工作时间大约为6.4小时,如果均摊到周末,就只有4.7小时。这个有效工作时间,刨除了什么吃饭,上厕所,喝水,发呆,休息,偶尔刷个微博这些所有的时间,实际上平均我在公司的时间大概每天11小时,刨去两餐和午休,大概也有9小时左右。

对所有时间分类的话

  • 回复邮件,各种项目中的Coordination,非正式的讨论和会议,包括回答Team里各种问题,一共占了30.2%,是最大头
  • Hands-On工作时间,包括自己写程序,脚本,分析报表,事故报告这种,一共占了28.6%
  • 各种正式会议,占了大概14.9%
  • 读Paper以及看一些资料,大概占了8.9%
  • One on one,以及具体单独对个人非项目细节层面的Mentorship,占了7.4%
  • Recruiting,占了6.7%
  • 正式的Code Review和Design Review,占了大概3.4%

Hands-on的时间还是多得超出我的意外,基本上已经没有写过什么Production Code了,但是看来仍然花了不少时间写脚本,下次统计的时候需要区分Production需要的工作,和实际额外Explore的工作。
Code Review和Design Review的时间少得令人意外,看来最近Code Review做得太少太不仔细了。
会议时间仍然稍稍偏多,需要减少,Coordination的时间需要再细分一下。
周末时间研究学习的时间大大少于我的意外,看来是被娃儿套牢了。

真是不记不知道,一记吓一跳。

想了一下,希望能够做到的有效工作时间大概是一周40-50小时,每个工作日能够过8,摊到周末也能到6以上,基本上希望在不增加平时工作时间,但是周末需要多抽出点时间看资料和分析问题的情况下做到。

  • Hands-On,20%,不包括任何Production Code,主要是探索性的分析和实验工作
  • Coordination,25-30%,这个没办法,总是逃不掉的。大概是部门内15%,跨部门15%
  • 会议,10%
  • Code Review/Design Review,10%-15%
  • One on one这样的Mentorship,10%-15%
  • Recruiting,5%,现在是因为还是有些重要的位置缺少合适的人选
  • 看Paper和资料,10-15%

话说很久没有看到好的技术文章了,一方面国内的高产的同学们,喜欢高屋建瓴,这个以微博上的各种“分析师”为首,之前是云计算,现在是Big Data,基本上都是扯淡,除了吼两嗓子让大家发现自己真不懂之外,没有什么价值,另一方面就是写得过细,比如一个MapReduce的WordCount的教程,基本上就是白开水。如同swordsp同学所说的“技术博文的典范”的文章基本看不到,好在老外同学们还是有不少好文章的,比如今天翻译的这篇DISCO,是最近几个月看过的难得的好文,这也是我其实非常喜欢Twitter的Data和Machine Learning部分的原因,简单快捷,容易实践,对于小公司非常值得效仿,如果不是目前的工作实在有趣,我觉得我会想方设法加入Twitter的。

看了这篇和之前翻译过的基于Hadoop的系统背后的数学,我觉得可以总结一下我眼中好的技术博文的三个特点:

  • 写别人没写过的内容
  • 谈一个具体但又足够通用的问题域,Big Data这样的Title太大,WordCount又太小
  • 别堆Code,看Code我们去GitHub而不是你的Blog,需要图/算法过程让大家简单易懂

两篇文章首先都是新的别人没写过的内容,其次选题够实践够具体,Hadoop那篇文章是讲Overhead Cost计算的,这篇文章是讲MR计算相似度算法优化复杂度的,既不是大而无当只能看看,但是又没有细节到一个过于简单的Case,没有任何代码,一篇文章几个公式和几个图把Overhead对系统影响的曲线画出来,一篇文章几个算法伪代码外加复杂度优化的实际数据出来,非常漂亮,看得人赏心悦目啊。唯一DISCO这篇有个缺陷是p和epsilon如何选取文章里没写要去看引用的paper。

我对自己未来技术文章的期望就是一年能有个两三篇这样水准的,如果写得出来,觉得一是写作(单指技术文章)过关了,还有就是也说明对于特定领域的确有insight和自己的东西了。

最后是这篇过于DISCO算法blog的中文翻译,越来越觉得自己翻译成中文是让我仔细看一个东西的最佳途径。


Dimension Independent Similarity Computation (DISCO)

MapReduce是一种用于处理大数据集的编程模型,典型地用于在普通电脑组成的集群上进行分布式计算。当你有大量的处理能力在手的时候,会很容易倾向于通过暴力求解的方法来解决问题。但是,我们常常可以将MapReduce和聪明的采样技术来增加它的效率。

让我们来考虑一个寻找所有的D组指标向量(0/1的条目), 每个向量的维度为N的数据对之间的相似度的问题。我们特别专注于所有D组向量对在R^N空间下的cosine相似度的问题。进一步地,我们假设所有的维度,都是L稀疏的,即每个维度最多在所有的点中,只有10个非0值。例如,典型的在Twitter的用户键计算两两相似度的数据可能是这样的:

D = 10M (1000万个向量/用户)
N = 1B (10亿个维度)
L = 1000(每个维度下只有至多1000个用户有值)

由于维度是稀疏的,所以将数据点按维度来存储是非常自然的想法。为了计算cosine相似度,我们可以很容易地将每个维度,通过下面的Mapper和Reducer的组合喂到MapReduce程序中去。

其中 #(w) 统计了点w中包含的维度数量,#(w1, w2)统计了w1和w2中均出现的维度的数量,也就是w1和w2之间的点积。上面的步骤计算了所有的点积,并最终通过cosine的归一化因子来计算。

有两个主要的复杂度衡量指标:"shuffle size"以及"reduce-key complexity"来简短地定义MapReduce(Ashish Goel and Kamesh Munagala 2012).

很容易可以知道,上述的mapper会输出O(NL^2)数量级的数据,这在我们给出的示例参数下来处理是几乎不显示的。mapper端输出的内容叫做“shuffle size”,因为这是需要通过网络shuffle到正确的reducer的数据。

进一步地,reduce到单个key的条目数的最大值是 #(w1, w2),也就是最多是N。这就是说,上面这种模式的"reduce-key complexity"是N。

我们可以激进地将shuffle size和reduce-key complexity的复杂度通过一些聪明的采样方式来缩小:


注: p和epsilon是过采样参数

在这个case中,reducer的删除是期望值为cosine相似度的随机变量。我们需要两个证明来确认这种模式的有效性。首先,这个期望值是正确的,并且由高概率来保障的,其次,shuffle size大大缩小了。

我们在(Reza Bosagh-Zadeh and Ashish Goel 2012)中证明了这两个断言。特别的,除了正确性之外,我们证明了上述模式的shuffle size只有O(DL log(D)/epsilon),也就是独立于维度N,就像这种算法的名称中所说的那样。

这意味着你指要有足够的mapper来读入你的数据,你可以使用DISCO采样的方式来使得shuffle size是容易处理的。进一步地,每个reduce的key最多只会得到O(log(D)/epsilon)个value,这使得reduce-key complexity也是易于处理的。

在Twitter中,我们通过DISCO采样模式来计算相似的用户。通过把每个tweets当作一个维度,其中出现的单词作为signal,我们同样可以使用这个模式来计算高度相似的单词对。我们进一步地通过经验来验证了这个假设,并且观察到shuffle size的大幅度减少,详细内容在这篇论文中。

最后,这个采样模式可以用于实现很多其他的相似度算法。对于Jaccard相似度,我们改进了著名的MinHash模式在Map-Reduce上的实现。

Posted by
Reza Zadeh (@Reza_Zadeh) and Ashish Goel (@ashishgoel) - Personalization & Recommendation Systems Group and Revenue Group

Bosagh-Zadeh, Reza and Goel, Ashish (2012), Dimension Independent Similarity Computation, arXiv:1206.2082

Goel, Ashish and Munagala, Kamesh (2012), Complexity Measures for Map-Reduce, and Comparison to Parallel Computing, http://www.stanford.edu/~ashishg/papers/mapreducecomplexity.pdf

14. August 2012 · 6 comments · Categories: Tech, Work · Tags: ,

我相信所有新晋的技术经理,都做过Team的工期紧张,自己加班动手写Code的事情,这种事情我自己也没少干过,事实上,偶尔我自己仍然会在critical的项目上写一些代码。相信不少同志们还引以为荣,并且不少技术管理的书上,对于技术管理人员是否应该去写代码也有不同的观点,有些认为不应该写,有些认为一定要写一点避免脱离群众外行指挥内行。我之前也一直犹犹豫豫有时候写点有时候逼着自己不写,但是黄易山在Quora上的这个回答,最终还是让我有了“还写砍手”的自我提醒。

理性上,我完全同意黄易山的观点,写工具是可以的,但是在deadline下写项目代码是对团队和个人都长期不利的,虽然也许短期内对自己的KPI有利。但是过去克制不住的愚蠢和冲动时不时让我冲到critical的项目上写一两个模块,但是每次反思,其实我知道这样对整个团队的效率,以及我自己的成长没有太大帮助。事实上,从这些项目中技术经理个人是得不到成长,还不如写点工具对自己的帮助大,原因就是为了进度压力,技术经理去写代码只能是重复自己已经做过的事情。而写代码本身是需要大片完整时间的,会占用掉大量你本来应该做的事情的时间。

也请认识我的朋友们监督我,如果还看到我在critical项目中冲进去写很多代码,阻止我一次请杯咖啡。


成为一个经理之后,你如何继续保持你的技术能力?

黄易山,一个前技术总监

作为一个足够大的团队的经理,你不应该继续写代码。我辅导过许多新晋的技术经理,我总是告诉他们 —— 当一个团队大于~4个人的时候,他们不应该再去写代码并且要抵制自己写代码的冲动。

原因在于,当你的团队遇到死命令的时候(比如,交付日期),一个年轻的经理很可能会被诱惑退回到他/她的舒适区中去解决问题。那就是,相较于做困难的(并且在时间上看来是很有风险的)更好地组织,激励团队,以及不管什么需要他们去做的“经理的工作”,他们立刻卷起袖子,熬夜加班,通过自己写代码来将项目完成。之所以这很糟糕是因为当像这样的艰难时刻出现的时候,恰恰是一个新的经理需要学习如何有效地管理,并避免退回去使用他们的旧的技能的时候。如果他们诉诸于使用他们的技术能力来帮助他们的团队,他们永远不会学会变成一个卓有成效的经理。这是一个那些前工程师是否最终成长为一个好的经理的至关重要的分界点。

除此之外,保持你的技术能力是非常简单明确的。

第一件事就是你真的不需要太担心失去你的优势。如果你过去干得不错,你不会像你想象地那样生锈的。在管理岗位上呆了2年+之后(并且担心这个问题),我加入了另一个公司并且重新回到了一个直接写代码的角色上,我发现非常奇怪地是,我的技术能力进步了。如果你是一个深入参与技术的技术经理,显然从一个更广的团队层面思考软件管理是有助于将通用的概念在一个更高的层面上组织起来的,并对回过来进行个人实践是有帮助的。另一方面,我并不知道如果你在管理岗位上呆上比如10年之后这一点是否仍然还是对的。

第二种方法就是写代码。但是,你不能为有交付期限的关键项目写代码。那就是说,你不应该为你的团队“需要”来贡献代码。这就时我在本文早先部分的答案——对于你的团队需要交付的项目,你应该通过更好地管理来提供贡献,而不是写代码。取而代之的是,你应该写一些内部工具或者为非关键项目写代码(也许是另一个团队的非正式的架子)。这些可以和那些有最后期限或者关键业务项目一样在技术上非常复杂,所以你无需担心你无法从合适的技术和算法中得到经验。或者,你可以在家里的空闲时间里写无关的技术项目。这是我第一次当经理时候选择的方法,在我的休息时间,我创建了一家创业公司并且学了一门新语言,以及关于可扩展性和数据库的许多东西。

所以,你可以用你一直用的方法来保持你的技术能力,写代码。只是不要为你的团队写代码


13. August 2012 · 1 comment · Categories: Tech, Work · Tags: ,

IT业内有两种比较极端的论调,一种叫做“程序员30岁要转行”,还有一种叫做“开发经理都是打酱油的”。前者说的是写程序超过30岁就没前途,必须转行做“管理”,无轮是顶个产品经理项目经理还是开发经理的头衔都好,不然以后没饭吃。后者是认为有NB程序员就可以了,技术管理的经理们基本属于IBM里面被食人族吃了的份,不见了其实也没有任何影响。其实两种观点骨子里都是一样的,认为管理或者说技术管理是个简单的事情,随便做做就好了,对于本身的产品和项目产出没有太大的影响,其实我原来也是这么认为的,特别是在某T公司遇到一些只会forward邮件的PM,问项目产品一问三不知,愈发加深了这种印象。

而自己虽然顶着管理职位的Title很多次,但是一直觉得管理职位做得很挣扎,属于操卖白粉的心,赚卖白菜钱的干活。直到见过各种靠谱不靠谱的经理之后,慢慢觉得这事情其实很有价值,但是却非常难做,一方面是做起来难,另一方面是直到要做什么之后仍然很难。参加过公司掏钱的管理培训,也翻过各种技术非技术的书,自己反复犯的错误也不少。而各种经验教训总结当中,觉得最让人一下子醍醐灌顶的的就是黄易山在Quora上回答的三个问题,所以决定抽时间翻译出来,翻译的一个好处是能够让自己安安心心仔仔细细把很多东西看完。性格急躁外加英文半吊子,所以很多东西虽然看得快但是囫囵吞枣,常常看完没多久就忘了。但是管理本身就像黄易山回答的那样,需要反复有意识地实践,凭习惯本能去做,结果一般是犯低级错误。

准备等有一天真得觉得做技术管理是让自己顺心顺手的时候写点自己的体会。

第一个问题的题目就很直白,叫做“什么使得技术管理很难?”


什么使得技术管理很难?

黄易山,一个前技术总监

技术管理很难的主要原因是管理就是很难的。使得技术管理困难的主要原因仅仅只有一个比较特别。

管理本身很难,是因为人不是为了管理进化过来的。有很多基本的管理行为人们是不会出自本性地去做的,比如下面这些:

  • 以一种不以自我为中心的合作的方式和他人相处
  • 通过逻辑和数据做出决策
  • 将逻辑和数据与直觉结合起来
  • 只在私下批评别人
  • 需要批评别人
  • 解雇表现不佳的人
  • 因为个人友谊或者熟悉程度而非客观表现而更加偏爱一些人
  • 将让人不舒服的批评加入到一个平衡的世界观里来

相较这些,人们倾向于进化成做下面这些事:

  • 以支配/服从的方式与人相处
  • 受情绪或者恐惧的驱使来做决定
  • 总是避免批评别人
  • 当众批评别人以羞辱或者伤害他们
  • 照顾哪些表现差的人
  • 晋升/偏爱熟悉的人(裙带关系)
  • 无视让人不舒服的信息

如果你想一下你认识的那些糟糕的经理,他们一定做过一些甚至是大多数第二个列表中的事。他们这么做是因为人本性就会做这些事;他们大都倾向于建立支配/服从的等级制度以及偏爱内部的部落族群,而不是互相之间平等合作或者建立没有边界的基于能力的管理模式。做第一个列表中的事情需要系统而有意识的训练以对抗人们的天性,并且心甘情愿地参与反复实践。很少有人能够有意识地要求去做这些——大部分人希望成为经理只是因为他们有意无意地想要在同伴之间建立一种支配的关系。[注1]

关于技术管理,使得技术管理的困难的特殊性主要来自一件事情,就是工程技术特别容易吸引内向个性的人,而熟练的管理技能需要更多的人际交互以及主动的情感共鸣。这对于一些技术背景的人来说很困难(或者更多的是:麻烦无聊)。然后,前面提到的代表性的进化倾向于支配。

所以如果你是一个经理,把这些记在心里:你不是生来就是一个经理。没有人是。这100%是一个学来的行动,而且要做好的话你需要努力学习。

[注1] 实际情况很复杂,有些人意识到了他们有这样的冲动,并且成功克服并成为了优秀的经理。


译后记:过去几年非常喜欢的几个产品,一个是twitter,twitter是很有趣的观点集结地,而另外一个就是quora,quora好就好在排名高的文章通常都是“知识”,“经验总结”而不是“观点”,国内很多论坛站点最让人烦的是都是一张嘴两张皮的“观点”,然后有无数扯淡不扯淡的“产品经理”(我认识的例外哈)。
悲剧地是在贵国上这两个网站都要翻墙,所以贵国只能继续落后50年,很悲哀。

20. April 2012 · 6 comments · Categories: Life, Tech, Work

在管理大规模数据处理工作的时候,发现不少工程师,包括一些老工程师,某种程度上,都对工作有着某种程度上的轻视,常常的口头禅是“这个技术上没有什么难度”,但是我其实不太认同,所谓数据处理,在技术上没有什么难度这种说法。

的确,在这个MapReduce的基础架构已经被Google设计清楚,由Doug Cutting通过Hadoop完善实现了之后,似乎大数据处理变成了一份体力工作。似乎工程师需要做的,只是写写简单的字符串解析,以及统计逻辑,对于外边很多人觉得看起来很美的工作,一旦实际接触后,常常又会觉得颇为无聊。不过,从我过去的经验来看,很多工程师也是这样对待Web时代的Struts和Spring,搜索时代的分词器,Lucene。

大量算得上不错的工程师,通常当熟练运用已有的技术,在一个特定模式下工作后,就会开始觉得工作无聊重复。然而实际上,一旦成为一个熟练工之后,很多人便开始停滞不前了。原先不熟悉框架的时候,他们需要10天摸索才能完成一个功能,现在熟练了,他们只需要3天了,但是之后,他们再也不能缩短开发时间,同时,他们的Bug数量也不会变少,当有新的需求出现的时候,通常第一反应就是套入到当前框架种处理,我通常称之为“1年经验重复10遍”。

有些工程师在进入这样的状况后,往往会寻求找一些新的工具、框架以及工作内容,通常,这意味着换一份工作,或者换一个开发团队,但是在新工作或者新团队下,一般在度过了一年蜜月期之后,会再次陷入“其实也就那样都是些体力劳动”状况,这种情况我一般称之为“八大菜系都吃过你也不是一个好厨子”,这个情况比“1年经验重复10遍”会好一些,但是仍然是一个糟糕的循环。

还有些工程师,会去研究所依赖的基础框架的源代码,开始依样画葫芦,搞些新轮子出来,部分热衷造轮子的同学会对所有的项目都造同样的轮子出来,这种情况我称之为“轮子爱好者”。

然而遗憾的是,这几种情况,其实都不是一个正确的,提高一个程序员解决问题水平的正常路线,这些方法也许能够帮助你从一个水准一般的程序员,变成一个还不错甚至算得上优秀的程序员,但是不能帮助你跨过平台,成为一个真正优秀的明星程序员,或者用个被用得糟烂的词——“架构师”。

这些程序员不少最终会觉得写程序是个没前途的事情,觉得只能往Manager这一条黑道上挤,从此,世界上少了一个本有希望能够贡献杰出代码的人。事实上,真正想要成为更优秀的工程师,需要做的,是在应用架构层面,去提高生产效率,乃至支持更多更强大的功能。区分真正优秀的程序员和普通程序员的差异,往往在于,是否能够真正地找到契合问题域的解决方案,通常这样的解决方案,能够在数量级上减少实际的开发工作。想像一下用EJB2做PetStore,再到用Struts,再到用Struts2/WebWork,再到用SpringMVC,乃至使用Rails。

“1年经验重复10遍”会每天反复操练EJB2,“八大菜系都吃过你也不是一个好厨子”会用JSP,Servlet,EJB2,Struts,PHP,C#.NET,“轮子爱好者”会看到Struts之后轮一个和Struts差不多的。但是真正优秀的程序员,能够改进Struts的不足,搞出WebWork,乃至Rails。这并不意味着你一定要很Fancy地去搞Google面试一样研究很多算法,也不需要你一定多熟悉编译原理,操作系统这样的底层技术,也不需要你18般武艺样样稀松地去看PHP和C#。你需要的是,在有了解决方案之后,仔细思考,真正理解问题域,寻求能够更好地满足问题域的解决方案,从细节上改进现有问题域的解决方案。这是来自我的教训,事实上,前面的三种陷阱我都荒废了不少时间,直到近两年,才愈发觉得无论是反复操练熟练工,还是18般武艺样样稀松的都会一些,甚或是轮一些别人轮过的轮子,都不是能让自己真正跨出成为顶尖程序员的一步。真正要解决好问题,交付出有价值的程序和框架,还是要回到问题域去。

这也是我喜欢Twitter技术团队以及推崇Nathan Marz的原因,无论是ElephantBird,Finagle,还是Storm,都不是庞然大物般的程序,而是贴近问题域,合理解决问题域的解决方案,也是从技术角度,希望自己能够在最近两年里能够达到的水准。

周末得空,把前一阵买的MEAP版本的Big Data已经出了的两张给翻完了,觉得有点不划算,主要是内容之前在Nathan Marz的博客,以及Twitter发布出来的各类Slides里都已经看过了(话说Twitter去年年头上说Rainbird要开源到现在也是坑爹地没个影)。但是有一个新词儿还是让我觉得“心有戚戚焉”,把最近在Team里数据处理架构做的各种迁移工作的精髓给说出来了,就是这个Human Fault-Tolerance。

在这个人人都热衷于叫唤Big Data,讨论CAP理论的时候,Nathan同学一针见血地指出了一点,其实CAP也好,Cassandra的Dynamo模型也好,HBase的Big Table模型也好,看似非常酷非常好用,解决或者部分解决了各种一致性和可用性问题,但是其实对于Big Data处理的架构的最关键的一点,在于对于各种人类错误的容错性。

其实即使在没有海量数据需要处理的时候,各个程序也要考虑各种人类容错性。最简单的例子就在设计数据库的时候,对于删除操作大家都喜欢用个标记字段来标记删除,而不是真把记录删掉。类似的,在各种实时数据处理的事务里,除了普通的各种check和特殊情况考虑之外,通常有经验的程序员会做两件事情,一个是做日志,记录所有实时输入的日志,而是在整个处理的逻辑外面捕获所有的Exception,然后对Exception也会记录日志。做这些事情的原因是有这样一个假设,人会犯错,程序员会写出Bug。即使对程序做了充分的测试,但是当程序进入真实环境运行的时候,仍然会有你想不到的意外情况发生。当意外发生的时候,这些日志,记录能够帮助你把数据恢复到一个正常的状态下。记得在我工作的第一个年头里,就曾经花过一整天,将由于一个Bug引发的数据错误通过人肉SQL恢复过来。

当进入Big Data时代的时候,光光依靠简单的日志记录和人工恢复,已经不能够解决这些问题了。一天如果有个几条数据在几千条数据里面出错,也许你能够手工恢复过来;但是如果当一天的数据有几亿条,聚合后生成的数据记录也有几千条的时候,恐怕你就不能使用记录错误日志,然后人肉恢复的方式来解决问题了。而需要依靠在系统实现的架构层面来解决这些问题,Twitter推荐的实现方式就是让事实数据immutable,所以所有的数据都会记录,要看的数据是基于事实数据,计算出来的视图,非常简单粗暴,但是有效的方式。

话说回来,基本上,能不能写出Human Fault-Tolerance可以看做是一个程序员是否有充足的工业界工作经验的一条标准,这个不是依靠聪明和天赋能够解决的问题,而是完全依靠血泪教训得来的,从这个角度讲,老兵不死。虽然IT特别是互联网行业常常充斥着“30岁要转行,因为加班加不动了”,但是我向来是以为,有经验的工程师的价值始终被低估了。即使是不是Super Star的老工程师,也许光光写新功能写算法,未必比新人强出多少,但是这些血泪教训带来的经验,只要能够躲过一次问题,带来的价值也许就是一个工程师一两个月的工作量了(当然,无论如何记得,10年工作经验和1年工作经验重复10次的差别)。当然,更好地是团队能够拥有天才程序员,比你年轻比你聪明还比你身体好,比如Nathan Marz同学……