Tensorflow 的 NCE-Loss 的實現和 word2vec

2021-02-18 機器學習算法與自然語言處理

這兩天在看 word2vec 的源碼,發現其損失函數不是 多元交叉熵,而是 NCE,於是查了下資料,看到了這篇博文,分享一下。

先看看tensorflow的nce-loss的API:

def nce_loss(weights, biases, inputs, labels, num_sampled, num_classes,
             num_true=1,
             sampled_values=None,
             remove_accidental_hits=False,
             partition_strategy="mod",
             name="nce_loss")

假設nce_loss之前的輸入數據是K維的,一共有N個類,那麼

inputs.shape = (batch_size, K)labels.shape = (batch_size, num_true)sampled_values: 採樣出的負樣本,如果是None,就會用不同的sampler去採樣。待會兒說sampler是什麼。remove_accidental_hits: 如果採樣時不小心採樣到的負樣本剛好是正樣本,要不要幹掉partition_strategy:對weights進行embedding_lookup時並行查表時的策略。TF的embeding_lookup是在CPU裡實現的,這裡需要考慮多線程查表時的鎖的問題。

nce_loss的實現邏輯如下:

_compute_sampled_logits: 通過這個函數計算出正樣本和採樣出的負樣本對應的output和labelsigmoid_cross_entropy_with_logits: 通過 sigmoid cross entropy來計算output和label的loss,從而進行反向傳播。這個函數把最後的問題轉化為了num_sampled+num_real個兩類分類問題,然後每個分類問題用了交叉熵的損傷函數,也就是logistic regression常用的損失函數。TF裡還提供了一個softmax_cross_entropy_with_logits的函數,和這個有所區別。

再來看看TF裡word2vec的實現,他用到nce_loss的代碼如下:

  loss = tf.reduce_mean(
tf.nn.nce_loss(nce_weights, nce_biases, embed, train_labels,
num_sampled, vocabulary_size))

可以看到,它這裡並沒有傳sampled_values,那麼它的負樣本是怎麼得到的呢?繼續看nce_loss的實現,可以看到裡面處理sampled_values=None的代碼如下:

    if sampled_values is None:
      sampled_values = candidate_sampling_ops.log_uniform_candidate_sampler(
          true_classes=labels,
          num_true=num_true,
          num_sampled=num_sampled,
          unique=True,
          range_max=num_classes)

所以,默認情況下,他會用log_uniform_candidate_sampler去採樣。那麼log_uniform_candidate_sampler是怎麼採樣的呢?他的實現在這裡:

他會在[0, range_max)中採樣出一個整數kP(k) = (log(k + 2) - log(k + 1)) / log(range_max + 1)

可以看到,k越大,被採樣到的概率越小。那麼在TF的word2vec裡,類別的編號有什麼含義嗎?看下面的代碼:

def build_dataset(words):
  count = [['UNK', -1]]
  count.extend(collections.Counter(words).most_common(vocabulary_size - 1))
  dictionary = dict()
  for word, _ in count:
    dictionary[word] = len(dictionary)
  data = list()
  unk_count = 0
  for word in words:
    if word in dictionary:
      index = dictionary[word]
    else:
      index = 0  # dictionary['UNK']
      unk_count += 1
    data.append(index)
  count[0][1] = unk_count
  reverse_dictionary = dict(zip(dictionary.values(), dictionary.keys()))
  return data, count, dictionary, reverse_dictionary

可以看到,TF的word2vec實現裡,詞頻越大,詞的類別編號也就越大。因此,在TF的word2vec裡,負採樣的過程其實就是優先採詞頻高的詞作為負樣本。

在提出負採樣的原始論文中, 包括word2vec的原始C++實現中。是按照熱門度的0.75次方採樣的,這個和TF的實現有所區別。但大概的意思差不多,就是越熱門,越有可能成為負樣本。

連結:https://www.jianshu.com/p/fab82fa53e16

下載1:四件套

在機器學習算法與自然語言處理公眾號後臺回復「四件套」

即可獲取學習TensorFlow,Pytorch,機器學習,深度學習四件套!


下載2:倉庫地址共享

在機器學習算法與自然語言處理公眾號後臺回復「代碼」

即可獲取195篇NAACL+295篇ACL2019有代碼開源的論文。開源地址如下:https://github.com/yizhen20133868/NLP-Conferences-Code

重磅!機器學習算法與自然語言處理交流群已正式成立

群內有大量資源,歡迎大家進群學習!

額外贈送福利資源!深度學習與神經網絡,pytorch官方中文教程,利用Python進行數據分析,機器學習學習筆記,pandas官方文檔中文版,effective java(中文版)等20項福利資源

獲取方式:進入群後點開群公告即可領取下載連結

注意:請大家添加時修改備註為 [學校/公司 + 姓名 + 方向]

