2011年11月1日

VI下DoxygenToolkit生成注释非常方便

曾几何时,我在Eclipse下进行Java编程时,对于生成Javadoc有过一个非常棒的插件。将光标放置到函数内部或者文件头部,按下快捷键就可以得到相关的符合Javadoc或者Doxygen标准的相关注释。当时对程序编写注释是一件非常舒服的事情,而且最终生成的文档也非常的漂亮。

从去年2月开始完全转入Linux环境后,我开始纯粹的C++编程,不管采用哪种编程IDE,都没有找回那种编写注释的感觉了。今天,这种感觉重新回来了。那就是VI下的DoxygenToolkit。在文件头输入DoxAuthor命令就能自动插入作者信息,输入DoxLic就能自动插入版权信息,更为强大的是在类或者函数的头部输入Dox命令就能得到标准的注释模板,而且一些域已经很好的自动补全了。

配合Doxygen生成的html网页或者latex pdf文档看起来都是相当的专业。

参考链接:

vim中两个实用插件doxygen和projects的安装与使用  http://yaronspace.cn/blog/archives/682
doxygen+VIM文档实用指南for C/C-liked Programmers http://blog.csdn.net/clarkZHUO/article/details/1471573

看来以后在VI下的编程时间会不断增加,还得熟悉一些相关插件,争取实现手指在键盘上飞的感觉。标记于此。

2011年10月17日

我的机器翻译学习经历以及即将开启的词对齐学习

统计机器翻译的第一步就是词对齐,随后抽取短语表,然后根据短语表进行翻译解码,中间会根据语言模型来选取最优的翻译结果。整个统计机器翻译的各个步骤都有很多人在不断的深入研究,从mt-archieve这个网页(http://www.mt-archive.info/subjects.htm)可以见识到相关论文的增长速度。面对如此海量的论文,对于一个统计机器翻译的新手,究竟该何去何从呢?这个问题长时间的困扰了我。

去年年初博士毕业后开始接触统计机器翻译。好友张慧一开始就建议我仔仔细细从零开始实现一个机器翻译的系统,可以完全从词对齐开始实现全部的步骤,也可以针对解码器从零开始实现解码功能,经过这个阶段后才能真正领悟统计机器翻译的魅力以及其中的症结。由于项目的压力,我只能抽出业余时间来完成这个计划。起初是想从零开始实现解码器,经过一个多月的业余开发,我的解码器可以得到和moses的最基本stack解码一模一样的各种概率输出。当时我小小的兴奋了一下,感觉对机器翻译总算有了一点点感觉。但是随着翻译句子长度的增加,我的解码器速度变得非常的慢,比起moses的速度差远了,内存开销方面我的解码器也比moses差很多。后续我开始研究moses的各种加速技术以及节省内存开销的方法。在网上四处转悠后发现了kenlm这个比srilm好很多的语言模型工具包。熟练使用后,我把kenlm的代码改装替换掉了我的解码器的语言模型,也同时替换掉了我的项目里使用的语言模型,当时我项目使用的decoder在内存开销方面节省了很多。随着更进一步的优化,我对stack解码器相关的技术了解了更多。当我开始尝试编写cube pruning解码方法时,开始被项目项目相关的其他事宜占用全部的时间,随后我的解码器业余时间研发计划就被搁置下来。仔细算来,我的这个事项居然被耽搁了半年多了。

随着对统计机器翻译的认识不断深入,我越发觉得如果想深入研究机器翻译或者从事相关的开发工作,词对齐方面的研究必不可少。给我造成这种直觉的直接原因,是我原本想准备完成一项短语表过滤的研究任务。但是随着调研和各种对比实验的深入,我发现单纯从已有的低质短语表出发,很难找到更加有效的过滤方法。更加fundamental的方法是进行更好的词对齐以及后续的短语抽取。这个路子可能才是解决问题的思路。

后续我阅读了近两年来的关于词对齐的论文,最近在reading group上主讲的《An Unsupervised Model for Joint Phrase Alignment and Extraction 》、《Feature-Rich Language-Independent Syntax-Based Alignment for Statistical Machine Translation 》、《Bayesian Word Alignment for Statistical Machine Translation》让我对词对齐任务有了进一步深入的认识。词对齐的根本目的是为了抽取短语,好的短语可以产生好的翻译。有人也在绕过词对齐,而直接作短语对齐。细数mt-archieve上的词对齐论文,几百篇的数量让人惊讶。

我想深入的学习词对齐这个点,力争在词对齐上有所突破后再向短语对齐方向努力,进而再结合解码过程中的特点来实现一种新型的短语抽取和解码过程直接相关的翻译系统。这个计划需要好好执行。

接下来的词对齐学习,我想就从Jorg Tiedemann今年5月刚出版的《Bitext Alignment》开始吧。153页的薄册子,希望能在半个月内能看完。给自己加油 :)

2011年9月27日

9月27,而立?!

今天是个特殊的日子,查了一下,居然发现历史上的今天居然这么多事情:

1961年9月27日――刘德华出生。
1971年9月27日――李亚鹏,中国男演员
1974年9月27日――许美静,新加坡歌手
1979年9月27日,世界旅游组织第3次代表大会确定每年的9月27日为世界旅游日
1991年9月27日,微软研究院成立。
1998年9月Google公司成立。Google官方确认的生日是9月27日。


