本教程的目的是帶領大家學會,根據譯文片段預測翻譯作者
本次用到的資料集是三個 txt 文本,分别是 cowper.txt、derby.txt、butler.txt ,該文本已經經過一些預處理,去除了表頭,頁眉等
接下來我們加載資料,這裡我們使用 tf.data.TextLineDataset API,而不是之前使用的 text_dataset_from_directory,兩者的差別是,前者加載 txt 檔案裡的每一行作為一個樣本,後者是加載整個 txt 檔案作為一個樣本
DIRECTORY_URL = 'https://storage.googleapis.com/download.tensorflow.org/data/illiad/'
FILE_NAMES = ['cowper.txt', 'derby.txt', 'butler.txt']
for name in FILE_NAMES:
text_dir = utils.get_file(name, origin=DIRECTORY_URL + name)
parent_dir = pathlib.Path(text_dir).parent
list(parent_dir.iterdir())
def labeler(example, index):
return example, tf.cast(index, tf.int64)
labeled_data_sets = []
for i, file_name in enumerate(FILE_NAMES):
lines_dataset = tf.data.TextLineDataset(str(parent_dir/file_name))
labeled_dataset = lines_dataset.map(lambda ex: labeler(ex, i))
labeled_data_sets.append(labeled_dataset)
如上圖所示,我們可以看到,txt 檔案裡的每一行确實是一個樣本,其實上面的資料已經經過進一步處理了,變成 (example, label) pair 了
接下來我們需要對文本進行 standardize and tokenize,然後再使用 StaticVocabularyTable,建立 tokens 到 integers 的映射
這裡我們使用 UnicodeScriptTokenizer 來 tokenize 資料集,代碼如下所示
tokenizer = tf_text.UnicodeScriptTokenizer()
def tokenize(text, unused_label):
lower_case = tf_text.case_fold_utf8(text)
return tokenizer.tokenize(lower_case)
tokenized_ds = all_labeled_data.map(tokenize)
上圖是 tokenize 的結果展示
下一步,我們需要建立 vocabulary,根據 tokens 的頻率做一個排序,并取排名靠前的 VOCAB_SIZE 個元素
tokenized_ds = configure_dataset(tokenized_ds)
vocab_dict = collections.defaultdict(lambda: 0)
for toks in tokenized_ds.as_numpy_iterator():
for tok in toks:
vocab_dict[tok] += 1
vocab = sorted(vocab_dict.items(), key=lambda x: x[1], reverse=True)
vocab = [token for token, count in vocab]
vocab = vocab[:VOCAB_SIZE]
vocab_size = len(vocab)
print("Vocab size: ", vocab_size)
print("First five vocab entries:", vocab[:5])
接下來,我們需要用 vocab 建立 StaticVocabularyTable,因為 0 被保留用于表明 padding,1 被保留用于表明 OOV token,是以我們的實際 map tokens 的integer 是 [2, vocab_size+2],代碼如下所示
keys = vocab
values = range(2, len(vocab) + 2) # reserve 0 for padding, 1 for OOV
init = tf.lookup.KeyValueTensorInitializer(
keys, values, key_dtype=tf.string, value_dtype=tf.int64)
num_oov_buckets = 1
vocab_table = tf.lookup.StaticVocabularyTable(init, num_oov_buckets)
最後我們要封裝一個函數用于 standardize, tokenize and vectorize 資料集,通過 tokenizer and lookup table
def preprocess_text(text, label):
standardized = tf_text.case_fold_utf8(text)
tokenized = tokenizer.tokenize(standardized)
vectorized = vocab_table.lookup(tokenized)
return vectorized, label
上圖是關于把 raw text 轉化成 tokens 的展示結果
接下來,我們需要對資料集進行劃分,然後再建立模型,最後就可以開始訓練了,代碼如下所示
all_encoded_data = all_labeled_data.map(preprocess_text)
train_data = all_encoded_data.skip(VALIDATION_SIZE).shuffle(BUFFER_SIZE)
validation_data = all_encoded_data.take(VALIDATION_SIZE)
train_data = train_data.padded_batch(BATCH_SIZE)
validation_data = validation_data.padded_batch(BATCH_SIZE)
vocab_size += 2
train_data = configure_dataset(train_data)
validation_data = configure_dataset(validation_data)
model = create_model(vocab_size=vocab_size, num_labels=3)
model.compile(
optimizer='adam',
loss=losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
history = model.fit(train_data, validation_data=validation_data, epochs=3)
上圖是訓練的結果展示,在驗證集上的準确率達到了 84.18%
inputs = [
"Join'd to th' Ionians with their flowing robes,", # Label: 1
"the allies, and his armour flashed about him so that he seemed to all", # Label: 2
"And with loud clangor of his arms he fell.", # Label: 0
]
predicted_scores = export_model.predict(inputs)
predicted_labels = tf.argmax(predicted_scores, axis=1)
for input, label in zip(inputs, predicted_labels):
print("Question: ", input)
print("Predicted label: ", label.numpy())
最後我們用訓練後的模型進行預測,結果如下圖所示
預測結果和實際标簽都對應上了
代碼位址:
https://codechina.csdn.net/csdn_codechina/enterprise_technology/-/blob/master/predict_translations_author.ipynb