偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

使用TENSORFLOW訓練循環(huán)神經(jīng)網(wǎng)絡(luò)語言模型

人工智能 深度學習
Language Model,即語言模型,其主要思想是,在知道前一部分的詞的情況下,推斷出下一個最有可能出現(xiàn)的詞。在本文中,我們更加關(guān)注的是,如何使用RNN來推測下一個詞。

讀了將近一個下午的TensorFlow Recurrent Neural Network教程,翻看其在PTB上的實現(xiàn),感覺晦澀難懂,因此參考了部分代碼,自己寫了一個簡化版的Language Model,思路借鑒了Keras的LSTM text generation。

代碼地址:Github

轉(zhuǎn)載請注明出處:Gaussic

語言模型

Language Model,即語言模型,其主要思想是,在知道前一部分的詞的情況下,推斷出下一個最有可能出現(xiàn)的詞。例如,知道了 The fat cat sat on the,我們認為下一個詞為mat的可能性比hat要大,因為貓更有可能坐在毯子上,而不是帽子上。

這可能被你認為是常識,但是在自然語言處理中,這個任務(wù)是可以用概率統(tǒng)計模型來描述的。就拿The fat cat sat on the mat來說。我們可能統(tǒng)計出第一個詞The出現(xiàn)的概率p(The)p(The),The后面是fat的條件概率為p(fat|The)p(fat|The),The fat同時出現(xiàn)的聯(lián)合概率:

  1. p(The,fat)=p(The)⋅p(fat|The)p(The,fat)=p(The)·p(fat|The) 
這個聯(lián)合概率,就是The fat的合理性,即這句話的出現(xiàn)符不符合自然語言的評判標準,通俗點表述就是這是不是句人話。同理,根據(jù)鏈式規(guī)則,The fat cat的聯(lián)合概率可求:
 
  1. p(The,fat,cat)=p(The)⋅p(fat|The)⋅p(cat|The,fat)p(The,fat,cat)=p(The)·p(fat|The)·p(cat|The,fat) 
在知道前面的詞為The cat的情況下,下一個詞為cat的概率可以推導(dǎo)出來:
 
  1. p(cat|The,fat)=p(The,fat,cat)p(The,fat)p(cat|The,fat)=p(The,fat,cat)p(The,fat) 
分子是The fat cat在語料庫中出現(xiàn)的次數(shù),分母是The fat在語料庫中出現(xiàn)的次數(shù)。
因此,The fat cat sat on the mat整個句子的合理性同樣可以推導(dǎo),這個句子的合理性即為它的概率。公式化的描述如下:
 
  1. p(S)=p(w1,w2,⋅⋅⋅,wn)=p(w1)⋅p(w2|w1)⋅p(w3|w1,w2)⋅⋅⋅p(wn|w1,w2,w3,⋅⋅⋅,wn−1)p(S)=p(w1,w2,···,wn)=p(w1)·p(w2|w1)·p(w3|w1,w2)···p(wn|w1,w2,w3,···,wn−1) 
(公式后的n-1應(yīng)該為下標,插件問題,下同)
 
可以看出一個問題,每當計算下一個詞的條件概率,需要計算前面所有詞的聯(lián)合概率。這個計算量相當?shù)凝嫶?。并且,一個句子中大部分詞同時出現(xiàn)的概率往往少之又少,數(shù)據(jù)稀疏非常嚴重,需要一個非常大的語料庫來訓練。
 
一個簡單的優(yōu)化是基于馬爾科夫假設(shè),下一個詞的出現(xiàn)僅與前面的一個或n個詞有關(guān)。
 
最簡單的情況,下一個詞的出現(xiàn)僅僅和前面一個詞有關(guān),稱之為bigram。
 
  1. p(S)=p(w1,w2,⋅⋅⋅,wn)=p(w1)⋅p(w2|w1)⋅p(w3|w2)⋅p(w4|w3)⋅⋅⋅p(wn|wn−1)p(S)=p(w1,w2,···,wn)=p(w1)·p(w2|w1)·p(w3|w2)·p(w4|w3)···p(wn|wn−1) 
再復(fù)雜點,下一個詞的出現(xiàn)僅和前面兩個詞有關(guān),稱之為trigram。
 
  1. p(S)=p(w1,w2,⋅⋅⋅,wn)=p(w1)⋅p(w2|w1)⋅p(w3|w1,w2)⋅p(w4|w2,w3)⋅⋅⋅p(wn|wn−2,wn−1)p(S)=p(w1,w2,···,wn)=p(w1)·p(w2|w1)·p(w3|w1,w2)·p(w4|w2,w3)···p(wn|wn−2,wn−1) 

這樣的條件概率雖然好求,但是會丟失大量的前面的詞的信息,有時會對結(jié)果產(chǎn)生不良影響。因此如何選擇一個有效的n,使得既能簡化計算,又能保留大部分的上下文信息。

以上均是傳統(tǒng)語言模型的描述。如果不太深究細節(jié),我們的任務(wù)就是,知道前面n個詞,來計算下一個詞出現(xiàn)的概率。并且使用語言模型來生成新的文本。

在本文中,我們更加關(guān)注的是,如何使用RNN來推測下一個詞。

數(shù)據(jù)準備
 
TensorFlow的官方文檔使用的是Mikolov準備好的PTB數(shù)據(jù)集。我們可以將其下載并解壓出來:
 
  1. $ wget http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz 
  2. $ tar xvf simple-examples.tgz 
部分數(shù)據(jù)如下,不常用的詞轉(zhuǎn)換成了<unk>標記,數(shù)字轉(zhuǎn)換成了N:
 
  1. we 're talking about years ago before anyone heard of asbestos having any questionable properties 
  2. there is no asbestos in our products now 
  3. neither <unk> nor the researchers who studied the workers were aware of any research on smokers of the kent cigarettes 
  4. we have no useful information on whether users are at risk said james a. <unk> of boston 's <unk> cancer institute 
  5. the total of N deaths from malignant <unk> lung cancer and <unk> was far higher than expected the researchers said 
讀取文件中的數(shù)據(jù),將換行符轉(zhuǎn)換為<eos>,然后轉(zhuǎn)換為詞的list:
 
  1. def _read_words(filename): 
  2.     with open(filename, 'r', encoding='utf-8'as f: 
  3.         return f.read().replace('\n''<eos>').split() 
  1. f = _read_words('simple-examples/data/ptb.train.txt'
  2. print(f[:20]) 
得到:
 
  1. ['aer''banknote''berlitz''calloway''centrust''cluett''fromstein''gitano''guterman''hydro-quebec''ipo''kia''memotec''mlx''nahb''punts''rake''regatta''rubens''sim'
構(gòu)建詞匯表,詞與id互轉(zhuǎn):
 
  1. def _build_vocab(filename): 
  2.     data = _read_words(filename) 
  3.  
  4.     counter = Counter(data) 
  5.     count_pairs = sorted(counter.items(), key=lambda x: -x[1]) 
  6.  
  7.     words, _ = list(zip(*count_pairs)) 
  8.     word_to_id = dict(zip(words, range(len(words)))) 
  9.  
  10.     return words, word_to_id 
  1. words, words_to_id = _build_vocab('simple-examples/data/ptb.train.txt'
  2. print(words[:10]) 
  3. print(list(map(lambda x: words_to_id[x], words[:10]))) 
輸出:
 
  1. ('the''<unk>''<eos>''N''of''to''a''in''and'"'s"
  2. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
將一個文件轉(zhuǎn)換為id表示:
 
  1. def _file_to_word_ids(filename, word_to_id): 
  2.     data = _read_words(filename) 
  3.     return [word_to_id[x] for x in data if x in word_to_id] 
  1. words_in_file = _file_to_word_ids('simple-examples/data/ptb.train.txt', words_to_id) 
  2. print(words_in_file[:20]) 
詞匯表已根據(jù)詞頻進行排序,由于第一句話非英文,所以id靠后。
 
  1. [9980, 9988, 9981, 9989, 9970, 9998, 9971, 9979, 9992, 9997, 9982, 9972, 9993, 9991, 9978, 9983, 9974, 9986, 9999, 9990] 
將一句話從id列表轉(zhuǎn)換回詞:
 
  1. def to_words(sentence, words): 
  2.     return list(map(lambda x: words[x], sentence)) 
將以上函數(shù)整合:
 
  1. def ptb_raw_data(data_path=None): 
  2.     train_path = os.path.join(data_path, 'ptb.train.txt'
  3.     valid_path = os.path.join(data_path, 'ptb.valid.txt'
  4.     test_path = os.path.join(data_path, 'ptb.test.txt'
  5.  
  6.     words, word_to_id = _build_vocab(train_path) 
  7.     train_data = _file_to_word_ids(train_path, word_to_id) 
  8.     valid_data = _file_to_word_ids(valid_path, word_to_id) 
  9.     test_data = _file_to_word_ids(test_path, word_to_id) 
  10.  
  11.     return train_data, valid_data, test_data, words, word_to_id 
以上部分和官方的例子有一定的相似之處。接下來的處理和官方存在很大的不同,主要參考了Keras例程處理文檔的操作:
 
  1. def ptb_producer(raw_data, batch_size=64, num_steps=20, stride=1): 
  2.     data_len = len(raw_data) 
  3.  
  4.     sentences = [] 
  5.     next_words = [] 
  6.     for i in range(0, data_len - num_steps, stride): 
  7.         sentences.append(raw_data[i:(i + num_steps)]) 
  8.         next_words.append(raw_data[i + num_steps]) 
  9.  
  10.     sentences = np.array(sentences) 
  11.     next_words = np.array(next_words) 
  12.  
  13.     batch_len = len(sentences) // batch_size 
  14.     x = np.reshape(sentences[:(batch_len * batch_size)], \ 
  15.         [batch_len, batch_size, -1]) 
  16.  
  17.     y = np.reshape(next_words[:(batch_len * batch_size)], \ 
  18.         [batch_len, batch_size]) 
  19.  
  20.     return x, y 
參數(shù)解析:
  •     raw_data: 即ptb_raw_data()函數(shù)產(chǎn)生的數(shù)據(jù)
  •     batch_size: 神經(jīng)網(wǎng)絡(luò)使用隨機梯度下降,數(shù)據(jù)按多個批次輸出,此為每個批次的數(shù)據(jù)量
  •     num_steps: 每個句子的長度,相當于之前描述的n的大小,這在循環(huán)神經(jīng)網(wǎng)絡(luò)中又稱為時序的長度。
  •     stride: 取數(shù)據(jù)的步長,決定數(shù)據(jù)量的大小。

代碼解析:

這個函數(shù)將一個原始數(shù)據(jù)list轉(zhuǎn)換為多個批次的數(shù)據(jù),即[batch_len, batch_size, num_steps]。

首先,程序每一次取了num_steps個詞作為一個句子,即x,以這num_steps個詞后面的一個詞作為它的下一個預(yù)測,即為y。這樣,我們首先把原始數(shù)據(jù)整理成了batch_len * batch_size個x和y的表示,類似于已知x求y的分類問題。

為了滿足隨機梯度下降的需要,我們還需要把數(shù)據(jù)整理成一個個小的批次,每次喂一個批次的數(shù)據(jù)給TensorFlow來更新權(quán)重,這樣,數(shù)據(jù)就整理為[batch_len, batch_size, num_steps]的格式。

打印部分數(shù)據(jù): 

  1. train_data, valid_data, test_data, words, word_to_id = ptb_raw_data('simple-examples/data'
  2. x_train, y_train = ptb_producer(train_data) 
  3. print(x_train.shape) 
  4. print(y_train.shape) 
輸出:
 
  1. (14524, 64, 20) 
  2. (14524, 64) 
可見我們得到了14524個批次的數(shù)據(jù),每個批次的訓練集維度為[64, 20]。
 
  1. print(' '.join(to_words(x_train[100, 3], words))) 
第100個批次的第3句話為:
 
  1. despite steady sales growth <eos> magna recently cut its quarterly dividend in half and the company 's class a shares 
  1. print(words[np.argmax(y_train[100, 3])]) 
它的下一個詞為:
 
  1. the 
 
構(gòu)建模型
 
配置項
 
  1. class LMConfig(object): 
  2.     """language model 配置項""" 
  3.     batch_size = 64       # 每一批數(shù)據(jù)的大小 
  4.     num_steps = 20        # 每一個句子的長度 
  5.     stride = 3            # 取數(shù)據(jù)時的步長 
  6.  
  7.     embedding_dim = 64    # 詞向量維度 
  8.     hidden_dim = 128      # RNN隱藏層維度 
  9.     num_layers = 2        # RNN層數(shù) 
  10.  
  11.     learning_rate = 0.05  # 學習率 
  12.     dropout = 0.2         # 每一層后的丟棄概率 
讀取輸入
 
讓模型可以按批次的讀取數(shù)據(jù)。
 
  1. class PTBInput(object): 
  2.     """按批次讀取數(shù)據(jù)""" 
  3.     def __init__(self, config, data): 
  4.         self.batch_size = config.batch_size 
  5.         self.num_steps = config.num_steps 
  6.         self.vocab_size = config.vocab_size # 詞匯表大小 
  7.  
  8.         self.input_data, self.targets = ptb_producer(data, 
  9.             self.batch_size, self.num_steps) 
  10.  
  11.         self.batch_len = self.input_data.shape[0] # 總批次 
  12.         self.cur_batch = 0  # 當前批次 
  13.  
  14.     def next_batch(self): 
  15.         """讀取下一批次""" 
  16.         x = self.input_data[self.cur_batch] 
  17.         y = self.targets[self.cur_batch] 
  18.  
  19.         # 轉(zhuǎn)換為one-hot編碼 
  20.         y_ = np.zeros((y.shape[0], self.vocab_size), dtype=np.bool) 
  21.         for i in range(y.shape[0]): 
  22.             y_[i][y[i]] = 1 
  23.  
  24.         # 如果到最后一個批次,則回到最開頭 
  25.         self.cur_batch = (self.cur_batch +1) % self.batch_len 
  26.  
  27.         return x, y_ 
模型
 
  1. class PTBModel(object): 
  2.     def __init__(self, config, is_training=True): 
  3.  
  4.         self.num_steps = config.num_steps 
  5.         self.vocab_size = config.vocab_size 
  6.  
  7.         self.embedding_dim = config.embedding_dim 
  8.         self.hidden_dim = config.hidden_dim 
  9.         self.num_layers = config.num_layers 
  10.         self.rnn_model = config.rnn_model 
  11.  
  12.         self.learning_rate = config.learning_rate 
  13.         self.dropout = config.dropout 
  14.  
  15.         self.placeholders()  # 輸入占位符 
  16.         self.rnn()           # rnn 模型構(gòu)建 
  17.         self.cost()          # 代價函數(shù) 
  18.         self.optimize()      # 優(yōu)化器 
  19.         self.error()         # 錯誤率 
  20.  
  21.  
  22.     def placeholders(self): 
  23.         """輸入數(shù)據(jù)的占位符""" 
  24.         self._inputs = tf.placeholder(tf.int32, [None, self.num_steps]) 
  25.         self._targets = tf.placeholder(tf.int32, [None, self.vocab_size]) 
  26.  
  27.  
  28.     def input_embedding(self): 
  29.         """將輸入轉(zhuǎn)換為詞向量表示""" 
  30.         with tf.device("/cpu:0"): 
  31.             embedding = tf.get_variable( 
  32.                 "embedding", [self.vocab_size, 
  33.                     self.embedding_dim], dtype=tf.float32) 
  34.             _inputs = tf.nn.embedding_lookup(embedding, self._inputs) 
  35.  
  36.         return _inputs 
  37.  
  38.  
  39.     def rnn(self): 
  40.         """rnn模型構(gòu)建""" 
  41.         def lstm_cell():  # 基本的lstm cell 
  42.             return tf.contrib.rnn.BasicLSTMCell(self.hidden_dim, 
  43.                 state_is_tuple=True
  44.  
  45.         def gru_cell():   # gru cell,速度更快 
  46.             return tf.contrib.rnn.GRUCell(self.hidden_dim) 
  47.  
  48.         def dropout_cell():    # 在每個cell后添加dropout 
  49.             if (self.rnn_model == 'lstm'): 
  50.                 cell = lstm_cell() 
  51.             else
  52.                 cell = gru_cell() 
  53.             return tf.contrib.rnn.DropoutWrapper(cell, 
  54.                 output_keep_prob=self.dropout) 
  55.  
  56.         cells = [dropout_cell() for _ in range(self.num_layers)] 
  57.         cell = tf.contrib.rnn.MultiRNNCell(cells, state_is_tuple=True)  # 多層rnn 
  58.  
  59.         _inputs = self.input_embedding() 
  60.         _outputs, _ = tf.nn.dynamic_rnn(cell=cell, 
  61.             inputs=_inputs, dtype=tf.float32) 
  62.  
  63.         # _outputs的shape為 [batch_size, num_steps, hidden_dim] 
  64.         last = _outputs[:, -1, :]  # 只需要最后一個輸出 
  65.  
  66.         # dense 和 softmax 用于分類,以找出各詞的概率 
  67.         logits = tf.layers.dense(inputs=last, units=self.vocab_size)    
  68.         prediction = tf.nn.softmax(logits)   
  69.  
  70.         self._logits = logits 
  71.         self._pred = prediction 
  72.  
  73.     def cost(self): 
  74.         """計算交叉熵代價函數(shù)""" 
  75.         cross_entropy = tf.nn.softmax_cross_entropy_with_logits( 
  76.             logits=self._logits, labels=self._targets) 
  77.         cost = tf.reduce_mean(cross_entropy) 
  78.         self.cost = cost 
  79.  
  80.     def optimize(self): 
  81.         """使用adam優(yōu)化器""" 
  82.         optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate) 
  83.         self.optim = optimizer.minimize(self.cost) 
  84.  
  85.     def error(self): 
  86.         """計算錯誤率""" 
  87.         mistakes = tf.not_equal( 
  88.             tf.argmax(self._targets, 1), tf.argmax(self._pred, 1)) 
  89.         self.errors = tf.reduce_mean(tf.cast(mistakes, tf.float32)) 
訓練
 
  1. def run_epoch(num_epochs=10): 
  2.     config = LMConfig()   # 載入配置項 
  3.  
  4.     # 載入源數(shù)據(jù),這里只需要訓練集 
  5.     train_data, _, _, words, word_to_id = \ 
  6.         ptb_raw_data('simple-examples/data'
  7.     config.vocab_size = len(words) 
  8.  
  9.     # 數(shù)據(jù)分批 
  10.     input_train = PTBInput(config, train_data) 
  11.     batch_len = input_train.batch_len 
  12.  
  13.     # 構(gòu)建模型 
  14.     model = PTBModel(config) 
  15.  
  16.     # 創(chuàng)建session,初始化變量 
  17.     sess = tf.Session() 
  18.     sess.run(tf.global_variables_initializer()) 
  19.  
  20.     print('Start training...'
  21.     for epoch in range(num_epochs):  # 迭代輪次 
  22.         for i in range(batch_len):   # 經(jīng)過多少個batch 
  23.             x_batch, y_batch = input_train.next_batch() 
  24.  
  25.             # 取一個批次的數(shù)據(jù),運行優(yōu)化 
  26.             feed_dict = {model._inputs: x_batch, model._targets: y_batch} 
  27.             sess.run(model.optim, feed_dict=feed_dict) 
  28.  
  29.             # 每500個batch,輸出一次中間結(jié)果 
  30.             if i % 500 == 0: 
  31.                 cost = sess.run(model.cost, feed_dict=feed_dict) 
  32.  
  33.                 msg = "Epoch: {0:>3}, batch: {1:>6}, Loss: {2:>6.3}" 
  34.                 print(msg.format(epoch + 1, i + 1, cost)) 
  35.  
  36.                 # 輸出部分預(yù)測結(jié)果 
  37.                 pred = sess.run(model._pred, feed_dict=feed_dict) 
  38.                 word_ids = sess.run(tf.argmax(pred, 1)) 
  39.                 print('Predicted:'' '.join(words[w] for w in word_ids)) 
  40.                 true_ids = np.argmax(y_batch, 1) 
  41.                 print('True:'' '.join(words[w] for w in true_ids)) 
  42.  
  43.     print('Finish training...'
  44.     sess.close() 

需要經(jīng)過多次的訓練才能得到一個較為合理的結(jié)果。 

 

責任編輯:龐桂玉 來源: 36大數(shù)據(jù)
相關(guān)推薦

2017-03-27 16:18:30

神經(jīng)網(wǎng)絡(luò)TensorFlow人工智能

2017-08-29 13:50:03

TensorFlow深度學習神經(jīng)網(wǎng)絡(luò)

2018-08-27 17:05:48

tensorflow神經(jīng)網(wǎng)絡(luò)圖像處理

2017-12-22 08:47:41

神經(jīng)網(wǎng)絡(luò)AND運算

2017-09-28 16:15:12

神經(jīng)網(wǎng)絡(luò)訓練多層

2018-03-22 13:34:59

TensorFlow神經(jīng)網(wǎng)絡(luò)

2018-02-27 09:32:13

神經(jīng)網(wǎng)絡(luò)自然語言初探

2025-02-24 08:00:00

機器學習ML架構(gòu)

2022-12-05 10:08:59

2017-08-22 16:20:01

深度學習TensorFlow

2023-05-06 12:47:41

2019-01-05 08:40:17

VGG神經(jīng)網(wǎng)絡(luò)

2018-07-29 06:46:07

神經(jīng)網(wǎng)絡(luò)RNN循環(huán)神經(jīng)網(wǎng)絡(luò)

2022-10-19 07:42:41

圖像識別神經(jīng)網(wǎng)絡(luò)

2018-12-14 08:02:55

神經(jīng)網(wǎng)絡(luò)機器學習二值模型

2019-07-24 05:36:32

神經(jīng)網(wǎng)絡(luò)語言模型NNLM

2023-01-11 07:28:49

TensorFlow分類模型

2018-07-03 16:10:04

神經(jīng)網(wǎng)絡(luò)生物神經(jīng)網(wǎng)絡(luò)人工神經(jīng)網(wǎng)絡(luò)

2017-07-19 11:39:25

深度學習人工智能boosting

2017-08-10 15:31:57

Apache Spar TensorFlow
點贊
收藏

51CTO技術(shù)棧公眾號