补充几条:
1981年9月27日,俺出生了,感谢父母赐予我生命并养育我成人;还有我的两位好友(方天、姜晓飞)也是这一天出生的。
2011年9月27日,俺而立之年的开始,感谢诸位朋友(Paul, Devi, Wenliang, Xiangyu, Xinyan, Nancy, Yufeng)中午为我准备的生日Party,也感谢中华从南京带来的盐水鸭(中华是我指导的第一位实习生,今早初次见面)。还要感谢一大堆在网上送来生日祝福的朋友们。还要感谢我的太太,早上传统的生日煮鸡蛋和长寿面还是那么的美味。

人生步入了新的阶段,为了心中的梦想,为了新的十年,努力!

2011年9月24日

机器学习的特征工程应该是领域知识转换的过程

脚趾甲动完手术,今天上午最后一次去诊所。我告诉医生,因为走路包扎的纱布完全脱落过一次。医生说对于我这种小手术,他最喜欢听到这样的事情发生,因为那就意味着伤口附近的肿痛消失了。

这让我想到了机器学习里的特征抽取,很多时候特征不能乱想,应该有实际的意义,就像"纱布完全脱落"可以作为肿痛消失的特征。说到底,特征工程应该是个领域知识转换的过程,这样的机器学习才会有效有意义。

针对我正在做的机器翻译,我得学些人工翻译方面的书籍了。

2011年9月23日

冰糖蒸梨--润喉止咳化痰养生

冰糖蒸梨具有润喉止咳化痰之养生食疗功效,对于经常说话的人,例如教师,具有很好的滋养作用。

一、最简便的加工方法:将梨去核切块,冰糖撒于其上,隔水蒸5-8分钟。

二、最传统的加工方法:将生梨从中间一剖二,去核;将冰糖(加川贝粉效果更佳)放入 半个生梨心中,用牙签将两个半个生梨"恢复"原样;隔水蒸约一个小时。

三、最时尚的加工方法:川贝舂碎,雪梨去芯,切成两半。将所有材料放入炖盅,以慢火炖一个小时。注意,这个方法最时尚的地方在于,不是隔水炖,而是隔着红酒炖。在川贝和冰糖的渗透下,梨原本晶莹剔透的玉色会一点点地在红酒和火力的熏染下变成暗红,房间里慢慢地弥漫出混合着果香的红酒味儿,打开炖盅时,冰糖和川贝已经就着蒸汽和梨汁化了,里面一定是一汪稠稠的羹,那种烹饪的感觉是如此奇妙。

2011年9月19日

不弄清程序的上下文环境容易出错:针对Moses的tunning解决一个重要Bug

最近发现我在服务器上运行的moses的tunning偶尔会出现不能得到结果的现象,居然两次发现moses tunning出来的moses-tunned.ini缺少参数。这个问题似乎从来没有出现过,仔细的检查的moses的参数处理的perl脚本,居然发现原因是moses的tunning出来的weight可能有科学计数法,例如-6.62728e-05。但是reuse-weight.perl中在识别这些weight时都是默认为纯小数的,例如-6.62728。在不能匹配科学计数法的数字时自然就会丢掉某些weight,导致后续的测试程序出现问题。

这个Bug较为隐蔽,似乎接触moses的两年多来都没有遇到过,仔细想想,肯定是以前tunning的结果的weight都是纯小数,最近的一些语料上的运行才出现了这个对极小数采用科学计数法的问题。

通过修改Perl匹配小数的正则表达式,这个Bug解决掉了,程序终于能畅快的继续运行了。

这个小事,让我想到一个问题,那就是写程序的时候往往会出现对输入输出数据的相关假设,编程人员务必需要仔细对各种输入情况进行考虑,最好的方法就是编写各种各样的测试用例来保证结果的正确性。

2011年8月7日

转载以明志:史蒂夫・乔布斯在斯坦福大学毕业典礼上的演讲(2005年)

篇尾的第二个注记很值得记住。
--------------------------------------------------------------------------------------------------



