Word2Vec在中文的應用


  google最近新開放出word2vec項目,該項目使用deep-learning技術將term表示為向量,由此計算term之間的相似度,對term聚類等,該項目也支持phrase的自動識別,以及與term等同的計算。

  word2vec(word to vector)顧名思義,這是一個將單詞轉換成向量形式的工具。通過轉換,可以把對文本內容的處理簡化為向量空間中的向量運算,計算出向量空間上的相似度,來表示文本語義上的相似度。

具體的原理還沒有去了解,在這里談一下怎么個應用法

  1. 分詞

1)  本人下載的是搜狗實驗室的互聯網媒體新聞語料,先從語料中提取出每篇文章的正文,在提取的過程中進行過濾操作,因為同一篇文章可能被多個媒體報道,如果不對文章進行排重的話,會對最終的結果有一些影響,從過濾的結果上看,100篇文章中大概有35篇是出現不止一次的,所以這一步還是挺必要的。

2)  提取出正文后進行分詞,且在分詞過程中統計詞頻,因為Word2Vec在運行過程中,占用內存的大小是由獨立詞的個數決定的,所以統計完詞頻后將分詞后的結果中的低頻詞去掉,在不去掉的情況下,大概要用到20G的內存空間,而只取前10萬個高頻詞的時候只需要1G的空間就可以了。本人用的是FudanNLP的開源分詞軟件,分詞速度還可以,大概300k/s,在i5-3470,8G內存的平台上進行。不過美中不足的是分詞的正確率感覺不大高,很多長詞被拆分成短詞了,估計是詞庫的問題。

具體的代碼如下:

  新聞結構存儲

 1 package cn.com.juefan.word2vec;
 2 
 3 import java.util.regex.Matcher;
 4 import java.util.regex.Pattern;
 5 
 6 public class Word2VecData {
 7     
 8     public String TEXT = new String();
 9     public String urlString = new String();
10     public String titleString = new String();
11     public String contentString = new String();
12     
13     public Word2VecData(String string){
14         TEXT = string;
15         urlString = match("url"    );
16         titleString = match("contenttitle");
17         contentString = match("content");
18         
19     }
20     
21     /**
22      * 匹配提取出內容
23      * @param string 搜狗數據集(一行)
24      * @return 提取的有效內容
25      */
26     public String match(String string){
27         String regex = "<" + string + ">" + ".*?" + "</" + string + ">";
28         Pattern p = Pattern.compile(regex, Pattern.CANON_EQ);
29         Matcher matcher = p.matcher(TEXT);
30         while(matcher.find()){
31             return matcher.group().replace("<" + string + ">" , "").replace("</" + string + ">", "");
32         }
33         return null;
34     }45     }
46 
47 }

 

  正文提取與存儲 

 

 1 package cn.com.juefan.word2vec;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.File;
 5 import java.io.FileInputStream;
 6 import java.io.FileReader;
 7 import java.io.FileWriter;
 8 import java.io.InputStreamReader;
 9 import java.util.HashSet;
