時間序列表示方法

  • 2020 年 1 月 27 日
  • 筆記

自然界中,除了2D、3D的圖片、影片駛距以外,更多的是一些類似於序列的數據,比如語音、文字,這些數據都是有時間先後順序的

現在就有這樣一個問題,對於一個2D圖片順序,我們用一個像素點的RGB值來表示這個像素的色彩度。但是對於語音、文字該如何表示呢?

語音在某一個時間段會產生一段波形,這段波形中波峰值就可以表示此刻聲音的強度。對於一段文字中的字元也可以表示。但是在PyTorch中是沒有string類型的,我們必須要把string類型表示為另外一種數值類型。如何進行時間序列的表示(Representation),如何進行時間序列的資訊提取(Information Extraction )就成了時間序列研究的關鍵問題

Sequence Representation

  • $[seq_len, feature_len]$ 假設一句話有5個單詞,那麼$seq_len=5$,而$feature_len$取決於你的應用場景,比方說每個單詞用一個1維向量來表示,那麼$feature_len=1$,如果每個單詞用一個100維向量來表示,那麼$feature_len=100$

例如下圖的歷史房價圖,所採用的表示方式就是[100,1]

How to represent a word

通常我們會使用one-hot Encoding的方式對文字進行編碼,看下面的一個例子

假設有下面的兩句話:

  • have a good day
  • have a great day 這兩句話共有5個辭彙,於是可以用$V$表示,其中$V={have, a, good, great, day}$。因為有5個辭彙,所以每個辭彙都用一個5維的向量進行表示,如下所示:
  • have = [1, 0, 0, 0, 0]
  • a = [0, 1, 0, 0, 0]
  • good = [0, 0, 1, 0, 0]
  • great = [0, 0, 0, 1, 0]
  • day = [0, 0, 0, 0, 1]

但這麼做有以下的缺點:

  1. 每個word的vector都是獨立的,所以使用one-hot Encoding沒有體現單詞語單詞之間的關係
  2. 如果辭彙量很多,則vector的維度會很大,同時造成數據稀疏問題

Word Embedding

上面one-hot Encoding存在很多問題,那麼應該如何修改呢?我們可以用另一種方式去定義每一個單詞——word embedding。下面這句話解釋word embedding很合適

Word embeddings embed meaning of text in a vector space.(把文本的意思嵌入到向量空間中)

有一些詞的詞性是相近的,比如「love」和「like」,對於這種詞性相近的詞,我們需要他們的向量表示也能相近,如何度量和定義向量之間的相似程度呢?非常簡單,就是使用兩個向量的夾角,夾角越小,越相近。舉個例子,下面有4段話

  1. The cat likes playing wool.
  2. The kitty likes playing wool.
  3. The dog likes playing ball
  4. The boy does not like playing ball or wool.

這裡面有4個詞,分別是cat,kitty,dog和boy。下面我們使用一個二維的詞向量(a,b)來表示每一個詞,其中a和b分別代表著這個詞的一種屬性,比如a代表是否喜歡玩球,b代表是否喜歡玩毛線,數值越大表示越喜歡,那麼我們就能用數值來定義每一個單詞

對於cat,我們可以定義他的word embedding為(-1, 4),因為它不喜歡玩球,喜歡玩毛線;kitty為(-2, 5);dog為(3, -2);boy為(-2,-3)。把這四個向量在坐標系中表示出來

從上圖就能明顯看出kitty和cat的夾角比較小,所以它們比較相似,dog和boy之間的夾角很大,所以它們不相似

下面說一下具體公式。對於向量$boldsymbol{x}, boldsymbol{y} in mathbb{R}^d$,它們的餘弦相似度是它們之間夾角的餘弦值

$$ frac{boldsymbol{x}^top boldsymbol{y}}{|boldsymbol{x}| |boldsymbol{y}|} in [-1, 1]. $$

在PyTorch中Word Embedding是通過一個函數來實現的nn.Embedding

import torch  import torch.nn as nn    word_to_idx = {"hello": 0, "world": 1} # 給每個詞打上索引    lookup_tensor = torch.tensor([word_to_idx["hello"]], dtype=torch.long) # 取出"hello"對應的索引    embeds = nn.Embedding(2, 5) # 2 words in vocab, 5 dimensional embeddings  hello_embed = embeds(lookup_tensor) # 傳入索引    print(hello_embed)

輸出

tensor([[-1.2999,  2.2142,  0.2436, -1.9585,  0.8714]],         grad_fn=<EmbeddingBackward>)

稍微解釋下這幾行程式碼,首先因為每個單詞都需要用一個數字去表示,所以我們要構建一個單詞-數字之間的映射

然後是nn.Embedding(2, 5),2表示有2個詞,5表示5維,其實也就是個2×5的矩陣。所以如果你有1000個詞,每個詞希望是100維,你就可以這樣寫這行程式碼nn.Embedding(1000, 100)