boostcampaitech2 / final-project-level3-nlp-06

final-project-level3-nlp-06 created by GitHub Classroom
5 stars 2 forks source link

유사도 모델 데이터셋 텐서 만들기... #6

Open BaekTree opened 2 years ago

BaekTree commented 2 years ago

image

각 기업 마다 List[psg]으로 구성되어 있음. 기업 마다 psg 수가 다름.

데이터셋 넣을 때 tensor 기업 마다 psg 수에 대한 텐서 크기가 다름.

TensorDataset으로 concat 해서 넣으려고 했는데 잘 안됨.

BaekTree commented 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)
BaekTree commented 2 years ago

padding으로 매꾸고 각 기업 마다 몇개인지 table tensor을 만들어서 데이터로더에 같이 넘김.

BaekTree commented 2 years ago

이렇게 하면 학습 함수에서 table을 보고 다시 padding에 해당하는 것으로 분리 가능했음...

또 문제는... 모델에 넣을 때도 어차피 stack된거 한꺼번에 넘기지 않나...?

BaekTree commented 2 years ago

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)
BaekTree commented 2 years ago

Cumstom Dataset으로 시도 했으나 여기도 어차피 stack으로 배치를 만든다.

# # 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