簡體   English   中英

Gensim Word2Vec 從預訓練模型中選擇次要的詞向量集

[英]Gensim Word2Vec select minor set of word vectors from pretrained model

我在 gensim 中有一個大型的預訓練 Word2Vec 模型,我想從中使用預訓練的詞向量作為 Keras 模型中的嵌入層。

問題是嵌入的大小很大,我不需要大部分詞向量(因為我知道哪些詞可以作為輸入出現)。 所以我想擺脫它們以減少嵌入層的大小。

有沒有辦法根據單詞白名單保留所需的詞向量(包括相應的索引!)?

感謝這個答案(我稍微改變了代碼以使其更好)。 您可以使用此代碼來解決您的問題。

我們有我們所有的次要集字restricted_word_set (它可以是列表或組)和w2v是我們的模型,所以這里的功能是:

import numpy as np

def restrict_w2v(w2v, restricted_word_set):
    new_vectors = []
    new_vocab = {}
    new_index2entity = []
    new_vectors_norm = []

    for i in range(len(w2v.vocab)):
        word = w2v.index2entity[i]
        vec = w2v.vectors[i]
        vocab = w2v.vocab[word]
        vec_norm = w2v.vectors_norm[i]
        if word in restricted_word_set:
            vocab.index = len(new_index2entity)
            new_index2entity.append(word)
            new_vocab[word] = vocab
            new_vectors.append(vec)
            new_vectors_norm.append(vec_norm)

    w2v.vocab = new_vocab
    w2v.vectors = np.array(new_vectors)
    w2v.index2entity = np.array(new_index2entity)
    w2v.index2word = np.array(new_index2entity)
    w2v.vectors_norm = np.array(new_vectors_norm)

警告:當你第一次創建模型時, vectors_norm == None所以如果你在那里使用這個函數你會得到一個錯誤。 在第一次使用后, vectors_norm將獲得一個numpy.ndarray類型的值。 因此在使用該函數之前,請嘗試使用most_similar("cat")以便vectors_norm不等於None

它根據Word2VecKeyedVectors重寫與單詞相關的所有變量。

用法:

w2v = KeyedVectors.load_word2vec_format("GoogleNews-vectors-negative300.bin.gz", binary=True)
w2v.most_similar("beer")

[('啤酒',0.8409687876701355),
('啤酒',0.7733745574951172),
('啤酒',0.71753990650177),
('飲料', 0.668931245803833),
('貯藏啤酒', 0.6570086479187012),
('Yuengling_Lager', 0.655455470085144),
('微釀', 0.6534324884414673),
('Brooklyn_Lager', 0.6501551866531372),
('suds', 0.6497018337249756),
('brewed_beer', 0.6490240097045898)]

restricted_word_set = {"beer", "wine", "computer", "python", "bash", "lagers"}
restrict_w2v(w2v, restricted_word_set)
w2v.most_similar("beer")

[('貯藏啤酒',0.6570085287094116),
('酒', 0.6217695474624634),
('bash', 0.20583480596542358),
('計算機', 0.06677375733852386),
('蟒蛇',0.005948573350906372)]

它也可以用於刪除一些單詞。

沒有內置功能可以做到這一點,但它不需要太多代碼,並且可以模仿現有的gensim代碼。 一些可能的替代策略:

  1. 加載完整的向量,然后以易於解析的格式保存 - 例如通過.save_word2vec_format(..., binary=False) 這種格式幾乎一目了然; 編寫您自己的代碼以刪除此文件中不在您的白名單中的所有行(確保更新 entry-count 的前導行聲明)。 load_word2vec_format()save_word2vec_format()的現有源代碼可能具有指導意義。 然后,您將擁有一個子集文件。

  2. 或者,假設您要使用您感興趣的語料庫(僅使用有趣的詞)訓練一個新的 Word2Vec 模型。 但是,只創建模型並執行build_vocab()步驟。 現在,您擁有未經訓練的模型,帶有隨機向量,但詞匯量恰到好處。 獲取模型的wv屬性 - 具有正確詞匯表的KeyedVectors實例。 然后分別加載過大的向量集,對於大小合適的KeyedVectors中的每個單詞,從較大的集合中復制實際向量。 然后保存大小合適的子集。

  3. 或者,查看 Word2Vec intersect_word2vec_format()上的 (possably-broken-since-gensim-3.4) 方法。 它或多或少地嘗試執行上面 (2) 中描述的操作:使用具有您想要的詞匯表​​的內存模型,僅合並來自磁盤上另一個 word2vec 格式集的重疊單詞。 它要么有效,要么為您想要做的事情提供模板。

幾年前,我編寫了一個名為embfile的實用程序包,用於處理“嵌入文件”(但我僅在 2020 年發布了它)。 它支持多種格式:

  • .txt(帶或不帶“標題行”)
  • .bin,谷歌 Word2Vec 格式
  • .vvm,我使用的自定義格式(它只是一個 TAR 文件,在單獨的文件中包含詞匯表、向量和元數據,因此可以在幾分之一秒內完全讀取詞匯表,並且可以隨機訪問向量)。

我想涵蓋的用例是創建一個預訓練的嵌入矩陣來初始化一個Embedding層。 我想通過盡可能快地加載我需要的詞向量來做到這一點。

import embfile

with embfile.open(EMBEDDING_FILE_PATH) as f:

    emb_matrix, word2index, missing_words = embfile.build_matrix(
        f, 
        words=vocab,     # this could also be a word2index dictionary as well
        start_index=1,   # leave the first row to zeros 
    )

此函數還處理文件詞匯表之外的單詞的初始化。 默認情況下,它在找到的向量上擬合正態分布,並使用它來生成新的隨機向量(這就是 AllenNLP 所做的)。 我不確定這個功能是否仍然相關:現在你可以使用 FastText 或其他工具為未知單詞生成嵌入。

該軟件包已被廣泛記錄和測試。 還有一些示例展示了如何將它與 Keras 一起使用

請記住,txt 和 bin 文件本質上是順序文件,需要進行全面掃描(除非您在結尾之前找到要查找的所有單詞)。 這就是我使用 vvm 文件的原因,它為向量提供隨機訪問。 一個人可以通過索引順序文件來解決這個問題,但是 embfile 沒有這個功能。 盡管如此,您可以將順序文件轉換為 vvm(這類似於創建索引並將所有內容打包到單個文件中)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM