成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

GRU網(wǎng)絡(luò)生成莎士比亞小說(shuō)

joyvw / 638人閱讀

摘要:介紹本文我們將使用網(wǎng)絡(luò)來(lái)學(xué)習(xí)莎士比亞小說(shuō),模型通過(guò)學(xué)習(xí)可以生成與小說(shuō)風(fēng)格相似的文本,如圖所示雖然有些句子并沒(méi)有實(shí)際的意思目前我們的模型是基于概率,并不是理解語(yǔ)義,但是大多數(shù)單詞都是有效的,文本結(jié)構(gòu)也與我們訓(xùn)練的文本相似。

介紹

本文我們將使用GRU網(wǎng)絡(luò)來(lái)學(xué)習(xí)莎士比亞小說(shuō),模型通過(guò)學(xué)習(xí)可以生成與小說(shuō)風(fēng)格相似的文本,如圖所示:

雖然有些句子并沒(méi)有實(shí)際的意思(目前我們的模型是基于概率,并不是理解語(yǔ)義),但是大多數(shù)單詞都是有效的,文本結(jié)構(gòu)也與我們訓(xùn)練的文本相似。
由于項(xiàng)目中使用到了Eager ExecutionGRU,所以我們先進(jìn)行簡(jiǎn)單介紹:

Eager Execution

TensorflowEager Execution之前想要評(píng)估操作必須通過(guò)運(yùn)行計(jì)算圖"sess.run()"的方式來(lái)獲取值,而使用Eager Execution可以立即評(píng)估操作。Eager Execution基于python流程控制并可以使用python的調(diào)試工具進(jìn)行錯(cuò)誤報(bào)告。

梯度計(jì)算:

先使用tf.GradientTape記錄然后再計(jì)算梯度,示例如下:

# tfe = tf.contrib.eager
w = tfe.Variable([[1.0]])
with tf.GradientTape() as tape:
  loss = w * w

grad = tape.gradient(loss, w)

常用函數(shù):
tfe.gradients_function:返回一個(gè)函數(shù),該函數(shù)會(huì)計(jì)算其輸入函數(shù)參數(shù)相對(duì)其參數(shù)的導(dǎo)數(shù)。
tfe.value_and_gradients_function:除了返回函數(shù)還會(huì)返回輸入函數(shù)的值。

其它:

在訓(xùn)練大數(shù)據(jù)集的時(shí)候,Eager Execution 性能與Graph Execution相當(dāng),但在小數(shù)據(jù)集中Eager Execution會(huì)慢一些。
Eager Execution勝在開(kāi)發(fā)和調(diào)試的便利性,但是在分布式訓(xùn)練,性能優(yōu)化,生產(chǎn)部署方面Graph Execution更好。
在未調(diào)用tf.enable_eager_execution(開(kāi)啟后不能關(guān)閉)的情況下可以使用tfe.py_func啟用Eager Execution。

GRU

GRULSTM的一種變體,它將LSTM的遺忘門(mén),輸入門(mén),輸出門(mén)改為更新門(mén)(LSTM的遺忘門(mén),輸入門(mén)合并),重置門(mén)。參數(shù)少,收斂快,不過(guò)在數(shù)據(jù)量較大的時(shí)候LSTM的表現(xiàn)更好。下圖是GRU網(wǎng)絡(luò)結(jié)構(gòu)和前向傳播計(jì)算方法。

更新門(mén):控制前一時(shí)刻的狀態(tài)信息被帶入到當(dāng)前狀態(tài)中的程度。
重置門(mén):控制忽略前一時(shí)刻的狀態(tài)信息,重置門(mén)的值越小說(shuō)明忽略的越多(被寫(xiě)入的信息越少)。

GRU訓(xùn)練:

我們要學(xué)習(xí)的參數(shù)有Wr、Wz、Wh、Wo,其中Wr、Wz、Wh是和ht-1拼接而成,所以需要進(jìn)行分割:

采用反向傳播對(duì)損失函數(shù)的各參數(shù)求偏導(dǎo):

中間參數(shù)為:

算出每個(gè)參數(shù)的偏導(dǎo)數(shù)之后就可以更新參數(shù)了。GRU通過(guò)門(mén)控機(jī)制選擇性的保留特征,為長(zhǎng)時(shí)傳播提供了保證。正因?yàn)殚T(mén)控機(jī)制的有效,門(mén)卷積目前也很受歡迎,感興趣的朋友可以閱讀相關(guān)文獻(xiàn)。

數(shù)據(jù)導(dǎo)入
import tensorflow as tf
import numpy as np
import os
import re
import random
import time

# 開(kāi)啟后不能關(guān)閉,只能重新啟動(dòng)新的python會(huì)話(huà)
tf.enable_eager_execution()

# 獲取數(shù)據(jù),你也可以使用其他數(shù)據(jù)集
path_to_file=tf.keras.utils.get_file("shakespeare.txt", "https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt")
text=open(path_to_file).read()

文字是不能直接放進(jìn)模型的需要將其轉(zhuǎn)換為對(duì)應(yīng)的ID表示:

# 去除重復(fù)字符并排序
unique=sorted(set(text))

# enumerate 返回value,index
# 文本轉(zhuǎn)id 
char2idx={value:idx for idx,value in enumerate(unique)}
# id轉(zhuǎn)文本
idx2char={idx:value for idx,value in enumerate(unique)}

部分參數(shù)配置:

# 每次輸入的最大文本長(zhǎng)度,對(duì)應(yīng)GRU模型的‘time_step’
max_length=100
vocab_size=len(unique)
# 詞嵌入維度
embedding_dim=256
hidden_units=1024
BATCH_SIZE=64
BUFFER_SIZE=10000

獲取ID表示的數(shù)據(jù)并創(chuàng)建標(biāo)簽

# 標(biāo)簽的定義方式如:
# data="ming"
# input="min" labels="ing"
input_text=[]
labels_text=[]

# 迭代獲取‘max_length’個(gè)數(shù)據(jù)
for i in range(0,len(text)-max_length,max_length):
    inputs=text[i:i+max_length]
    labels=text[i+1:i+1+max_length]
    
    input_text.append([char2idx[i] for i in inputs])
    labels_text.append([char2idx[i] for i in labels])

dataset讀取數(shù)據(jù):

dataset=tf.data.Dataset.from_tensor_slices((input_text,output_text))
# drop_remainder:小于batch_size 是否刪除,默認(rèn)不刪除
dataset=dataset.batch(BATCH_SIZE,drop_remainder=True)
創(chuàng)建模型

我們的模型包含三層:Embedding層,GRU層,全連接層。

class Model(tf.keras.Model):
    """
    GRU:重置門(mén),更新門(mén) LSTM:遺忘門(mén),輸入門(mén),輸出門(mén)
    GRU,參數(shù)少,容易收斂,數(shù)據(jù)量大的時(shí)候LSTM表現(xiàn)更好
    """
    def __init__(self,vocab_size,embedding_dim,units,batch_size):
        super(Model, self).__init__()

        self.units=units
        self.batch_size=batch_size
        self.embedding=tf.keras.layers.Embedding(
            input_dim=vocab_size,
            output_dim=embedding_dim
        )
        if tf.test.is_gpu_available:
            # 使用GPU加速訓(xùn)練
            self.gru=tf.keras.layers.CuDNNGRU(
                units=self.units,
                return_sequences=True,
                return_state=True,
                recurrent_initializer="glorot_uniform"
            )
        else:
            self.gru=tf.keras.layers.GRU(
                units=self.units,
                return_sequences=True,
                return_state=True,
                # 默認(rèn)激活函數(shù)為:hard_sigmoid
                recurrent_activation="sigmoid",
                recurrent_initializer="glorot_uniform"
            )
        self.fc=tf.keras.layers.Dense(units=vocab_size)
    def __call__(self, x,hidden):
        x=self.embedding(x)
        
        # output:[batch_size,max_length,hidden_size]
        # states:[batch_size,hidden_size]
        output,states=self.gru(x,initial_state=hidden)

        # 轉(zhuǎn)換至:(batch_size*max_length,hidden_size)
        output=tf.reshape(output,shape=(-1,output.shape[2]))
        
        # output:[batch_size*max_length,vocab_size]
        x=self.fc(output)

        return x,states
