1. 程式人生 > >在Keras模型中使用預訓練的詞向量

在Keras模型中使用預訓練的詞向量

轉自:wuwt.me/2017/08/21/pre-trained-embedding-keras/

“詞向量”(詞嵌入)是將一類詞的語義對映到向量空間中的自然語言處理技術。即將一個詞用特定的向量來表示,向量之間的距離(例如,任意兩個向量之間的L2正規化距離或更常用的餘弦距離)一定程度上表徵了詞之間的語義關係。由這些向量形成的幾何空間被稱為一個嵌入空間。

例如,“椰子”和“北極熊”是語義上完全不同的詞,所以它們的詞向量在一個合理的詞嵌入空間的距離會非常遙遠。但“廚房”和“晚餐”是相關的話,所以它們的詞向量之間的距離會相對小。

理想的情況下,在一個良好的嵌入空間裡,從“廚房”向量到“晚餐”向量的“路徑”向量會精確地捕捉到這兩個概念之間的語義關係。在這種情況下,“路徑”向量表示的是“發生的地點”,所以你會期望“廚房”向量-“晚餐”向量(兩個詞向量的差異)捕捉到“發生的地點”這樣的語義關係。基本上,我們應該有向量等式:晚餐+發生的地點=廚房(至少接近)。如果真的是這樣的話,那麼我們可以使用這樣的關係向量來回答某些問題。例如,應用這種語義關係到一個新的向量,比如“工作”,我們應該得到一個有意義的等式,工作+發生的地點=辦公室,來回答“工作發生的地點在哪裡?”。

詞向量通過降維技術表徵文字資料集中的詞的共現資訊。方法包括神經網路(“word2vec”技術),或矩陣分解。

Glove詞向量與資料集

本文使用GloVe詞向量。Glove是”Global Vectors for Word Representation”的縮寫,一種基於共現矩陣分解的詞向量。本文使用的Glove詞向量是在2014年的英文維基百科上訓練,有400k個不同的詞,每個詞用100維向量表示。點此下載(友情提示,詞向量檔案大小約為822M)。

本文使用的資料集時著名的“20 Newsgroup dataset”。該資料集共有20種新聞文字資料,我們將實現對該資料集的文字分類任務。資料集的說明和下載請參

這裡

不同類別的新聞包含大量不同的單詞,在語義上存在極大的差別。一些新聞類別如下所示

comp.sys.ibm.pc.hardware

comp.graphics

comp.os.ms-windows.misc

comp.sys.mac.hardware

comp.windows.x

rec.autos

rec.motorcycles

rec.sport.baseball

rec.sport.hockeycomp.os.ms-windows.misc

comp.sys.mac.hardware

comp.windows.x

rec.autos

rec.motorcycles

rec.sport.baseball

rec.sport.hockey

實驗方法

以下使我們如何解決分類問題的步驟

  • 將所有新聞樣本轉化為詞索引序列。所謂詞索引就是為每一個詞一次分配一個整數ID。遍歷所有的新聞文字,我們只保留 常見的20000個詞,而且每個新聞文字最多保留1000個詞。
  • 生成一個詞向量矩陣。第i列表示詞索引為i的詞的詞向量。
  • 將詞向量矩陣載入Keras Embedding層,設定該層的權重不可在訓練(也就是說在之後的網路訓練過程中,詞向量不再改變)。
  • Keras Embedding層之後連線一個1D的卷積層,並用一個softmax全連線輸出新聞類別

資料預處理

我們首先遍歷語料檔案下的所有資料夾,獲得不同類別的新聞以及對應的類別標籤,程式碼如下

texts = []  #新聞樣本內容列表
labels_index = {}  # 標籤名字和id對映表
labels = []  # 標籤id
for name in sorted(os.listdir(TEXT_DATA_DIR)):
    path = os.path.join(TEXT_DATA_DIR, name)
    if os.path.isdir(path):
        label_id = len(labels_index)
        labels_index[name] = label_id
        for fname in sorted(os.listdir(path)):
            if fname.isdigit():
                fpath = os.path.join(path, fname)
                f = open(fpath)
                texts.append(f.read())
                f.close()
                labels.append(label_id)

