1. 程式人生 > >詞嵌入、句向量等方法彙總

詞嵌入、句向量等方法彙總




在cips2016出來之前,筆者也總結多類似詞向量的內容,自然語言處理︱簡述四大類文字分析中的“詞向量”(文字詞特徵提取)事實證明,筆者當時所寫的基本跟CIPS2016一章中總結的類似,當然由於入門較晚沒有CIPS2016裡面說法權威,於是把CIPS2016中的內容,做一個摘錄。


CIPS2016 中文資訊處理報告《第五章 語言表示與深度學習研究進展、現狀及趨勢》第三節 技術方法和研究現狀中有一些關於語言表示模型劃分的內容P33-P35,其中:
這裡寫圖片描述
語言表示方法大體上可以從兩個維度進行區分。一個維度是按不同粒度進行劃分,語言具有一定的層次結構,語言表示可以分為字、詞、句子、篇章等不同粒度的表示。另一個維度是按表示形式進行劃分,可以分為離散表示和連續表示兩類。離散表示是將語言看成離散的符號,而將語言表示為連續空間中的一個點,包括分散式表示和分散式表示。

一、離散的方法## 標題 ##表示

1、詞向量

  • 一個詞可以表示為One-Hot 向量(一維為1 其餘維為0
    的向量),也叫區域性表示。離散表示的缺點是詞與詞之間沒有距離的概念,這和事實不符。
  • 一種改進的方法是基於聚類的詞表示。其中一個經典的方法是Brown 聚類演算法,該演算法是一種層次化的聚類演算法。在得到層次化結構的詞類簇之後,我們可以用根節點到詞之間的路徑來表示該詞。

2、句向量

有了詞的表示之後,我們可以進一步得到句子或篇章的表示。句子或篇章的離散表示通常採用詞袋模型、N 元模型等。
.
.
.

二、連續表示—分散式表示

這樣就可以通過共現矩陣的方式來進行詞的表示,這類方法也叫分散式表示(Distributional Representations)

1、詞向量

潛在語義分析模型(Latent Semantic Analysis, LSA)、潛在狄利克雷分配模型(Latent Dirichlet Allocation,LDA)、隨機索引(random indexing)等。

2、句向量

句子的表示方式對應於共現矩陣,另一列,在LDA中句子-詞語矩陣中就是很好地句子表示方式。
.
.
.

★三、連續表示——分散式表示

另一種連續表示是分散式表示(Distributed Representations),即將語言表示為稠密、低維、連續的向量

1、詞向量

研究者最早發現學習得到詞嵌入之間存在類比關係。比如apple−apples ≈ car−cars, man−woman ≈ king – queen 等。這些方法都可以直接在大規模無標註語料上進行訓練。詞嵌入的質量也非常依賴於上下文視窗大小的選擇。通常大的上下文視窗學到的詞嵌入更反映主題資訊,而小的上下文視窗學到的詞嵌入更反映詞的功能和上下文語義資訊。

2、句向量

句子編碼主要研究如何有效地從詞嵌入通過不同方式的組合得到句子表示。其中,比較有代表性的方法有四種。

  • (1)神經詞袋模型

簡單對文字序列中每個詞嵌入進行平均/加總,作為整個序列的表示。
這種方法的缺點是丟失了詞序資訊。對於長文字,神經詞袋模型比較有效。但是對於短文字,神經詞袋模型很難捕獲語義組合資訊。

  • (2)遞迴神經網路(Recursive Neural Network)

按照一個給定的外部拓撲結構(比如成分句法樹),不斷遞迴得到整個序列的表示。遞迴神經網路的一個缺點是需要給定一個拓撲結構來確定詞和詞之間的依賴關係,因此限制其使用範圍。

  • (3)迴圈神經網路(Recurrent Neural Network)

將文字序列看作時間序列,不斷更新,最後得到整個序列的表示。

  • (4)卷積神經網路(Convolutional Neural Network)

通過多個卷積層和子取樣層,最終得到一個固定長度的向量。

