霍格沃茲見!用RNN和TensorFlow創作自己的《哈利波特》小說

2021-01-07 讀芯術

全文共5949字,預計學習時長15分鐘

圖源:unsplash

還在等待霍格沃茨的錄取通知書?想在大禮堂裡享用晚宴?想探索通往霍格莫德的秘密通道?想在奧利凡德魔杖店買第一根魔杖?嘆氣,你不是一個人。這麼久了,我還是沉迷於哈利波特的魔法世界。

最近我開始學習神經網絡,著迷於深度學習的強大創造力。靈光乍現,我為什麼不把它們融合在一起呢?因此,我使用TensorFlow執行了一個簡單的文本生成模型來創作我自己的《哈利·波特》短篇小說。

本文將介紹了我為實現它而編寫的完整代碼。各位巫師可以在這裡直接找到github代碼並自己運行它:https://github.com/amisha-jodhani/text-generator-harry-potter

當你閒來無事時,它可以向無聊施一個驅逐咒。

背景

RNN是什麼?

循環神經網絡(RNN)與其他神經網絡不同,它是有記憶的神經網絡,可以存儲它處理過的所有層的信息,並在記憶的基礎上計算下一層。

GRU vs LSTM

二者在文本生成上都表現出色,GRU(門控循環單元)是比較新的概念,實際上並沒有一種方法可以確定二者哪個更好。優化超參數比選擇一個好的架構更能提高模型性能。

如果數據量不成問題,那麼則是LSTM(長短期記憶網絡)性能更優。如果數據量較少,那麼GRU參數更少,因此訓練更快,並能很好地泛化。

為什麼是基於字符的?

在處理這樣的大型數據集時,一個語料庫中不重複單詞的總量遠遠高於唯一字符的數量。一個大型數據集有許多不重複的單詞,當為如此大的矩陣分配獨熱編碼時,很可能會遇到內存問題。光是標籤本身就可以佔據Tb級的內存。用來預測單詞的原則也可以應用在這裡,但是現在要處理的詞彙量要小得多。

代碼

圖源:unsplash

首先導入所需的庫

import tensorflow as tf

import numpy as np

import os

import time

現在,讀取數據

可以從 一個Kaggle數據集找到並下載所有《哈利波特》的文稿(https://www.kaggle.com/alex44jzy/harrypotter)。我將這七本書合併到一個名為「harrypotter.txt」的文本文件中,你也可以挑選你喜歡的任何一本來訓練模型。

files= [『1SorcerersStone.txt』, 『2ChamberofSecrets.txt』, 『3ThePrisonerOfAzkaban.txt』,『4TheGobletOfFire.txt』, 『5OrderofthePhoenix.txt』, 『6TheHalfBloodPrince.txt』,『7DeathlyHollows.txt』]

with open(『harrypotter.txt』, 『w』) as outfile:

for file in files:

with open(file) as infile:

outfile.write(infile.read())

text = open(『harrypotter.txt』).read()

查看數據

print(text[:300])

處理數據

通過建立兩個查找表將 vocab 中所有唯一的字符串映射到數字:

· 將字符映射到數字(char2index)

· 將數字映射回字符(index2char)

然後把文本轉換成數字:

vocab = sorted(set(text))

char2index = {u:i for i, u in enumerate(vocab)}

index2char = np.array(vocab)

text_as_int = np.array([char2index[c] for c in text])#how it looks:

print ('{} -- characters mapped to int -- > {}'.format(repr(text[:13]),text_as_int[:13]))

「Harry Potter」——字符映射到數字→ [39 64 81 81 88 3 47 78 83 83 68 81 3]

每個輸入模型的序列包含文本中seq_length 數量的字符,其對應的目標序列長度相同,所有字符都向右移動了一個位置,因此將文本分為 seq_length+1塊。

tf.data.Dataset.from_tensor_slices 將文本向量轉換為字符索引流, batch方法(分批處理法)將這些字符按所需的長度分批。

通過使用 map 方法對每個批處理應用一個簡單的函數,可以創建輸入和目標:

seq_length = 100

examples_per_epoch = len(text)//(seq_length+1)

char_dataset = tf.data.Dataset.from_tensor_slices(text_as_int)

sequences = char_dataset.batch(seq_length+1, drop_remainder=True)defsplit_input_target(data):

input_text = data[:-1]

target_text = data[1:]

return input_text, target_textdataset =sequences.map(split_input_target)

在將這些數據輸入到模型之前對數據進行隨機排列,並將其劃分批次。tf.data維護一個緩衝,在緩衝區中它會隨機排列元素。

BATCH_SIZE = 64

BUFFER_SIZE = 10000dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE,drop_remainder=True)

搭建模型