例如 —— 哈工大+張三+對話系統。

號主,微商請自覺繞道。謝謝!

推薦閱讀:

工業界求解NER問題的12條黃金法則

三步搞定機器學習核心:矩陣求導

神經網絡中的蒸餾技術,從Softmax開始說起

相關焦點

  • [教程]一篇最簡單的NLP入門:在Python上構建Word2Vec詞嵌入模型(Tensorflow篇)
    在本例中,大部分代碼都是以這裡的 TensorFlow Word2Vec 教程(https://github.com/tensorflow/tensorflow/blob/r1.2/tensorflow/examples/tutorials/word2vec/word2vec_basic.py)為參考講解以這篇文章
  • 白話Word2Vec
    關於Hierarchical Softmax和Negative Sampling的原理細節(包含太多數學公式,白話不出來了,誰要能幫我把這部分講清楚,我請吃飯_)可參看以下文章:word2vec 代碼實現(1) – Skip gramhttps://link.jianshu.com/?
  • 同義詞詞向量訓練--python實現
    word2vec簡要介紹      word2vec 是 Google 於 2013 年開源推出的一個用於獲取 word vector 的工具包,它簡單、高效,因此引起了很多人的關注。對word2vec數學原理感興趣的可以移步word2vec 中的數學原理詳解,這裡就不具體介紹。
  • word2vec模型深度解析
    【前言】word2vec是一個被廣泛應用的word embedding方法,由於最近研究需要,將算法模型研究了一下由於word2vec內容很多,這裡儘量講解核心內容,有不足之處還請指出!word2vec是輕量級的神經網絡,其模型僅僅包括輸入層、隱藏層和輸出層,模型框架根據輸入輸出的不同,主要包括CBOW和skip-gram模型,CBOW模型是通過上下文的內容預測中間的目標詞,而skip-gram則相反,通過目標詞預測其上下文的詞,通過最大化詞出現的概率,我們訓練模型可得到各個層之間的權重矩陣,我們所說的得到的word embedding vector就是從這個權重矩陣裡面得來的。
  • TensorFlow練手 | 使用循環神經網絡(RNN)實現影評情感分類
    這裡我劃分成三份,訓練集、開發集和測試集的佔比為[0.8,0.1,0.1]。劃分的方式為輪盤賭法,在numpy中可以使用cumsum和searchsorted來簡潔地實現輪盤賭法。() for line in f_lines: tmp_vec = [str(utils.get_id_by_word(word, word2id)) for word in line.strip().split()] vec.append(tmp_vec) # 寫入文件中 with open(vec_path, 'w') as
  • 教程 | 用TensorFlow Estimator實現文本分類
    通過本文你將學到如何使用 word2vec 詞嵌入和遷移學習技術,在有標籤數據稀缺時獲得更好的模型性能。本文主要內容如下:本文選自介紹 TensorFlow 的 Datasets 和 Estimators 模塊系列博文的第四部分。
  • TensorFlow開發者證書 中文手冊
    2.0.0 和 tensorflow-datasets,conda install tensorflow==2.0.0,conda install tensorflow-datasets==1.3.2__version__)print(tf.test.is_gpu_available())print(tf.test.is_built_with_cuda())如果程序正常輸出了 版本號和2個True ,就代表 tensorflow-gpu 已經安裝成功。
  • 370頁《TensorFlow 機器學習方案手冊》(附 pdf 和完整代碼)
    #loss = tf.add(tf.reduce_mean(tf.square(y_target - model_output)), regularization_param)# Declare the Ridge loss function# Ridge loss = L2_loss + L2 norm of sloperidge_param = tf.constant
  • 詞向量詳解:從word2vec、glove、ELMo到BERT
    生成詞向量的方法有很多種,本文重點介紹word2vec,glove和bert。、fastText:優化效率高,但是基於局部語料glove:基於全局預料,結合了LSA和word2vec的優點elmo、GPT、bert:動態特徵從one-hot到word2vec到elmo,可以看到技術的演進總是在現有基礎上解決之前的問題,同時引出新的問題
  • 直觀理解並使用Tensorflow實現Seq2Seq模型的注意機制
    關於這類主題的文章通常涉及用於實現的大代碼段和來自多個庫的大量API調用,對概念本身沒有直觀的理解。在這方面,我們既要講求理論,也要講求執行。除了實現之外,我們還將詳細了解seq2seq體系結構和注意力的每個組件表示什麼。本文中使用的代碼可以在最後的資源列表中找到。
  • OpenCV+Tensorflow實現實時人臉識別演示
    FaceNet網絡設計目標任務有如下1.驗證-驗證是否為同一張臉2.識別-識別是否為同一個人3.聚類-發現人臉具有相同之處的人關於什麼是神經網絡嵌入,這個解釋比較複雜,簡單的說神經網絡的嵌入學習可以幫助我們把離散變量表示為連續的向量,在低維空間找到最近鄰,tensorflow中的word2vec就是用了嵌入。
  • 代碼+實戰:TensorFlow Estimator of Deep CTR——DeepFM/NFM/AFM/...
    loss------    loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=y, labels=labels)) + \        l2_reg * tf.nn.l2_loss(FM_W) + l2_reg * tf.nn.l2_loss(FM_V)    # Provide an
  • python代碼實戰 | 用 TensorFlow 實現序列標註:基於bi-LSTM+CRF和字符嵌入實現NER和POS
    我們來看看Tensorflow代碼。 回想一下,當 Tensorflow 接收批量的單詞和數據時,我們需要填充句子以使它們具有相同的長度。因此,我們需要定義2個佔位符:word_ids = tf.placeholder(tf.int32, shape=[None, None])sequence_lengths = tf.placeholder(tf.int32, shape=[None])現在,讓我們使用 tensorflow 內置函數來加載單詞嵌入
  • 教程 | 利用TensorFlow和神經網絡來處理文本分類問題
    它的高計算效率,豐富的開發資源使它被企業和個人開發者廣泛採用。在我看來,學習 TensorFlow 的最好的方法就是使用它的官網教程(https://www.tensorflow.org/)。在這個網站上,你可以瀏覽「getting started」教程。我首先將會對 TensorFlow 的基本定義和主要特徵進行介紹。
  • Tensorflow 全網最全學習資料匯總之Tensorflow 的入門與安裝【2】
    最終以一個手寫數字識別的實例將這些點串起來進行了具體說明。2.包括生成三維數據,然後用一個平面擬合它,以及通過 variable 實現一個簡單的計數器等。第三篇則實際上是基於史丹福大學基於深度學習的自然語言處理課程的學習筆記,該系列其他的文章還講述了循環神經網絡(RNN)和 word2vec 模型等更深入的知識,感興趣的讀者可以從文章的作者頁找到更多文章。上述文章都更傾向於 TensorFlow 的簡單介紹了基礎用法,但對於TensorFlow具體安裝過程的講述則不夠細緻。因此這裡專門針對TensorFlow的安裝過程推薦一篇教程。
  • 手把手教你如何用TensorFlow實現基於DNN的文本分類
    至於算法和函數內部的實現機制,可以等了解整個流程之後,在實踐中進行更深入的學習和掌握。那麼問題來了,既然作為初學者不需要掌握算法細節,但實現模型的過程中又必須用到相關算法,怎麼辦呢?答案是藉助於網際網路上已經實現好的函數庫,例如 TensorFlow。在本文中,我們將利用 TensorFlow 實現一個基於深度神經網絡(DNN)的文本分類模型,希望對各位初學者有所幫助。
  • 手把手教你NumPy來實現Word2vec
    超參數在進入word2vec的實現之前,讓我們先定義一些稍後需要用到的超參數。即使我們的詞彙量很小,我們仍然可以通過計算單詞之間的餘弦相似度來實現函數vec_sim 。本文是對Word2Vec的介紹,並解除了單詞嵌入(word embedding)的世界。另外還值得注意的是,有預訓練的嵌入可用,如GloVe、fastText和ELMo,你可以直接下載和使用。此外還有Word2Vec的擴展,如Doc2Vec和最近的Code2Vec,在這倆方法中文檔和代碼被轉換成向量。
  • 損失函數理解匯總,結合PyTorch1.7和TensorFlow2
    :返回loss和的平均值;sum:返回loss的和。[1] https://www.tensorflow.org/api_docs/python/tf/keras/losses/BinaryCrossentropy[2] https://www.tensorflow.org/api_docs/python/tf/keras/losses/binary_crossentropy[3] https://www.tensorflow.org
  • 從 Word2Vec 到 BERT
    在 word2vec 出現之前,一種簡單的對詞的表示是 One-hot 向量表示,即一個位置是 1,其餘位置都是 0,這種表示方法的最大缺點在於沒辦法表示出詞語之間的相似性。放出兩篇論文後,當時仍在谷歌工作的 Mikolov 又馬不停蹄的放出了大殺器——word2vec 工具,並在其中開源了他的方法。順便提一下的是,很多人以為 word2vec 是一種模型和方法,其實 word2vec 只是一個工具,背後的模型是 CBOW 或者 Skip-gram,並且使用了 Hierarchical Softmax 或者 Negative Sampling 這些訓練的優化方法。
  • 【綜述專欄】損失函數理解匯總,結合PyTorch和TensorFlow2
    不使用約簡;mean:返回loss和的平均值;sum:返回loss的和。外鏈地址:[1] https://www.tensorflow.org/api_docs/python/tf/keras/losses/BinaryCrossentropy[2] https://www.tensorflow.org/api_docs/python/tf/keras/losses/binary_crossentropy