推荐系统中的恶意用户过滤浅析

这篇文章大约很早前就想写了,不过随着自己屡次复发的拖延症一起被淹没了,直到最近有人在网络上咨询我才重新拿起来写篇博文。

这个题目其实来自于一道基于Hadoop MapReduce的编程类比赛题目,原题大约如下:基于公开数据集MovieLens数据集上的用户评价数据,计算用户对其未看过,并且可能会看的电影的评分。同时请各参赛队伍考虑数据稀疏性问题和恶意用户问题,使推荐系统在上述极端情况下具有较好的性能,其中的恶意用户被定义为在推荐系统中,存在一系列的恶意用户,其行为主要体现在随机打分或为多部电影打相同的分。为了检验推荐算法是否可以减少或避免恶意用户的影响,将通过随机加入恶意用户的方法,比率为5%,10%,并分别执行推荐算法,计算RMSE和MAE。,可以理解成那些在豆瓣上,电影放映期间的水军。

与Spark自己构建了一个MLlib的思路不同,Hadoop将主要精力focus在存储的HDFS和任务分配执行的YARN(包含可以执行MapReduce的任务部分)上面,所以如果熟悉Hadoop MapReduce的人都知道基于这个平台做分布式机器学习一个很好的轮子就是借助于Mahout。当然Mahout确实不怎么好用,依稀记得2013年Reynold来我校进行Spark的“地推”时,有个年轻老师就问了这个问题,Reynold就强烈吐槽了Mahout的难用。时过境迁,Mahout在2015年宣布了不再接受新的MapReduce算法(see 0.10.0 release notes),其执行引擎从Hadoop MapReduce全面转型为Scala + Spark和H2O,真是让人感叹技术圈的技术更新迭代。

回到题目本身,很容易想到的就是前端接一个过滤算法,后端再接一个推荐算法,推荐算法的选择就用工业界已经证明相当成熟的ALS-WR即可,Mahout很早就在Hadoop中实现了该部分,所以把轮子拿来用即可(稍微出乎我意料的是,这个比赛中貌似有些队伍自己实现了基于类似简单协同过滤等方法的推荐系统,效果还很一般,不知为何放着现成的好轮子不用)。数据稀疏性问题不大,毕竟ALS在过拟合以及稀疏数据上的效果都不错,但是如何应对恶意用户,因为自己不是纯做机器学习出身,所以就去搜了一下这方面的论文。恶意用户攻击一般在英文中被表述成shilling attack(托攻击),关于这方面内容的研究似乎不是非常多,在08、09年左右Mehta等人关于robust collaborative filtering的研究取得了不错的进展,过滤恶意用户的方法也就是著名的PCA。原理就是恶意用户的生成往往是遵从一些既有的设定模式,所以这些恶意用户间的协方差比较小,恶意用户与正常用户间的协方差比较大。PCA的核心思想就是压缩原始矩阵的特征维度,在这里就是压缩用户维度,保留包含信息量更大的用户下来(认为是真实用户),论文中用皮尔逊相关系数图表征了这一关系:
50个正常用户与20个攻击用户的皮尔逊积图
PCA部分的算法阐述如下:
PCA select 方法
需要注意的是这里的算法阐述是用求原始输入矩阵的协方差矩阵之后再求特征向量计算来计算SVD,实际分布式环境下一般用SVD得到矩阵Usigma来求PCA,论文中也提及了一般3~5个主成分的精度就可以了。该算法原理清晰,论文有数据支撑,但是本以为很快就搞定的东西居然遇到了困难,首先是Hadoop处理数据(movielens ml-10M)太慢,跑一轮程序需要13、14min左右,跑完还得看结果是否符合预期,验证时候没想到论文中在10% atack size下动辄90%+的精确度,在我这里居然只有很可怜的2、30%。由于当时我还在微软实习,白天得忙着公司的工作,晚上还得折腾这个比赛,由于Hadoop实现的验证太慢,所以我在Spark上又实现了一个PCA,结果发现Spark的实现也没快到哪去。由于整个流程比较长,所以我从向数据中插入恶意用户的代码开始,到数据预处理,中间数据处理(如何存储序列化矩阵)到最后的结果验证,一步步review了代码,在确信各个步骤的实现正确后,我一时没有头绪……此时我突然想到,既然论文中所用的数据movielens-100k规模不大,何不实现一个单机版本的算法用于我的理论验证,所以我很快用breeze(一个用scala写的线性代数库)实现了一个,并且在其上得到了与分布式版本一样糟糕的精确度= =

