在Hadoop上運行基於RMM中文分詞算法的MapReduce程序

我知道這個文章標題很「學術」化,很俗,讓人看起來是一篇很牛B或者很裝逼的論文!其實否則,只是一份普通的實驗報告,同時本文也不對RMM中文分 詞算法進行研究。這個實驗報告是我作高性能計算課程的實驗裏提交的。因此,下面的內容是從個人實驗報告裏摘錄出來的,看成是我學習hadoop分享出來的 一些我的經驗。python

實驗目標算法

學習編寫 Hadoop 上的 MapReduce 程序。
使用 Hadoop 分佈式計算小說《倚天屠龍記》裏的中文單詞頻率,比較張無忌身邊的兩個女人周芷若與趙敏誰在小說裏的熱度高。(爲何要提到倚天屠龍記呢?由於個人一位舍 友最近把賈靜雯演的這部戲看完了,他無時無刻不提到賈靜雯演的趙敏,因此這個實驗也取材自個人大學生活……)app

實驗原理
jsp

經過自學Hadoop的Streaming工做模式,使用Streaming可讓Hadoop運行非Java的MapReduce程序。分佈式

爲了減小咱們的實驗時間,咱們使用了以開發效率著名的Python語言來編寫咱們的mapper.py和reducer.py。其中,咱們還使用到 了一個小巧的中文分詞模塊smallseg.py,引用自(http://code.google.com/p/smallseg/,Apache License 2.0)。函數

對於中文詞庫,咱們使用搜狗實驗室提供的中文詞庫main.dic以及一個字庫suffix.dic,都可從smallseg項目中得到。oop

分佈式計算的輸入爲一個文本文件:倚天屠龍記.txt,咱們從網下下載此文本資源,而且轉換爲utf8文本編碼以方便咱們在Linux下進行分詞計算。性能

iconv -fgbk -tutf8 倚天屠龍記.txt > 倚天屠龍記utf8.txt學習

實驗環境測試

NameNode:
OS: Ubuntu11.04
CPU: Intel Core I3
Memory: 512MB
IP: 125.216.244.28

DataNode1:
OS: Ubuntu11.10
CPU: Intel Pentium 4
Memory: 512MB
IP: 125.216.244.21

DataNode2:
OS: Ubuntu11.10
CPU: Intel Pentium 4
Memory: 512MB
IP: 125.216.244.22

Mapper程序

下面是mapper.py的代碼。

    #!/usr/bin/env python
    from smallseg import SEG
    import sys
    seg = SEG()
    
    for line in sys.stdin:
        wlist = seg.cut(line.strip())
        for word in wlist:
            try:
                print "%s\t1" % (word.encode("utf8"))
            except:
                pass

      smallseg爲一個使用RMM字符串分割算法的中文分詞模塊。Mapper程序的過程很簡單,對每一行的中文內容進行分詞,而後把結果以單詞和頻率的格式輸出。對於全部的中文單詞,都是下面的格式,

      單詞[tab]1

      每一個單詞的頻率都爲1。Mapper並不統計每一行裏的單詞出現頻率,咱們把這個統計頻率的工做交給Reducer程序。

      Reducer程序

      下面是reducer.py的代碼.

      #!/usr/bin/env python
      import sys
      current_word,current_count,word = None, 1, None
      
      for line in sys.stdin:
          try:
              line = line.rstrip()
              word, count = line.split("\t", 1)
              count = int(count)
          except: continue
      
          if current_word == word:
              current_count += count
          else:
              if current_word:
                  print "%s\t%u" % (current_word, current_count)
              current_count, current_word = count, word
      
      if current_word == word:
          print "%s\t%u" % (current_word, current_count)

      從標準輸入中讀取每個單詞頻率,而且統計。由於這些單詞已經由Hadoop爲咱們排好了順序,因此咱們只須要對一個單詞的出現次數進行累加,當出現不一樣的單詞的時候,咱們就輸出這個單詞的頻率,格式以下

      單詞[tab]頻率

      實驗步驟

      實驗使用一個NameNode節點和兩個DataNode節點。
      首先,把所須要的文件複製到每一臺主機上。這些文件都放在/home/hadoop/wc目錄下。

      scp -r wc hadoop@125.216.244.21:.
      scp -r wc hadoop@125.216.244.22:.
      scp -r wc hadoop@125.216.244.28:.

      運行Hadoop Job

      本次任務,使用3個Mapper進程以及2個Reducer進程。由於分詞的步驟最爲耗時,因此咱們儘可能分配最多數目的Mapper進程。

      hadoop@xiaoxia-vz:~/hadoop-0.20.203.0$ ./bin/hadoop jar contrib/streaming/hadoop-streaming-0.20.203.0.jar -mapper /home/hadoop/wc/mapper.py -reducer /home/hadoop/wc/reducer.py -input 2-in -output 2-out -jobconf mapred.map.tasks=3 -jobconf mapred.reduce.tasks=2
      [...] WARN streaming.StreamJob: -jobconf option is deprecated, please use -D instead.
      packageJobJar: [/tmp/hadoop-unjar2897218480344074444/] [] /tmp/streamjob7946660914041373523.jar tmpDir=null
      [...] INFO mapred.FileInputFormat: Total input paths to process : 1
      [...] INFO streaming.StreamJob: getLocalDirs(): [/tmp/mapred/local]
      [...] INFO streaming.StreamJob: Running job: job_201112041409_0005
      [...] INFO streaming.StreamJob: To kill this job, run:
      [...] INFO streaming.StreamJob: /home/hadoop/hadoop-0.20.203.0/bin/../bin/hadoop job  -Dmapred.job.tracker=http://125.216.244.28:9001 -kill job_201112041409_0005
      [...] INFO streaming.StreamJob: Tracking URL: http://localhost:50030/jobdetails.jsp?jobid=job_201112041409_0005
      [...] INFO streaming.StreamJob:  map 0%  reduce 0%
      [...] INFO streaming.StreamJob:  map 9%  reduce 0%
      [...] INFO streaming.StreamJob:  map 40%  reduce 0%
      […] INFO streaming.StreamJob:  map 67%  reduce 12%
      [...] INFO streaming.StreamJob:  map 71%  reduce 22%
      [...] INFO streaming.StreamJob:  map 100%  reduce 28%
      [...] INFO streaming.StreamJob:  map 100%  reduce 100%
      [...] INFO streaming.StreamJob: Job complete: job_201112041409_0005
      [...] INFO streaming.StreamJob: Output: 2-out

      Map過程耗時:41s
      Reduce過程耗時:21s
      總耗時:62s

      計算結果

      複製計算結果到本地文件系統。

      ./bin/hadoop dfs -get 2-out/part* ../wc/

      查看part*的部份內容:

      hadoop@xiaoxia-vz:~/wc$ tail part-00000
      龍的    1
      龍眼    1
      龍虎    2
      龍被    1
      龍身    2
      龍鎮    1
      龍骨    1
      龜壽    2
      龜山    1
      龜裂    1
      hadoop@xiaoxia-vz:~/wc$ tail part-00001
      龍門    85
      龍飛鳳舞        1
      龍駕    1
      龜      3
      龜一    1
      龜二    1
      龜息    1
      龜縮    1
      龜蛇    3

      下面,對輸出的結果進行合併,並按照頻率進行排序。該過程比較快,在1秒內就已經完成。

      hadoop@xiaoxia-vz:~/wc$ cat part-00000 part-00001 | sort -rnk2,2 > sorted
      hadoop@xiaoxia-vz:~/wc$ head sorted
      的      7157
      張無忌  4373
      是      4199
      道      3465
      了      3187
      我      2516
      他      2454
      你      2318
      這      1991
      那      1776

      咱們去掉單個字的干擾,由於咱們的實驗目的只對人名感興趣。

      hadoop@xiaoxia-vz:~/wc$ cat sorted | awk '{if(length($1)>=4) print $0}' | head -n 50
      張無忌  4373
      說道    1584
      趙敏    1227
      謝遜    1173
      本身    1115
      甚麼    1034
      張翠山  926
      武功    867
      一個    777
      我們    767
      周芷若  756
      教主    739
      笑道    693
      明教    685
      一聲    670
      聽得    634
      姑娘    612
      師父    606
      只見    590
      無忌    576
      少林    555
      如此    547
      弟子    537
      之中    527
      殷素素  518
      楊逍    496
      他們    490
      不知    484
      如何    466
      咱們    453
      兩人    453
      叫道    450
      二人    445
      今日    443
      心想    433
      張三丰  425
      聲道    425
      義父    412
      出來    402
      雖然    395
      滅絕師太        392
      之下    389
      這時    381
      蓮舟    374
      心中    374
      即是    371
      不敢    371
      俞蓮    369
      不能    359
      身子    356

      統計圖表

      結論

      趙敏以1227票的頻率完勝周芷若的756票,由此可知趙敏在《倚天屠龍記》裏的熱度比周芷若高。

      通過本次實驗,咱們對 Hadoop 原理有了必定程度的瞭解,而且順利的完成Mapper函數和Reducer函數的設計和測試。可以運用 Hadoop 進行簡單的並行計算的實現。咱們也對並行算法和串行算法的區別和設計有了更深一層的瞭解。此外,實驗還增進了咱們的合做精神,提升了咱們的動手能力。

      相關文章
      相關標籤/搜索