天天看點

charRNN和word2vec的實作原理下面來說說自動生成古詩的整個項目的思路。相對于字母來說,漢字的種類比較多,可能會導緻模型過大 。 對此再以下兩種優化方法:embeding的使用方式?

charRNN其實實作的是自動生成的功能,比如說自動生成英文,自動生成古詩,自動生成代碼。

下面來說說自動生成古詩的整個項目的思路。

首先我們需要個古詩樣本集合,這裡面存放了大量的唐詩。

那麼我們将面臨一個問題,如何去處理這些中文。有一個處理方法是,統計該古詩集中所有用到的中文字,并給每一個中文字打上1,2,3,4,5...這樣不重複的數字标簽。讓後用數字标簽替換掉中文形成數字詩集。

那麼如何讓rnn來達到學習古詩詞并且自動生成古詩詞的目的呢?

這就要考慮到損失函數是如何來定義的。我們知道損失函數一般是生成值減去實際值的平方然後累加。那麼這裡的實際值其實是它下一個位置的數字辨別。那麼在經過多次的疊代之後,rnn網絡是可以形成根據目前字元生成下一字元的能力的。

相對于字母來說,漢字的種類比較多,可能會導緻模型過大 。 對此再以下兩種優化方法:

1. 取最常用的 N 個漢字。将剩下的漢字變成單獨一類,并用一個特殊的字元<unk>進行标注 。

2.在輸入時,可以加入一層 embedding 層,這個 embedding 層可以将漢字轉換為較為稠密的表示 , 它可以代稀疏的獨熱表示,取得更好的效果 。之是以對字母不使用 embedding ,是因為單個字母不具備任何含義 ,隻需要使用獨熱表示即可 。 而單個漢字還是有高一定實際意義的,是以可以使用 embedding 将真映射到一個較為稠密的空間 。embedding的具體實作邏輯後面介紹。

embeding的使用方式?

在tensorflow中,可以使用下面代碼來完成embeding的編碼工作。将input和embeding的結構定義輸入到embedding_lookup中,得到的結構就是embeding處理後的資料。

embedding = tf.get_variable('embedding', [self.num_classes, self.embedding_size])
self.lstm_inputs = tf.nn.embedding_lookup(embedding, self.inputs)      

但是embeding背後使用的word2vec卻是要複雜很多的。

首先我們需要搞清楚word2vec解決的是什麼樣的問題?

word2vec可以形成密集的矩陣來代替獨熱編碼,做到用矩陣唯一代表單詞的作用。因為單詞的資料集是非常大的,獨熱編碼的次元又是資料集的大小,這個時候使用獨熱編碼來表示單詞或漢字明顯是不合适的,而word2vec的資料次元一般使用128維就夠用了,是以這個時候使用word2vec是非常合适的選擇。

詞嵌入word2vec的兩種方式

CBOW連續詞袋模型

核心思想是利用這個詞的上下文來預測這個詞。

首先考慮用一個詞來預測另一詞的情況,這個用法其實就是charRNN中的用于進行中文漢字的時的用法。

charRNN和word2vec的實作原理下面來說說自動生成古詩的整個項目的思路。相對于字母來說,漢字的種類比較多,可能會導緻模型過大 。 對此再以下兩種優化方法:embeding的使用方式?

x1到xv是一個單詞或漢字的獨熱表示,它經過一個全連接配接層得到隐層h,再經過一個全連接配接層得到輸出成y。其中隐層神經元個數是要小于v的,一般設128,256,512。在這個模型中的實際y值是下個詞的獨熱表示,當這個模型訓練完成後,隐層的值就是詞的嵌入表示,也就是word2vec。

用多個詞來預測一個詞的情況

charRNN和word2vec的實作原理下面來說說自動生成古詩的整個項目的思路。相對于字母來說,漢字的種類比較多,可能會導緻模型過大 。 對此再以下兩種優化方法:embeding的使用方式?

與用一個詞來預測一個詞的模型相比較,它隻是将所有隐層的中做了個相加的操作。

當然也有使用1個詞來預測多個詞的思想Skip-Gram

Skip-Gram 方法和 CBOW 方法正好相反:使用“出現的詞”來預測E “上下文文中詞”。如在之前的句子中,是使用“ woman ” ,來預測“ man ”“ fell ”等單詞 。 是以,可以把 Skip-Gram 方法看作從一個單詞預測另一個單詞的問題 。在損失的選擇上,和 CBOW 一樣,不使用 V 類分類的 Softmax 交叉摘損失, 而是取出一些“噪聲詞”,訓練一個兩類分類器(即同樣使用 NCE損失)。

但是現在依然是存在問題的,現在整個網絡是一個v分類器,而我現在并不是要做分類的任務,我們隻是想用更少次元的向量來表示單詞。解決方法是使用2分類模型來降低計算的複雜度。具體來說,設要預測的目标詞彙是“ mat”,會在整個單詞表中,随機地取出一些詞作為“躁聲詞彙",如computer”,“ fork ” 。 模型會做一個兩類分類:判斷一個詞彙是否屬于“躁聲詞彙” 。通過優化二分類損失函數來訓練模型後,最後得到的模型中的隐含層可以看作是 word2vec 中的“vec”向量 。

在編碼的過程中我們會看到下面的代碼

loss = tf.reduce_mean(
    tf.nn.nce_loss(weights=nce_weights,
                   biases=nce_biases,
                   labels=train_labels,
                   inputs=embed,
                   num_sampled=num_sampled,
                   num_classes=vocabulary_size))      

對于輸入資料 train inputs ,用一個 tf.nn.embedding_lookup 函數,可以根據 embeddings 變量将真轉換成對應的詞嵌入向量 embed 。對比 embed和輸入資料的标簽 train labels ,用 tf.nn.nce loss 函數可以直接走義其 NCE損失。在這裡nec其實是有使用實際标簽隐性轉換為2分類的模型的。

在代碼編寫過程中還有一個處理是十分關鍵的。那就是如何去找尋資料和lable之間的對應關系。下面簡答介紹一個問題的思路。

例句:我 想 吃 大 餐。

如果我們想通過我 想 大 餐 來預測 吃這個字的話。那麼資料集是[我 想 大 餐], 标簽集是[ 吃 吃 吃 吃]。這個是使用CBOW的思想。

如果我們想通過 吃 來預測 我 想 大 餐這四個字的話。那麼資料集是[ 吃 吃 吃 吃], 标簽集是[我 想 大 餐],。這個是使用SKIP-GRAM的思想。

繼續閱讀