还好,这说明了我之前的实现是没有问题的。所以我回头看核心的算法表述,并且在网上找到了一个slides,原来根本问题是z-score时的trick,z-score也就是归一化输入矩阵在论文中被一句带过了,该trick就是将输入矩阵的缺失值当作0处理,根据被填上0的每个user的instance来计算均值和标准差,再对该instance进行归一化,而我原来的做法则是将缺失值忽略掉进行计算。在此基础上我果然重现了论文中的精确度。当然这个算法虽然精确度很高,但是有着一个比较致命的弱点,就是恶意攻击用户的比例是需要人为设置的,还好,这是一个比赛,所以题目中已经提及了恶意用户比例,使用这个算法再合适不过了。但是因为输入数据不同,但是我们无法判断输入数据是哪一种类型(正常的,稀疏的还是掺有虚假数据的),所以其他两种case时,仍然会对正常数据进行过滤,去除掉正常的数据会对最后的推荐带来负面影响,所以我离线测试了一下三种case在不同过滤比例下的RMSE,最终选择了过滤4%的数据,(做题嘛,毕竟要应试导向)。我还采用了另外一种方法来避免正常数据的过滤,由于插入虚假数据用户往往会对大量电影进行评分,从而提高其在推荐系统中的影响,所以对于嫌疑用户还加了一个限制,也就是如果该嫌疑用户的评分电影数目大于全局用户平均评分数的2倍以上(做实验的经验值),就认为其是恶意用户。
过滤不同比例恶意用户对应的RMSE

后来比赛的结果是我们在这道题上拿了第一(时间和RMSE的结果综合评价),实事求是的讲,我觉得我在这道题无论思路还是做法都挺直白简单的,只能说大牛没来参加吧(XD)。回头看整个项目的核心insight就是先在小数据集上进行单机debug,再在分布式上验证,这也应该是合理的开发模式。

我在github上放了其中PCA检测的部分代码,包含基于Mahout、Spark和Breeze的实现。

我的2015,那些电影·书·漫画·音乐·游戏·小事

窗外的雪悉悉索索地下着,据说南京遭遇了25年以来最冷的一天,我总觉得下雪的时候,最适合发呆和怀旧。回味2015年,遇到了一些人,学到了一些知识,发生了一些故事,每个人总要对自己的一年生活做些总结,所以我准备用这过去的一年所看的电影,所读的书,所读的漫画,所听的音乐等等来刻画这逝去的一年。

#####我的年度电影
本着严肃的态度,我仔细统计了一下,2015年我一共去了30次电影院看了29部电影,唯一一部看了两次的电影是《大圣归来》,而我的年度电影也就是这部电影。实事求是地说,这部电影在线下所引发现象级故事发展比电影本身的故事更为精彩。我第一次看到这部电影的宣传是在6月底的北京三里屯,大概就是日后出名的三里屯优衣库附件的路边宣传栏上,差不多就是下面这张图:
大圣归来
后来上映的故事想必大家都或多或少记得,排片率和票房一路逆袭而上,脚踢《栀子花开》拳打《小时代》,还创造了自来水一词,即使在国内第一宅坛爱撕衣,一帮信奉着“故事和音乐是人生的魔法”的动漫爱好者也没能预料到这部电影后续的票房走势,乐观如我亦不过认为4亿的票房是其上限。最终超过9亿的票房打了很多人的脸,但是我们被打脸地很开心,两个月的上映时间陪伴了我几乎一个暑假,我最后的这个暑假,正如这个记录着票房变化的帖子里所写的那样:

沉舟侧畔众山小 欲穷千里待下回
60天很短,眨眼有一个夏天悄然结束
60天很长,唤起了太多回忆,写满了太多惊喜
天下没有不散的筵席,但却有不会停止的梦想

感谢这部横空出世的电影,很多年后我都无法忘记这个夏天。

