[Week 9- Day 4] 회고

2022. 3. 18. 00:02About Me/AI Tech

# Byte Pair Encoding (BPE)

from typing import List
from collections import Counter
from itertools import chain

# 단어 끝을 나타내는 문자
WORD_END = '_'

def build_bpe(
    corpus: List[str],
    max_vocab_size: int
) -> List[int]:
    """ BPE Vocab 만들기
    Byte Pair Encoding을 통한 Vocab 생성을 구현하세요.
    단어의 끝은 '_'를 사용해 주세요.
    이때 id2token을 서브워드가 긴 길이 순으로 정렬해 주세요.
    
    Note: 만약 모든 단어에 대해 BPE 알고리즘을 돌리게 되면 매우 비효율적입니다.
          왜냐하면 대부분의 단어는 중복되기 때문에 중복되는 단어에 대해서는 한번만 연산할 수 있다면 매우 효율적이기 때문입니다.
          따라서 collections 라이브러리의 Counter를 활용해 각 단어의 빈도를 구하고,
          각 단어에 빈도를 가중치로 활용하여 BPE를 돌리면 시간을 획기적으로 줄일 수 있습니다.
          물론 이는 Optional한 요소입니다.

    Arguments:
    corpus -- Vocab을 만들기 위한 단어 리스트
    max_vocab_size -- 최대 vocab 크기

    Return:
    id2token -- 서브워드 Vocab. 문자열 리스트 형태로 id로 token을 찾는 매핑으로도 활용 가능
    """
    ### YOUR CODE HERE
    ### ANSWER HERE ###
    vocab = list(set(chain.from_iterable(corpus)) | {WORD_END})
    corpus = {' '.join(word + WORD_END): count for word, count in Counter(corpus).items()}

    while len(vocab) < max_vocab_size:
        counter = Counter()
        for word, word_count in corpus.items():
            word = word.split()
            counter.update({
                pair: count * word_count 
                for pair, count in Counter(zip(word, word[1:])).items()
            })

        if not counter:
            break
        
        pair = counter.most_common(1)[0][0]
        vocab.append(''.join(pair))
        corpus = {
            word.replace(' '.join(pair), ''.join(pair)): count
            for word, count in corpus.items()
        }

    id2token = sorted(vocab, key=len, reverse=True)
    return id2token
def encode(
    sentence: str,
    id2token: List[str]
) -> List[int]:
    """ BPE 인코더
    문장을 받아 BPE 토큰화를 통하여 고유 id의 수열로 바꿉니다.
    문장은 공백으로 단어단위 토큰화되어있다고 가정하며, Vocab은 sentence의 모든 문자를 포함한다고 가정합니다.
    찾을 수 있는 가장 긴 토큰부터 바꿉니다.
    
    Note: WORD_END를 빼먹지 마세요.

    Arguments:
    sentence -- 인코드하고자 하는 문장
    id2token -- build_bpe를 통해 만들어진 Vocab
    
    Return:
    token_ids -- 인코드된 토큰 id 수열
    """

    ### YOUR CODE HERE
    ### ANSWER HERE ###
    def recursive(word: str):
        if not word:
            return []
        for token_id, token in enumerate(id2token):
            index = word.find(token)
            if index != -1:
                break
        else:
            raise Exception("토큰을 찾을 수 없습니다!")

        return recursive(word[:index]) + [token_id] + recursive(word[index+len(token):])
    
    token_ids = list(chain.from_iterable(recursive(word + WORD_END) for word in sentence.split()))
    return token_ids

 

# Bucketing

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)]

 

 

## 피어 세션

수다 떠느라 Further Question을 내일 다 하기로 하고, 멘토링 시간을 갖었다.

오피스 아워 때, 논문을 읽고 이해한 것을 구현하는 것을 추천하였다. 만약 아직 그렇게 하기 힘들다면, 허깅페이스에서 만든 transformer 코드를 잘 뜯어보거나 남이 만든 Simple model을 많이 보는 것이 좋다고 한다.

멘토링 시간에는 실수가 결국은 장애물이 될 수 있도록 하라는 얘기를 잠시 했다. 또 대회를 시작하기 전에 꼭 Task와 관련된 논문을 찾아보라고 하셨다. 요새 needs가 많은 Task에 대해 질문을 했었는데, 검색/ 음성 인식/ 합성을 추천하였다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'About Me > AI Tech' 카테고리의 다른 글

[Week 10- Day 1] 회고  (0) 2022.03.22
[Week 9- Day 5] 회고  (0) 2022.03.18
[Week 9- Day 3] 회고  (0) 2022.03.17
[Week 9- Day 2] 회고 - 깃허브 특강  (0) 2022.03.15
[Week 9- Day 1] 회고  (0) 2022.03.15