print('Found %s texts.' % len(texts))

之後,我們可以將新聞樣本轉化為神經網路訓練所用的張量。所用到的Keras庫是keras.preprocessing.text.Tokenizer和keras.preprocessing.sequence.pad_sequences。程式碼如下

from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences

tokenizer = Tokenizer(nb_words=MAX_NB_WORDS)
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)

word_index = tokenizer.word_index
print('Found %s unique tokens.' % len(word_index))

data = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)

labels = to_categorical(np.asarray(labels))
print('Shape of data tensor:', data.shape)
print('Shape of label tensor:', labels.shape)

# 切分成測試集和驗證集
indices = np.arange(data.shape[0])
np.random.shuffle(indices)
data = data[indices]
labels = labels[indices]
nb_validation_samples = int(VALIDATION_SPLIT * data.shape[0])

x_train = data[:-nb_validation_samples]
y_train = labels[:-nb_validation_samples]
x_val = data[-nb_validation_samples:]
y_val = labels[-nb_validation_samples:]

Embedding layer 設定

接下來,我們從Glove檔案中解析出每個詞和它所對應的詞向量,並用字典的方式儲存

embeddings_index = {}
f = open(os.path.join(GLOVE_DIR, 'glove.6B.100d.txt'))
for line in f:
    values = line.split()
    word = values[0]
    coefs = np.asarray(values[1:], dtype='float32')
    embeddings_index[word] = coefs
f.close()

print('Found %s word vectors.' % len(embeddings_index))

此時,我們可以根據得到的字典生成上文所定義的詞向量矩陣

embedding_matrix = np.zeros((len(word_index) + 1, EMBEDDING_DIM))
for word, i in word_index.items():
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        # words not found in embedding index will be all-zeros.
        embedding_matrix[i] = embedding_vector

現在我們將這個詞向量舉證載入到Embedding 層中,注意,我們設定trainable=False使得這個編碼層不可再訓練。

from keras.layers import Embedding

embedding_layer = Embedding(len(word_index) + 1,
                            EMBEDDING_DIM,
                            weights=[embedding_matrix],
                            input_length=MAX_SEQUENCE_LENGTH,
                            trainable=False)

一個Embedding層的輸入應該是一系列的整數序列,比如一個2D的輸入,它的shape值為(samples,indices),也就是一個samples行,indices列的矩陣。每一次的batch訓練的輸入應該被padded成相同大小(儘管Embedding層有能力處理不定長序列,如果你不指定數列長度這一引數dim)。所有的序列中的整數都被對應的詞向量矩陣中的對應的列(也就是它的詞向量)代替,比如序列[1,2]將被序列詞向量1,詞向量2代替。這樣,輸入一個2D張量後,我們可以得到一個3D張量。

訓練1D卷積

最後,我們可以使用一個小型的1D卷積解決這個新聞分類的問題。

sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
x = Conv1D(128, 5, activation='relu')(embedded_sequences)
x = MaxPooling1D(5)(x)
x = Conv1D(128, 5, activation='relu')(x)
x = MaxPooling1D(5)(x)
x = Conv1D(128, 5, activation='relu')(x)
x = MaxPooling1D(35)(x)  # global max pooling
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
preds = Dense(len(labels_index), activation='softmax')(x)

model = Model(sequence_input, preds)
model.compile(loss='categorical_crossentropy',
              optimizer='rmsprop',
              metrics=['acc'])

# happy learning!
model.fit(x_train, y_train, validation_data=(x_val, y_val),
          nb_epoch=2, batch_size=128)

在兩次迭代後,這個模型最後可以達到0.95的分類準確率(4:1分割訓練和測試集合)。你可以利用正則方法(例如dropout)或在Embedding層上進行fine-tuning獲得更高的準確率。

我們可以做一個對比實驗,直接使用Keras自帶的Embedding層訓練詞向量而不用Glove向量。程式碼如下所示