#####我的年度书籍
我是一个不爱读书的人,因为从小就不喜欢看密密麻麻全是字的书,本着实用主义的精神,我更多的精力都用在应试的教材或者学习工作要用的技术类书籍,大概会闲暇时分读点社科类书籍,所以我一直都很羡慕和崇拜那些读很多书的人。2015年印象最深的一本书其实是一本2012年出版的《乡关何处》,当然现在纸质版书籍已经不大好买,我在豆瓣上购买了电子版。其实我很早就知道了作者野夫,当时是本科的一位读了很多书的死党推荐,奈何不好学的我直到2015年底才第一次阅读了他的书,书籍内容由他的若干篇散文组成,写了他的故乡、故人、故事,有乡愁,有生离死别,有悲欢离合,2016年的第一天我的奶奶离我而去,让我回味他的文字时有了别样的惆怅。只是,野夫的文字大抵都是有些用力过度,也难怪,家族的兴衰造和他命运的坎坷成了他持不同政见的态度和这些悲伤的文字。

#####我的年度漫画
前面说到,我不是很喜欢读有字的书,所以我喜欢读漫画,漫画里有线条和阴影,有剧情和分镜。2015年又读了不少漫画,印象最深的也还是一部补完的旧作《20世纪少年》。故事第一话的前14页就给出了4个时间段的时间线画面,这是在日本漫画中极为罕见的,一般而言多线环形叙事结构常常出现在小说电影中,今年上映的华语电影《心迷宫》就使用了这种叙事方式(豆瓣2015年最佳华语片),漫画由于绘制比较费时费力,往往连载频度是周更或者月更,非线性叙事往往会消磨读者的耐心,当然,《20世纪少年》的作者浦泽直树非常擅长悬疑类的叙事,所以读起来经常是欲罢不能,废寝忘食,只是当终于读完全24卷内容(完结部分内容在最后2卷的《21世纪少年》中),看明白了故事来龙去脉,心中只想说一声WTF……从故事上来说还是短而小的Pluto更精彩一些。

BTW,20世纪少年这个名字来自一首歌曲,浦泽直树是一个摇滚乐迷,这部漫画完结后还特地发表了一张专辑《半世纪の男》,收录了漫画里出现的歌曲(基本都是作者自己创作演唱),真的是切漫画主题摇滚乐拯救世界

#####我的年度歌曲
不知从何时开始我已经不怎么听外文歌曲,所听的歌曲大多都是华语歌曲,先讲两首印象很深的歌曲,一首是五条人的《广东姑娘》,整首歌的意象仿佛非常有趣,曲调亦是别有风味。另一首歌是35年前的《风中的早晨》,自认为从台湾民谣运动开始的李双泽、杨弦、胡德夫等人,到最喜爱的罗大佑,再到后期商业化很成功的李宗盛,基本上民谣运动潮中的那些歌曲我都听过,没想到还是漏掉了这首佳作,起床的时候听这首歌,感觉一天都充满了精神。不过我印象最深的歌曲实际上都没有发行过单曲或者小样,是一首带着mv画面的歌曲《我的2003》(这个链接是youtube的,国内优酷也有搬运),歌曲的旋律配合MV十分漂亮,非常适合在异乡的人在过年前想念故人故乡,歌曲的作者是“红烧肉”,也就是后来导演了《少年班》的肖洋,冯小刚的御用剪辑师,本科西安交大的少年班建筑系,在德国读了媒体信息后回国半路出家做了剪辑,正如美术出身的冯小刚导演在2015年的金马奖拿了最佳男演员,同样非科班出身。可惜这部电影杂糅了他太多青春私货,拍出来效果实在一般。

#####我的年度游戏
我的主机平台有Xbox One和掌机PSV,11月趁着国服开放入了Steam的坑,可是回顾起来整整一年居然没有一款游戏通关,似乎游戏带给我的乐趣不在于玩本身,而是游戏打折时购买的捡白菜的快感,当然,主要原因也是因为没有什么时间玩。如果非要说一款游戏,应该是PC和手机上的炉石传说,作为一名喜欢玩YGO的TCG game爱好者,炉石传说这种游戏还是挺吸引我的,可惜对于F2P游戏,我总有不想花钱的强迫症,入坑又太迟,反正玩了一段时间后发现实在打不过老玩家和氪金用户,怒删退坑了= =

