基於spark word2vec實踐

1、word2vec簡介、作用
1)解決哪些問題
word2vec,字面意思,將word轉化爲vector,word是順序有意義的實體,比如文檔中單詞、用戶依次點擊的商品。
word2vec得到實體向量,可以用來度量實體間相似度,在此基礎上,以下方向都可以應用(部分方向未實踐,參考資料所得):
分類
聚類
推薦
句子向量
短文本分類

2)兩種實現方式
Skip-gram:用一個詞語作爲輸入,來預測它周圍的上下文。同義詞
CBOW :用一個詞語的上下文作爲輸入,來預測這個詞語本身。完形填空


2、已實現word2vec的工具
1)Genvim,python版本
2)Spark.ml word2vec,DataFrames實現Skip-gram模型
3)Spark.mllib word2vec,RDD實現Skip-gram模型


3、Spark mllib word2vec實踐&tips
1)語料
http://www.sogou.com/labs/resource/ca.php,全網新聞數據,下載.tar.gz
解壓、轉碼、替換<content>:
 tar -zxvf news_tensite_xml.full.tar.gz
 cat news_tensite_xml.dat | iconv -f gbk -t utf-8 -c | grep "<content>"  > news.txt
 sed -i "s/<\/content>//g" news
 sed -i "s/<content>//g" news
語料較大,單機處理較慢,建議集羣上分詞、訓練word2vec模型。

2)分詞
使用哈工大分詞器分詞,maven依賴如下:
<dependency>
    <groupId>com.hankcs</groupId>
    <artifactId>hanlp</artifactId>
    <version>portable-1.2.8</version>
</dependency>
<dependency>
    <groupId>org.scalanlp</groupId>
    <artifactId>nak_2.10</artifactId>
    <version>1.3</version>
</dependency>
分詞過程:全角轉半角、停用詞處理、分詞、存儲
def segment(sc:SparkContext): Unit = {                                                                                                                                                             
    //stop words
    val stopWordPath = "停用詞路徑"
    val bcStopWords = sc.broadcast(sc.textFile(stopWordPath).collect().toSet)

    //content segment
    val inPath = "訓練語料路徑"
    val segmentRes = sc.textFile(inPath)
      .map(AsciiUtil.sbc2dbcCase) //全角轉半角
      .mapPartitions(it =>{
        it.map(ct => {
          try {
            val nlpList = NLPTokenizer.segment(ct)
            import scala.collection.JavaConverters._
            nlpList.asScala.map(term => term.word)
              .filter(!bcStopWords.value.contains(_))
              .mkString(" ")
          } catch {
            case e: NullPointerException => println(ct);""
          }
        })
      })

    //save segment result
    segmentRes.saveAsTextFile("分詞結果路徑")
    bcStopWords.unpersist()
  }
public class AsciiUtil {
    public static final char SBC_SPACE = 12288; // 全角空格 12288

    public static final char DBC_SPACE = 32; //半角空格 32

    // ASCII character 33-126 <-> unicode 65281-65374

    public static final char ASCII_START = 33;

    public static final char ASCII_END = 126;

    public static final char UNICODE_START = 65281;

    public static final char UNICODE_END = 65374;

    public static final char DBC_SBC_STEP = 65248; // 全角半角轉換間隔

    private static char sbc2dbc(char src){
        if (src == SBC_SPACE) {
            return DBC_SPACE;
        }

        if (src >= UNICODE_START && src <= UNICODE_END) {
            return (char) (src - DBC_SBC_STEP);
        }

        return src;
    }

    /**
     * Convert from SBC case to DBC case
     *
     * @param src
     * @return DBC case
     */
    public static String sbc2dbcCase(String src) {
        if (src == null) {
            return null;
        }
        char[] c = src.toCharArray();
        for (int i = 0; i < c.length; i++) {
            c[i] = sbc2dbc(c[i]);
        }
        return new String(c);
    }

