簡體   English   中英

如何更快地將 Word2Vec 預訓練的 model 加載到 Gensim 中?

[英]How can a Word2Vec pretrained model be loaded in Gensim faster?

我正在使用以下方法加載 model:

model = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True) 

現在每次我在 Pycharm 中運行文件時,它都會再次加載 model。

那么,有沒有一種方法可以加載一次,並且在我運行諸如model['king']model.doesnt_match("house garage store dog".split())之類的東西時可用

因為每當我要檢查相似性或不匹配的單詞時,都會花費很多時間。 當我運行model.most_similar('finance')時,它真的很慢,整個筆記本電腦凍結了大約 2 分鍾。 那么,有沒有辦法讓事情變得更快,因為我想在我的項目中使用它,但我不能讓用戶等待這么久。

有什么建議么?

這是一組在磁盤上大約 3.6GB 的詞向量,加載時稍大一些 - 因此僅磁盤 IO 可能需要相當長的時間。

此外,至少在gensim-4.0.0 (現在可作為 beta 預覽版)之前,Gensim 到 3.8.3 的版本需要在第一次使用.most_similar().doesnt_match()操作(及其他)。 此步驟也可能需要很長時間,然后立即需要幾 GB 的 memory 才能獲得完整的 model,例如GoogleNews - 在任何 RAM 少於 8GB 的機器上,使用較慢的虛擬內存甚至崩潰的風險內存錯誤。 (從gensim-4.0.0beta開始,一旦 model 加載,第一個.most_similar()將不需要任何額外的預計算/分配。)

避免這種煩人的延遲的主要方法是構建您的代碼或服務,以便在每次計算之前單獨重新加載它。 通常,這意味着保持一個已加載的交互式 Python 進程處於活動狀態,為您的額外操作(或以后的用戶請求,可能是 Web 部署服務的情況)做好准備。

聽起來您可能正在開發單個 Python 腳本,例如mystuff.py ,並通過 PyCharm 的執行/調試/等實用程序運行它以啟動 Python 文件。 不幸的是,在每次完成執行時,這將使整個 Python 進程結束,完全釋放任何加載的數據/對象。 再次運行腳本必須再次執行所有加載/預計算。

如果您的主要興趣是自己對一組詞向量進行一些調查性檢查和實驗,那么一個很大的改進是轉移到一個交互式環境,該環境可以保持單個 Python 運行並等待您的下一行代碼。

例如,如果您在命令行中運行ipython解釋器,在單獨的 shell 中,您可以加載 model,執行一些查找/相似性操作以打印結果,然后讓提示等待您的下一個代碼。 在您選擇退出解釋器之前,該進程的滿載 state 仍然可用。

同樣,如果您在 Web 瀏覽器中使用 Jupyter Notebook,您將在不斷增長的可重新運行的可編輯代碼和結果“單元”中獲得相同的解釋器體驗。 所有人都共享相同的后端解釋器進程,並具有持久的 state - 除非您選擇重新啟動“內核”。

如果您為用戶的調查工作提供腳本或庫代碼,他們也可以使用此類持久解釋器。

但是,如果您正在構建 web 服務或其他持續運行的工具,您同樣需要確保 model 在用戶請求之間保持加載。 (具體如何操作取決於您的部署細節,包括 web 服務器軟件,因此最好將其作為一個單獨的問題詢問/搜索,以提供更多詳細信息。 )

還有另一個技巧可能有助於您不斷重新啟動的情況。 Gensim 可以以自己的本機格式保存和加載,這可以利用“內存映射”。 本質上,磁盤上的文件范圍可以直接由操作系統的虛擬 memory 系統使用。 然后,當許多進程都在自己的內存空間中將相同的文件指定為他們想要的東西的規范版本時,操作系統知道他們可以重用該文件中已經在 memory 中的任何部分。

這種技術在 `gensim-4.0.0beta' 和更高版本中更簡單,所以我只描述那里所需的步驟。 (如果您想在 Gensim 4.0 正式發布之前強制進行此預覽安裝,請參閱此消息。)

首先,加載原始格式的文件,然后以 Gensim 的格式重新保存它:

from gensim.models import KeyedVectors
kv_model = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True) 
kv_model.save('GoogleNews-vectors-negative300.kv')

請注意,如果您將 model 移至其他位置,則會創建一個額外的.npv文件,該文件必須與GoogleNews-vectors-negative300.kv一起保存。 只需執行一次即可創建新文件。

其次,當您以后需要 model 時,使用 Gensim 的 .load .load()mmap選項:

kv_model = KeyedVectors.load('GoogleNews-vectors-negative300.kv', mmap='r')
# do your other operations

馬上, .load()應該更快地完成。 但是,當您第一次嘗試訪問任何單詞時——或.most_similar()中的所有單詞——仍然需要從磁盤讀取,只是將延遲轉移到以后。 (如果您只進行單個單詞查找或少量.doesnt_match()單詞,您可能不會注意到任何長時間的滯后。)

此外,根據您的操作系統和 RAM 量,您甚至可以在運行一次腳本時獲得一些加速,讓它完成,然后很快再次運行它。 在某些情況下,即使操作系統已經結束了先前的進程,它的虛擬內存機制也可能會記住一些尚未清除的舊進程 memory 頁面仍在 RAM 中,並且對應於內存映射文件。 因此,下一個內存映射將重用它們。 (我不確定這種效果,如果您處於記憶力低下的情況,那么從已完成內容中重復使用的機會可能會完全消失。

但是,您可以通過采取第三步來增加 model 文件保持內存駐留的機會:啟動單獨的 Python 進程以預加載 model 直到退出。 為此,請制作另一個 Python 腳本,例如preload.py

from gensim.models import KeyedVectors
from threading import Semaphore
model = KeyedVectors.load('GoogleNews-vectors-negative300.kv', mmap='r')
model.most_similar('stuff')  # any word will do: just to page all in
Semaphore(0).acquire()  # just hang until process killed

在單獨的 shell: python preload.py中運行此腳本。 它將 map 將 model 轉換為 memory,然后掛起直到您CTRL-C退出它。

現在,您在同一台機器上運行的任何其他內存映射同一文件的代碼將自動重新使用來自此單獨進程的任何已加載的 memory 頁面。 (在內存不足的情況下,如果依賴任何其他虛擬內存,范圍仍可能從 RAM 中清除。但如果您有充足的 RAM,這將確保每次新引用同一文件時磁盤 IO 最小。)

最后,可以與其中任何一個混合的另一個選項是僅加載完整的 300 萬令牌、3.6GB 的GoogleNews集的子集。 不太常見的詞在這個文件的末尾附近,跳過它們不會影響很多用途。 因此,您可以使用load_word2vec_format()limit參數僅加載一個子集 - 加載速度更快,使用更少的 memory,並更快地完成以后的全集搜索(如.most_similar() )。 例如,僅加載第一個 1,000,000 個字,從而節省大約 67% 的 RAM/加載時間/搜索時間:

from gensim.models import KeyedVectors
kv_model = KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin',  limit=1000000, binary=True) 

暫無
暫無

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

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