#####我的年度美食
今年印象最深的美食都不贵,一个是聚宝源的烧饼,据说是京城最好吃的铜锅涮肉火锅,和好友排了大约2个半小时队后终于入座吃上了,那些生切牛羊肉的味道算不上惊艳,可是那烧饼的味道却着实惊着了我,这辈子怕是没吃过这么好吃的烧饼,其貌不扬却千层酥脆回味无穷,当时也没拍照片,从网上盗了张图:
聚宝源烧饼
大概是因为没有任何心理期待,吃了真是惊叹不已。

还有道美食就更容易吃到了,北京的外卖“夹克的虾”,没看错,是一家只做外卖的麻辣小龙虾,其专攻O2O的理念,加上精致的包装以及相当不错的味道,作为一名程序员,对这家充满着互联网精神的美食外卖店倍感有趣。当然,麻小是北京非常火也非普遍的寻常菜肴,可惜无论是麻辣诱惑的小龙虾,还是簋街上徒有虚名的胡大饭店在我看来都不如“夹克的虾”(尤其是胡大饭店,真的是太一般了)

#####我的年度体验
2015年在北京,在微软实习了半年,算是2015年最难忘的体验,有半夜1、2点才从公司回去的痛苦,有免费饮料导致的肥胖,也有family day和年会的热闹。所待的产品组的部门老大在我没去几天后就在年前跳槽到了阿里,我也目睹了好几位位同事的离职跳槽。在互联网创业的热潮中,这个国家的年轻人们或南下深圳,或在帝都,或还在巨硬继续着他们的奋斗人生。这些人中,有同为90后,却经常教育我的顾老师,过上了结婚transfer到Redmon的人生赢家生活;有带我飞的可爱少女心女汉子珣爷;有腼腆的ACM Final选手金将军;有一副幼齿面容却污力十足的Luffy同学;有整日求帅哥的倩倩同学;有装作PM的程序员Jianlei君;有也经常加班的Yunjie学姐;有教我做人的data scientist马老师、葛大师。当然,还有我的两位mentor,谦逊的Xudong和正在为事业新高峰奋斗的Hucheng。

作为无数歌曲电影中出现的帝都北京,在这个满载着全中国大量文艺青年、知识青年“北漂”梦想的城市中,虽然雾霾层层,气候干燥,房价高高在上,但却难阻人们的初心。2016年下半年,我也将进入社会,进入到这个充满机遇也充满了危机的时代,希望我能有个有趣而又充满未知的职业生涯开端。

#####2016,你好
多学点知识,多读点书,身体健康,学点绘画,多抱着一份对世界的期许。

Build YGOPro on Windows without DirectX SDK

The first time I play YGOPro is three years ago on Mycard萌卡, but unfortunately Mycard community has gone out of businesses now.
As the offical website said: YGOPRO is a free online dueling system made for playing Yu-Gi-Oh! duels, if you’re familiar with Yu-Gi-Oh!, I think you have ever heard about YGOPro software.

The original source code of YGOPro is located at Github/Fluorohydride, of which the author is from China and have learned at NTU, Singapore.(I cannot find more information about this programer except his Baidu’s home page)

Anyway, this post mainly focuses on how to build YGOPro on Windows without DirectX SDK based on YGOPro’s wiki. The original build guide is too complex and out of date for freshman, that’s why I write this post.

I’m using Windows 10 and Visual Sudio 2013 for this setup.
STEP 1: Download source code from mater.zip or git clone https://github.com/Fluorohydride/ygopro-core.git to get source code.

STEP 2: Download the following folders from soarqin/ygopro:

Copy these 5 folders under ygopro root folder. If you haven’t installed DirectX9 SDK, please comment #define _IRR_COMPILE_WITH_DIRECT3D_9 and #define _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ in IrrCompileConfig.h header file under ygopro\irrlicht\include folder.

