1一個輸入層 ; 1 個隱含層; 1個輸出層
syn0 input -> hidden 的 weights 在code中是一個1維數組,但是應該按照二維數組來理解。
訪問時實際上可以看成 syn0[i, j] i爲第i個單詞,j爲第j個隱含單元。
大小: 詞典大小 * 隱含層大小
syn1 hidden->output 的 weights
neu1 浮點型數組, 隱含層神經的值
大小: 隱含層大小
neu1e 隱含層誤差量
大小: 隱含層大小
vocab_size 不同單詞個數,也就是詞典大小。
layer1_size 向量長度,實際上就是隱含層的大小。
分析完其實就是一個BP網絡,不過還是不知道爲啥要將前後幾個詞和當前詞聯繫起來,要完全理解此場景的模型思想,看來還是得看論文了。
- TrainModelThread
while (1)- 打印訓練的進度情況
- (while)從輸入文件中讀入1000個單詞組成一個句子,存入sen, sen[i] = word_index, 也就是sen數組裏的順序與單詞在原文中的順序一致,而sen存放的值爲詞典中該單詞的位置。
sentence_length - 該sen數組的長度
sentence_position - 爲最外層while循環遍歷該句子時,對記錄當前單詞在此句子中的位置。 - 如果 處理的單詞個數超出了分配給當前線程的個數,則結束。
- 獲取當前單詞。 從句子sen中取出 word_index = sen[sentence_position];
- 初始化 隱含層神經neu1 、隱含層誤差 neu1e 爲0
- b 產生隨機數b, 取值目前爲0~4之間。 窗口值window默認爲5
- cbow
- in -> hidden (正向傳播, 得到隱含層)
for (遍歷左右窗口詞,c從 sentence_position - (window -b) 到 sentence_position + (window -b) , 且 c != sentence_position- 得到c處存放的單詞索引 last_word = sen[c];
- 將該詞對應到的每一個in->hidden的網絡權重係數syn0 累加到 隱含層單元neu1中
for (c = 0; c < layer1_size; c++) neu1[c] += syn0[c + last_word * layer1_size];
- HIERARCHICAL SOFTMAX 目前默認hs爲1的。
for (遍歷該詞的huffman編碼串)- f = 0
- 計算出該詞在hidden-output 網絡中的權重存儲位置 l2 = vocab_[word_index].point[d] * layer1_size;
這裏的point[d]有疑問?? 是否有可能超出vocab_size呢?
>> 不會,這個是哈夫曼樹中的非葉子節點路徑上的點,也就是多個二分類的決策點 - hidden -> output (正向傳播,得到該編碼單元對應的output 值f)
for (c = 0; c < layer1_size; c++) f += neu1[c] * syn1[c + l2]; - 對 f 進行Sigmoid變換 (這裏是預先存放在了expTable表中)
- 計算下降的梯度g (乘了學習率alpha)
g = (1 - vocab_[word_index].code[d] - f) * alpha; - output - > hidden (反向傳播 得到隱含層誤差)
for (c = 0; c < layer1_size; c++) neu1e[c] += g * syn1[c + l2]; - 學習權重 hidden-output
for (c = 0; c < layer1_size; c++) syn1[c + l2] += g * neu1[c];
- NEGATIVE SAMPLING 目前運行時默認未走此步
- hidden -> in (反向傳遞, 更新in-hidden網絡權重)
for (遍歷左右窗口詞,c從 sentence_position - (window -b) 到 sentence_position + (window -b) , 且 c != sentence_position- 得到c處存放的單詞索引 last_word = sen[c];
- 學習權重input-hidden 將隱含層單元誤差量neu1e 加到 該詞對應到的每一個in->hidden的網絡權重係數syn0上
for (c = 0; c < layer1_size; c++) syn0[c + last_word * layer1_size] += neu1e[c];
- in -> hidden (正向傳播, 得到隱含層)
- skip-gram
這裏居然沒有隱含神經元的概念,其實也是neu1,只是這裏的neu1[c] = syn0[c + last_word * layer1_size] ,所以省去了用neu1[c]去計算;因此計算輸出值f的時候,直接用的是兩層網絡的權重syn0與syn1相乘;
第1層網絡權重用的是窗口詞的, 第2層網絡權重用的是當前詞的;
其餘部分和cbow模型類似。
- 保存結果
將input-hidden網絡權重(syn0)作爲了詞向量保存,其實是保存的爲neu1,隱含層的值,隱含層的值爲n-1個詞爲0,一個詞A爲1時候的詞典向量的特徵表示,相當於詞A的特徵表示,所以將其作爲詞A的特徵向量。