有了目前算出來的所有字符,下一個字符會是什麼?這就要訓練RNN模型來預測了。使用 tf.keras.Sequential定義模型,因為其中的所有層都只有一個輸入並產生一個輸出。使用的不同層是:

· tf.keras.layers.Embedding:這是輸入層。嵌入用於將所有唯一字符映射到具有 embedding_dim維數的多維空間中的向量。

· tf.keras.layers.GRU:有rnn_units個單元數的RNN。(也可以在此處使用LSTM來看看哪種最適合已有數據。)

· tf.keras.layers.Dense:輸出層,有vocab_size 大小的輸出。

單獨定義所有的超參數也很有用,這樣以後無需編輯模型定義就可以更很容易地修改它們。

文本生成訓練示例

vocab_size = len(vocab)

embedding_dim = 300

# Number of RNN units

rnn_units1 = 512

rnn_units2 = 256

rnn_units= [rnn_units1, rnn_units2]def build_model(vocab_size, embedding_dim,rnn_units, batch_size):

model = tf.keras.Sequential([

tf.keras.layers.Embedding(vocab_size,embedding_dim,

batch_input_shape=[batch_size,None]), tf.keras.layers.GRU(rnn_units1, return_sequences=True,

stateful=True,recurrent_initializer='glorot_uniform'), tf.keras.layers.GRU(rnn_units2,return_sequences=True,

stateful=True,recurrent_initializer='glorot_uniform'), tf.keras.layers.Dense(vocab_size) ])

return modelmodel = build_model(

vocab_size = vocab_size,

embedding_dim=embedding_dim,

rnn_units=rnn_units,

batch_size=BATCH_SIZE)

訓練模型

標準的tf.keras.losses.sparse_categorical_crossentropy 損失函數與這個模型一起使用時效果最佳,因為它應用於預測的最後一層。將 from_logits設置為True,因為該模型返回logits。然後選擇adam優化器並編譯模型。

def loss(labels, logits):

returntf.keras.losses.sparse_categorical_crossentropy(labels,

logits,from_logits=True)model.compile(optimizer='adam', loss=loss,metrics=['accuracy'])

可以像這樣配置檢查點,以確保在訓練期間保存了檢查點。

# Directory where the checkpoints will be saved

checkpoint_dir = 『./training_checkpoints』

# Name of the checkpoint files

checkpoint_prefix = os.path.join(checkpoint_dir, 「ckpt_{epoch}」)

checkpoint_callback=tf.keras.callbacks.ModelCheckpoint(

filepath=checkpoint_prefix,save_weights_only=True)

每個期(epoch)的訓練時間取決於模型層和超參數的使用。我將期設置為50,以觀察準確性和損失如何隨時間變化,但可能不需要訓練所有50期。當你看到損失開始增加或在幾個期內保持不變時,一定要停止訓練。訓練的最後一個期將存儲在latest_check中。如果使用Google Colab,則將runtime設置為GPU以減少訓練時間。

EPOCHS= 50

history = model.fit(dataset, epochs=EPOCHS, callbacks=[checkpoint_callback])

latest_check = tf.train.latest_checkpoint(checkpoint_dir)

圖源:unsplash

文本生成

如果希望使用不同的批處理大小,則需要在運行之前重新構建模型並重新加載檢查點。為了保持簡單,我設置batch_size 為1。可以運行model.summary() 來了解模型的各個層以及每個層運行之後的輸出形狀。

model = build_model(vocab_size, embedding_dim, rnn_units, batch_size=1)

model.load_weights(latest_check)

model.build(tf.TensorShape([1, None]))

model.summary()

下面的函數就在生成文本:

· 接收start_string,初始化RNN的狀態並將輸出字符數賦給 num_generate。

· 使用 start_string 和RNN狀態獲取下一個字符的預測分布。然後它會計算預測字符的索引,作為模型的下個輸入。

· 模型返回的輸出狀態反饋到模型中,這樣它就有了更多的上下文(如下所示)。在預測下一個字符之後,循環繼續。通過這種方式,RNN可以從之前的輸出中建立記憶。

文本生成示例

· 較低的scaling會產生更可預測的文本,而較高的scaling會產生更令人驚訝的文本。

def generate_text(model, start_string): num_generate = 1000 #can beanything you like input_eval =[char2index[s] for s in start_string]

input_eval = tf.expand_dims(input_eval,0) text_generated = [] scaling = 0.5 #kept at a lower valuehere # Here batch size == 1

model.reset_states()

for i in range(num_generate):

predictions = model(input_eval)

# remove the batch dimension

predictions = tf.squeeze(predictions,0)

predictions = predictions / scaling

predicted_id =tf.random.categorical(predictions,

num_samples=1)[1,0].numpy()