10 import java.util.Map;
11 import java.util.Scanner;
12 import java.util.Set;
13 
14 import edu.fudan.juefan.personer.StopWord;
15 import edu.fudan.ml.types.Dictionary;
16 import edu.fudan.nlp.cn.tag.CWSTagger;
17 import edu.fudan.nlp.cn.tag.POSTagger;
18 
19 public class SplitContent {
20 
21     /**
22      * 將指定內容寫入指定文件中
23      * 以追加的方式寫入
24      * @param fileWriter  文件路徑
25      * @param context  存儲內容
26      * @param bool 是否覆蓋寫入
27      */
28     public static void FileWrite(String fileName, String context, boolean bool){
29         try{
30             @SuppressWarnings("resource")
31             FileWriter fileWriter = new FileWriter(fileName, bool);
32             fileWriter.write(context);
33             fileWriter.flush();
34         }catch (Exception e) {
35         }
36     }
37 
38     public static void main(String[] args) throws Exception {
39         Set<String> set = new HashSet<String>();
40         /**加載分詞器*/
41         CWSTagger tag2 = new CWSTagger("./models/seg.m");
42         String fileNameString = "\\output\\sogou\\SplitContent_";
43         
44         /**加載停用詞
45          * 該類是自己寫的,個人可以自己寫一個,主要是對分詞后的結果進行過濾操作
46          */
47         StopWord stopWord = new StopWord();
48         int TRAC = 0;
49         int NUM = 0;
50         StringBuilder builder = new StringBuilder();
51         BufferedReader reader = null;
52         try{
53             /**讀取搜狗語料*/
54             File fileScanner = new File(System.getProperty("user.dir") + "\\input\\news_tensite_xml.txt");
55             
56             if(new File(System.getProperty("user.dir") + "\\input\\news_tensite_xml.txt").exists()){
57                 System.out.println("正在讀取文件......");
58                 InputStreamReader isr = new InputStreamReader(new FileInputStream(fileScanner), "GBK");
59                 reader = new BufferedReader(isr);
60                 String tmString = null;
61                 while((tmString = reader.readLine()) != null){
62                     builder = builder.append(tmString);
63                     
64                     /**搜狗語料的結構為每6行構成一篇報道*/
65                     if(++TRAC % 6 == 0){
66                         Word2VecData data = new Word2VecData(builder.toString());
67                         if(!set.contains(data.contentString)){
68                             /**上面是判斷該新聞是否與出現過,下面是將分詞后的結果進行停用詞過濾操作,且每50000篇文章為一個小文件*/
69                             stopWord.Filtration(tag2.tag(data.contentString));
70                             FileWrite(System.getProperty("user.dir") + fileNameString + Integer.toString(NUM++ / 50000), stopWord.builder.toString() + "\n", true);
71                             set.add(data.contentString);
72                             if(NUM % 10000 == 0)
73                                 System.out.println(NUM);
74                         }
75                         builder.delete(0, builder.length());
76                     }
77                 }
78                 System.out.println("讀取文件成功!");
79             }
80         }catch (Exception e) {
81             System.out.println("文件不存在!");
82         }
83     }
84 
85 }

 

 

 

==================久違了,寫一下Word2Vec的操作====================

上面的是語料的分詞,接下來就利用分詞后的語料進行Word2Vec的訓練了

步驟1:

  首先要做的肯定是從官網上下載word2vec的源碼:http://word2vec.googlecode.com/svn/trunk/ ,然后把其中makefile文件的.txt后綴去掉,在終端下執行make操作,這時能發現word2vec文件夾下多了好幾個東西。

  如果make不成功的話,需要修改makefile的內容,把第四行修改為

CFLAGS = -lm -pthread -O2 -Wall -funroll-loops

  然后再進行make編譯,這回估計就能成功了!

步驟2:

  對語料進行訓練,在Word2Vec文件夾下會有一個word2vec程序,執行

 ./word2vec sougo.txt vertors.bin
./word2vec -train resultbig.txt -output vectors.bin -cbow 0 -size 200 -window 5 -negative 0 -hs 1 -sample 1e-3 -threads 12 -binary 1

  此時將會訓練生成詞向量文件vertors.bin

步驟3:

  調用vertors.bin文件輸出詞的相似詞結果,執行

[juefan@xxx Word2Vec]$ ./distance vectors.bin 
Enter word or sentence (EXIT to break): 

  此時只要輸入一個詞,就能夠輸出對應的相關詞了

 

參數說明:
這里寫圖片描述
參數解釋: 
-train 訓練數據 
-output 結果輸入文件,即每個詞的向量 
-cbow 是否使用cbow模型,0表示使用skip-gram模型,1表示使用cbow模型,默認情況下是skip-gram模型,cbow模型快一些,skip-gram模型效果好一些 
-size 表示輸出的詞向量維數 
-window 為訓練的窗口大小,8表示每個詞考慮前8個詞與后8個詞(實際代碼中還有一個隨機選窗口的過程,窗口大小<=5) 
-negative 表示是否使用NEG方,0表示不使用,其它的值目前還不是很清楚 
-hs 是否使用HS方法,0表示不使用,1表示使用 
-sample 表示 采樣的閾值,如果一個詞在訓練樣本中出現的頻率越大,那么就越會被采樣 
-binary 表示輸出的結果文件是否采用二進制存儲,0表示不使用(即普通的文本存儲,可以打開查看),1表示使用,即vectors.bin的存儲類型

除了上面所講的參數,還有: 
-alpha 表示 學習速率 
-min-count 表示設置最低頻率,默認為5,如果一個詞語在文檔中出現的次數小於該閾值,那么該詞就會被舍棄 
-classes 表示詞聚類簇的個數,從相關源碼中可以得出該聚類是采用k-means

曬一下結果出來給大家看下。。。

 

沒有做過對比,不過個人感覺這個效果是挺不錯的了。。。。點贊!

 

http://blog.csdn.net/baidu_26550817/article/details/48653889


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM