同義詞詞向量訓練--python實現

2021-03-02 python制霸

Boblee人工智慧碩士畢業,擅長及愛好python,基於python研究人工智慧、群體智能、區塊鏈等技術,並使用python開發前後端、爬蟲等。

本文基於https://zhuanlan.zhihu.com/p/28979653進行修改。

word2vec簡要介紹

      word2vec 是 Google 於 2013 年開源推出的一個用於獲取 word vector 的工具包,它簡單、高效,因此引起了很多人的關注。對word2vec數學原理感興趣的可以移步word2vec 中的數學原理詳解,這裡就不具體介紹。word2vec對詞向量的訓練有兩種方式,一種是CBOW模型,即通過上下文來預測中心詞;另一種skip-Gram模型,即通過中心詞來預測上下文。其中CBOW對小型數據比較適合,而skip-Gram模型在大型的訓練語料中表現更好。

   2.  同義詞訓練

     本文基於哈工大提供的同義詞詞林進行訓練,數據集請見:      https://github.com/TernenceWind/replaceSynbycilin

     本文訓練採取以下步驟:

    1. 提取同義詞將所有詞組成一個列表,為構建詞頻統計,詞典及反轉詞典。因為計算機不能理解中文,我們必須把文字轉換成數值來替代。

   2.構建訓練集,每次隨機選擇一行同義詞,比如選取「人類、主人、全人類」這一行,輸入「人類」預測「主人」,輸入「主人」預測「全人類」。


3.python實現

初始化數據

from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionfrom random import choiceimport collectionsimport mathimport randomimport numpy as npfrom six.moves import xrangeimport tensorflow as tfdata = []all_word = []for line in open('cilin.txt', 'r', encoding='utf8'):    line =  line.replace('\n','').split(' ')[1:]            data.append(line)    for element in line:        if element not in all_word:            all_word.append(element)dictionary = [i for i in range(len(all_word))]reverse_dictionary_ = dict(zip(dictionary, all_word))reverse_dictionary = dict(zip(all_word, dictionary))

獲取訓練集

batch_size = 128embedding_size = 128skip_window = 1num_skips = 2valid_size = 4    valid_window = 100num_sampled = 64   vocabulary_size  =len(all_word)valid_word = ['專家','住戶','祖父','家鄉']valid_examples =[reverse_dictionary[li] for li in valid_word]def generate_batch(data,batch_size):    data_input = np.ndarray(shape=(batch_size), dtype=np.int32)    data_label = np.ndarray(shape=(batch_size, 1), dtype=np.int32)    for i in range(batch_size):        slice = random.sample( choice(data), 2)        data_input[i ] = reverse_dictionary[slice[0]]        data_label[i , 0] = reverse_dictionary[slice[1]]    return data_input, data_label

構建網絡

graph = tf.Graph()with graph.as_default():    train_inputs = tf.placeholder(tf.int32, shape=[batch_size])    train_labels = tf.placeholder(tf.int32, shape=[batch_size, 1])    valid_dataset = tf.constant(valid_examples, dtype=tf.int32)    with tf.device('/cpu:0'):        embeddings = tf.Variable(            tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))        embed = tf.nn.embedding_lookup(embeddings, train_inputs)        nce_weights = tf.Variable(            tf.truncated_normal([vocabulary_size, embedding_size],                                stddev=1.0 / math.sqrt(embedding_size)))        nce_biases = tf.Variable(tf.zeros([vocabulary_size]),dtype=tf.float32)    loss = tf.reduce_mean(tf.nn.nce_loss(weights=nce_weights,                                         biases=nce_biases,                                         inputs=embed,                                         labels=train_labels,                                         num_sampled=num_sampled,                                         num_classes=vocabulary_size))    optimizer = tf.train.GradientDescentOptimizer(1.0).minimize(loss)    norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keep_dims=True))    normalized_embeddings = embeddings / norm    valid_embeddings = tf.nn.embedding_lookup(normalized_embeddings, valid_dataset)    similarity = tf.matmul(valid_embeddings, normalized_embeddings, transpose_b=True)    init = tf.global_variables_initializer()

