Open BaekTree opened 2 years ago
Custom Dataset을 만들었다. 만들기는 가능. 로더에 적재도 가능. 학습할 때도 그대로 될는지 실험 필요 시도 중...
for batch in dataloader:
...
이렇게 하면
/opt/conda/lib/python3.8/site-packages/torch/utils/data/_utils/collate.py in default_collate(batch)
53 storage = elem.storage()._new_shared(numel)
54 out = elem.new(storage)
---> 55 return torch.stack(batch, 0, out=out)
56 elif elem_type.__module__ == 'numpy' and elem_type.__name__ != 'str_' \
57 and elem_type.__name__ != 'string_':
RuntimeError: stack expects each tensor to be equal size, but got [3, 3, 512] at entry 0 and [3, 26, 512] at entry 1
default_collate을 사용하는데 이걸 custom으로 바꾸면 가능할 수도?
dataloader에서 호출하는 default_collate을 알아봤는데... 여기도 어차피 stack을 사용함.
https://github.com/pytorch/pytorch/blob/master/torch/utils/data/_utils/collate.py
def default_collate(...
if isinstance(elem, torch.Tensor):
out = None
if torch.utils.data.get_worker_info() is not None:
# If we're in a background process, concatenate directly into a
# shared memory tensor to avoid an extra copy
numel = sum(x.numel() for x in batch)
storage = elem.storage()._new_shared(numel)
out = elem.new(storage)
return torch.stack(batch, 0, out=out)
padding으로 매꾸고 각 기업 마다 몇개인지 table tensor을 만들어서 데이터로더에 같이 넘김.
이렇게 하면 학습 함수에서 table을 보고 다시 padding에 해당하는 것으로 분리 가능했음...
또 문제는... 모델에 넣을 때도 어차피 stack된거 한꺼번에 넘기지 않나...?
pooling이 커저 OOM이 났음.
# 데이터 원형 만들기
# 기업과 뉴스 pair가 만들어져 있다고 가정. 여기서 0번째 두 데이터가 페어라고 가정.
for psg in dart_data[0]:
# print( ( news_data[0], psg ) )
( news_data[0], psg )
break
# 데이터 셋에 넣을 때 tensor 형태로 넣을 수 있다.
# 각 ids, token, type 텐서로 쪼개진다.
# 뉴스는 (3, len_seq)
# 다트는 (k, 3, len_seq)
news_tok = tokenizer(news_data,padding = "max_length", return_tensors = "pt", truncation = True) # string 1개
news_input_ids = news_tok['input_ids']
news_type_ids = news_tok['token_type_ids']
news_att_mask = news_tok['attention_mask']
torch.stack( (news_att_mask, news_att_mask, news_att_mask), dim = 0 ).shape
# error -> tokenized list is None...
# from collections import defaultdict
# dic = defaultdict(int)
# for d in dart_data:
# dic[len(d)] += 1
# if len(d) == 0:
# print(d)
# sorted(dic.items(), key = lambda x:x[0])
# 다트 데이터
dart_input_ids = []
dart_type_ids = []
dart_att_mask = []
psg_table = []
max_num_psg = 0
for d in dart_data:
if len(d) > 0:
d_tok = tokenizer(d, padding = "max_length", return_tensors = "pt", truncation = True ) # List[str]
dart_input_ids.append( d_tok['input_ids'] )
dart_type_ids.append( d_tok['token_type_ids'] )
dart_att_mask.append( d_tok['attention_mask'] )
num_psg = d_tok['attention_mask'].shape[0]
max_num_psg = max(num_psg, max_num_psg)
psg_table.append( num_psg )
psg_table = torch.tensor(psg_table)
# 차원 맞추기 위해서 채워넣어야 한다. 0 텐서?
# 1개로 test
ids = dart_input_ids[0]
ids.shape
seq_len = ids.shape[1]
data_size = ids.shape[0]
padding = torch.zeros( max_num_psg - data_size, seq_len )
res = torch.cat((ids, padding))
# check all value maintained and same
ids == res[:data_size]
padding.shape, ids.shape, res.shape, res[:data_size].shape#, ids, res[:data_size]
res.shape
# 전체 다트 데이터에 대해서 passing 채워넣기
input_ids_list_same_size = []
type_ids_list_same_size = []
att_mask_list_same_size = []
for i in range(len(dart_input_ids)):
ids = dart_input_ids[i]
ids.shape
seq_len = ids.shape[1]
data_size = ids.shape[0]
padding = torch.zeros( max_num_psg - data_size, seq_len )
res = torch.cat((dart_input_ids[i], padding))
input_ids_list_same_size.append( res )
res = torch.cat((dart_type_ids[i], padding))
type_ids_list_same_size.append( res )
res = torch.cat((dart_att_mask[i], padding))
att_mask_list_same_size.append( res )
dart_input_ids = torch.stack(input_ids_list_same_size)
dart_type_ids = torch.stack(type_ids_list_same_size)
dart_att_mask = torch.stack(att_mask_list_same_size)
dart_att_mask.shape, news_att_mask.shape, psg_table.shape
for batch in dataloader:
news_data = {
'input_ids' : batch[0].to(device).to(torch.int64), # ( B, seq_len )
'token_type_ids' : batch[1].to(device).to(torch.int64),
'attention_mask' : batch[2].to(device).to(torch.int64),
}
B = batch[3].shape[0]
max_psg_len = batch[3].shape[1]
dart_data = {
'input_ids' : batch[3].view(B * max_psg_len, -1).to(device).to(torch.int64), # (B, max_psg_len, seq_len)
'token_type_ids' : batch[4].view(B * max_psg_len, -1).to(device).to(torch.int64),
'attention_mask' : batch[5].view(B * max_psg_len, -1).to(device).to(torch.int64),
}
model.train()
model.zero_grad()
model(**dart_data)
# # Dustom dataset으로 시도
# from torch.utils.data import Dataset
# class Train_Dataset(Dataset):
# def __init__(self):
# # def __init__(self, df, source_column, target_column, transform=None, freq_threshold = 5,
# # source_vocab_max_size = 10000, target_vocab_max_size = 10000):
# news_tok = tokenizer(news_data,padding = "max_length", return_tensors = "pt", truncation = True) # string 1개
# self.news_input_ids = news_tok['input_ids']
# self.news_type_ids = news_tok['token_type_ids']
# self.news_att_mask = news_tok['attention_mask']
# self.dart_input_ids = []
# self.dart_type_ids = []
# self.dart_att_mask = []
# psg_table = []
# max_num_psg = 0
# for d in dart_data:
# if len(d) > 0:
# d_tok = tokenizer(d, padding = "max_length", return_tensors = "pt", truncation = True ) # List[str]
# self.dart_input_ids.append( d_tok['input_ids'] )
# self.dart_type_ids.append( d_tok['token_type_ids'] )
# self.dart_att_mask.append( d_tok['attention_mask'] )
# def __len__(self):
# return self.news_input_ids.shape[0]#len()
# '''
# __getitem__ runs on 1 example at a time. Here, we get an example at index and return its numericalize source and
# target values using the vocabulary objects we created in __init__
# '''
# def __getitem__(self, index):
# # self.
# news_source = torch.stack( (self.news_att_mask[index], self.news_att_mask[index], self.news_att_mask[index]), dim = 0 )#.shape
# dart_source = torch.stack( (self.dart_att_mask[index], self.dart_att_mask[index], self.dart_att_mask[index]), dim = 0 )#.shape
# # source_text = self.source_texts[index]
# # target_text = self.target_texts[index]
# # if self.transform is not None:
# # source_text = self.transform(source_text)
# # #numericalize texts ['<SOS>','cat', 'in', 'a', 'bag','<EOS>'] -> [1,12,2,9,24,2]
# # numerialized_source = [self.source_vocab.stoi["<SOS>"]]
# # numerialized_source += self.source_vocab.numericalize(source_text)
# # numerialized_source.append(self.source_vocab.stoi["<EOS>"])
# # numerialized_target = [self.target_vocab.stoi["<SOS>"]]
# # numerialized_target += self.target_vocab.numericalize(target_text)
# # numerialized_target.append(self.target_vocab.stoi["<EOS>"])
# #convert the list to tensor and return
# # return torch.tensor(numerialized_source), torch.tensor(numerialized_target)
# return torch.tensor(news_source), torch.tensor(dart_source)
# train_set = Train_Dataset()
# BATCH_SIZE = 2
# dataloader = DataLoader(train_set, batch_size=BATCH_SIZE)
# dataloader
각 기업 마다 List[psg]으로 구성되어 있음. 기업 마다 psg 수가 다름.
데이터셋 넣을 때 tensor 기업 마다 psg 수에 대한 텐서 크기가 다름.
TensorDataset으로 concat 해서 넣으려고 했는데 잘 안됨.