史蒂夫・乔布斯在斯坦福大学毕业典礼上的演讲(2005年) - 东西
今天,能在这所世界上最好的大学之一和你们一起参加毕业典礼,我感到很荣幸。说实话,我自己从来没有从大学毕业,那么今天恐怕是我一生中最接近大学毕业的一天了。在此,我只想向你们讲述我生命中的三个故事。不是什么惊天动地的事情,只是三个我自己的故事而已。 第一个故事是关于如何把生命中的点点滴滴的经历联系起来。 我在里德学院(美国一所著名的私立大学)读了六个月之后就退学了。但是在那以后的十八个月里,我还留...

  今天,能在这所世界上最好的大学之一和你们一起参加毕业典礼,我感到很荣幸。说实话,我自己从来没有从大学毕业,那么今天恐怕是我一生中最接近大学毕业的一天了。在此,我只想向你们讲述我生命中的三个故事。不是什么惊天动地的事情,只是三个我自己的故事而已。

  第一个故事是关于如何把生命中的点点滴滴的经历联系起来。

  我在里德学院(美国一所著名的私立大学)读了六个月之后就退学了。但是在那以后的十八个月里,我还留在学校里。十八个月后,我才彻底地离开那里。我为什么要退学呢?

  故事从我出生的时候讲起。我的生母是一个年轻的,还没有结婚的大学毕业生。在我出生之前,她决定让别人收养我。她非常希望我能被大学毕业生收养,所以在我出生的时候,她已经联系好了一个律师的家庭来收养我。但是当我出生之后,那对律师夫妇突然决定他们想要一个女孩。所以医院连夜联系了我现在的养父母。他们说:"我们现在这儿有一个男婴等着领养,你们想要他吗?"他们回答道:"当然!"但是后来我生母的拒绝签这个领养合同,因为她发现我的养母从来没有上过大学,我的养父甚至从未完成高中学业。经过几个月的协商,我的养父母承诺一定会让我上大学,我的生母才最终妥协了。

  在我十七岁那年,我上了大学。天真的我选择了一个几乎和斯坦福大学一样贵的私立学校,我蓝领阶层的养父母履行了他们的承诺,把所有的积蓄都拿给我做学费,这是一笔巨大的投资。但是六个月后,我意识到这样的投资毫无价值。我还不知道我这一生到底想做什么,我也看不出这样的大学生活能够帮我找到答案。而于此同时,我在一点一点地花光我父母这一辈子的所有积蓄。所以我决定退学,并坚定的相信那是个正确的决定。不可否认,我当时确实非常害怕,但是现在看来,那的确是我这一生中最棒的一个决定。从我退学的那一刻起,我终于可以不需要去选那些无聊的必修课程,而有时间去旁听一些我真正感兴趣的东西。

  然而事情并非一帆风顺。学校收回了我的宿舍,所以我只能在朋友房间的地板上面睡觉。我得去捡可乐瓶子然后送到回收站,每个瓶子我能挣5分钱,我用这些钱来买食物. 每个星期天的晚上,我要走七英里的路程,穿过这个城市到Hare Krishna寺庙去吃上一顿丰盛的晚餐。虽然很苦,但是我非常喜欢这样的生活。在那段日子里,我的好奇心和直觉领着我学到很多东西,此后被证明是无价之宝。让我来给你们举一个例子。

  里德大学在那时提供几乎是全美最好的美术字课程。大学里面的每个海报,每个抽屉的标签上全都是漂亮的美术字。因为我退学了,没有了必选课的约束,所以我决定去听听这个课程,学学怎样写出漂亮的美术字。在那里我学到了什么是Serif和San Serif字体[1]。我还学会了怎么样在不同的字母组合之中改变字母之间的距离,还有怎么样才能作出最棒的印刷式样。那是一种科学永远不能捕捉到的,美丽的,真实的艺术精妙,我深深的陶醉其中。

  当时看起来,这些东西仅仅是我的兴趣爱好,没什么实际用处。但是十年之后,当我们在设计第一台Macintosh电脑的时候,他们神奇地充分发挥了实用价值。我把当时学到的东西都融合在Macintosh的设计当中,使它成为第一台拥有漂亮显示字体的电脑。如果我当时没有退学而去参加那个美术字课程,Macintosh电脑就不会有这么多丰富多样而且错落有致的字体,同样,现在的个人电脑也就不会有这么美妙的字体了。当然我在大学的时候,还不可能把从前的点点滴滴串连起来,但是当我十年后回顾这一切的时候,一切变得豁然开朗。

  你在向前展望的时候,你不可能将这些经历片段串连起来;只有在回顾过去的时候,你才发现他们原来紧密相连,所以你应该相信你的经历会在未来的某一天连系起来。你必须要相信某些东西:你的勇气、你的目标、生命的价值和万事之间的因果连系。因为只有你相信你的经历将来会连系在一起,你会受益于这些经历,你才能自信走你真正想走的那条路。这条路有时可能带领你偏离主流的价值观,而也正因如此,你的人生才会与众不同。

  我的第二个故事是关于爱和失去的。

  我认为自己非常幸运,因为我在很早的时候就找到了我钟爱的事业。Woz(苹果公司的另外一个创始人)和我在二十岁的时候就在我父母的车库里面开创了苹果公司。我们拼命工作,十年之后,苹果公司发展成一个市值20亿美元,拥有超过四千名的员工的大公司。在公司成立的第九年,我们发布了最伟大的产品--Macintosh电脑。我也快要到三十岁了。而就在那一年,我被解雇了。有些人一定不理解,你怎么可能被你自己创立的公司解雇呢?事情是这样的。在公司快速成长的时候,我们雇用了一个很有天分的人和我一起管理这个公司,在最初的几年,公司运转的很好。但是后来我们对公司远景规划发生了分歧,最终我们吵了起来。当我们的分歧越来越大的时候,董事会站在了他那一边。所以,在三十岁的时候,我被解雇了。众目睽睽之下,我失去了我为之奋斗了十几年的事业,这对我来说真是毁灭性的打击。

  在最初的几个月里,我真的是不知所措。我把从前的创业激情给丢了,我觉得自己辜负了企业家前辈们对我的期望。我约David Pack和Bob Boyce见面,并试图向他们道歉。舆论和媒体给我很大压力,我甚至有过离开硅谷的念头。但是不久以后,我渐渐振作起来并看到了希望,我发现自己仍然深深喜爱着我在行业做的事情。苹果公司发生的这些事情丝毫的没有改变这些,一点也没有。我被解雇了,但是我仍然对这份事业情有独钟。所以我决定从头再来。

  我当时并没有觉察,但是事后证明,从苹果公司被炒是我这辈子发生的最棒的事情。因为,被解雇之后,作为一个世人皆知的成功者的负担没有了,我再次感受到了作为一个创业者的轻松,未来再次变得不可知而充满魅力。这让我觉得重获自由,进入了我生命中最有创造力的一个阶段。

  在接下来的五年里,我创立了两家新的公司,NeXT和Pixar,并和我后来的妻子,迷人的Laurence相爱。Pixar 制作了世界上第一个用电脑制作的动画电影--"玩具总动员"。Pixar现在已经成为世界上最成功的电脑制作工作室。1996年,苹果公司收购了 NeXT,我又回到了苹果公司。我们在NeXT开发的技术在苹果公司的复兴之中发挥了关键的作用。我还和Laurence一起建立了一个幸福的家庭。

  我可以非常确定的说,如果我不被苹果公司开除的话,这一切都不会成为现实。这剂"良药"的味道实在是太苦了,但是我相信,良药苦口利于病。挫折是难免的,有些时候就好像生活拿起一块砖头向你的脑袋上猛拍一下。但是面对挫折,千万不要失去信心。我坚信,唯一使我坚持走下去的,是我对我做的事情的无比钟爱。你需要去找到你所爱的东西。对于工作如此,对于你的爱人也是如此。你的工作将会占据生活中很大的一部分。只有相信自己所做的是伟大的工作,你才能怡然自得,把工作做好。如果你现在还没有找到你最爱的工作,那么继续找,不要停下来,全心全意的去找。当你找到的时候,你就会知道这一切都是值得的。就像任何真诚的关系,随着岁月的流逝只会越来越紧密。所以继续找,直到你找到它,千万不要停下来!

  我的第三个故事是关于死亡的。

  当我十七岁的时候,我读到了一句话:"如果你把每一天都当作生命中最后一天去生活的话,总有一天你会发现那一天真的来到了"。这句话给我留下了深刻的印象。从那时开始,在以后的33年里,我在每天早晨都会对着镜子问自己:"如果今天是我生命中的最后一天,我会不会想要完成我今天要做的事情呢?" 当答案连续很多天都是"不是"的时候,我知道自己需要做一些改变了。

  "记住你即将死去"是我一生中遇到的最重要箴言。它帮我做了生命中很多重要的选择。因为几乎所有的事情,包括别人的对你的期望,所有的荣誉、所有的骄傲、所有对难堪和失败的恐惧,在死亡面前都会消失,而留下来的才是真正重要的东西。你有时候会患得患失,顾虑重重,"记住你即将死去"是我知道的避免这些想法的最好的办法。面对即将来临的死亡,你已经一无所有了,你没有理由不去真正倾听来自你内心的召唤。

  大概一年以前,我被诊断出癌症。我清楚的记着,那天早晨七点半我做了一个检查,检查结果清楚的显示在我的胰腺有一个肿瘤。我当时都不知道胰腺是什么东西。医生告诉我那很可能是一种无法治愈的癌症,我还有最多三到六个月的生命。医生建议我回家,处理以下生活中的事情。我很清楚,其实医生就是让我准备好迎接死亡。那意味着你将要把未来十年对你小孩说的话在几个月里面说完.;那意味着把家里每件事情都安排好,让你的家人以后可以尽可能轻松的生活;那意味着--你要说"再见了"。

  我那整天都在不停地想这个诊断。那天晚上,医生为了确诊,又给我作了一个活切片检查,他们将一个内窥镜从我的喉咙伸进去,通过我的胃,然后进入我的肠子,用一根针在我的胰腺上的肿瘤上取了几个细胞。我当时被麻醉了,什么都不记得。但是我的妻子在那里。她后来告诉我,当医生在显微镜地下观察这些细胞的时候,他们竟然激动的流泪了,因为这些细胞原来竟然是一种非常罕见的可以用手术治愈的胰腺癌症。我做了这个手术,现在我痊愈了。

  那是我最接近死亡的时候,我还希望这也是以后的几十年最接近的一次。在那之前,死亡对我来说,只是一个概念;但在那之后,我对死亡有了更深的感悟。正因如此,在此我可以更肯定的跟你们分享一些我对死亡的看法:

  没有人愿意死,即使那些想上天堂的人们也不会为了去那里而死。但是死亡是我们每个人共同的终点,从来没有人能够逃脱它。也许正该如此,因为死亡是生命的延续,它将旧的事物清除,从而让新的事物诞生。你们现在是"新"的,但是在不久的将来,你们将会逐渐的变成"旧"的,然后走出历史舞台。这可能听起来很戏剧性,很残酷,但是这就是现实。

  生命有限,所以不要为别人而活,因为那是浪费生命。不要被教条束缚,因为那意味着你将永远沿着别人的思路生活。不要被他人观点掩盖你自己内心的声音。还有最重要的是,你要有勇气去跟随你的心和你的直觉--它们在某种程度上知道你真正想要成为一个什么样的人。所有其他的事情都是次要的。

  当我年轻的时候,有一本叫做"地球目录" (The Whole Earth Catalog)的杂志,它被我们那一代人视为像"圣经"一样的读物。它的作者叫Stewart Brand,就住在离这里不远的Menlo Park,他象诗一般神奇地将这本书带到了这个世界。那是六十年代后期,在个人电脑出现之前,所以这本书全部是用打字机,裁纸刀还有快速成像相机做成的。完全可以把这本杂志比喻成"包在书皮里的Google",但它出现在Google出现的三十五年之前--它充满了理想主义色彩,其中有许多巧妙的工具和伟大的想法。

  Stewart和他的团队出版了几期的"地球目录",时代变迁,当它就要完成自己使命的时候,他们做出了最后一期。那是在七十年代的中期,我那时跟你们差不多大。在最后一期的封底上是一张清晨乡村公路的照片。如果你富有冒险精神的话,你完全可以想像你会某一天在这样的一条路上徒步旅行,时不时搭顺风车到下一个目的地,那是多么美妙。在照片之下有这样一段话:"Stay Hungry. Stay Foolish"[2],作为这本精彩杂志的停刊赠言。"Stay Hungry. Stay Foolish"也成了我的座右铭,我总是希望自己能够那样。现在,在你们即将毕业,开始新的旅程,我把这句话送给你们,希望你们能够:

  Stay Hungry. Stay Foolish.

  谢谢大家。