開始訓練

num_steps = 2000000with tf.Session(graph=graph) as session:        init.run()    print("Initialized")    average_loss = 0    for step in xrange(num_steps):        batch_inputs, batch_labels = generate_batch(data,batch_size)        feed_dict = {train_inputs: batch_inputs, train_labels: batch_labels}                        _, loss_val = session.run([optimizer, loss], feed_dict=feed_dict)        average_loss += loss_val        if step % 2000 == 0:            if step > 0:                average_loss /= 2000                        print("Average loss at step ", step, ": ", average_loss)            average_loss = 0                if step % 10000 == 0:            sim = similarity.eval()            for i in xrange(valid_size):                print(valid_examples[i])                valid_word = reverse_dictionary_[valid_examples[i]]                top_k = 8                  nearest = (-sim[i, :]).argsort()[:top_k]                log_str = "Nearest to %s:" % valid_word                for k in xrange(top_k):                    close_word = reverse_dictionary_[nearest[k]]                    log_str = "%s %s," % (log_str, close_word)                print(log_str)    final_embeddings = normalized_embeddings.eval()    np.save('tongyi.npy',final_embeddings)

可視化

def plot_with_labels(low_dim_embs, labels, filename='images/tsne3.png',fonts=None):    assert low_dim_embs.shape[0] >= len(labels), "More labels than embeddings"    plt.figure(figsize=(15, 15))      for i, label in enumerate(labels):        x, y = low_dim_embs[i, :]        plt.scatter(x, y)        plt.annotate(label,                    fontproperties=fonts,                    xy=(x, y),                    xytext=(5, 2),                    textcoords='offset points',                    ha='right',                    va='bottom')
plt.savefig(filename,dpi=800)
try: from sklearn.manifold import TSNE import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties font = FontProperties(fname=r"simhei.ttf", size=14)
tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000) plot_only = 100 low_dim_embs = tsne.fit_transform(final_embeddings[:plot_only, :]) labels = [reverse_dictionary_[i] for i in xrange(plot_only)] plot_with_labels(low_dim_embs, labels,fonts=font)except ImportError: print("Please install sklearn, matplotlib, and scipy to visualize embeddings.")

4.實驗結果

訓練結果

從圖中可見 同義詞基本訓練出來了。

5.結語

     本文基於前人的基礎上實現了同義詞詞向量生成,下一步就可以用於nlp文本處理了。

