일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 백트랙킹
- dfs
- 구현
- ODQA
- 백준
- Level2
- Level2_PStage
- 파이썬 3
- 단계별문제풀이
- 개인회고
- python3
- 기술면접
- 알고리즘스터디
- U_stage
- 다이나믹프로그래밍
- 부스트캠프_AITech3기
- mrc
- 이진탐색
- 부스트캠프_AITech_3기
- 최단경로
- 다시보기
- 프로그래머스
- 그리디
- 그래프이론
- 이코테
- Level1
- dp
- 정렬
- 주간회고
- 알고리즘_스터디
- Today
- Total
국문과 유목민
[NLP과제] 함수 정리 (chain, Pythonic) 본문
부스트캠프_AITech 8주차에 진행되었던 과제를 풀고 Solution을 보면서, Pythonic하게 만들어진 코드를 보고서 기억해두면 좋을 것 같아서 정리하고자 한다. 해당 과제의 문제를 올리지는 않고, 주어진 문제에 대해서 어떻게 코드를 간결하게 짰는지에 대해서만 정리하고자 하며, 추가적으로 새로 알게 된 좋은 함수들을 정리하고자 한다.
기본과제3_Subword_level_Language_Model
Subword_level_Language_Model을 만들기 위해서 BPE Vocabulary를 만드는 함수를 구현하는 문제였다. 해당 문제에서 chain함수와 Counter 객체를 활용해 연산에 필요한 변수를 간결하게 정의할 수 있었다.
from itertools import chain
from collections import Counter
### BPE Vocab을 만들기 위한 Word tokenizing방법
WORD_END = '_'
corpus = ['low'] * 5 + ['lower'] * 2 + ['newest'] * 6 + ['widest'] * 3
# Chain
vocabulary = list(set(chain.from_iterable(corpus)) | {WORD_END})
print(vocabulary
# Counter
corpus = {' '.join(word + WORD_END): count for word, count in Counter(corpus).items()}
print(corpus)
### 이하 생략 ###
### Output ###
# > ['w', 'r', 'd', 'e', 'o', 'n', 'i', 'l', '_', 't', 's']
# > {'l o w _': 5, 'l o w e r _': 2, 'n e w e s t _': 6, 'w i d e s t _': 3}
해당 코드에서 내가 얻었던 인사이트는 다음과 같다.
- Set을 통한 단어 추가
- { }을 활용한 List Comprehension
- chain함수의 사용
그 중 Chain 함수에 대해 알아보던 도중 꽤 유용하다는 생각이 들었다. 우선 Chain함수는 여러 개의 리스트를 하나의 리스트로 만들어주는 fancy한 함수이다. (단, itertools 객체 이므로 List로 형변환이 필요하다.) 여기서는 chain.from_iterable을 사용하는데, iterble 객체를 입력으로 받아서 chain 함수를 적용시켜준다.
import numpy as np
ls1 = np.random.randint(50, 100, 5)
ls2 = np.random.randint(1, 50, 5)
list(chain(ls1, ls2))
### Output ###
# > [76, 84, 51, 81, 72, 28, 4, 4, 2, 38]
ls3 = [[i]for i in range(10)]
print(ls3)
# [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
list(chain.from_iterable(ls3))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
기본과제4_Preprocessing_for_NMT_Model
Natural Machine Translation을 하기 위해 필요한 함수들을 작성하는 과제였다. 해당 과제를 진행하면서 Pythonic하게 짜인 코드를 본 것 같아서 해당 코드를 좀 정리해두고자 한다. 특히, Pad_sequence함수를 사용함에 있어서 torch의 pad_sequence는 List가 아닌 Tensor를 입력으로 받기 때문에 이를 형변환 해줘야 한다는 사실을 새로 알게 됐다. 그리고 이 과정에서 좀 코드를 깔끔하게 짜지 못했었다.
collate_fn
다양한 길이의 문장을 배치화하기 위하여 한 배치 내의 최대 길이 문장을 기준으로 문장에 패딩을 넣는 과정이 필요하다. 이때, 길이가 다른 문장들의 경우 차원이 맞지 않기 때문에, Padding(=0)을 넣어서 차원을 맞춰줘야 한다.
# dictionary는 튜플을 키값으로 줄 수 있다.
batched_samples = [([1, 2, 3, 4], [1]), ([1, 2, 3], [1, 2]), ([1, 2], [1, 2, 3]), ([1], [1, 2, 3, 4])]
src_sentence_list, trg_sentence_list = zip(*batched_samples)
src_sentences = pad_sequence([torch.Tensor(sentence).to(torch.long) for sentence in src_sentence_list],
batch_first=True,
padding_value=PAD)
tgt_sentences = pad_sequence([torch.Tensor(sentence).to(torch.long) for sentence in trg_sentence_list],
batch_first=True,
padding_value=PAD)
해당 코드에서 내가 얻었던 인사이트는 다음과 같다.
- Pad_sequence는 텐서만 입력으로 가능하기 때문에 Lis로의 형변환이 필요하다.
- [torch.Tensor(sentence).to(torch.long) for sentence in src_sentence_list]: 주어진 Sentence List를 Tensor로 바꿔주는 함수
- zip함수는 입력으로 들어오는 Tuple들을 idx별로 묶어준다. (반복문 없이 한 번에 List형태로 return되는 것은 처음 봤음)
Bucketing
Bucketing은 델의 학습 시간을 단축하기 위해 고안된 방법으로 주어진 문장의 길이에 따라 데이터를 그룹화하여 패딩을 적용하는 기법입니다. 이 문장의 길이에 따라 미리 그룹화하여 패딩을 적용하면 학습을 효율적으로 진행할 수 있습니다.
sentence_length = [(random.randint(min_len, max_len), random.randint(min_len, max_len))
for _ in range(dataset_length)]
batch_size = 64
max_pad_len = 5
bucket_dict = defaultdict(list)
for index, (src_length, trt_length) in enumerate(sentence_length):
bucket_dict[(src_length // max_pad_len, trt_length // max_pad_len)].append(index)
batch_indices_list = [bucket[start:start+batch_size] for bucket in bucket_dict.values() for start in range(0, len(bucket), batch_size)]
해당 코드에서 내가 얻었던 인사이트는 다음과 같다.
- src_length와 trt_length를 padding length와 나눠 나온 몫의 쌍을 Key값으로 활용한다. 그렇게 함으로써 특정 범위가 Key값으로 설정이 되고, 이를 활용해 해당 범위에 있는 Value들을 별도로 Grouping할 수 있다.
- 이렇게 나온 Group들을 반복적으로 돌면서 batch_size만큼 잘라서 list에 넣어주면 된다.
- 이럴 경우 문장 수가 batch_size보다 작은 배치가 만들어질 수도 있지만, 그 수는 'src_length//max_pad_len'과 'tgt_length//max_pad_len'의 각 개수들의 곱을 넘지 않는다. (5개, 5개이면 작은 배치는 25개를 넘지 않는다.)
'IT 견문록 > 함수 및 코드 (디지털치매 대비)' 카테고리의 다른 글
Python String 관련 함수 (0) | 2022.03.21 |
---|---|
Plotly: Interactive Visualization (0) | 2022.02.18 |
Linux Shell & Vi Editor Command (0) | 2022.02.15 |
Visualization Libraries (Missingno, Treemap, WaffleChart, Venn) (0) | 2022.02.11 |
Matplotlib [polar, pie] 사용법 (0) | 2022.02.10 |