<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 使用 Skip-Gram 嵌入 在之前的秘籍中,我們在訓練模型之前決定了我們的文本嵌入。使用神經網絡,我們可以使嵌入值成為訓練過程的一部分。我們將探索的第一個這樣的方法叫做 Skip-Gram 嵌入。 ## 做好準備 在此秘籍之前,我們沒有考慮與創建單詞嵌入相關的單詞順序。 2013 年初,Tomas Mikolov 和谷歌的其他研究人員撰寫了一篇關于創建解決這個問題的單詞嵌入的論文( [https://arxiv.org/abs/1301.3781](https://arxiv.org/abs/1301.3781) ),他們將他們的方法命名為 word2vec。 基本思想是創建捕獲單詞關系方面的單詞嵌入。我們試圖了解各種單詞如何相互關聯。這些嵌入可能如何表現的一些示例如下: `king - man + woman = queen` `India pale ale - hops + malt = stout` 如果我們只考慮它們之間的位置關系,我們可能會實現這樣的數字表示。如果我們能夠分析足夠大的相關文檔來源,我們可能會發現在我們的文本中,`king`,`man`和`queen`這兩個詞在彼此之間相互提及。如果我們也知道`man`和`woman`以不同的方式相關,那么我們可以得出結論,`man`是`king`,因為`woman`是`queen`,依此類推。 為了找到這樣的嵌入,我們將使用一個神經網絡來預測給定輸入字的周圍單詞。我們可以輕松地切換它并嘗試在給定一組周圍單詞的情況下預測目標單詞,但我們將從前面的方法開始。兩者都是 word2vec 過程的變體,但是從目標詞預測周圍詞(上下文)的前述方法稱為 Skip-Gram 模型。在下一個秘籍中,我們將實現另一個方法,從上下文預測目標詞,這稱為連續詞袋方法(CBOW): ![](https://img.kancloud.cn/be/a7/bea739abe908d7fbaa904fb98e0beb21_867x663.png) 圖 4:word2vec 的 Skip-Gram 實現的圖示。 Skip-Gram 預測目標詞的上下文窗口(每側窗口大小為 1)。 對于這個秘籍,我們將在康奈爾大學的一組電影評論數據上實現 Skip-Gram 模型( [http://www.cs.cornell.edu/people/pabo/movie-review-data/](http://www.cs.cornell.edu/people/pabo/movie-review-data/) ])。 word2vec 的 CBOW 方法將在下一個秘籍中實現。 ## 操作步驟 對于這個秘籍,我們將創建幾個輔助函數。這些函數將加載數據,正則化文本,生成詞匯表并生成數據批量。只有在這之后我們才開始訓練我們的單詞嵌入。為了清楚起見,我們不是預測任何目標變量,而是我們將擬合單詞嵌入: 1. 首先,我們將加載必要的庫并啟動圖會話: ```py import tensorflow as tf import matplotlib.pyplot as plt import numpy as np import random import os import string import requests import collections import io import tarfile import urllib.request from nltk.corpus import stopwords sess = tf.Session() ``` 1. 然后我們聲明一些模型參數。我們將一次查看 50 對單詞嵌入(批量大小)。每個單詞的嵌入大小將是一個長度為 200 的向量,我們只考慮 10,000 個最常用的單詞(每隔一個單詞將被歸類為未知單詞)。我們將訓練 5 萬代,并每 500 代打印一次。然后我們將聲明一個我們將在 loss 函數中使用的`num_sampled`變量(我們將在后面解釋),并且我們還聲明了我們的 Skip-Gram 窗口大小。在這里,我們將窗口大小設置為 2,因此我們將查看目標每側的周圍兩個單詞。我們將通過名為`nltk`的 Python 包設置我們的停用詞。我們還想要一種方法來檢查我們的單詞嵌入是如何執行的,因此我們將選擇一些常見的電影評論單詞并從每 2,000 次迭代中打印出最近的鄰居單詞: ```py batch_size = 50 embedding_size = 200 vocabulary_size = 10000 generations = 50000 print_loss_every = 500 num_sampled = int(batch_size/2) window_size = 2 stops = stopwords.words('english') print_valid_every = 2000 valid_words = ['cliche', 'love', 'hate', 'silly', 'sad'] ``` 1. 接下來,我們將聲明我們的數據加載函數,該函數會檢查以確保在下載之前我們沒有下載數據。否則,如果之前保存了數據,它將從磁盤加載數據。使用以下代碼執行此操作: ```py def load_movie_data(): save_folder_name = 'temp' pos_file = os.path.join(save_folder_name, 'rt-polarity.pos') neg_file = os.path.join(save_folder_name, 'rt-polarity.neg') # Check if files are already downloaded if os.path.exists(save_folder_name): pos_data = [] with open(pos_file, 'r') as temp_pos_file: for row in temp_pos_file: pos_data.append(row) neg_data = [] with open(neg_file, 'r') as temp_neg_file: for row in temp_neg_file: neg_data.append(row) else: # If not downloaded, download and save movie_data_url = 'http://www.cs.cornell.edu/people/pabo/movie-review-data/rt-polaritydata.tar.gz' stream_data = urllib.request.urlopen(movie_data_url) tmp = io.BytesIO() while True: s = stream_data.read(16384) if not s: break tmp.write(s) stream_data.close() tmp.seek(0) tar_file = tarfile.open(fileobj=tmp, mode='r:gz') pos = tar_file.extractfile('rt-polaritydata/rt-polarity.pos') neg = tar_file.extractfile('rt-polaritydata/rt-polarity.neg') # Save pos/neg reviews pos_data = [] for line in pos: pos_data.append(line.decode('ISO-8859-1').encode('ascii',errors='ignore').decode()) neg_data = [] for line in neg: neg_data.append(line.decode('ISO-8859-1').encode('ascii',errors='ignore').decode()) tar_file.close() # Write to file if not os.path.exists(save_folder_name): os.makedirs(save_folder_name) # Save files with open(pos_file, 'w') as pos_file_handler: pos_file_handler.write(''.join(pos_data)) with open(neg_file, 'w') as neg_file_handler: neg_file_handler.write(''.join(neg_data)) texts = pos_data + neg_data target = [1]*len(pos_data) + [0]*len(neg_data) return(texts, target) texts, target = load_movie_data() ``` 1. 接下來,我們將為文本創建正則化函數。此函數將輸入字符串列表并使其為小寫,刪除標點,刪除數字,刪除額外的空格,并刪除停用詞。使用以下代碼執行此操作: ```py def normalize_text(texts, stops): # Lower case texts = [x.lower() for x in texts] # Remove punctuation texts = [''.join(c for c in x if c not in string.punctuation) for x in texts] # Remove numbers texts = [''.join(c for c in x if c not in '0123456789') for x in texts] # Remove stopwords texts = [' '.join([word for word in x.split() if word not in (stops)]) for x in texts] # Trim extra whitespace texts = [' '.join(x.split()) for x in texts] return(texts) texts = normalize_text(texts, stops) ``` 1. 為了確保我們所有的電影評論都能提供信息,我們應該確保它們足夠長,以包含重要的單詞關系。我們會隨意將其設置為三個或更多單詞: ```py target = [target[ix] for ix, x in enumerate(texts) if len(x.split()) > 2] texts = [x for x in texts if len(x.split()) > 2] ``` 1. 為了構建我們的詞匯表,我們將創建一個函數來創建一個帶有計數的單詞字典。任何不常見的詞都不會使我們的詞匯量大小被截止,將被標記為`RARE`。使用以下代碼執行此操作: ```py def build_dictionary(sentences, vocabulary_size): # Turn sentences (list of strings) into lists of words split_sentences = [s.split() for s in sentences] words = [x for sublist in split_sentences for x in sublist] # Initialize list of [word, word_count] for each word, starting with unknown count = [['RARE', -1]] # Now add most frequent words, limited to the N-most frequent (N=vocabulary size) count.extend(collections.Counter(words).most_common(vocabulary_size-1)) # Now create the dictionary word_dict = {} # For each word, that we want in the dictionary, add it, then make it the value of the prior dictionary length for word, word_count in count: word_dict[word] = len(word_dict) return(word_dict) ``` 1. 我們需要一個函數將一個句子列表轉換為單詞索引列表,我們可以將它們傳遞給嵌入查找函數。使用以下代碼執行此操作: ```py def text_to_numbers(sentences, word_dict): # Initialize the returned data data = [] for sentence in sentences: sentence_data = [] # For each word, either use selected index or rare word index for word in sentence: if word in word_dict: word_ix = word_dict[word] else: word_ix = 0 sentence_data.append(word_ix) data.append(sentence_data) return data ``` 1. 現在我們可以實際創建我們的字典并將我們的句子列表轉換為單詞索引列表: ```py word_dictionary = build_dictionary(texts, vocabulary_size) word_dictionary_rev = dict(zip(word_dictionary.values(), word_dictionary.keys())) text_data = text_to_numbers(texts, word_dictionary) ``` 1. 從前面的單詞字典中,我們可以查找我們在步驟 2 中選擇的驗證字的索引。使用以下代碼執行此操作: ```py valid_examples = [word_dictionary[x] for x in valid_words] ``` 1. 我們現在將創建一個將返回 Skip-Gram 批次的函數。我們想訓練一對單詞,其中一個單詞是訓練輸入(來自我們窗口中心的目標單詞),另一個單詞是從窗口中選擇的。例如,句子`the cat in the hat`可能導致(輸入,輸出)對,如下所示:(`the`,`in`),(`cat`,`in`),(`the`,`in` ),(`hat`,`in`)如果是目標詞,我們每個方向的窗口大小為 2: ```py def generate_batch_data(sentences, batch_size, window_size, method='skip_gram'): # Fill up data batch batch_data = [] label_data = [] while len(batch_data) < batch_size: # select random sentence to start rand_sentence = np.random.choice(sentences) # Generate consecutive windows to look at window_sequences = [rand_sentence[max((ix-window_size),0):(ix+window_size+1)] for ix, x in enumerate(rand_sentence)] # Denote which element of each window is the center word of interest label_indices = [ix if ix<window_size else window_size for ix,x in enumerate(window_sequences)] # Pull out center word of interest for each window and create a tuple for each window if method=='skip_gram': batch_and_labels = [(x[y], x[:y] + x[(y+1):]) for x,y in zip(window_sequences, label_indices)] # Make it in to a big list of tuples (target word, surrounding word) tuple_data = [(x, y_) for x,y in batch_and_labels for y_ in y] else: raise ValueError('Method {} not implmented yet.'.format(method)) # extract batch and labels batch, labels = [list(x) for x in zip(*tuple_data)] batch_data.extend(batch[:batch_size]) label_data.extend(labels[:batch_size]) # Trim batch and label at the end batch_data = batch_data[:batch_size] label_data = label_data[:batch_size] # Convert to numpy array batch_data = np.array(batch_data) label_data = np.transpose(np.array([label_data])) return batch_data, label_data ``` 1. 我們現在可以初始化嵌入矩陣,聲明占位符,并初始化嵌入查找函數。使用以下代碼執行此操作: ```py embeddings = tf.Variable(tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0)) # Create data/target placeholders x_inputs = tf.placeholder(tf.int32, shape=[batch_size]) y_target = tf.placeholder(tf.int32, shape=[batch_size, 1]) valid_dataset = tf.constant(valid_examples, dtype=tf.int32) # Lookup the word embedding: embed = tf.nn.embedding_lookup(embeddings, x_inputs) ``` 1. 損失函數應該是諸如`softmax`之類的東西,它計算預測錯誤單詞類別時的損失。但由于我們的目標有 10,000 個不同的類別,因此非常稀疏。這種稀疏性導致關于模型的擬合或收斂的問題。為了解決這個問題,我們將使用稱為噪聲對比誤差的損失函數。這種 NCE 損失函數通過預測單詞類與隨機噪聲預測將我們的問題轉化為二元預測。 `num_sampled`參數指定批量變成隨機噪聲的程度: ```py nce_weights = tf.Variable(tf.truncated_normal([vocabulary_size, embedding_size], stddev=1.0 / np.sqrt(embedding_size))) nce_biases = tf.Variable(tf.zeros([vocabulary_size])) loss = tf.reduce_mean(tf.nn.nce_loss(weights=nce_weights, biases=nce_biases, inputs=embed, labels=y_target, num_sampled=num_sampled, num_classes=vocabulary_size)) ``` 1. 現在我們需要創建一種方法來查找附近的單詞到我們的驗證單詞。我們將通過計算驗證集和所有單詞嵌入之間的余弦相似性來完成此操作,然后我們可以為每個驗證字打印出最接近的單詞集。使用以下代碼執行此操作: ```py norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keepdims=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) ``` 1. 我們現在聲明我們的優化函數并初始化我們的模型變量: ```py optimizer = tf.train.GradientDescentOptimizer(learning_rate=1.0).minimize(loss) init = tf.global_variables_initializer() sess.run(init) ``` 1. 現在我們可以訓練我們的嵌入并在訓練期間打印損失和最接近我們驗證集的單詞。使用以下代碼執行此操作: ```py loss_vec = [] loss_x_vec = [] for i in range(generations): batch_inputs, batch_labels = generate_batch_data(text_data, batch_size, window_size) feed_dict = {x_inputs : batch_inputs, y_target : batch_labels} # Run the train step sess.run(optimizer, feed_dict=feed_dict) # Return the loss if (i+1) % print_loss_every == 0: loss_val = sess.run(loss, feed_dict=feed_dict) loss_vec.append(loss_val) loss_x_vec.append(i+1) print("Loss at step {} : {}".format(i+1, loss_val)) # Validation: Print some random words and top 5 related words if (i+1) % print_valid_every == 0: sim = sess.run(similarity, feed_dict=feed_dict) for j in range(len(valid_words)): valid_word = word_dictionary_rev[valid_examples[j]] top_k = 5 # number of nearest neighbors nearest = (-sim[j, :]).argsort()[1:top_k+1] log_str = "Nearest to {}:".format(valid_word) for k in range(top_k): close_word = word_dictionary_rev[nearest[k]] log_str = "%s %s," % (log_str, close_word) print(log_str) ``` > 在前面的代碼中,我們在調用`argsort`方法之前采用相似矩陣的否定。我們這樣做是因為我們想要找到從最高相似度值到最低相似度值的索引,而不是相反。 1. 這導致以下輸出: ```py Loss at step 500 : 13.387781143188477 Loss at step 1000 : 7.240757465362549 Loss at step 49500 : 0.9395825862884521 Loss at step 50000 : 0.30323168635368347 Nearest to cliche: walk, intrigue, brim, eileen, dumber, Nearest to love: plight, fiction, complete, lady, bartleby, Nearest to hate: style, throws, players, fearlessness, astringent, Nearest to silly: delivers, meow, regain, nicely, anger, Nearest to sad: dizzying, variety, existing, environment, tunney, ``` ## 工作原理 我們通過`Skip-Gram`方法在電影評論數據集上訓練了一個 word2vec 模型。我們下載了數據,將單詞轉換為帶有字典的索引,并將這些索引號用作嵌入查找,我們對其進行了訓練,以便附近的單詞可以相互預測。 ## 更多 乍一看,我們可能期望驗證集的附近單詞集合是同義詞。事實并非如此,因為很少有同義詞實際上在句子中彼此相鄰。我們真正得到的是預測我們的數據集中哪些單詞彼此接近。我們希望使用這樣的嵌入將使預測更容易。 為了使用這些嵌入,我們必須使它們可重用并保存它們。我們將通過實現 CBOW 嵌入在下一個秘籍中執行此操作。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看