注记:

[1] Serif字体和Sans Serif字体是字体的两大基本分类。在Serif字体中,字的笔画开始及�束的地方有额外的装饰;与之相反,Sans Serif字体没有在笔画末端的修饰。通常Serif字体更加易读,特别是在字号较小的情况下,所以正文多用Serif字体。而Sans Serif字体则多用于标题中。

[2] 我花了很多时间也没有能够找到对"Stay Hungry. Stay Foolish"的简洁明了的中文翻译。理解这句话需要结合这篇演讲的全文,Steve Jobs的经历以及苹果公司著名的"Think Different"广告词。"Stay Hungry"是说要永远不满足已经取得的成就,奋斗不息。"Stay Foolish"是说不要被别人的声音所影响,要相信自己,走自己的路,不要为取悦别人而活着。也许开始你会被别人以为"愚蠢"(foolish),甚至 "疯狂",但正是这样的与众不同,往往会带你走向伟大的成功。

译者按:

作为一个苹果公司的忠实用户和对Steve Jobs本人的崇拜者,我觉得这篇演讲稿值得每一个人去读。在翻译中,我参考了网上的一些不知出处的译文,他们对我的翻译很有帮助。我还要感谢我的太太,以及我的好友Erik,他们帮助我更好的理解这篇演讲稿。