相關焦點

  • Chinese Word Vectors:目前最全的中文預訓練詞向量集合
    在這裡,你可以輕鬆獲得具有不同屬性的預訓練向量,並將它們用於各類下遊任務。此外,開發者還在該工具中提供了一個中文類比推理數據集 CA8 及其評估工具包,用戶可以以此評估自己詞向量的質量。格式本資源中的預訓練詞向量文件以文本格式存儲。
  • 資源 | Chinese Word Vectors:目前最全的中文預訓練詞向量集合
    項目連結:https://github.com/Embedding/Chinese-Word-Vectors該項目提供使用不同表徵(稀疏和密集)、上下文特徵(單詞、n-gram、字符等)以及語料庫訓練的中文詞向量(嵌入)。在這裡,你可以輕鬆獲得具有不同屬性的預訓練向量,並將它們用於各類下遊任務。
  • 機器也能自主區分反義詞-同義詞 ?!
    在性能方面,這些經過調整的向量表示法在很大程度上超過了標準的向量模型,實現了跨詞類(形容詞,名字,動詞)區分反義詞與同義詞這兩種語義關係,平均精確度達到0.66-0.76。此外,我們把詞彙對比向量整合入基於skip-gram模型的目標函數中。該新型向量表示法在運用SimLex-999預測詞彙相似度與區分反-同義詞兩個方面均優於state-of-the-art模型。
  • 預訓練好的詞向量資源
    詞向量是用來表示詞的向量,通常也被認為是詞的特徵向量。現在已經成為自然語言處理的基礎技術。詞向量的好壞,會直接影響模型的實驗結果,對於沒有GPU資源的人來,訓練詞向量是一個很消耗時間的過程,訓練好的詞向量還不一定好。所以,本文列舉出一些公開的訓練好的詞向量資源連結。
  • 詞向量背後精妙的數學
    為了方便後面論述,我們稱「寵物、擼、可愛、動物」等與「貓」一起出現的詞為「貓的上下文」。貓則是「目標詞」。這個時候,如果我們給貓、狗各一個向量,並要求用這個向量預測它們的上下文,就是所謂的skip-gram算法。由於它們的上下文幾乎一樣,所以作為輸入的詞向量也會幾乎一樣。這樣,我們就實現了一個重要的目標:上下文相似的幾個詞語,它們的詞向量也相似。
  • ACL 2018資源:100+ 預訓練的中文詞向量
    本項目提供了一些用不同語言表示(密集的、稀疏的)、上下文特徵(單詞、n-gram、字符等)和語料庫訓練好的中文詞向量(嵌入),有需要的開發者可以把這些具有不同屬性的預訓練數據用於各類下遊任務。此外,我們也提供了一個中文類比推理數據集CA8和評估工具包,用戶可以用它們來評估詞向量的質量。預訓練數據的格式是文本文檔,文檔的每一行包含一個詞語和對應向量。
  • 【NLP筆記】理論與實踐詳解詞向量
    這裡我們可以查看到,向量的維度太大我們通過將每個詞語獨熱碼話,我們會發現一個問題,就是沒有相似性概念了。結論: 簡單one-hot向量無法給出單詞間的相似性,我們需要將維度減少到一個低維度的子空間,來獲得稠密的詞向量,獲得詞之間關係SVD Based Methodssvd的原理類似於主成分分析,但是主成分分析只能針對方陣,而svd可以針對所有矩陣進行我這裡不詳細
  • NLP基礎|中英文詞向量評測理論與實踐
    最近在做詞向量相關工作,訓練的詞向量如何進行評測?V詞向量評測腳本,方便大家使用。這個任務的目的是評估詞向量模型在兩個詞之間的語義緊密度和相關性的能力,例如男人與女人,男孩與女孩,中國與北京這些詞對之間的相似度。
  • 詞向量模型解讀
    這個向量的維度是詞表大小,向量中只有一個維度的值為1,其餘維度為0,這個維度就代表了當前的詞。例如:蘋果 [0,0,0,1,0,0,0,0,0,……]One-Hot缺點:(1)每個詞對應一個長度為N的向量,容易受維度災難困擾。
  • 動態詞向量算法—ELMo
    傳統的詞向量模型,例如 Word2Vec 和 Glove 學習得到的詞向量是固定不變的,即一個單詞只有一種詞向量,顯然不適合用於多義詞。而 ELMo 算法使用了深度雙向語言模型 (biLM),只訓練語言模型,而單詞的詞向量是在輸入句子實時獲得的,因此詞向量與上下文信息密切相關,可以較好地區分歧義。
  • 基於PaddlePaddle的詞向量實戰 | 深度學習基礎任務教程系列
    ;  在這個映射到的實數向量表示中,兩個語義 (或用法) 上相似的詞對應的詞向量「更像」,這樣如「母親節」和「康乃馨」的對應詞向量的餘弦相似度就不再為零了。  詞向量模型可以是概率模型、共生矩陣 (co-occurrence matrix) 模型或神經元網絡模型。
  • Hello NLP(1)——詞向量Why&How
    但是,對於人工智慧的徵途來說,NLP才是皇冠上的那顆珍珠,NLP是AI完全問題,當NLP的問題解決了,機器才真正具備了理解、思考的能力,我們才敢說實現了真正的「智能」。從今天起,我們一起來學習詞向量word2vector(簡稱w2v)相關的知識。雖然,對於NLP來說,w2v技術和操作已經爛大街了,隨便一個NLP任務,底層基本都要搞一個w2v,但是到底為什麼需要w2v,它背後的思想是什麼,是怎麼訓練得到的,也許很多經常使用w2v的人都不一定很清楚。不清楚,就會導致我們知道w2v很好用很神奇,但是出了問題卻不知道從哪裡去改善。
  • Word2vec如何得到詞向量
    得到你想要的processed corpus之後,將他們的one-hot向量作為word2vec的輸入,通過word2vec訓練低維詞向量(word embedding)就ok了。不得不說word2vec是個很棒的工具,目前有兩種訓練模型(CBOW和Skip-gram),兩種加速算法(Negative Sample與Hierarchical Softmax)。
  • 手把手教你PaddlePaddle 做詞向量模型 SkipGram實戰
    得到詞向量副產品;今天要講解的就是 SkipGram 模型就屬於第三種方法,它的主要思想是利用的詞義的分布式表示。我們還會詳細的說明如何一步步的用 PaddlePaddle 實現它。1、什麼是詞向量首先我們需要了解什麼是詞向量。NLP 和圖像不太一樣,圖像的輸入本身就是一個有數值特徵的矩陣,而 NLP 的輸入通常只是一堆自然語言的符號,它們本身是不具備數學特性的。因此,在計算語言學中,我們通常會希望用數值向量來表示這些符號。
  • 手把手教你用飛槳做詞向量模型 SkipGram
    我們還會詳細的說明如何一步步的用飛槳(PaddlePaddle)實現它。1.什麼是詞向量首先我們需要了解什麼是詞向量。這種強調中心詞的結構對某些具有較低頻率的生僻詞比較友好,因此低頻詞也可以學到質量較高的向量表示;但可能是因為 CBOW 的結構相對簡單些,經驗顯示,CBOW 的訓練速度要比 SkipGram 快的多,因此兩者其實各有優勢。
  • 詞向量因何存在:一段往計算機輸入文字的歷史
    理性主義告訴我們,人類(尤其是受過人類語言科學方面訓練的人)會知道這些相似性信息,我們可以設計數據結構顯式地對其進行編碼,讓我們的程序在需要時訪問這些信息。一個代表性的工作是 WordNet,它使用 13 個詞法資料庫存儲單詞及其之間的關係(例如,同義:兩個單詞意味著同樣的事情;上下位關係:一個詞的意思是另一個詞更加具象化的表現)。
  • 基於PaddlePaddle的詞向量實戰 | 深度學習基礎任務教程系列(二)
    ;在這個映射到的實數向量表示中,兩個語義(或用法)上相似的詞對應的詞向量「更像」,這樣如「母親節」和「康乃馨」的對應詞向量的餘弦相似度就不再為零了。詞向量模型可以是概率模型、共生矩陣(co-occurrence matrix)模型或神經元網絡模型。在用神經網絡模型求詞向量之前,傳統的做法是統計一個詞語的共生矩陣X,在對X做矩陣分解,得到了所有詞的詞向量。
  • 詞向量學習算法 Word2Vec
    Word2Vec 是 google 在2013年提出的詞向量模型,通過 Word2Vec 可以用數值向量表示單詞,且在向量空間中可以很好地衡量兩個單詞的相似性。 1.
  • 乾貨 | Word2Vec是如何得到詞向量的?
    得到你想要的processed corpus之後,將他們的one-hot向量作為word2vec的輸入,通過word2vec訓練低維詞向量(word embedding)就ok了。不得不說word2vec是個很棒的工具,目前有兩種訓練模型(CBOW和Skip-gram),兩種加速算法(Negative Sample與Hierarchical Softmax)。
  • NLP·一、詞向量Word Embedding(一)
    一、詞嵌入/詞向量為什麼可行一句話概括就是:一個詞的語義由其上下文的單詞決定。