STEP 3: Downlad Premake4 to get premake4.exe and place it under ygopro root folder. Type premake4 --help to get the supported IDE list. You can type in premake4 vs2013, however, if you meet information like [string "newaction..."]:14: attempt to index global 'vstudio' (a nil value), try premake4 vs2012 and upgrade in Visual Studio itself if you are use Visual Studio 2012 later.

STEP 4: Open ygopro\build\ygo.sln to open the ygo project in Visual Studio. Build ygopro project, and it will compile and build the 8 projects to get the target ygopro.exe under ygopro\bin\debug folder.

Completed, enjoy this game!

mmap初探

######缘起
前几日某业内一线程序员电面我,被问及了mmap(memory-mapped file)内容,虽然我以前就听说过这个概念,尤其是在Tachyon这个分布式内存系统中,被广泛使用,官方doc在Current Features第一条还特地强调了一下:“Tachyon’s native API is similar to that of the java.io.File class, providing InputStream and OutputStream interfaces and efficient support for memory-mapped I/O.”,可惜我以前对这个概念真的不是很熟悉,最近看了些文档,简单跑了点实验,所以这里写个短文,讲一讲mmap。
######概念
下面是一张来自MSDN的图片, 很好地阐释了磁盘上的文件,物理内存中的file mapping object和各个进程所看到的file view这三者之间的关系。

核心概念看,mmap就是利用操作系统的虚拟内存技术,将文件映射到内存中(并不是copy到内存,所以mmap又有“lazy loading”的优势),当某一个进程需要读取该文件的某一部分时,不是使用传统的系统调用read(),而是让内存利用内存管理机制将所需要的内容载入到内存中。因为避免了相对缓慢的系统调用,mmap能够在大多数情况下明显的提升IO性能。另外,因为在用户进程看来,这个文件仿佛存在内存一般,所以可以用来当作文件共享给各个进程使用,在多进程环境下尤其能体现IO性能(这也就是为什么Tachyon会强调这一特性的原因)
######一些小缺点

  1. 对于很小的文件不太合适,因为mmap需要进行内存对齐来提高性能,而一般操作系统的page size是4KB,所以5KB的文件就会占据8KB的空间。
  2. tradeoff between I/O and page faults。相关页已经加载到物理内存,但是尚未在MMU注册,操作系统需要在MMU中注册修改,这种情况容易发生在多进程读写环境中,又称之为软性页中断(minor page fault),从而导致在某些特定情况下,mmap的读写性能要差于标准I/O
    ######简单实验
    别人那里借来了点Python代码,做了些简单修改,分别在Win8.1 和CentOS 6上面跑了一下,很明显的能看到mmap在读写性能上与标准读写I/O的区别。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    import mmap
    import os
    import time
    import sys

    if len(sys.argv) > 1:
    s = sys.argv[1]
    else:
    s = "test.txt" #size of the file should better larger than 50MB

    def normal_mmap(mode):
    f = open(s, 'r')
    buffer_size = 64
    retract_size = -32
    threshold = 1024 * 1024 * 50;
    start_time = time.time()
    if mode is 'normal':
    while True:
    f.seek(buffer_size, os.SEEK_CUR)
    f.seek(retract_size, os.SEEK_CUR)
    if f.tell() > threshold:
    break
    end_time = time.time()
    f.close()
    print('normal Time elapsed: {0}'.format(end_time - start_time))
    elif mode is 'mmap':
    m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    while True:
    m.seek(buffer_size, os.SEEK_CUR)
    m.seek(retract_size, os.SEEK_CUR)
    if m.tell() > threshold:
    break
    end_time = time.time()
    m.close()
    f.close()
    print('mmap Time elapsed: {0}'.format(end_time - start_time))
    else:
    print('illegal input, please choose "normal" or "mmap" mode')

    def main():
    for i in range(1, 5):
    normal_mmap('normal')
    time.sleep(3)
    normal_mmap('mmap')

    if __name__ == '__main__':
    main()
    在CentOS 6上的运行情况:

ShadowSocks IPv4 IPv6 配置

8月下旬的时候,网上传言ShadowSocks的作者clowwindy被请去喝茶了,事后的一系列发展验证了这则传言,如今ShadowSocks的主页已经只剩下了空荡荡的README文件,以及里面一行说明: Removed according to regulations.据说作者供职于知乎。