2011年6月3日

小铁匠的人生追求和佛陀的指点

佛陀涅�前,阿难陪他来到一个小村庄,遇到一个叫纯陀的善良的年轻铁匠。

第二天清早,佛陀在村头的小河边上散步,远远望见年轻的铁匠一个人躺在河边的沙滩上,眼望着蓝天,木然地在想着什么。这时,朝云出岫,曙色飞散,霞光似锦,清晨的天空别有一番景象。只见年轻的铁匠用好奇的目光,仰望天际,欣喜留连,好像有什么沉重的心事。

于是,佛陀近前问道:"年轻人,你在想什么?"

铁匠微微叹息一声:"佛陀,我在想,我怎么样才能荣华富贵呢?

我想,将来总会有那么一天??"

"唔,你在想荣华富贵!"

"是的,佛陀。"年轻人思索片刻,默默地凝视着远天,津津有味地说:"我现在打铁,省吃俭用,长此下去,将来就会积攒下很多钱,一天比一天多。"

"唔,你要那么多钱干什么?"

"有了钱,我就拆了现在住的这几间破茅屋,重新盖上一幢漂亮舒适的大房子,有花园,有亭阁,宽敞,亮堂,舒服。"

"要那么漂亮的宅院干什么呢?"

"这还用问?"年轻人的脸上露出轻松的笑容,充满了对幸福的憧憬,"有了宽绰讲究的宅院,自然就不愁娶一个年轻漂亮的老婆了!她嘛,白天晚上陪伴着我,别提多么美满幸福了!"

"那么后来呢?"

"往后我就可以早晨一起来,就舒舒服服地躺在这小河边的沙滩上,悠闲自在地欣赏明净碧蓝的天空,听天上飞翔的云雀鸣叫。你看,佛陀,那日子过得该有多么幸福啊!"

"看天空,听云雀鸣叫?"

"是呀,佛陀,我愿意为这种享受而终生追求。"

"哈哈,"佛陀仰天大笑:"聪明的年轻人,你何必为此而苦心追求呢?你现在已经达到你一生最终追求的目的了!"

2011年5月8日

人生的追求

你成天忙这些为了什么?你的理想或长远追求是什么?

两个简单的问题可以直击你的心灵。

儿时的我,经常一个人跑到西南交通大学的校内书店瞎逛,记得买回的第一本书讲的是科学家的故事。打那时起,我的理想就是长大成为一名科学家。

今年4月,研究所改变了头衔体制,我从原来的Research Fellow变成了Scientist I。虽然本质上没有任何区别,但是我还是小小的激动了一把。因为儿时的梦想可以说在头衔上已经实现了。

前两天小组开会,老板又提到了让我们得有长远规划,例如未来3-5年想做什么。之前还有一次,老板对我说,我将来可以有两条长远规划,一是去一流公司纯做工程开发,二是纯做研究。

回想自己从2000年上大学以来的经历,工程开发远大于科学研究。总结自己做研究最快乐的时光,居然是五次数学建模竞赛、自己独立半年时间完成的科技创新项目、以及硕博期间组织的五次全校机器学习小组活动。

所谓经常做什么就会在什么方面学得多些。十年来参与过不少项目的申请、组织、实际完成以及结题后,我对于做项目的激情居然大于对做研究的感觉了。

为什么呢?这个感觉似乎不符合我的理想预期啊。仔细想想,应该和Sunner提到的"人的快乐来自于持续的成就感"不谋而合。

作项目过程中的那种不断涌现的成就感远比作研究过程中的成就感要多得多。或者这个感觉只是我的个人感受。我猜想那些论文生成器类型的研究人员应该在研究过程中也会有持续的成就感。

在网上查了一下什么是科学家。看完下面链接中的描述,才算更多了解了科学家的方方面面。儿时的梦想不清晰,不明确,不知道还有这么多的细节。为了理想而努力吧。

http://baike.baidu.com/view/66827.htm

细细总结自己十年来关注的事情,提炼成关键词不外乎就这么几点:数学、编程、英语、机器学习、太极、自然语言处理。仔细想想自己无数次给自己制定的计划和兴趣的不断转移,都不外乎在这几点里面。

2011年4月21日

羽毛球与太极云手

