자연어 처리 기초

chkkkky·2024년 8월 18일

토큰화

텍스트 데이터를 단순화하여 알고리즘이 이해하고 처리할 수 있도록 관리하기 쉽게 만드는 것

유형

  1. 단어 토큰화 : 개별단어로 분해
  2. 문장 토큰화 : 개별 문장으로 분해
  3. 하위 단어 토큰화 : 단어를 더 작은 의미 단위로 분해
    unhappiness" → ["un", "hap", "pi", "ness"]
  4. 문자 토큰화 : 텍스트를 개별 문자로 분해

과정

텍스트 정규화 : 소문자 변환, 불필요한 구두점과 공백 제거
구분자 사용 : 공백이나 구두점을 기준으로 텍스트 분해
고급 토큰화 기법 : 언어의 문법적, 의미적 구조를 고려하여 토큰 생성

고급 토큰화 기법

  • 형태소 분석
    단어를 구성하는 최소 의미 단위인 형태소 분석
    ex) "cats"는 "cat"과 복수형 접미사 "s"로 분해

  • 어간 추출
    어간을 추출하여 형태를 단순화
    ex) "running", "runs", "ran" → "run"

  • 어근 추출
    단어의 어근을 추출하여 형태를 표준화
    ex) "better"는 어근 "good"으로 변환

  • BPE
    자주 등장하는 바이트 쌍을 병합하여 점진적으로 단어를 분해
    ex) "lowest"가 "l", "o", "w", "e", "s", "t"로 분해되고, 자주 등장하는 "lo", "we"가 결합되어 "low", "est"로 변환

  • WordPiece
    BPE와 유사하지만, 서브워드(subword) 단위로 토큰을 생성
    ex) "unhappiness" → ["un", "##happiness"]
    트랜스포머 모델(BERT 등)에서 사용

  • SentencePiece
    언어에 중립적인 방식으로 텍스트를 서브워드 단위로 분해합니다.
    BPE와 유사하지만, 문장을 토큰화하는 과정에서 공백을 고려하지 않음
    ex) "unhappiness" → ["un", "ha", "ppiness"]
    Google의 T5, ALBERT 모델에서 사용

=================================================

** from tensorflow.keras.preprocessing.text

text_to_word_sequence
주어진 텍스트를 단어 단위로 분할하여 리스트로 변환

Tokenizer() #토큰화 함수 지정
-> 텍스트를 정수 시퀀스로 변환하도록 설계

token = Tokenizer()
token.fit_on_texts(docs) #토큰화 함수에 문장 적용

word_counts : 순서를 기억하여 단어 카운트
document_count : 문장 카운트
word_docs : 각 단어가 몇 개의 문장에 포함되어 있는지
word_index : 각 단어에 매겨진 인덱스 값
=> 단어의 빈도에 따라 가장 빈번한 단어부터 / 동일 빈도일 경우 먼저 등장한 단어가 더 낮은 인덱스 할당

================================================

Okt 형태소 분석기

** from konlpy.tag import Okt
from collections import Counter

okt = Okt()
okt.morphs(sentence) -> 형태소 분석
Counter(tokens) -> 형태소 빈도 계산

================================================

word_size:

고유 단어의 총 개수에 1을 더한 값
이는 NLP에서 일반적인 관행으로, "0" 인덱스를 포함하기 위해 사용
-> "0" 인덱스는 패딩(padding)에 사용되거나, 구현에 따라 알 수 없는 단어를 나타낼 우려

num_classes :

총 클래스 수를 지정
이 경우 어휘 크기(word_size)로 설정되어, One-Hot Encoding에 어휘의 모든 단어에 대한 슬롯과 추가 "0" 인덱스가 있는지 확인

One-Hot Encoding :

to_categorical 함수는 클래스 벡터(정수 인덱스)를 바이너리 클래스 행렬로 변환

===================================================

Embedding 레이어 :

자연어 처리나 시퀀스 데이터를 다루는 모델에서 자주 사용되는 레이어로, 입력 데이터를 고정된 크기의 고차원 벡터로 변환해주는 역할

고차원 공간(예: 원-핫 인코딩된 벡터)의 단어를 저차원의 연속 벡터 공간으로 매핑하며 이는 표현을 더욱 효율적으로 만들고 계산 복잡성을 줄인다

ex) model.add(Embedding(word_size, 8, input_length=4))

word_size: 입력 차원의 크기, 즉 어휘 크기
데이터 세트에 있는 총 고유 단어 수에 1을 더한 값
8: 임베딩 벡터의 크기. 각 단어는 8차원 벡터로 표현
input_length=4: 입력 시퀀스의 길이
이 모델은 각 입력 시퀀스의 길이가 4일 것으로 예상(예: 입력당 4개의 단어)

_embedding을 사용한 모델 생성 후 평가_

from keras.datasets import imdb
from keras.preprocessing.sequence import pad_sequences
from keras.models import Sequential
from keras.layers import Embedding, Flatten, Dense

(X_train, y_train),(X_test, y_test) = imdb.load_data(num_words=10000)
** num_words 훈련 데이터에서 가장 자주 나타나는 상위 만개의 단어만 사용하겠다는 의미

X_train = pad_sequences(X_train, maxlen=100)
X_test = pad_sequences(X_test, maxlen=100)
** pad_sequences 서로 다른 길이의 데이터를 맞춰준다
여기서는 100으로
padding = 'pre'면 앞에 0을 채워서 맞춤(뒤는 post)


model = Sequential()
model.add(Input(shape=(100,))) # 모든 입력 데이터를 동일한 길이로 맞춰야 하기 때문에 패딩 사용 후 100으로 맞춤

model.add(Embedding(10000,8)) # 입력 차원은 단어 인덱스의 최대값 +1, 출력 차원은 임베딩 후 벡터 크기
#임베딩 레이어는 모델이 학습할 수 있는 단어 인덱스의 총 개수를 설정

model.add(Flatten()) # 임베딩된 시퀀스를 평탄화
model.add(Dense(1, activation='sigmoid')) # 긍정과 부정을 분류하므로 시그모이드 활성화 함수 사용

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.summary()

history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_split=0.2)

loss, accuracy = model.evaluate(X_test, y_test)
print(f"Test Accracy: {accuracy}")

0개의 댓글