embedding_layer = Embedding(len(word_index) + 1,
                            EMBEDDING_DIM,
                            input_length=MAX_SEQUENCE_LENGTH)

兩次迭代之後,我們可以得到0.9的準確率。所以使用預訓練的詞向量作為特徵非常有效的。一般來說,在自然語言處理任務中,當樣本數量非常少時,使用預訓練的詞向量是可行的(實際上,預訓練的詞向量引入外部語義資訊,往往對模型很有幫助)。

以下部分為譯者新增

國內的Rachel-Zhang用sklearn對同樣的資料集做個基於傳統機器學習演算法的實驗,請點選這裡。 同時Richard Socher等在那篇論文中提出GloVe詞向量,指出GloVe詞向量比word2vec的效能更好1,之後的研究表示word2vec和GloVe其實各有千秋,例如Schnabel等提出了用於測評詞向量的各項指標,測評顯示 word2vec在大部分測評指標優於GloVe和C&W詞向量2。本文實現其實可以利用谷歌新聞的word2vec詞向量再做一組測評實驗。

參考文獻

相關推薦

文字分類實戰(四)—— Bi-LSTM模型 文字分類實戰(一)—— word2vec訓練向量

1 大綱概述   文字分類這個系列將會有十篇左右,包括基於word2vec預訓練的文字分類,與及基於最新的預訓練模型(ELMo,BERT等)的文字分類。總共有以下系列:   word2vec預訓練詞向量   textCNN 模型   charCNN 模型   Bi-LSTM 模型   Bi-LST

文字分類實戰(七)—— Adversarial LSTM模型 文字分類實戰(一)—— word2vec訓練向量

1 大綱概述   文字分類這個系列將會有十篇左右,包括基於word2vec預訓練的文字分類,與及基於最新的預訓練模型(ELMo,BERT等)的文字分類。總共有以下系列:   word2vec預訓練詞向量   textCNN 模型   charCNN 模型   Bi-LSTM 模型   Bi-LST

文字分類實戰(十)—— BERT 訓練模型 文字分類實戰(一)—— word2vec訓練向量

1 大綱概述   文字分類這個系列將會有十篇左右,包括基於word2vec預訓練的文字分類,與及基於最新的預訓練模型(ELMo,BERT等)的文字分類。總共有以下系列:   word2vec預訓練詞向量   textCNN 模型   charCNN 模型   Bi-LSTM 模型   Bi-LST

文字分類實戰(一)—— word2vec訓練向量

1 大綱概述   文字分類這個系列將會有十篇左右,包括基於word2vec預訓練的文字分類,與及基於最新的預訓練模型(ELMo,BERT等)的文字分類。總共有以下系列:   word2vec預訓練詞向量   textCNN 模型   charCNN 模型   Bi-LSTM 模型   Bi-LST

tensorflow : 使用訓練向量

目前使用深度網路進行文字任務模型訓練時,第一步應該是將文字轉為詞向量進行處理。但一般詞向量的效果跟語料的大小有關,而處理任務的語料不足支援我們的實驗,這時就需要使用網上公開的大規模語料訓練詞向量。 1、下載 網上公開的詞向量下載地址:https://gi

tensorflow如何正確加載訓練向量

global color news doc ... elf import loading initial 使用預訓練詞向量和隨機初始化詞向量的差異還是挺大的,現在說一說我使用預訓練詞向量的流程。   一、構建本語料的詞匯表,作為我的基礎詞匯   二、遍歷該詞匯表,從預訓練詞

tensorflow使用訓練向量

目前使用深度網路進行文字任務模型訓練時,第一步應該是將文字轉為詞向量進行處理。但一般詞向量的效果跟語料的大小有關,而處理任務的語料不足支援我們的實驗,這時就需要使用網上公開的大規模語料訓練詞向量。1、下載網上公開的詞向量下載地址:https://github.com/xgli

word2vec訓練向量

NLP中的Word2Vec講解     word2vec是Google開源的一款用於詞向量計算 的工具,可以很好的度量詞與詞之間的相似性;   word2vec建模是指用CBoW模型或Skip-gram模型來計算不同 詞語的向量(word vector)   CBoW是給定上下文來預測輸入詞、Ski