在上述四種基本方法的基礎上,很多研究者綜合這些方法的優點,結合具體的任務,已經提出了一些更復雜的組合模型,例如雙向迴圈神經網路(Bi-directional Recurrent Neural Network)、長短時記憶模型(Long-Short Term Memory)等。
同時根據上面的內容,句向量的表徵在RNN、CNN之間,到底哪個更好呢? 有一篇文章在這點上講得比較清楚,會在下面的延伸三:《NLP 模型到底選 RNN 還是 CNN?》提到。

3、篇章表示

如果處理的物件是比句子更長的文字序列(比如篇章),為了降低模型複雜度,一般採用層次化的方法,先得到句子編碼,然後以句子編碼為輸入,進一步得到篇章的表示。具體的層次化可以採用以下幾種方法:

  • (1)層次化的卷積神經網路

即用卷積神經網路對每個句子進行建模,然後以句子為單位再進行一次卷積和池化操作,得到篇章表示。

  • (2)層次化的迴圈神經網路

即用迴圈神經網路對每個句子進行建模,然後再用一個迴圈神經網路建模以句子為單位的序列,得到篇章表示。

  • (3)混合模型

先用迴圈神經網路對每個句子進行建模,然後以句子為單位再進行一次卷積和池化操作,得到篇章表示。在上述模型中,迴圈神經網路因為非常適合處理文字序列,因此被廣泛應用在很多自然語言處理任務上。
.
.
.

四、總結

基於深度學習的方法在自然語言處理中取得了很大的進展,因此,分散式表示也成為語言表示中最熱門的方法,不但可以在特定的任務中端到端地學習字、詞、句子、篇章的分散式表示,也可以通過大規模未標註文字自動學習。
分散式表示可以非常方便地應用在下游的各種自然語言處理任務上,並且可以端到端地學習,給研究者帶來了很大的便利。但是分散式表示對以下幾種情況還不能很好地處理,需要進一步解決。

  1. 語言中出現所有符號是否都需要使用統一的表示模型?比如,無意義的符號、變數、數字等。
  2. 新詞以及低頻詞的表示學習方法。目前的表示學習方法很難對這些詞進行很好的建模,而這些詞都是極具資訊量的,不能簡單忽略。
  3. 篇章的語言表示。目前對篇章級別的文字進行建模方法比較簡單,不足以表示篇章中的複雜語義。
  4. 語言表示的基礎資料結構。除了目前的基於向量的資料結構之外是否有更好的表示結構,比如矩陣、佇列、棧等。
    .
    .

延伸一:句向量的表示方式

該部落格較多是對分散表示詞向量進行一定的總結與歸納。

1、詞向量簡單相加/平均(類似神經詞袋模型)

對詞向量的相加/平均,但是譬如以下的兩句話質心是一致的:

You are going there to teach not play.
You are going there to play not teach

這樣的方式,再來求句子距離,其實是在求句子的質心距離(centroid distance)。
另外一種改良版本,用Word Movers’ Distance

這裡寫圖片描述

相近詞之間求距離,然後把這樣的相近距離相加。

2、深度學習方面

以上的方法並沒有關照到句子的序列資訊。
1、CNN
用CNN來句子表示(paper:Convolutional Neural Networks for Sentence Classification),操作流程是:
padding句子讓其長度一致 -> 使用詞表示技術成為方陣 -> 使用CNN -> 使用Max-overtime pooling -> 全連線層 -> 獲得句向量。

3、fasttext表示

延伸二:句向量表達:Sentence 2 vec

跟眼神一中詞向量簡單相加減類似,是通過PCA/SVD的加權得到了句向量,同時作者在實驗過程中,發現這一表徵方式,可以跟LSTM表徵的效果媲美。
這裡寫圖片描述

# test
embedding_size = 4   # dimension of the word embedding
w1 = Word('Peter', [0.1, 0.2, 0.3, 0.4])
w2 = Word('was', [0.2, 0.1, 0.3, 0.4])
w3 = Word('here', [0.1, 0.4, 0.1, 0.4])

sentence1 = Sentence([w1, w2, w3])
sentence2 = Sentence([w2, w3, w1])
sentence3 = Sentence([w3, w1, w2])

# calculate and display the result
print(sentence_to_vec([sentence1, sentence2, sentence3], embedding_size))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

.

延伸三:NLP 模型到底選 RNN 還是 CNN?

本文來源於文章《AI技術講座精選:NLP 模型到底選 RNN 還是 CNN?》,不過實質上並沒有得出非常建設性的答案。
paper地址:https://arxiv.org/pdf/1702.01923.pdf

CNN 是分層架構,RNN 是連續結構。一般靠常規直覺來判斷:

  1. 傾向於為分類型別的任務選擇 CNN,例如情感分類,因為情感通常是由一些關鍵詞來決定的;
  2. 對於順序建模任務,我們會選擇 RNN,例如語言建模任務,要求在瞭解上下文的基礎上靈活建模。

在實踐中,得到的結論:

  1. CNN 和 RNN 為文字分類任務提供補充資訊。至於哪個架構的執行效果更好一點,取決於對整個序列的語義理解的重要程度。
  2. 目前來看,RNN 在文字級別的情感分類表現得很好(Tang et al., 2015),對於LSTM,封閉的 CNN
    在語言建模任務上同比 LSTM 更勝一籌
  3. RNN 表現較好並且在大範圍內的任務中都較為穩健。除了以下種情況:當前的任務本質上是一項在一些情感探測和問答匹配設定中識別關鍵詞的任務。
  4. 隱藏層尺寸hidden size和批尺寸batch size會使 DNN 的效能變得非常不穩定,波動較大,從實踐來看這兩個引數對結果的影響非常大。

.

延伸四:對詞向量干預,可以提高效率

本文提出了一種對已有的詞向量進行預處理的方法,用來對學習到的詞向量降噪。基於詞向量自身的幾何結構 — 均值非零以及各項不同性,本文提出了一個反直觀的處理方法:從所有的詞向量中移除均值,以及移除部分導致各項不同性的方向。雖然這種處理方式忽略了詞向量中的部分資訊,但是它可以使多種通過不同方式訓練出來的詞向量加強詞向量中包含的語義資訊。經過預處理之後的詞向量在一系列intrinsic衡量方式上(similarity, analogy, concept categorization)得到了一致性地提高。同時,我們通過了不同的應用上進行了測試,試驗結果表明該預處理已經在諸多neural network中有所體現,進一步證實了對詞向量進行預處理的重要性。

.

延伸五:NLP+Skip-Thoughts-Vectors︱基於TensorFlow的帶語義特徵的句向量編碼方式

Skip-Thoughts 模型概要

Skip-Thoughts 模型是一個句子編碼器。它學習將輸入的句子編碼成固定維度的向量表示,這些向量表示能夠對許多工有用,例如檢測釋義,或對產品評論進行積極或消極的分類等等。有關模型架構和更多示例應用的詳細資訊,可以參閱Ryan Kiros 等人的 NIPS 論文 Skip-Thought Vectors。

一個訓練好的 Skip-Thoughts 模型會在嵌入的向量空間中對相互臨近的相似句子進行編碼。以下示例展示了對電影評論資料集中的一些句子的餘弦相似性的最近鄰域。
我們描述了一種通用、分散式句子編碼器的無監督學習方法。使用從書籍中提取的連續文字,我們訓練了一個編碼器-解碼器模型,試圖重建編碼段落周圍的句子。語義和語法屬性一致的句子因此被對映到相似的向量表示。我們接著引入一個簡單的詞彙擴充套件方法來編碼不再訓練預料內的單詞,令詞彙量擴充套件到一百萬詞。同時建立word2vec到skip-thoughts向量之間的對映關係。
在訓練模型後,我們用線性模型在8個任務上提取和評估我們的向量,包括:語義相關性,釋義檢測,影象句子排序,問題型別歸類,以及4個基準情緒和主觀性資料集。最終的結果是一個非專門設計的編碼器,能夠生成高度通用性的句子表示,在實踐中表現良好。
這裡寫圖片描述