input_eval =tf.expand_dims([predicted_id], 0)

text_generated.append(idx2char[predicted_id])return(start_string + 『』.join(text_generated))

然後就完成了!

輸出

可以嘗試不同的初始字符串以獲得不同的輸出。

這是用我最喜歡的人物名輸出的一部分:

print(generate_text(model, start_string=u」Severus Snape「))

也可以嘗試不同的句子:

如果你只使用第一本《哈利波特與魔法石》來訓練模型,可以得到下面結果:

你會發現模型知道什麼時候大寫,什麼時候另起一段,它還模仿了魔法風格的寫作詞彙!

為了使句子更連貫,你可以通過以下方法改進模型:

· 改變不同參數,如 seq_length , rnn_units , embedding_dims , scaling的值來找出最佳設置。

· 訓練更多期

· 為GRU / LSTM添加更多層

圖源:unsplash

這個模型可以訓練你喜歡的任何系列書籍。好啦,惡作劇完畢~

留言點讚關注

我們一起分享AI學習與發展的乾貨

如轉載,請後臺留言,遵守轉載規範

相關焦點

  • 分享TensorFlow Lite應用案例
    一般聲明的 variables 如果是用 `tf.get_variable()` 出來的,直接用即可。`tf.Variable()` 和 `tf.get_variable()`   儘量用後者,因為`tf.Variable()`對 variable scope 無效。   2.
  • 手寫GRU-[TensorFlow]
    手頭堆了一堆論文都沒辦法去看了,推免應該是遙遙無期了 = =    但是發現,在NER中,當前時刻標籤的標註是會基於上一時刻的標註結果,其實個人感覺就是循環神經網絡的機制可以完成,然而循環神經網絡輸出為隱藏單元的狀態,直接將這種狀態作為標籤應該是不夠準確的,所以大多論文中會在最後一層網絡中添加一層MLP什麼的,對隱藏單元序列進行解碼輸出所謂標籤,然而作為TensorFlow菜雞,一直就用人家封裝好的函數如下
  • TensorFlow 攜手 NVIDIA,使用 TensorRT 優化 TensorFlow Serving...
    HTTP/REST API at:localhost:8501 …$ curl -o /tmp/resnet/resnet_client.py https://raw.githubusercontent.com/tensorflow/serving/master/tensorflow_serving/example/resnet_client.py
  • TensorFlow極速入門
    最後給出了在 tensorflow 中建立一個機器學習模型步驟,並用一個手寫數字識別的例子進行演示。1、tensorflow是什麼?tensorflow 是 google 開源的機器學習工具,在2015年11月其實現正式開源,開源協議Apache 2.0。
  • 使用Tensorflow實現RNN-LSTM的菜鳥指南
    如果您尚未安裝Tensorflow,請按照此頁面上的說明進行操作,然後繼續。導入張量流為tf導入張量流後,我們將定義兩個變量來保存輸入數據和目標數據。我們已經製作了Tensorflow佔位符,它們基本上就是它們,佔位符將在稍後提供數據。現在我們將創建RNN單元。Tensorflow支持LSTM,GRU(與LSTM略有不同的架構)和簡單的RNN單元。我們將使用LSTM完成此任務。
  • 《哈利波特》:霍格沃茲學院外的禁林中都有哪些神奇的生物?
    當然,在霍格沃茲中,哈迷們見證了哈利波特、赫敏、羅恩等小夥伴們的成長歲月。然而,在霍格沃茲學院外有著一個被命名為「禁林」的地方,那裡暗藏著多種神奇的生物,今天就和小編繼續跟著我們共同的記憶回到魔法世界,回到霍格沃茲,回到傳說中的黑森林,去看一看哪裡的神奇生物吧!
  • 谷歌開放GNMT教程:如何使用TensorFlow構建自己的神經機器翻譯系統
    機器之心對該教程進行簡要的描述,跟詳細和精確的內容請查看項目原網站。GitHub 連結:https://github.com/tensorflow/nmt機器翻譯,即跨語言間的自動翻譯,是機器學習社區最活躍的研究領域。在機器翻譯的眾多方法中,序列到序列(sequence-to-sequence,seq2seq)模型 [1, 2] 近期獲得巨大成功。
  • 玩轉TensorFlow?你需要知道這30功能
    地址是:tensorflow.org/tfx/?網址是:https://www.tensorflow.org/serving/?我還需要多用用這個網址:https://www.tensorflow.org/swift/11)KerasKeras 如今直接集成在 TF 中,也就是
  • Tensorflow 全網最全學習資料匯總之Tensorflow 的入門與安裝【2】
    包括生成三維數據,然後用一個平面擬合它,以及通過 variable 實現一個簡單的計數器等。經過了以上來自民間的實踐教程之後,相信各位讀者對TensorFlow的大致情況和具體安裝方法已經有了自己的理解。下面對於那些想要更全面和深入地了解TensorFlow的讀者,我們推薦幾個官方的教程。5.
  • 趣說哈利波特:霍格沃茲學校的四大院長中,誰的魔法實力最強?
    《哈利波特》中,海格初次見到哈利後,給他普及魔法界的常識時,就提到過伏地魔黑暗勢力最為鼎盛時也沒有打過霍格沃茲的主意,因為霍格沃茲有伏地魔最為忌憚的鄧布利多在。不過話說回來,霍格沃茲除了校長鄧布利多外,以麥格教授為首的四大學院院長也是實力強大的精英巫師,這也使伏地魔不敢輕易來霍格沃茲搞事。
  • tensorflow初級必學算子
    在之前的文章中介紹過,tensorflow框架的核心是將各式各樣的神經網絡抽象為一個有向無環圖,圖是由tensor以及tensor變換構成;雖然現在有很多高階API可以讓開發者忽略這層抽象,但對於靈活度要求比較高的算法仍然需要開發者自定義網絡圖,所以建議開發者儘量先學習tf1.x
  • Tensorflow基礎教程15天之創建Tensor
    常量Tensor用『zero』填充Tensorzero_tsr = tf.zeros([row_dim, col_dim])用『one』填充Tensor ones_tsr = tf.ones([row_dim, col_dim])使用現有常數創建Tensor constant_tsr = tf.constant([1,2,3])映射Tensor我們也可以映射其他Tensor來創建新的Tensor
  • 在Windows中安裝Tensorflow和Kears深度學習框架
    在命令提示符窗口輸入下列命令: 建立Tensorflow Anaconda虛擬環境 conda create --name tensorflow python=3.5 anaconda 執行後屏界面顯示如圖3-9所示。
  • 教程| 如何用TensorFlow在安卓設備上實現深度學習推斷
    她在 Insight 工作的時候,在安卓系統上用 TensorFlow 部署了一個 WaveNet 模型。本文詳細介紹了部署和實現過程。對於個人和公司來說,存在許多狀況是更希望在本地設備上做深度學習推斷的:想像一下當你在旅行途中沒有可靠的網際網路連結時,或是要處理傳輸數據到雲服務的隱私問題和延遲問題時。
  • 基於TensorFlow 、OpenCV 和 Docker 的實時視頻目標檢測
    此外,在次項目我還添加了一個視頻後處理功能,同樣使用 multiprocessing 庫來減少處理時間(使用 Tensorflow 原始目標檢測 API 處理時間會非常長)。實時和視頻目標識別都可以在我的個人筆記本電腦上以高性能運行,僅使用 8GB CPU。
  • TensorFlow 中文資源全集,學習路徑推薦
    入門教程,簡單的模型學習和運行。實戰項目,根據自己的需求進行開發。/GitHub:https://github.com/tensorflow安裝教程中文安裝教程Mac安裝:http://www.cnblogs.com/tensorflownews/p/7298646.htmlubuntu 16.04 安裝 tensorflow-gpu:http://www.tensorflownews.com/2017/09/02/tensorflow-gpu-install-ubuntu
  • TensorFlow極簡教程:創建、保存和恢復機器學習模型
    bare在每個例子中,我們用一條直線擬合一些數據。使用梯度下降(gradient descent)確定最適合數據的線的斜率和 y 截距的值。如果你不知道梯度下降,請查看維基百科:https://en.wikipedia.org/wiki/Gradient_descent創建所需的變量後,數據和線之間的誤差是可以被定義(計算)的。
  • 《哈利波特》:霍格沃茲四個學院的代表人物,原來有這幾個人?!
    在《哈利波特》系列故事中,描繪了一個神秘的魔法世界,在這個世界裡有一所專門培養魔法師的學院——霍格沃茲魔法學校。而霍格沃茲又分別由格蘭芬多、赫奇帕奇、拉文克勞、斯萊特林 四個分學院組成。當然,每個學院招收的學生也風格迥異。
  • 步履不停:TensorFlow 2.4新功能一覽!
    ParameterServerStrategy        https://tensorflow.google.cn/api_docs/python/tf/distribute/experimental/ParameterServerStrategy參數伺服器訓練集群包含工作節點和參數伺服器。
  • TensorFlow 資源大全中文版
    TensorFlow 最初由Google Brain 小組(隸屬於Google機器智能研究機構)的研究員和工程師們開發出來,用於機器學習和深度神經網絡方面的研究,但這個系統的通用性使其也可廣泛用於其他計算領域。