昨晚打羽毛球时又遇到了那位发球很快的同事。他的发球有的左有的右,有的吊短,有的拉长,最常用的就是反后方的快球。更难办的是当你往后退一点准备接反后方求时,他又来一个靠外侧的吊球。只要他发球我们就比较紧张。

一次,球过来时拍档更快的接过去了,而且回的是一个那位同事反后手的位置,得分了。

原来,接这位同事球的时候应该比他更快。轮到我接他球的时候,为了应对他的变化多端,我把球拍排面竖直往下,位于脸正对的前面一尺位置。球过来时,我可以快速的变换接球的姿势回球。

成功一次后,第二次失败了。原因是手不够灵活。第三次,我先采用这个姿势,按太极云手的方式左右转了几次,凭着云手的感觉,我接球的以静制动的成功率很快上升,到后来这位同事的球我都能回过去了,以至于他一看到接球的是我时,他都有点紧张了。

太极云手的感觉不错。忽然想到,球拍守中线并快速变换的策略和李小龙练的永春拳是一个思路。都是以静制动,以不变应万变。

2011年3月31日

Google Cpp Style Guide 1.1 #define保护:里面没写清楚对svn或者git管理项目源代码的假设

=============================
1.1. #define 保护
Tip 所有头文件都应该使用 #define 防止头文件被多重包含, 命名格式当是: <PROJECT>_<PATH>_<FILE>_H_
为保证唯一性, 头文件的命名应该依据所在项目源代码树的全路径. 例如, 项目 foo 中的头文件 foo/src/bar/baz.h 可按如下方式保护:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
xxxxx

Google Cpp Style Guide 1.1 #define保护:里面没写清楚对svn或者git管理项目源代码的假设

------------------------------------------------------------
1.1. #define 保护
Tip 所有头文件都应该使用 #define 防止头文件被多重包含, 命名格式当是: <PROJECT>_<PATH>_<FILE>_H_
为保证唯一性, 头文件的命名应该依据所在项目源代码树的全路径. 例如, 项目 foo 中的头文件 foo/src/bar/baz.h 可按如下方式保护:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_

初步接触Google Style和Cpplint

试着看了一下Google Style的C++编码规范,先随手写了一个最简单的程序来试试Cpplit。代码如下
------------------------------------
#include <iostream>

using namespace std;

int main() {
    cout << "Hello World!" << endl;
    return 0;
}
------------------------------------
运行指令
------------------------------------
g++ main.cpp -o main
./main
------------------------------------
得到结果
------------------------------------
Hello World!

------------------------------------
运行Cpplint,得到的结果如下
------------------------------------
main.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
main.cpp:1:  Streams are highly discouraged.  [readability/streams] [3]
main.cpp:3:  Do not use namespace using-directives.  Use using-declarations instead.  [build/namespaces] [5]
Done processing main.cpp
Total errors found: 3
------------------------------------
第一条说我没有版权信息,第二条没看懂,第三条说的是不能用std全部空间,建议使用具体用到的函数。

仔细上网查了半天,终于弄懂了第二条是什么意思。

------------------------------------------
5.9. 流
Tip 只在记录日志时使用流.
定义: 流用来替代 printf() 和 scanf().
优点: 有了流, 在打印时不需要关心对象的类型. 不用担心格式化字符串与参数列表不匹配 (虽然在 gcc 中使用 printf 也不存在这个问题). 流的构造和析构函数会自动打开和关闭对应的文件.
缺点: 流使得 pread() 等功能函数很难执行. 如果不使用 printf 风格的格式化字符串, 某些格式化操作 (尤其是常用的格式字符串 %.*s) 用流处理性能是很低的. 流不支持字符串操作符重新排序 (%1s), 而这一点对于软件国际化很有用.
结论: 不要使用流, 除非是日志接口需要. 使用 printf 之类的代替.

使用流还有很多利弊, 但代码一致性胜过一切. 不要在代码中使用流.

拓展讨论:
对这一条规则存在一些争论, 这儿给出点深层次原因. 回想一下唯一性原则 (Only One Way): 我们希望在任何时候都只使用一种确定的 I/O 类型, 使代码在所有 I/O 处都保持一致. 因此, 我们不希望用户来决定是使用流还是 printf + read/write. 相反, 我们应该决定到底用哪一种方式. 把日志作为特例是因为日志是一个非常独特的应用, 还有一些是历史原因.

流的支持者们主张流是不二之选, 但观点并不是那么清晰有力. 他们指出的流的每个优势也都是其劣势. 流最大的优势是在输出时不需要关心打印对象的类型. 这是一个亮点. 同时, 也是一个不足: 你很容易用错类型, 而编译器不会报警. 使用流时容易造成的这类错误:
cout << this;   // Prints the address
cout << *this;  // Prints the contents
由于 << 被重载, 编译器不会报错. 就因为这一点我们反对使用操作符重载.

有人说 printf 的格式化丑陋不堪, 易读性差, 但流也好不到哪儿去. 看看下面两段代码吧, 实现相同的功能, 哪个更清晰?
cerr << "Error connecting to '" << foo->bar()->hostname.first
     << ":" << foo->bar()->hostname.second << ": " << strerror(errno);

fprintf(stderr, "Error connecting to '%s:%u: %s",
        foo->bar()->hostname.first, foo->bar()->hostname.second,
        strerror(errno));
你可能会说, “把流封装一下就会比较好了”, 这儿可以, 其他地方呢? 而且不要忘了, 我们的目标是使语言更紧凑, 而不是添加一些别人需要学习的新装备.

每一种方式都是各有利弊, “没有最好, 只有更适合”. 简单性原则告诫我们必须从中选择其一, 最后大多数决定采用 printf + read/write.
------------------------------------------

最终改好的程序如下,Cpplint能通过,g++也能通过
------------------------------------------
// Copyright 2011 Bill_Lang
#include <cstdio>
int main() {
    printf("Hello World!");
    return 0;
}
------------------------------------------

直接看Google Style会一会儿就烦了,但是配合着使用Cpplint,还是挺有乐趣的。看来还能帮助自己提高C++编程的实际水平。

推荐朋友们也玩玩这个。

2011年3月30日

2011年3月简述

对照年度总结

每周精读一篇论文:这个月项目压的太紧,居然一篇也没读!!
锻炼:打了三次羽毛球,还有一次是球馆在装修;参加了一次台球厅的活动,斯诺克不好打,但更有意思
读书:这月读书只完成一本书(《大学,究竟读什么》)的1/5。读完大学再看这本书,感觉挺有意思
工作:今天上午顺利完成计划内的项目发布,保持了三个月升级一次的记录,感谢折腾我的Bug们,两个完整的周末都搭进去了
生活:师弟正华实习结束回哈尔滨去了,新加坡的芒果和榴莲开始大面积上市了,好吃但不能多吃

下月主要改进:项目告一段落,开始读论文,读书,读代码,读PPT

2011年3月26日

鬼魅般的Bug吃掉了我的榴莲

一周来,不停的和各种Bug斡旋着,三日前解决了一个重大的GBK里GB2312外汉字的不能翻译的问题,算是小小进步。

三日来被一个鬼魅般的Bug萦绕着,这个Bug飘忽不定,在一个确定的配置下在确定的句子上翻译时就会Crash掉,原因据GDB说是内存重复释放。但换一个配置就会在另外的特定句子上Crash掉。挖地三尺,都快到六尺了还没有搞定。

昨晚太太买回两盒刚上市的新鲜榴莲犒劳我,吃完一盒打算另一盒放到冰箱。结果拎着垃圾袋和另一盒榴莲去楼道口仍的时候,竟然将垃圾袋和另一盒榴莲随手同时扔进了那种直接通往地下的垃圾通道。瞬间就意识到"问题的严重性"。太太听了后,过了一会儿才算谅解。

仔细想想,应该算是这个鬼魅般的Bug吃掉了我的榴莲。Bug还得继续调啊。送你榴莲了,让我Fix掉这个Bug吧~~

2011年3月10日

折纸是艺术,也是科学:看Robert Lang的TED演讲有感

昨天在Gtalk上写的状态是“折纸和剪纸都是一张纸的艺术世界”,yu fei朋友回复的内容是“让我突然想起前一阵子看的一个TED的视频:http://www.ted.com/talks/robert_lang_folds_way_new_origami.html

