前言
這篇博客以PTB數據集為例,詳細講解了如何將txt格式的數據集文件,轉換為pytorch框架可以直接處理的tensor變量,並附上相應代碼
@
1. PTB 數據集
PTB數據集含有三個txt文件,分別作為訓練集(train),驗證集(valid)和測試集(test);這三個txt文件分別包含42000,3000和3000句英文;
我們要將其轉化為pytorch可處理的tensor類型數據集,需要以下幾步:
- 依次讀取每一行的訓練集文件(train.txt),為每一個讀到的單詞分配序號,構建詞匯表
- 出現頻率低於min_ooc(通常默認為3)次的詞匯,單詞一率變為未知單詞 < unk > ,分配序號1
- < sos >為每句話的起始信號,分配序號2
- < eos >為每句話的結束信號,分配序號3
- 由於每句話長度不一樣,而pytorch批處理數據,需要統一句子長度,因此長度較短的句子用 < pad > 填充,分配序號0
- 統一句子長度為max_sentence_length(默認50)
- 高於50個單詞的句子,只保留前50個單詞;
- 低於50個單詞的句子,用 < pad > 信號填充到50
- 根據訓練集構建的詞匯表,將訓練集,驗證集和測試集都變成數字序號表示的句子,如 a cat not is dog變成 2 25 54 12 0 0
- 構建三個數據集加載轉換后的用數字序號表示的句子,並將其錯位句子作為該句子的標簽(target),例如, a cat not is dog變成 2 25 54 12 0 0, 那它對應的target就是 25 54 12 3 0 0 了 (2 3 分別為起始,末尾信號)
- 將其轉換為批處理的tensor變量
這樣我們就能得到pytorch可以直接加載處理的tensor類型數據集了
2. 構建詞匯表
我們先定義一個字典類型的變量,該字典類型變量,會將輸入的句子里的新單詞添加到字典中,並記錄該單詞的出現次數
引入庫文件:
import json
import torch
import numpy as np
from nltk.tokenize import TweetTokenizer
from collections import Counter, OrderedDict,defaultdict
import io
import os
from torch.utils.data import DataLoader
class OrderedCounter(Counter, OrderedDict): #這樣定義的字典類型變量,會將輸入的句子里的新單詞添加到字典中,並記錄該單詞的出現次數
"""Counter that remembers the order elements are first encountered"""
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
依次讀入ptb.train.txt的每一句話,並對其進行分詞,不區分大小寫;
- 分詞:由於默認可以通過空格來分開每個單詞,但專業的分詞函數更好些
def create_vocab(split):
tokenizer = TweetTokenizer(preserve_case=False) #分詞,不區分大小寫
w2c = OrderedCounter()
w2i = dict()
i2w = dict()
special_tokens = ['<pad>', '<unk>', '<sos>', '<eos>']
for st in special_tokens:
i2w[len(w2i)] = st
w2i[st] = len(w2i)
with open(split, 'r') as file:
for i, line in enumerate(file):
words = tokenizer.tokenize(line)
w2c.update(words) #這段程序將文件中出現過的所有單詞加載到字典類型變量w2c中,並存儲了他們出現的次數
for w, c in w2c.items():
if c > 3 and w not in special_tokens: #依次為出現次數大於3,且不是那4種特殊信號的單詞分配序號
i2w[len(w2i)] = w
w2i[w] = len(w2i) #w2i格式為'cat':50這種,i2w為50:'cat'這種
return w2i,i2w
實例化一下試試:
3. 將訓練集,驗證集和測試集根據詞匯表轉換為數字序號,並轉換為tensor
def create_data(split,w2i): #split為待轉換的txt文件地址
tokenizer = TweetTokenizer(preserve_case=False) #分詞,不區分大小寫
data = defaultdict(dict)
with open(split, 'r') as file: #讀取該文件的每一行
for i, line in enumerate(file):
words = tokenizer.tokenize(line) #分詞
input = ['<sos>'] + words #輸入的開頭增加<sos>信號
input = input[:50] #只保留前50個(起始信號<sos> + 文本的前49個單詞)
target = words[:50-1] #輸入對應的target,也只保留50個(取文本的前49個單詞+ 結束信號<eos>)
target = target + ['<eos>']
length = len(input)
input.extend(['<pad>'] * (50-length)) #輸入和target,不足50個的,用<pad>補足50個
target.extend(['<pad>'] * (50-length))
input = [w2i.get(w, w2i['<unk>']) for w in input]
target = [w2i.get(w, w2i['<unk>']) for w in target]
id = len(data) #id表示該數據集的第id句話
inpu_t = torch.from_numpy(np.asarray(input)) #轉換為tensor形式
targe_t = torch.from_numpy(np.asarray(target))
data[id]['input'] = inpu_t
data[id]['target'] = targe_t
data[id]['length'] = length
return data
實例化一下試試:
3. 轉換為批處理的tensor變量
data_loader = DataLoader(
dataset= data,
batch_size= 64,#批處理大小
shuffle=True #是否打亂排序
)
實例化試試:
總結
這篇博客以PTB數據集為例,介紹了如何將txt形式的數據集轉換為pytorch框架中可以使用的,批處理的tensor形式
參考項目:github上以PTB數據集訓練的一個語言模型的項目