在文本資料中,每個句子的長度不同,常使用填充的操作将句子長度補齊。然而,在自然語言進行中,句子并非随機選取,而是在上下文之間有關聯的内容,我們必須将前面的句子的資訊傳遞到後面的句子。如果模型沒有大小限制,顯然最理想的情況就是将整個文檔前後連接配接起來作為一個句子來訓練(如下圖所示,有若幹個序列,每個序列代表一個句子,每個句子中包含經過預處理的相應單詞的編碼)。
但是現實根本無法實作,由于文本中通常會包含大量的詞彙,是以這種情況必然會導緻計算圖過大,另外序列過長還可能造成訓練中梯度爆炸的問題(梯度爆炸)。為此,我們可以采用并行處理句子的方法,每一次計算可以對多個句子進行并行處理。解決方案是,先将所有的句子即序列羅列成列向量
之後再從中切分出若幹個batch大小的資料集(程式中為data,這裡隻畫出前幾個)
每次訓練需要處理的句子個數和句子中包含的單詞數量可以由使用者自由設定(即一個batch的行數和列數) 同時,我們還需從每個句子的第二個單詞起按照同樣的batch大小進行切分(程式中為label),每個label中包含着對應data中所有句子的需要預測的下一個單詞。 該方法叫做batching方法
import codecs
import numpy as np
output_path="train.txt" #語句中相應單詞對應的編碼檔案
TRAIN_BATCH_SIZE = 20 #一個batch的行數
TRAIN_NUM_STEP = 35 #一個batch的列數
def read_data(file_path):
with codecs.open(file_path, 'r', 'utf-8') as fin:
id_string = ' '.join([line.strip() for line in fin])
id_list = [int(w) for w in id_string.split()]
return id_list
def make_batches(id_list, batch_size, num_step):
num_batches = len(id_list) // (batch_size * num_step) #擷取batch的大小
data = np.array(id_list[:num_batches * batch_size * num_step])
data = np.reshape(data, [batch_size, num_batches * num_step])
data_batches = np.split(data, num_batches, axis=1)
label = np.array(id_list[1:num_batches * batch_size * num_step + 1])
label = np.reshape(label, [batch_size, num_batches * num_step])
label_batches = np.split(label, num_batches, axis=1)
return list(zip(data_batches, label_batches))
def main():
train_batches = make_batches(read_data(output_path), TRAIN_BATCH_SIZE, TRAIN_NUM_STEP)
# 在這裡插入模型訓練代碼
if __name__== "__main__":
main()