Skip-Thought 模型是 NIPS 2015論文 Skip-Thought Vectors 中描述的模型的一個 TensorFlow 實現,學習對句子的語義屬性進行編碼。

引用:Ryan Kiros, Yukun Zhu, Ruslan Salakhutdinov, Richard S. Zemel, Antonio Torralba, Raquel Urtasun, Sanja Fidler. Skip-Thought Vectors. In NIPS, 2015.

這裡寫圖片描述

編碼句子示例

該示例的句子來自電影評論資料集(Movie Review Data)。

ipython  # Launch iPython.

In [0]:

# Imports.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import os.path
import scipy.spatial.distance as sd
from skip_thoughts import configuration
from skip_thoughts import combined_encoder

In [1]:
# Set paths to the model.
VOCAB_FILE = "/path/to/vocab.txt"
EMBEDDING_MATRIX_FILE = "/path/to/embeddings.npy"
CHECKPOINT_PATH = "/path/to/model.ckpt-9999"
# The following directory should contain files rt-polarity.neg and
# rt-polarity.pos.
MR_DATA_DIR = "/dir/containing/mr/data"

In [2]:
# Set up the encoder. Here we are using a single unidirectional model.
# To use a bidirectional model as well, call load_encoder() again with
# configuration.ModelConfig(bidirectional_encoder=True) and paths to the
# bidirectional model's files. The encoder will use the concatenation of
# all loaded models.
encoder = combined_encoder.CombinedEncoder()
encoder.load_encoder(configuration.ModelConfig(),
                     vocabulary_file=VOCAB_FILE,
                     embedding_matrix_file=EMBEDDING_MATRIX_FILE,
                     checkpoint_path=CHECKPOINT_PATH)

In [3]:
# Load the movie review dataset.
data = []
with open(os.path.join(MR_DATA_DIR, 'rt-polarity.neg'), 'rb') as f:
  data.extend([line.decode('latin-1').strip() for line in f])
with open(os.path.join(MR_DATA_DIR, 'rt-polarity.pos'), 'rb') as f:
  data.extend([line.decode('latin-1').strip() for line in f])

In [4]:
# Generate Skip-Thought Vectors for each sentence in the dataset.
encodings = encoder.encode(data)

In [5]:
# Define a helper function to generate nearest neighbors.
defget_nn(ind, num=10):
  encoding = encodings[ind]
  scores = sd.cdist([encoding], encodings, "cosine")[0]
  sorted_ids = np.argsort(scores)
  print("Sentence:")
  print("", data[ind])
  print("\nNearest neighbors:")
  for i in range(1, num + 1):
    print(" %d. %s (%.3f)" %
          (i, data[sorted_ids[i]], scores[sorted_ids[i]]))

