GloVe 教程之實戰入門+python gensim 詞向量

前幾天看論文,忽然看到了一個跟word2vec並列的詞向量工具,這麼厲害?還能跟word2vec相提並論?

果斷需要試試。

GloVe 

它來自斯坦福的一篇論文,GloVe全稱應該是 Global Vectors for Word Representation


大概長這樣,上面還有訓練好的模型可以下載



下面開始動手。

官方的代碼的GitHub在此 : https://github.com/stanfordnlp/GloVe



可以看到,這是個c的版本,並且跑在linux下。

畢竟最愛的是python,首先想,有沒有python版本的,GitHub上其實還真搜到了一個,不過看了一下,應該是哪個小夥伴自己寫的,試了一下,發現一百句話的語料它的速度就已經慢得不能忍受了。我們是要面對至少幾百M幾個G的語料,顯然這個是不能接受的。所以就不放鏈接了。

那就只能用C的代碼訓練,然後再用python來處理結果。讓人欣喜的是,GloVe訓練的結果,是可以用gensim裏面word2vec的load直接加載並且使用的,那就簡單了。

首先,找到一個linux系統的機器,把上面GitHub上的代碼down下來。

進入glove目錄下,首先先參考README.txt,裏面主要介紹這個程序包含了四部分子程序,按步驟分別是vocab_count、cooccur、shuffle、glove:

1.vocab_count:用於計算原文本的單詞統計(生成vocab.txt,每一行爲:單詞  詞頻)

2.cooccur:用於統計詞與詞的共現,目測類似與word2vec的窗口內的任意兩個詞(生成的是cooccurrence.bin,二進制文件,呵呵)

3. shuffle:對於2中的共現結果重新整理(一看到shuffle瞬間想到Hadoop,生成的也是二進制文件cooccurrence.shuf.bin)

4.glove:glove算法的訓練模型,會運用到之前生成的相關文件(1&3),最終會輸出vectors.txt和vectors.bin(前者直接可以打開,下文主要針對它做研究,後者還是二進制文件)

上面已經介紹了這個程序的執行流程,下面就具體訓練出這個vectors.txt。

首先二話不說,直接makefile,

make 

就會多出來一個build文件夾

然後再執行sh demo.sh就行了:

sh demo.sh

其中,可以再demo.sh裏面,設置訓練語料路徑(默認是從網上下載一個語料,把這段刪了,改成自己的語料路徑就行了),還可以設置迭代次數,向量的維度等等,自己隨便折騰就行了

經歷漫長的等待之後(取決於你的語料有多大,當然了,中文的話,記得分詞)

現在,得到了vectors.txt,這就是訓練出來的詞向量的結果。下面,我們看看怎麼用python來加載並使用它。

首先,默認已經裝好python+gensim了,並且已經會用word2vec了。

其實,只需要在vectors.txt這個文件的最開頭,加上兩個數,第一個數指明一共有多少個向量,第二個數指明每個向量有多少維,就能直接用word2vec的load函數加載了

假設你已經加上這兩個數了,那麼直接

    # Demo: Loads the newly created glove_model.txt into gensim API.
    model=gensim.models.Word2Vec.load_word2vec_format(' vectors.txt',binary=False) #GloVe Model

就行了,剩下的操作就跟word2vec一樣了

下面附上 這一段的完整代碼(包括把 vectors.txt改成能load的格式,和加載模型)

def load(filename):

    # Input: GloVe Model File
    # More models can be downloaded from http://nlp.stanford.edu/projects/glove/
    # glove_file="glove.840B.300d.txt"
    glove_file = filename

    dimensions = 300

    num_lines = getFileLineNums(filename)
    # num_lines = check_num_lines_in_glove(glove_file)
    # dims = int(dimensions[:-1])
    dims = 300

    print num_lines
    #
    # # Output: Gensim Model text format.
    gensim_file='glove_model.txt'
    gensim_first_line = "{} {}".format(num_lines, dims)
    #
    # # Prepends the line.
    if platform == "linux" or platform == "linux2":
        prepend_line(glove_file, gensim_file, gensim_first_line)
    else:
        prepend_slow(glove_file, gensim_file, gensim_first_line)

    # Demo: Loads the newly created glove_model.txt into gensim API.
    model=gensim.models.Word2Vec.load_word2vec_format(gensim_file,binary=False) #GloVe Model

    model_name = filename[5:-4]
    
    model.save('model\\' + model_name)

    return model

def getFileLineNums(filename):
    f = open(filename,'r')
    count = 0

    for line in f:
        
        count += 1
    return count

def prepend_line(infile, outfile, line):
    """
    Function use to prepend lines using bash utilities in Linux.
    (source: http://stackoverflow.com/a/10850588/610569)
    """
    with open(infile, 'r') as old:
        with open(outfile, 'w') as new:
            new.write(str(line) + "\n")
            shutil.copyfileobj(old, new)

def prepend_slow(infile, outfile, line):
    """
    Slower way to prepend the line by re-creating the inputfile.
    """
    with open(infile, 'r') as fin:
        with open(outfile, 'w') as fout:
            fout.write(line + "\n")
            for line in fin:
                fout.write(line)

這是一段加載模型之後使用的例子,當然了,這個就跟word2vec一樣了

def load_model_and_use(model_name):
    model = gensim.models.Word2Vec.load('model/'+model_name)
    print len(model.vocab)
    word_list = [u'發燒',u'流感']

    for word in word_list:
        print word,'--'
        for i in model.most_similar(word, topn=10):
            print i[0],i[1]
        print ''

結果如下

83078
發燒 --
瘟癘 0.561131298542
多無發 0.438511788845
感冒 0.423784643412
寒戰 0.41094905138
發冷 0.400202810764
肌肉痠痛 0.394035518169
畏寒 0.391746163368
頭痛 0.390283048153
惡寒 0.387357711792
石岐 0.385719358921


流感 --
芭比 0.693880617619
嗜血 0.660785496235
H1N1 0.543790698051
肺炎 0.520848989487
流行性感冒 0.517322063446
副流感 0.51515519619
甲型 0.495822429657
肺炎球菌 0.491611480713
H10N8 0.490446418524
H3N2 0.486712753773


這個是經典的那個 man - king, women -? 的例子

    for i in w2v_model.most_similar(positive=['肺炎', '肺'], negative=['胃炎']):
        print i[0],i[1]

肺部 0.662135243416
肺門區 0.556283473969
通氣 0.548550665379
肺泡 0.529182732105
肺氣腫 0.525536477566
慢阻 0.512038588524
胸片 0.503533244133
萎陷 0.502206265926
肺透明膜病 0.498196214437
肺段 0.492621898651

可見,效果不太好,可能是語料太少的原因。

關於word2vec模型的格式的探究,可見:


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