回头再看看曾经被广为使用的GoAgent,如今作者的Github主页只留下了一句话:Everything that has a beginning has an end 据说作者供职于南京某公司,南大软院毕业。

最近时值大中华帝国阅兵,看到那番伟大场景的同时,不得不对祖国日益强盛的互联网封锁力量感到困惑和愤怒。祝这些在与GFW作斗争中倒下的民间前辈们,一路走好。

回到title的内容,虽然clowwindy已经不再维护ShadowSocks项目(以下简称SS),不过SS中的衍生项目shadowsocks-libev的代码还在,貌似还在维护中,想来服务器上的SS已经有一段时间没有升级了,便远程登上去升级了一番,不过随之带来一个麻烦,就是原先配置文件中只要使用"server":"::",就可以达到的同时监听服务器IPv4和IPv6地址的配置失效,原始的设定只能支持IPv6,虽然校园网内可以连接IPv6,奈何公网环境还是需要有IPv4的地址支持。修改其实也很简单,参照这里的issue即可,将server的配置修改成"server":["[::0]", "0.0.0.0"],即可。

最后附一张图:

再见了,我的暑假们

提到暑假,第一个想到的居然是一款我从未玩过,也许买过盗版光盘的游戏:《我的暑假》。

那时候,每到高中放短假时,都会到学校附近的游戏店,淘两盘盗版PS2游戏,那些5块钱、10块钱一张的光盘游戏,大多只是被我放进PS2里面玩个初章,就再也没拿出来玩过了。时过境迁,没想到过了这么多年,即使是打折买的正版游戏也大多只是被我玩个初章而已,说不明白自己是不是更喜欢买游戏时的那种对未知内容的好奇感,还是仅仅按捺不住网络上对某款游戏夸张的评价想管中窥豹而已。

回到这款游戏,虽然我也许没玩过,不过很喜欢里面对于暑假的描绘:蓝天白云,海洋草地,在这里玩泥巴。我想心目中的暑假应该就是这般吧,在大自然中,放下所有对于学业对于暑假作业的压力,看海看树、睡觉和吃饭。虽然每个暑假我都是浑浑噩噩地过着没有早晨和上午,黑白颠倒的日子,直到开学前才会聚精会神地拿出印着“暑假快乐”的暑假作业端详起来。

上了这么多年学,转眼已经过完了“最后”的暑假,就算以后有雅致突然想读个PhD,也没有现在的心境了,吃了睡睡了吃,被爸妈宠着。觉得人真是贱,在家嫌弃父母,离家的时候却又十分想念父母,觉得自己特别不厚道,亦或许是只有我才这么贱吧。

再见了,暑假们,再见了,那些孩提时代,青春时代浪费掉的漫漫夏日们,我会永远想念你们的。

Welcome to Ghost

You’re live! Nice. We’ve put together a little post to introduce you to the Ghost editor and get you started. You can manage your content by signing in to the admin area at <your blog URL>/ghost/. When you arrive, you can select this post from a list on the left and see a preview of it on the right. Click the little pencil icon at the top of the preview to edit this post and read the next section!

Getting Started

Ghost uses something called Markdown for writing. Essentially, it’s a shorthand way to manage your post formatting as you write!

Writing in Markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use shortcuts to style your content. For example, a list:

  • Item number one
  • Item number two
    • A nested item
  • A final item

or with numbers!

  1. Remember to buy some milk
  2. Drink the milk
  3. Tweet that I remembered to buy the milk, and drank it

Want to link to a source? No problem. If you paste in a URL, like http://ghost.org - it’ll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here’s a link to the Ghost website. Neat.

What about Images?

Images work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:

The Ghost Logo

Not sure which image you want to use yet? That’s ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:

![A bowl of bananas]

Quoting

Sometimes a link isn’t enough, you want to quote someone on what they’ve said. Perhaps you’ve started using a new blogging platform and feel the sudden urge to share their slogan? A quote might be just the way to do it!

Ghost - Just a blogging platform

Working with Code

Got a streak of geek? We’ve got you covered there, too. You can write inline <code> blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.
.awesome-thing {
display: block;
width: 100%;
}

