티스토리 뷰

자연어처리

[3] 정수 인코딩

up_one 2025. 3. 28. 16:31

2025.03.24 - [자연어처리] - [2] 정제와 추출

 

[2] 정제와 추출

2025.03.21 - [자연어처리] - [1] 토큰화(Tokenizer) [1] 토큰화(Tokenizer)NLP(Natural Language Processing)은 인간의 언어를 이해하고 해석하기 위한 목적으로 발전해 왔습니다. 다만 분석 모델의 학습 데이터셋은

up-one-coding.tistory.com

정제와 추출을 겪은 텍스트는 드디어 학습에 사용하기 위해 숫자의 형태로 바꿀 준비가 되어 있습니다. 텍스트 데이터를 숫자의 형태로 바꾸는 가장 대표적인 방법은 빈도수에 따라 매핑하는 것입니다.

"A barber is a person. A barber is good person barber good person
2 1 2

 

위의 예시처럼, 문장에서 불용어를 제거한 Token을 만들고 그 Token이 나오는 빈도 수로 매핑하는 것입니다. 이처럼 각 단어를 특정 방법을 활용해 고유한 정수에 맵핑(Mapping)시키는 작업을 '정수 인코딩'이라고 합니다. 이번에는 각 단어가 등장하는 빈도 수에 따라 텍스트를 인코딩하는 방법에 대해 알아보겠습니다.

 

1. 전처리를 위한 클래스 선언

Python의 Class 문법을 활용하여 높은 빈도수를 가진 단어일수록 낮은 인덱스로 인코딩을 시키고, 인코딩 값이 특정 수보다 큰 것은 삭제하는 전처리를 적용하겠습니다.

class TextPreProcessor:
  def __init__(self, *text):
    self.text = text
    self.stopwords = stopwords.words('english')
    self.vocab_size = 5         #삭제할 index값 기준
    self.cleaned_tokens = []    #불용어 제거 및 정제를 걸친 Token 저장
    self.freq_vocab = {}        #Token의 빈도 수 저장
    self.word_index = {}        #인덱스를 저장한 딕셔너리
    self.encoded = []           #인코딩 결과 저장

 

불용어의 기준은 영어로 설정하고, 인코딩 값이 5보다 크면 삭제하는 기준으로 설정하였습니다.

 

2. 불용어 제거 및 정제

인코딩 전 과정으로, 영어 불용어를 제거하고 모든 글자를 소문자로 변환하는 과정을 적용하였습니다.

def preprocessing(self):    #불용어 제거 및 정제 처리 후 빈도 수 저장
    for sentence in self.text:
      words = word_tokenize(sentence.lower())
      for word in words:
        if word not in self.stopwords:
          self.cleaned_tokens.append(word)

    #빈도 수 저장
    for token in self.cleaned_tokens:
      if token not in self.freq_vocab:    #딕셔너리에 해당 token이 없으면 빈도 수를 1로 지정
        self.freq_vocab[token]=1
      else:
        self.freq_vocab[token]+=1
    return self.freq_vocab

text = "A barber is a person. a barber is good person. a barber is huge person. he Knew A Secret! The Secret He Kept is huge secret. Huge secret. His barber kept his word. a barber kept his word. His barber kept his secret. But keeping and keeping such a huge secret to himself was driving the barber crazy. the barber went up a huge mountain."
example1 = TextPreProcessor(text)
print(example1.preprocessing())
#{'barber': 8, 'person': 3, '.': 10, 'good': 1, 'huge': 5, 'knew': 1, 'secret': 6, '!': 1, 'kept': 4, 'word': 2, 'keeping': 2, 'driving': 1, 'crazy': 1, 'went': 1, 'mountain': 1}

 

불용어를 제거하고 소문자로 변환한 Token의 빈도 수를 확인해 보면, 의미 없는 단어의 빈도 수가 많이 존재하는 것을 확인할 수 있습니다. 따라서 정의한 vocab size에 따라 삭제하는 과정을 적용하겠습니다.

 

  def encoding(self):
    sorted_vocab = sorted(self.freq_vocab.items(), key=lambda x:x[1], reverse=True)
    sorted_vocab = sorted_vocab[:self.vocab_size]
    self.word_index = {word:idx+1 for idx, (word,_) in enumerate(sorted_vocab)}
    self.word_index['OOV'] = len(self.word_index)+1 #OOV은 단어 집합에 없는 단어를 의미
    return self.word_index
    
  #{'.': 1, 'barber': 2, 'secret': 3, 'huge': 4, 'kept': 5, 'person': 6, 'word': 7, 'OOV': 8}

 

첫 번째로, 빈도수에 따라 딕서너리(self.freq_vocab)를 내림차순 하였고, value가 설정한 vocab_size까지만 출력하는 것으로 정하였습니다. self.word_index 딕셔너리는 word가 위치한 인덱스를 매핑하여 인코딩한 것입니다.

 

예를 들어, ['barber', 'person']이 있다면, 이 문장에 대해서는 [1, 5]로 인코딩 되는 것입니다. 다만 self.word_index에 존재하지 않은 단어를 인코딩할 때는 OOV라는 단어 집합을 사용합니다. OOV(단어 집합에 없는 단어)에 한해서는 'OOV'의 인덱스로 인코딩합니다.

  def encode_texts(self):
    #문장을 단어인덱스로 변환하여 정수 인코딩 실행
    for sentence in self.cleaned_tokens:
        encoded_sentence = []
        for word in sentence:
            # 존재하는 단어면 매핑된 정수 인덱스, 없으면 OOV 인덱스 사용
            encoded_sentence.append(self.word_index.get(word, self.word_index['OOV']))      

        self.encoded.append(encoded_sentence)

 

설정한 OOV의 역할은 매핑되는 정수 인덱스는 단어가 존재할 때만 가능한데, 이 단어가 존재하지 않을 경우 OOV 인덱스를 활용하는 것입니다. 위 OOV 인덱스는 8로 설정되었고, 만약 단어 집합에 존재하지 않은 것을 인덱싱시킬 경우에는 8로 매핑이 되는 것입니다.

'자연어처리' 카테고리의 다른 글

[4] TF - IDF을 이용한 특징 추출  (0) 2025.03.29
[2] 정제와 추출  (0) 2025.03.24
[1] 토큰화(Tokenizer)  (0) 2025.03.21
TAG more
글 보관함
최근에 올라온 글