為什么要使用Embedding

Embedding將高緯離散向量轉(zhuǎn)為低緯稠密的連續(xù)向量,并且表現(xiàn)出了向量間的相似性。

如圖所示,one-hot表示只有一個(gè)位置是1,其余為0,當(dāng)文字較多時(shí)維度將會(huì)非常的大,并且由于one-hot編碼后的單詞存在獨(dú)立性,導(dǎo)致不能利用相似詞匯進(jìn)行學(xué)習(xí)。那么Embedding又是怎么做的呢?

使用Embedding的第一步是通過(guò)索引對(duì)句子進(jìn)行編碼,然后根據(jù)索引創(chuàng)建嵌入矩陣,這樣我們使用嵌入矩陣替代one-hot編碼向量。每個(gè)單詞向量不再是由一個(gè)獨(dú)立向量代替,而是替換成用于查找嵌入矩陣中向量的索引。

模型訓(xùn)練
# model初始化
model=Model(vocab_size,embedding_dim,hidden_units,BATCH_SIZE)
optimizer=tf.train.AdamOptimizer(learning_rate=0.001)

# 創(chuàng)建損失函數(shù)
def loss_fn(lables,preds):
    # 交叉熵?fù)p失函數(shù)在值域上邊界依然可以保持較高的激活值
    return tf.losses.sparse_softmax_cross_entropy(
        labels=lables,
        logits=preds
    )

模型保存:

# 讀取checkpoint需要重新定義圖結(jié)構(gòu)
checkpoint_dir = "./training_checkpoints"
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
checkpoint = tf.train.Checkpoint(optimizer=optimizer,
                                 model=model)

開(kāi)始訓(xùn)練:

EPOCHS = 20

for epoch in range(EPOCHS):
    start = time.time()
    
    # 每迭代完成一次數(shù)據(jù)集重置hidden-state
    hidden = model.reset_states()
    
    for (batch, (inp, target)) in enumerate(dataset):
          # 使用GradientTape記錄
          with tf.GradientTape() as tape:
              predictions, hidden = model(inp, hidden)
              
              target = tf.reshape(target, (-1,))
              loss = loss_function(target, predictions)
              
          grads = tape.gradient(loss, model.variables)
          # 更新
          optimizer.apply_gradients(zip(grads, model.variables))

          if batch % 100 == 0:
              print ("Epoch {} Batch {} Loss {:.4f}".format(epoch+1,
                                                            batch,
                                                            loss))
    # 每迭代5次數(shù)據(jù)集保存一次模型數(shù)據(jù)
    if (epoch + 1) % 5 == 0:
      checkpoint.save(file_prefix = checkpoint_prefix)

讀取保存的checkpoint文件:

checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))
預(yù)測(cè)

要指定輸入字符以及希望模型生成的文本長(zhǎng)度:

# 需要生成的文字長(zhǎng)度
num_generate=1000

start_string="Q"
# 將輸入字符轉(zhuǎn)為對(duì)應(yīng)ID表示
input_eval=[char2idx[s] for s in start_string]
# 擴(kuò)展一維 batch_size
input_eval=tf.expand_dims(input_eval,0)

text_generated=""
# hidden state shape:(batch_size,rnn units)
# hidden 初始化
hidden=[tf.zeros((1,hidden_units))]

for i in range(num_generate):
    precit,hidden=model(input_eval,hidden)
    # 注:這里batch_size == 1
    # 代碼參考,很好理解:
    # output = tf.transpose(output,[1,0,2])
    # last = tf.gather(output,int(output.get_shape()[0]-1)
    predict_id=tf.argmax(predict[-1]).numpy()
    # 將前一時(shí)刻的輸出作為下一時(shí)刻的輸入,一直到迭代完成
    input_eval=tf.expand_dims(predict_id,0)
    # 轉(zhuǎn)換成對(duì)應(yīng)字符
    text_generated+=idx2char[predict_id]