Ready for a Break?

Throw 3 or more dashes down on any new line and you’ve got yourself a fancy new divider. Aw yeah.


Advanced Usage

There’s one fantastic secret about Markdown. If you want, you can write plain old HTML and it’ll still work! Very flexible.

That should be enough to get you started. Have fun - and let us know what you think :)

那些年,火影那点事

火影真的完结了,说完结就真的完结了。

火影连载了十五年,我在04年时候第一次接触到火影忍者的漫画,距今已经十年了,下面是一个与火影共度了十年的漫迷的絮絮叨,随便扯点。

  • 最早是在初中学校旁边租书店看到这部漫画的,当时我们这群小屁孩都没听过火影这部漫画,我只是觉得封面的角色有点龙珠画风的感觉,就借来看了。对,这就是命运中相逢的第一次。
  • 后来看了些访谈,果然鸟山明对岸本齐史有很大影响,难怪早起画风有点龙珠的感觉。第二部疾风传开始后,感觉整体画风明显变得干净了不少,其实还是更喜欢早期的画风。
  • 早期的时候,因为火影整体的国内人气还不是很高,漫画中的角色还有其他翻译,比如鸣人,有翻译成鸣门的,卡卡西,有按照意思翻译成稻草人的(好奇怪),就连“火影忍者”这个作品名字,都有类似“狐忍”这种翻译。当然了,这些都是比较早的历史了,现在的翻译早已稳定下来了。
  • 初中那时候看火影漫画,真的真的以为鸣人是一个希望被别人认可的吊车尾,恰巧体内封印了九尾而已(四代目封印时,凑巧抓了一个路人这种),谁知道丫就是一个官/影二代,真是欺骗人感情。其实,热血战斗向漫画基本主角都有一个比较开挂的老爸,当然,我领悟到这一点是后来的事情了。
  • 后来嫌租书看不过瘾,我直接在租书店买了一套四拼一火影漫画。当时我已经在校住宿,那一套火影漫画就在宿舍内、宿舍间广为传递了,晚上熄灯后,舍友们各自拿着某一本在被窝里挑灯夜读。当时我们宿舍有位名为“大杰”的仁兄,特别喜欢看火影,在宿舍卫生间上大号时,就喜欢拿一本进去看,也不知道此君是真的大号时间长,还是只是看漫画看得入迷了忘记了时间,总而言之就是经常一个午休的时光他都是在宿舍里的卫生间度过了(也不怕腿麻麽……)说来也奇怪,初中毕业后,我就再也没联系过此君,但是当年他这个技能至今也没忘记。
  • 其实我一直没搞明白作品标题的《Naruto》是什么意思,因为在字典里面查怎么都找不到这个单词,毕竟当时没学过五十音,以至于我后来还直接拿着这个单词去问初中英语老师了……她的回复还算正确,像是一个人名。
  • 大约05年的时候,火影不知怎么就在我们那个三、四线小城火了,到处都是火影的周边产品,什么手套、护额之类。学校食堂的电视也是经常播放火影的动画片VCD,由于我是我们那一帮学生中第一个接触火影的,加之当时又在班上当班长,经常跟人吹嘘本人眼光独特(其实火影火遍全国关你鸟事啊喂!
  • 看漫画没有看动画的感官刺激,所以当时觉得最佳的体验应该是追动画,但是04、05年,作为尚未到达法定年龄可以进入网吧的初中生,以及那个时候的网络资源、带宽的普及率限制,我追火影动画的方式除了在食堂看火影动画VCD外,就只能自己买碟看了。那个时候DVD还没普及开(至少我家没有……)于是长春音像出版社每期15元两碟的套装VCD,就成了我每周去新华书店必买的东西了。现在可能大家对于VCD不熟悉了,当时两碟装VCD,可以存储5集到6集动画,价格要15元,(十年前的15元,貌似还稍微值点钱)当然我也没指望买到的是有版权的正版,但是人傻没上网条件,只能买碟回来看了。家里这种VCD屯了好多,除了火影,还有全26话的EVA、几集钢之炼金术师等等这些。当然,我也会拿出来借给同学看,或者换着看。鬼眼狂刀全集就是借别人的VCD看的。今天在亚马逊上居然找到了当年买的那些碟片信息, 没想到现在还能在互联网搜到,真是稍微有点意外。
  • 后来很快就买DVD机了,终于可以跟坑爹的VCD说再见了,一盘D9就能装下50话的年番了啊。不过那个时候火影动画已经进入到了鸣人几人众追佐助的剧情了,后来无聊的原创剧情消磨殆尽了我追动画的激情了,以至于从那开始,我就基本只追漫画了。
  • 后面追火影,更像是生活中的一种习惯,平平淡淡,谈不上激情满满,也谈不上无聊乏味,只是每周四晚上,习惯性想起来去网上看看更新而已。
  • 火影相比海贼王,最大的缺点就是格局太小,看上去舞台很宏大,但是说到底还是男一和男二之间你追我不回的羁绊,更多的是两人之间的友谊,格局稍小了些。
  • 最喜欢的动画歌曲是早期的《Go!!!》和《青春狂骚曲》
  • 最喜欢的战斗场剧情是三忍大战吧,鸣人终于学会了螺旋丸,三忍第一次一起亮相,感觉打怪升级到了一个新层面,帅呆了。
  • 最喜欢的角色,应该是李洛克吧,至今我还记得看动画第100话「热血师徒的羁绊~男人贯彻忍道的时候~」,我看哭了,哭得稀里哗啦,我对这种单纯地坚持自己理想的角色真是毫无抵抗力。当然,我也挺喜欢鹿丸的,因为我也是一个怕麻烦的人啊(笑  。对了,还有主角鸣人,可惜后期他嘴炮太多,有点受不了

其实我们在这里追忆火影,其实更多的是对自己逝去青春的追忆吧,就如同十年来每周陪伴你的老友,对你说,“嘿,哥们,我的故事该结束了,以后的日子你继续加油啊”这般感受。

再见了,鸣人,再见了,青春。

一个陌生人的自杀

早晨醒来,打开微博看世界杯决赛的结果,德国加时1:0战胜了阿根廷,有点心疼自己唯一一次足彩下注的50元。我不是足球迷,这届世界杯一场比赛也没看,所以这随风逝去的50元就让他随风去吧。接着,看到了@李沐M转发的一条微博:

虽然缺少上下文,但是看着这些转发的语言,估计可能又是一位自杀者的留言,前一位转发者提到原文作者是学CS的,一种同行相惜的情愫顿时涌上心头,在我看来学习Computer Science的人都是有着清晰严密逻辑热爱冷静分析的,怎么会想不开自杀呢,所以顺着看下去了,于是,也就有了本文,本博客很久没更新的一篇。

以下是原作者的长微博原文:

想来作者是因为爱情自杀,文中他有一个理论,他认为一切都是随机的,人的生死悲欢,和谁遇到,和谁走散,甚至是人本身的构成,都是一种随机,人的生死,从一种随机到另一种随机,不必悲伤和遗憾。这番话,让我想到身边一个搞theory的同学,经常在面临选择时会说random sampling is best,想来有点想笑,也有点悲伤。这位作者就连在github上的博客也叫“Random”,看了他博客的内容,大多都是些旅行的照片,只有一篇是关于技术方面的机器学习模型调试,写得思路很清晰,文笔也是深入浅出,想来此人的技术水平一定很不错。

说点其他的,作者早在6月27日时,就尝试了时光机功能(如下图),想来这次自杀可能在那时就已经有了打算,其实这让我想到每个程序员测试功能的严谨性,越发这样一丝不苟就越为这个家伙感到惋惜。

我与这位仁兄现在看来可谓是毫无交集,不是校友,尚未工作,又比我年长几岁,但作为同行,难免惺惺相惜,这个世界上,有一个陌生人自杀了,同时,有一个陌生人帮他写了篇不是悼念文章的文章,想来我们也算有缘。在这条告别微博下面,看到他朋友的一条回复,没想到他在死之前还用定时软件给朋友们发送了告别邮件,人类的感情和计算机技术的交融,让我难免为这位兄台动情。

再见,兄台,虽然我们只是陌生人,祝你在天国安息 @ljwsummer