In [6]:
# Compute nearest neighbors of the first sentence in the dataset.
get_nn(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

輸出:

Sentence:
 simplistic , silly and tedious .

Nearest neighbors:
 1. trite , banal , cliched , mostly inoffensive . (0.247)
 2. banal and predictable . (0.253)
 3. witless , pointless , tasteless and idiotic . (0.272)
 4. loud , silly , stupid and pointless . (0.295)
 5. grating and tedious . (0.299)
 6. idiotic and ugly . (0.330)
 7. black-and-white and unrealistic . (0.335)
 8. hopelessly inane , humorless and under-inspired . (0.335)
 9. shallow , noisy and pretentious . (0.340)
 10. . . . unlikable , uninteresting , unfunny , and completely , utterly inept . (0.346)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

延伸六:Doc2Vec的情感分析以及相似性

Tutorial for Sentiment Analysis using Doc2Vec in gensim (or “getting 87% accuracy in sentiment analysis in under 100 lines of code”)
github:https://github.com/linanqiu/word2vec-sentiments

也可以用doc2vec來做相似性分析,其他辦法有:
第一種方法,使用docsim;第二種辦法,使用doc2vec;第三種方式:使用LSH。
部落格裡面也有code

.

延伸七:能夠表徵相似的:基於CNN的短文字表達模型及相似度計算的全新優化模型

LSF-SCNN,即基於詞彙語義特徵的跳躍卷積模型 (Lexical Semantic Feature based Skip Convolution neural network ),基於卷積神經網路模型引入三種優化策略:詞彙語義特徵 (Lexical Semantic Feature, LSF)、跳躍卷積 (Skip Convolution, SC)和K-Max均值取樣 (K-Max Average Pooling, KMA) ,分別在詞彙粒度、短語粒度、句子粒度上抽取更加豐富的語義特徵,從而更好的在向量空間構建短文字語義表達模型,並廣泛的適用於問答系統 (question answering)、釋義識別 (paraphrase identification) 和文字蘊含 (textual entailment)等計算成對兒出現的短文字的相似度的任務中。
LSF特徵怎樣計算得到?
問題和答案中的每一個單詞都會有一個LSF特徵,具體來說是一個[0,t]上的整數值。LSF的計算過程可通過下面一個例子說明,當我們想要求解問題中general一詞的LSF特徵時,第一步我們需要計算general與答案中每一個詞的餘弦相似度並選取其中的最大值,因此chief被選取出來。第二步,餘弦相似度值的最大值0.79將通過一個對映函式對映為一個[0,t]區間的整數,當我們假定t=10,最終計算得到general的LSF特徵為3。這是合理的,general和chief一定程度上是近義詞。
這裡寫圖片描述

.

延伸八:473個模型試驗告訴你文字分類中的最好編碼方式

論文地址:https://arxiv.org/pdf/1708.02657.pdf
來源機器之心:學界 473個模型試驗告訴你文字分類中的最好編碼方式
本論文實證研究了在文字分類模型中漢語、日語、韓語(CJK)和英語的不同編碼方式。該研究討論了不同層面的編碼,包括 UTF-8 bytes、字元級和詞彙級。對於所有的編碼層面,我們都提供了線性模型、fastText (Joulin et al., 2016) 和卷積網路之間的對比。對於卷積網路,我們使用字元字形(character glyph)影象、one-hot(或 one-of-n)編碼和嵌入方法比較了不同的編碼機制。總的來說,該實驗涉及 473 個模型,並使用了四種語言(漢語、英語、日語和韓語)的 14 個大規模文字分類資料集。該研究所得出來的一些結論:基於 UTF-8 位元組層面的 one-hot 編碼在卷積網路中始終生成優秀結果;詞層面的 N 元線性模型即使不能完美地分詞,它也有強大的效能;fastText 使用字元層面的 N 元模型進行編碼取得了最好的效能,但當特徵太多時容易過擬合。
這裡寫圖片描述

通過比較以上表格中的誤差率,作者得出以下結論:

  • 1、fastText模型對中、日、韓文字(CJK語言文字)在character級編碼的處理結果更好;而對英語文字則在word級編碼的處理結果更好;
  • 2、對於fastText和線性模型,CJK語言的word級編碼在沒有完美分割的情況下效果相當;
  • 3、卷積網路的最佳編碼機制是byte級獨熱編碼(byte-level one-hot encoding)。
    這表明卷積網路能夠從低級別的表示中理解文字,並提供了一致的和統一的方式來處理多種語言。
  • 4、fastText相比於卷積網路更傾向於過擬合,而相比於線形模型也並沒有表現出更多的表示能力(representation
    capacity)。

當然,儘管作者在此列了473種模型進行對比,但仍不是全部。例如深度學習模型本文只用了卷積網路模型,但其實還有別的一些有意思的模型,例如週期性網路(recurrent networks)等。作者似乎計劃在之後會對週期性網路進行研究,同時還會改進卷積網路模型,看會有什麼樣的效果。