    private static char dbc2sbc(char src){
        if (src == DBC_SPACE) {
            return SBC_SPACE;
        }
        if ((src <= ASCII_END) && (src >= ASCII_START)) {
            return (char) (src + DBC_SBC_STEP);
        }
        return src;
    }

    /**
     * Convert from DBC case to SBC case.
     *
     * @param src
     * @return SBC case string
     */
    public static String dbc2sbcCase(String src) {
        if (src == null) {
            return null;
        }

        char[] c = src.toCharArray();
        for (int i = 0; i < c.length; i++) {
            c[i] = dbc2sbc(c[i]);
        }

        return new String(c);
    }
}
停用詞,鏈接: https://pan.baidu.com/s/1brfLc7P 密碼: g66b

3)Skip-gram模型訓練,參考spark
spark.mllib word2vec訓練:
  def word2VecRun(sc:SparkContext) = {
    val input = sc.textFile("分詞結果路徑").map(line => line.split(" ").toSeq)
    //model train
    val word2vec = new Word2Vec()
      .setVectorSize(50)
      .setNumPartitions(64)

    val model = word2vec.fit(input)
    println("model word size: " + model.getVectors.size)

    //Save and load model
    model.save(sc, "word2vec模型路徑")
    val local = model.getVectors.map{
      case (word, vector) => Seq(word, vector.mkString(" ")).mkString(":")
    }.toArray
    sc.parallelize(local).saveAsTextFile("word2vec詞向量路徑")

    //predict similar words
    val like = model.findSynonyms("中國", 40)
    for ((item, cos) <- like) {
      println(s"$item  $cos")
    }
	
    //val sameModel = Word2VecModel.load(sc, "word2vec模型路徑")
  }
//中國,word2vec同義詞結果:
大國  0.7586380435991317
國際舞臺  0.7484820784140288
重振  0.7443842915770801
強國  0.7440432134955456
亞洲地區  0.7336309627565089
值得羨慕  0.7254971855043949
拉美  0.7199528766085572
走向世界  0.7195522594105694
世界第二大  0.7176901062252401
國力  0.7152167405425096
國際  0.7129751314747532
世界  0.711542837711965
與日俱增  0.7105297033943727
衰落  0.7080864535531732
政治化  0.7068762377142492
經濟大國  0.7046257249995131
版圖  0.7036082614700551
淨土宗  0.7005121068489949
廣播網  0.6990517002783354
全球華語  0.698620969507982
朱迪思·柯林斯  0.6985765569099095
中國政府  0.6946647084746524
21世紀  0.6935087636144573
蒸蒸日上  0.6934873373151971
超級大國  0.689131237979483
非洲  0.6862589700025773
世界工廠  0.6850311314455563
25所孔子學院  0.6794086519488903
中國崛起  0.6771866694599513
威脅論  0.6761148442425337
深遠影響  0.6760546747445543
新興國家  0.6751478515878965
前景  0.6750538485175515
之路  0.6735198878198577
發展史  0.6727135014527849
在世界上  0.6692064139295489
國際形象  0.6677791969781638
現代史  0.6668052040062915
國際關係  0.6667875117151274
強盛  0.6643625930792731
4、可能遇到的問題:
1)單機本地訓練,heap size過小
run-->edit configurations --> vim options -Xmx1024m(或者更大)

2)集羣模式訓練,tast只有一個
word2vec默認參數只有一個partition,需設置分區數:
new Word2Vec().setNumPartitions(64)
另外,word2vec訓練中,需要collect訓練樣本,因此driver memory需要設置大一些

3)minCount和vector_size設置問題
spark word2vector 默認 vocab * vector_size < Integer.Max_Value/8,否則無法訓練
minCount:詞頻量,默認參數5
vectorSize:詞向量大小,默認參數100

4)集羣模式分詞,Class not found exception
spark任務提交時,添加jar依賴:--jars "nak_2.10-1.3.jar,hanlp-portable-1.2.8.jar"

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章