print(start_string+text_generated)
總結(jié)

GRU網(wǎng)路作為L(zhǎng)STM網(wǎng)路的變體,參數(shù)少收斂快。Eager模式下代碼簡(jiǎn)潔,調(diào)試便利雖然比Graph Execution功能遜色,但勝在便利性。RNN現(xiàn)在很多項(xiàng)目都會(huì)結(jié)合注意力機(jī)制使用,效果很好。注意力簡(jiǎn)單來(lái)說(shuō)就是對(duì)輸入不再是同等看待,而是根據(jù)權(quán)重值大小來(lái)區(qū)別訓(xùn)練。

本文內(nèi)容部分參考Yash Katariya,在此表示感謝。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42763.html

相關(guān)文章

  • 美麗的神經(jīng)網(wǎng)絡(luò):13種細(xì)胞構(gòu)筑的深度學(xué)習(xí)世界

    摘要:網(wǎng)絡(luò)所有的神經(jīng)元都與另外的神經(jīng)元相連每個(gè)節(jié)點(diǎn)功能都一樣。訓(xùn)練的方法是將每個(gè)神經(jīng)元的值設(shè)定為理想的模式,然后計(jì)算權(quán)重。輸入神經(jīng)元在網(wǎng)絡(luò)整體更新后會(huì)成為輸入神經(jīng)元。的訓(xùn)練和運(yùn)行過(guò)程與十分相似將輸入神經(jīng)元設(shè)定為固定值,然后任網(wǎng)絡(luò)自己變化。 新的神經(jīng)網(wǎng)絡(luò)架構(gòu)隨時(shí)隨地都在出現(xiàn),要時(shí)刻保持還有點(diǎn)難度。要把所有這些縮略語(yǔ)指代的網(wǎng)絡(luò)(DCIGN,IiLSTM,DCGAN,知道嗎?)都弄清,一開(kāi)始估計(jì)還無(wú)從下...

    zsirfs 評(píng)論0 收藏0
  • 神經(jīng)網(wǎng)絡(luò)

    摘要:通過(guò)將神經(jīng)元的值設(shè)置為希望的模式來(lái)訓(xùn)練網(wǎng)絡(luò),之后可以計(jì)算權(quán)重。輸入神經(jīng)元在完整網(wǎng)絡(luò)更新結(jié)束時(shí)變成輸出神經(jīng)元。在某種程度上,這類(lèi)似于峰值神經(jīng)網(wǎng)絡(luò),并不是所有的神經(jīng)元始終都在發(fā)射并且點(diǎn)的生物合理性得分。 隨著新的神經(jīng)網(wǎng)絡(luò)架構(gòu)不時(shí)出現(xiàn),很難跟蹤這些架構(gòu)。知道所有縮寫(xiě)(DCIGN,BiLSTM,DCGAN,任何人?)起初可能有點(diǎn)壓倒性。 所以我決定編寫(xiě)一個(gè)包含許多這些體系結(jié)構(gòu)的備忘單。這些大多...

    Anonymous1 評(píng)論0 收藏0
  • 難以置信!LSTM和GRU的解析從未如此清晰

    摘要:作為解決方案的和和是解決短時(shí)記憶問(wèn)題的解決方案,它們具有稱(chēng)為門(mén)的內(nèi)部機(jī)制,可以調(diào)節(jié)信息流。隨后,它可以沿著長(zhǎng)鏈序列傳遞相關(guān)信息以進(jìn)行預(yù)測(cè),幾乎所有基于遞歸神經(jīng)網(wǎng)絡(luò)的技術(shù)成果都是通過(guò)這兩個(gè)網(wǎng)絡(luò)實(shí)現(xiàn)的。和采用門(mén)結(jié)構(gòu)來(lái)克服短時(shí)記憶的影響。 短時(shí)記憶RNN 會(huì)受到短時(shí)記憶的影響。如果一條序列足夠長(zhǎng),那它們將很難將信息從較早的時(shí)間步傳送到后面的時(shí)間步。 因此,如果你正在嘗試處理一段文本進(jìn)行預(yù)測(cè),RNN...

    MrZONT 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<