Keras模型使用訓練向量

轉自:wuwt.me/2017/08/21/pre-trained-embedding-keras/ “詞向量”(詞嵌入)是將一類詞的語義對映到向量空間中的自然語言處理技術。即將一個詞用特定的向量來表示,向量之間的距離(例如,任意兩個向量之間的L2正規化距離或更常用的餘

keras調用訓練模型分類

dict 拓展 span 類別 就是 num pan 維度 上下 在網上看到一篇博客,地址https://www.pyimagesearch.com/2017/03/20/imagenet-vggnet-resnet-inception-xception-keras/,是關

使用 rnn 訓練向量模型

詞向量說明如下: 詞向量模型表徵的是詞語與詞語之間的距離和聯絡,詞向量也叫詞嵌入 word embedding CBOW 模型: 根據某個詞的上下文,計算中間詞出現的概率,預測的是中心詞 Skip-Gram 模型: 跟據中間詞,分別計算它的上下文概率,與 CBOW 模型相反

keras】載入VGG16模型訓練權重

#!/usr/bin/python3 # -*- coding: utf-8 -*- # @Time: 2018/8/15 # @Author: xfLi #載入模型的預訓練權重 import numpy as np from keras.applications.vgg

Tensorflow實戰學習(十八)【向量、維基百科語料庫訓練向量模型

詞向量嵌入需要高效率處理大規模文字語料庫。word2vec。簡單方式,詞送入獨熱編碼(one-hot encoding)學習系統,長度為詞彙表長度的向量,詞語對應位置元素為1,其餘元素為0。向量維數很高,無法刻畫不同詞語的語義關聯。共生關係(co-occurre

【tf.keras】tf.keras載入AlexNet訓練模型

目錄 從 PyTorch 中匯出模型引數 第 0 步:配置環境 第 1 步:安裝 MMdnn 第 2 步:得到 PyTorch 儲存完整結構和引數的模型(pth 檔案) 第 3 步:匯出 Py

[Algorithm & NLP] 文本深度表示模型——word2vec&doc2vec向量模型

www. 頻率 cbo homepage 算法 文章 有一個 tro 概率 閱讀目錄 1. 詞向量 2.Distributed representation詞向量表示 3.詞向量模型 4.word2vec算法思想 5.doc2vec算法思

訓練向量

1 def word_vector_gener(): 2 """ 3 幾種不同的方法來生成詞向量 4 :return: 5 """ 6 from gensim.models import Word2Vec 7 from gensim.test

Spark Mlib(三)用spark訓練向量

自然語言處理中,在詞的表示上,向量的方式無疑是最流行的一種。它可以作為神經網路的輸入,也可直接用來計算。比如計算兩個詞的相似度時,就可以用這兩個詞向量的距離來衡量。詞向量的訓練需要大規模的語料,從而帶來的是比較長的訓練時間。spark框架基於記憶體計算,有忘加快詞向量的訓練速度。 以下是sp

基於python的gensim word2vec訓練向量

準備工作 當我們下載了anaconda後,可以在命令視窗通過命令 conda install gensim 安裝gensim gensim介紹 gensim是一款強大的自然語言處理工具,裡面包括N多常見模型,我們體驗一下: interfa

Keras:在訓練的網路上fine-tune

準備 fine-tune的三個步驟: 搭建vgg-16並載入權重; 將之前定義的全連線網路載入到模型頂部,並載入權重; 凍結vgg16網路的一部分引數. 在之前的Keras:自建資料集影象分類的模型訓練、儲存與恢復裡製作了實驗用的資料集並初步進

Windows下執行C語言版Word2Vec訓練向量

在Word2vec模型中,演算法可以通過無監督的方法為每個詞計算出一個d維的向量,即將每個詞對映為d維的空間中的一個點,d維空間中點之間的距離(即每個詞對應的d維向量的距離)可反映詞之間的相似性。 dav/word2vec是一個經典的利用多執行緒訓練詞向量的程