코딩딩딩

[NLP] 텍스트 전처리 - Text Cleaning, Tokenization 본문

NLP

[NLP] 텍스트 전처리 - Text Cleaning, Tokenization

komizke 2024. 9. 5. 12:00

1. Text Cleaning

● 소문자 변환: 대문자와 소문자의 차이 제거

 

● 불필요한 문자 제거: HTML 태그, HTTP 링크, 특수문자, 숫자, 긴 공백 등 제거

 

import re

def clean_text(text):
    # '-' -> ' ' 공백으로 변환
    # ex. state-of-the-art 이런 형태로 '-' 문자는 글에서 많이 사용됨.
    text = text.replace('-',' ')
    
    # HTML 태그 제거
    text = re.sub('<.*?>','',text)

    # HTTP 링크 제거
    text = re.sub(r'http\S+','',text)
    
    # 특수 문자 및 숫자 제거
    text = re.sub(r'[^a-zA-Z\s]','',text)
    
    # 불필요한 공백 제거
    text = ' '.join(text.split())
    
    # 소문자 변환
    text = text.lower()

    return text

text = "<p>50 basis-point cut <b>on the back of</b> softer commodity prices.</p> “We do expect higher volatility over coming weeks,” Visit https://finance.yahoo.com/"
cleaned_text = clean_text(text) 
print(cleaned_text)
# basis point cut on the back of softer commodity prices we do expect higher volatility over coming weeks visit

 

2. Tokenization

문장을 더 작은 단위로 분리하는 과정

 

● Word Tokenization

텍스트를 단어 단위로 분리

 

합성어, 복합어 등을 제대로 처리하기 어려움.

 

● Subword Tokenization

단어를 더 작은 단위로 분리

 

BERT, GPT와 같은 모델에서 사용함.

 

Ex1) WordPiece

문맥에 맞는 의미를 잘 반영하고 자주 사용되는 subword 생성

 

from transformers import BertTokenizer

# BERT 토크나이저 초기화
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

text = "tokenization"
# 문장 토큰화
tokens = tokenizer.tokenize(text)
print(tokens)
# 출력: ['token', '##ization']
# "##": 이 기호는 해당 토큰이 단어의 중간이나 끝부분임을 나타냄

 

Ex2) SentencePiece

텍스트를 하나의 연속적인 문자열로 취급

 

공백을 포함한 모든 문자를 동등하게 취급하여 언어에 구애 받지 않음.

 

import sentencepiece as spm

# 학습 데이터로부터 SentencePiece 모델 학습
spm.SentencePieceTrainer.Train(input='input.txt', model_prefix='m', vocab_size=5000)

# 모델 불러오기
sp = spm.SentencePieceProcessor()
sp.load('m.model')

# 문장 토큰화
text = "Hello, how are you?"
tokens = sp.Encode(text, out_type=str)
print(tokens)
# 예상 출력: ['▁', 'Hello', ',', '▁how', '▁are', '▁you', '?']

 

Ex3) Byte-Pair Encoding ((BPE))

자주 등장하는 문자 쌍 반복적으로 결합하여 subword 생성

 

from collections import Counter, defaultdict

# 가장 자주 등장하는 문자 쌍 찾는 함수
def get_stats(vocab):
    pairs = defaultdict(int)
    for word, freq in vocab.items():
        # 문자 단위로 자르기
        symbols = word.split()    
        
        # 문자 쌍으로 결합하여 빈도수 카운팅
        for i in range(len(symbols) - 1):
            pairs[symbols[i], symbols[i+1]] += freq
    
    return pairs

# 가장 자주 등장하는 문자 쌍 병합
def merge_vocab(pair, v_in):
    # 병합후 새로운 어휘사전
    v_out = {}
    
    # vocab: 단어를 공백으로 구분
    bigram = ' '.join(pair) 
    
    # 병합할 문자 병합하기
    replacement = ''.join(pair)
    
    for word in v_in:
        # word 안에서 bigram -> replacement 형태로 저장
        w_out = word.replace(bigram, replacement)
        
        # 새로운 어휘집합의 어휘별 빈도수 업데이트
        v_out[w_out] = v_in[word]
    
    return v_out

# 초기 어휘 사전
# </w>: 단어의 끝을 나타내는 토큰
vocab = {
    'h e l l o </w>': 5,
    'h e l l o w o r l d </w>': 2,
    'h e l p </w>': 6,
    'h e a v e n </w>': 3
}
# 병합 횟수
num_merges = 5
for i in range(num_merges):
    pairs = get_stats(vocab)
    best = max(pairs, key=pairs.get)
    vocab = merge_vocab(best,vocab)
    print(f'Step {i+1}: {best}')
    print(vocab)
# 출력예시
# Step 1: ('h', 'e')
# {'he l l o </w>': 5, 'he l l o w o r l d </w>': 2, 'he l p </w>': 6, 'he a v e n </w>': 3}

# Step 2: ('he', 'l')
# {'hel l o </w>': 5, 'hel l o w o r l d </w>': 2, 'hel p </w>': 6, 'he a v e n </w>': 3}

# Step 3: ('hel', 'l')
# {'hell o </w>': 5, 'hell o w o r l d </w>': 2, 'hel p </w>': 6, 'he a v e n </w>': 3}

# Step 4: ('hell', 'o')
# {'hello </w>': 5, 'hello w o r l d </w>': 2, 'hel p </w>': 6, 'he a v e n </w>': 3}

# Step 5: ('hel', 'p')
# {'hello </w>': 5, 'hello w o r l d </w>': 2, 'help </w>': 6, 'he a v e n </w>': 3}

'NLP' 카테고리의 다른 글

나만의 Chatbot 생성 (Fine-tuning "gpt-3.5-turbo")  (0) 2023.09.02
Fine-tuning "GPT-3.5-turbo"  (0) 2023.09.02
Comments