折腾了半天,看完了这个TED视频。谢谢yu fei的推荐,这个TED演讲真不错。Robert Lang是个奇才。折纸是个可以用科学来铸就的艺术,这一点是Robert Lang的这个演讲中能看出来的。他创建的网站也充分的展示了这一点(http://www.langorigami.com/index.php4),按照他发布的TreeMaker软件,几乎能做出模拟任何物体的折纸(http://www.langorigami.com/science/treemaker/treemaker5.php4)。由衷的佩服!

演讲末尾的那个动画展示让人很惊讶,折纸的世界真是神奇。

忽然又想起了电影《三日危情》(http://movie.douban.com/subject/3808604/)里的那段关于教男主角如何越狱的台词。最关键的一句就是要注意观察,尤其是那些异常的细节。从中能发现漏洞。然后充分利用这些异常的漏洞来完成你的壮举。

猜想Robert Lang起初是个折纸迷,后来全身心总结后发现了其中的奥秘并完成了这样一个伟大的软件(Robert戏说,这个软件可以运行在任何平台上,甚至是Windows :)   )。就像视频末尾介绍的几个应用折纸艺术(或者该叫技术)来协助设计一些重要器件那样,折纸艺术真是应用很广啊。

呵呵,一时激动,写了这段文字。一句话的感悟是,做科研或者技术就得注意观察任何异常,并不断总结,达到艺术与技术的融合。观察与思考,得出自己的结论很重要!

2011年3月1日

2011年2月简述

对照年度总结

每周精读一篇论文:这条完成得很不好,只精读了一篇
锻炼:每周都参加了羽毛球活动,额外的两次锻炼也在住处的小区保质保量完成(主要是跳绳,仰卧起坐加双杠)
读书:看完非专业书籍《禅里禅外悟人生》和《大学毕业等于零》,在读专业书籍《Essential C++》
工作:进展顺利,主要围绕语料整理和新的toolkit的封装
生活:新加坡最北边的地段比市区凉快,也更安静

下月主要改进:上班时需全身心工作,下班回家后全身心休息

2011年2月27日

折腾语料的全角半角

折腾语料:整理语料时需要统一编码,开始是折腾utf8和gb的统一,后来折腾全角半角。又折腾出来一个经验:如果语聊中全角半角混杂的话,需要谨慎的统一,现在试验找到的final solution是先全部转半角,再全部转全角。由于转全角时保留了英文字幕为半角,原先的方案是直接将语料全部转全角,这两天发现那样原先语料库中的全角英文字母就会一直存在。

恩,还得谨慎啊。

2011年2月21日

重学C++之01《Essential C++》:P5程序的#include 注释与否

----------------------------------------------
#include <iostream>
#include <string>

using namespace std;

int main()
{
    string user_name;
    cout << "Please enter your first name: ";
    cin >> user_name;
    cout << '\n'
         << "Hello, "
         << user_name
         << " ... and goodbye! \n";
    return 0;
}
----------------------------------------------
上面这段程序在Ubuntu 10.04上g++编译没问题,执行也没问题。按照P6页底的练习1.2将第二行注释掉,g++编译没问题,执行也没问题。

本来想忽略掉练习题直接往下看的,刚才等待某程序执行的过程中,一时兴致,将这个练习作了一下。这个有点超出我的想象了。为什么不引用<string>也可以呢。遍访google的结果,找到了大致的原因如下:

----------------------------------------------------------
以前也有同事遇到一样的问题,好的习惯是使用时包含string头。iostream间接引用了string,在VC下的确会出现操作符不能使用的情况,我觉得这个做法是正确的,g++使用的STL实现可以在只包含iostream头时照样使用那些操作符。
----------------------------------------------------------
参见:http://topic.csdn.net/t/20051213/12/4456074.html


有人专研的很深:
----------------------------------------------------------
我找到了原因。

在<iostream>中的“stringbuf”类使用到了string定义它的一个public member.

class stringbuf{
public:
string str ( ) const;
void str ( const string & s );
...
}

所以<iostream>应该要包含<string>才可以完成这个声明。

感谢各位。
----------------------------------------------------------
参见:http://topic.csdn.net/u/20100121/05/7abe6594-5ad2-4f1e-b1f8-8c9f74c3bc59.html


有人还引用《Effective C++》来说明类似问题的解决方案:
----------------------------------------------------------
《Effective   STL》

条款48:总是#include适当的头文件

STL编程的次要麻烦之一是虽然可以很容易地建立可以在一个平台上编译的软件,但在其它平台上则需要附加的#include指示。这个烦恼来自一个事实:C++标准(不像C标准)未能指定哪一个标准头文件必须或者可能被其他标准头文件#include。由于有了这样的灵活性,不同的实现就会选择去做不同的东西。

这在实践中意味着什么?我可以给你一些的概念。我使用了五个STL平台(咱们叫它们A、B、C、D和E),花了一些时间在它们上测试了一些小程序来看看我可以在忽略哪个标准头文件的情况下仍然成功编译。这间接地告诉我哪个头文件#include了其他的。这是我所发现的:

        *   对于A和C, <vector>   #includes   <string> .
        *   对于C, <algorithm>   #includes   <string> .
        *   对于C和D,   <iostream>   #includes   <iterator> .
        *   对于D,   <iostream>   #includes   <string>   and   <vector> .
        *   对于D和E,   <string>   #includes   <algorithm> .
        *   对于所有的五个实现, <set>   #includes   <functional> .

除了 <set>   #include   <functional> 外,我无法使缺少头文件的程序通过实现B。按照Murphy定律,你总是会在像A、C、D或E那样的平台上开发,然后移植到像B那样的平台,尤其是当移植的压力很大而且完成的时间很紧的情况下。

但是请别指责你将要移植的编译器或库实现。如果你缺少了需要的头文件,这就是你的过错。无论何时你引用了std名字空间里的元素,你就应该对   #include合适的头文件负责。如果你遗漏了它们,你的代码也可能编译,但你仍然缺少了必要的头文件,而其他STL平台可能正好会抵制你的代码。

要帮你记起需要的东西,关于在每个标准STL相关的头文件中都有什么,这里有一个快速概要:

        *   几乎所有的容器都在同名的头文件里,比如,vector在 <vector> 中声明,list在 <   list> 中声明等。例外的是 <set> 和 <map> 。 <set> 声明了set和multiset, <   map> 声明了map和multimap。
        *   除了四个算法外,所有的算法都在 <algorithm> 中声明。例外的是accumulate(参见条款37)、inner_product、adjacent_difference和 partial_sum。这些算法在 <numeric> 中声明。
        *   特殊的迭代器,包括istream_iterators和istreambuf_iterators(参见条款29),在 <iterator> 中声明。
        *   标准仿函数(比如less <T> )和仿函数适配器(比如not1、bind2nd)在 <functional> 中声明。

无论何时你使用了一个头文件中的任意组件,就要确定提供了相应的#include指示,就算你的开发平台允许你不用它也能通过编译。当你发现移植到一个不同的平台时这么做可以减少压力,你的勤奋将因而得到回报。
----------------------------------------------------------
参见:http://topic.csdn.net/t/20051213/12/4456074.html

2011年2月16日

Am old?

不当家不知柴油盐米贵,不锻炼不知长期不动弹身体有多差!

昨晚准备活动后跳绳400下,仰卧起坐13下。今早起床时赖床25分钟,还觉得身上有感觉。顿觉一个多月没锻炼身体变差不少啊。

2011年2月7日

展望2011

何时是一年的开始,因人而异。有人是元旦节,有人是春节。显然,我是春节那伙儿的。

回顾我的2010,基本实现了两大年度目标,总体表现自己的打分能到80分。展望2011,给自己的目标如下:

1. 心态放宽,扎实基础,量化的目标是每周精读一篇相关论文;

2. 锻炼身体很重要,刚结束的三周回国之旅赶上重感冒,发烧咳嗽头晕的感觉真不好,量化的目标是每周参与单位组织的羽毛球活动,外加两次额外的身体锻炼;

3. 多读书是必须的,现在刚搬的住处到单位需要一个小时,每天利用好这段时间多读书,量化的目标是每月读完一本喜欢的书;

4. 不轻易的给自己制定计划,一旦制定必须严格执行,量化的目标是制定的计划必须有每次完成的日志。

目标很杂,一句话概括就是夯实基础,争取突破。

在这里恭祝各位朋友兔年吉祥,万事如意!