使用Chinese-Word-Vectors做爲pytorch中的預訓練向量

如何在深度學習中使用開源Chinese Word Vectors

摘要:Chinese-Word-Vectors開源項目提供了100多種預訓練模型,但在深度學習中使用時,加載預訓練向量存在詞表重複項問題。本文着重於解決加載問題。

1. 原由

去年半年一直在搭建個人NLP練習項目——爲語音識別文本進行標點恢復,使用的技術以下所示:python

  • 詞向量訓練
  • BiLSTM
  • CRF

可是上面的技術在訓練網絡的時候,詞向量是在訓練中不斷訓練獲得的。一方面這樣的詞向量更配合網絡的結構,具備任務特定性;可是另外一方面,受限於語料大小和計算資源,直接由本身的數據集訓練出的詞向量確定是不夠泛化,不夠強健的git

2. Chinese-Word-Vectors技術方案存在的問題

時至今日,在2019年bert橫掃NLP任務以後,使用預訓練模型已經再也不稀奇。使用預訓練的模型能夠用更少的訓練資源獲得較好的效果。即便是使用傳統的word2vec也能有效提升模型的泛化性。github

Chinese-Word-Vectors是北京師範大學和人民大學的研究者開源出來的100多箇中文預訓練詞向量,全部向量都是在word2vec和skip-gram上訓練出來的。網絡

久仰大名,碼下好久,可是何嘗親自試用。親自使用後,便發現了一些問題。app

  • 如何讀取從Chinese-Word-Vectors下載下來的詞向量?
  • 讀取時發現詞表有重複,致使存入python字典中後,致使詞表大小和訓練好的詞向量矩陣不一致?
  • 讀取到的詞向量矩陣如何載入到深度學習模型的詞嵌入矩陣embedding中?

果真紙上得來終覺淺,絕知此事要躬行工具

3. 問題解決方式

  1. 詞向量文件自己是以文本方式存儲的,第一行是詞向量size信息,後面每一行是每一個詞和它的詞向量。經過使用ngram2vec工具中的代碼能夠加載詞向量(Chinese-Word-Vectors也使用了ngram2vec工具來訓練):
def load_dense(path):
    vocab_size, size = 0, 0
    vocab = {}
    vocab["i2w"], vocab["w2i"] = [], {}
    with codecs.open(path, "r", "utf-8") as f:
        first_line = True
        for line in f:
            if first_line:
                first_line = False
                vocab_size = int(line.strip().split()[0])
                size = int(line.rstrip().split()[1])
                matrix = np.zeros(shape=(vocab_size, size), dtype=np.float32)
                continue
            vec = line.strip().split()
            vocab["i2w"].append(vec[0])
            # vocab的length不斷增加
            matrix[len(vocab["i2w"])-1, :] = np.array([float(x) for x in vec[1:]])
    for i, w in enumerate(vocab["i2w"]):
        vocab["w2i"][w] = i
    return matrix, vocab, size
  1. 詞表重複問題,是實際加載詞向量中遇到的比較麻煩的問題,重複的詞表致使沒法用字典來索引每一個詞對應的詞向量,因此上一步的詞向量加載,實際上應該考慮重複問題:
def load_dense_drop_repeat(path):
    vocab_size, size = 0, 0
    vocab = {}
    vocab["i2w"], vocab["w2i"] = [], {}
    count = 0
    with codecs.open(path, "r", "utf-8") as f:
        first_line = True
        for line in f:
            if first_line:
                first_line = False
                vocab_size = int(line.strip().split()[0])
                size = int(line.rstrip().split()[1])
                matrix = np.zeros(shape=(vocab_size, size), dtype=np.float32)
                continue
            vec = line.strip().split()
            if not vocab["w2i"].__contains__(vec[0]):
                vocab["w2i"][vec[0]] = count
                matrix[count, :] = np.array([float(x) for x in vec[1:]])
                count += 1
    for w, i in vocab["w2i"].items():
        vocab["i2w"].append(w)
    return matrix, vocab, size, len(vocab["i2w"])
  1. 如何將獲得的此向量矩陣matrix載入到torch中的embedding中?(上一步中,爲了減小每次讀matrix的耗時,能夠將matrix用numpy保存到npy文件):
emb = np.load(emb)
    print('emb的shape:', emb.shape)
    self.embedding = nn.Embedding(vocab_size, embedding_size)
    self.embedding.weight.data.copy_(torch.from_numpy(emb))
    self.embedding.weight.requires_grad = True

4. 總結

總的來看Chinese-Word-Vectors預訓練數據是有其價值的,減小了不少的訓練資源。可是因爲天然語言處理的文本自己具備很是大的噪聲,很難保證詞向量是完美的、不包含任何錯字和重複。學習

在使用Chinese-Word-Vectors過程當中,儘可能要匹配好本身的需求。ui

相關文章
相關標籤/搜索