수달이네 기술 블로그

1. 자연어처리 본문

AI공부/자연어처리

1. 자연어처리

슬픈 수달이 2026. 2. 16. 18:58

자연어

인간이 의사소통에 사용하는 언어(말, 글)

  • 문법, 어휘, 맥락, 뉘앙스 등의 복잡한 요소로 구성
  • 규칙적인 구조와 함께 다양한 변형이 가능
  • NLP(자연어처리, Natural Language Processing)기술로 처리
  • 텍스트 분석, 번역, 음성 인식, 챗봇등 다양한 응용 가능

자연어 처리

컴퓨터가 인간의 언어를 이해하고, 처리하며 생성할 수 있도록 돕는 인공지능 분야

  • 언어학, 컴퓨터과학, 인공지능의 융합으로 이루어짐
  • 형태소 분석, 구문 분석, 의미 분석등 여러 단계가 포함됨.

토큰화(Tokenization)

텍스트데이터를 분석하거나 처리하기 위해 의미있는 단위로 나누는 과정

  • 단어, 어절, 형태소, 문자등의 단위일 수 있다.
  • 영어는 공백, 구두점을 기준으로 나누지만 한국어, 일본어등은 형태소 분석기로 어절, 형태소 단위로 나눠야함.

문장 토큰화

텍스트를 문장단위로 나누는 과정

  • 일반적으로 마침표, 물음표, 느낌표등의 문장부호를 기준으로 하나, 약어 Dr.등의 마침표로 나누면 안되므로 규칙, 모델이 필요하다.
  • 한국어는 https://github.com/hyunwoongko/kss 를 추천한다.

정수 인코딩

자연어 처리 상에서 텍스트 데이터를 모델이 이해할 수 있는 숫자 형태로 변환하는 과정.

  • 문장을 토큰화하여 단어, 서브워드, 문자단위로 나누어 각 토큰에 고유한 정수 ID를 부여하여 문장을 숫자 시퀀스로 표현
    • 모델, 토크나이징, 임베딩의 방식에 따라 결과가 달라질 수 있어 주의

정수 인코딩 연습

from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding
import numpy as np
  • 띄어쓰기를 기준으로 하는 토크나이저
# 전처리할 텍스트를 정합니다.
text = '커피 한잔 어때'

# Tokenizer 객체 생성 및 fit_on_texts로 단어 인덱스 학습
tokenizer = Tokenizer()
# 공백기준으로 분리
# 빈도수 계산, 정수 인덱스 부여
tokenizer.fit_on_texts([text])  # 여러 문장이 들어갈 수 있으므로 리스트처리
word_index = tokenizer.word_index
word_index

# {'커피': 1, '한잔': 2, '어때': 3}
  • 공백을 기준으로 나눈 것을 확인
      • 일부 특수문자, 구두점 제거
    • 영어의 경우 모두 손문자로 변환
    • 공백단위 토큰화 + 단순한 전처리만 적용
# texts_to_sequences로 텍스트를 시퀀스로 변환
sequences = tokenizer.texts_to_sequences([text])
print(sequences)

# [[1, 2, 3]]
  • 나눈 것을 시퀀스화
# 단어 빈도수 세기

# 전처리하려는 세 개의 문장을 정합니다.
docs = ['먼저 텍스트의 각 단어를 나누어 토큰화합니다.',
       '텍스트의 단어로 토큰화해야 딥러닝에서 인식됩니다.',
       '토큰화한 결과는 딥러닝에서 사용할 수 있습니다.',
       ]
# 토큰화 함수를 이용해 전처리 하는 과정입니다.
tokenizer = Tokenizer()            # 토큰화 함수 지정
tokenizer.fit_on_texts(docs)       # 토큰화 함수에 문장 적용

print("단어 카운트: ", tokenizer.word_counts)  # 단어 빈도수 계산

print("문장 카운트: ", tokenizer.document_count)
print("각 단어가 몇 개의 문장에 포함되어 있는가: ", tokenizer.word_docs)
print("각 단어에 매겨진 인덱스 값: ",  tokenizer.word_index)

# 단어 카운트:  OrderedDict([('먼저', 1), ('텍스트의', 2), ('각', 1), ('단어를', 1), ('나누어', 1), ('토큰화합니다', 1), ('단어로', 1), ('토큰화해야', 1), ('딥러닝에서', 2), ('인식됩니다', 1), ('토큰화한', 1), ('결과는', 1), ('사용할', 1), ('수', 1), ('있습니다', 1)])
# 문장 카운트:  3
# 각 단어가 몇 개의 문장에 포함되어 있는가:  defaultdict(<class 'int'>, {'텍스트의': 2, '나누어': 1, '각': 1, '토큰화합니다': 1, '먼저': 1, '단어를': 1, '딥러닝에서': 2, '인식됩니다': 1, '단어로': 1, '토큰화해야': 1, '수': 1, '있습니다': 1, '사용할': 1, '결과는': 1, '토큰화한': 1})
# 각 단어에 매겨진 인덱스 값:  {'텍스트의': 1, '딥러닝에서': 2, '먼저': 3, '각': 4, '단어를': 5, '나누어': 6, '토큰화합니다': 7, '단어로': 8, '토큰화해야': 9, '인식됩니다': 10, '토큰화한': 11, '결과는': 12, '사용할': 13, '수': 14, '있습니다': 15}
# 전처리할 텍스트를 정합니다.
texts = ['커피 한잔 어때', '오늘 날씨 참 좋네', '옷이 어울려요']

# Tokenizer 객체 생성 및 fit_on_texts로 단어 인덱스 학습
tokenizer = Tokenizer()
tokenizer.fit_on_texts(texts)
# texts_to_sequences로 텍스트를 시퀀스로 변환
sequences = tokenizer.texts_to_sequences(texts)
sequences
# [[1, 2, 3], [4, 5, 6, 7], [8, 9]]
  • 시퀀스는 문장에 따라 위와 같이 나뉜다.
word_index = tokenizer.word_index
word_index

# {'커피': 1,
#  '한잔': 2,
#  '어때': 3,
#  '오늘': 4,
#  '날씨': 5,
#  '참': 6,
#  '좋네': 7,
#  '옷이': 8,
#  '어울려요': 9}
  • 모델에 따라 시퀀스가 나뉜다.
  • 0을 비워두는 이유: 빈문자, 패딩된 문자를 쓸때 사용한다.
model = Sequential()
model.add(Embedding(input_dim=len(word_index) + 1, output_dim=5))   
# 데이터를 준비하는 과정인 임베딩
# 자연어 처리는 비전과 달리 학습을 2번 정도함
# 임베딩: 위치적(의미적)으로 단어끼리 가까운 것을 학습하는 단어사전을 만든다.
# input_dim: 단어 사전의 크기 (전체 단어 개수 + 1)
# output_dim: 단어가 임베딩될 벡터의 길이(정해지지 않음)
  • output_dim: 단어를 비교할때 차원이 많이 필요함(이 단어를 표현할 차원)
# 패딩을 통해 시퀀스 길이를 맞춥니다.
print("\\n시퀀스:\\n", sequences)
padded_sequences = pad_sequences(sequences, 4)  
print("\\n패딩된 시퀀스:\\n", padded_sequences)

# 시퀀스:
#  [[1, 2, 3], [4, 5, 6, 7], [8, 9]]

# 패딩된 시퀀스:
#  [[0 1 2 3]
#  [4 5 6 7]
#  [0 0 8 9]]

  • 모델에 넣을때 문장의 길이를 맞춰주어야 한다.
    • 행렬 연산을 위하여 맞춰준다!(행렬의 길이가 맞아야 계산 가능하기 때문에)
embedding_output = model.predict(padded_sequences)
print("\\n임베딩 결과:\\n", embedding_output)

# 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 23ms/step

# 임베딩 결과:
#  [[[ 0.04737275 -0.00143818  0.00594553 -0.02770106 -0.00686034]
#   [ 0.04405904  0.02269593  0.04388585  0.0211556  -0.03958638]
#   [-0.01468633  0.03858126 -0.03623948  0.03250653 -0.01439165]
#   [ 0.02324993 -0.03056538  0.01624867 -0.00173782  0.02228792]]

#  [[ 0.04240013  0.02599138  0.01345729 -0.02803561  0.01581384]
#   [ 0.03963676 -0.04338383  0.03543309  0.04778124 -0.01030276]
#   [-0.0031928  -0.01447866  0.00706546  0.02091349  0.02095609]
#   [ 0.04585375 -0.00227988  0.00853407 -0.04537152 -0.04710513]]

#  [[ 0.04737275 -0.00143818  0.00594553 -0.02770106 -0.00686034]
#   [ 0.04737275 -0.00143818  0.00594553 -0.02770106 -0.00686034]
#   [-0.03826556  0.02017671  0.04388057 -0.01880065 -0.02062644]
#   [ 0.03166319 -0.01272701  0.03670799  0.00877791 -0.02947029]]]
  • 5차원으로 만들어진 것을 알 수 있다.
    • 해당 단어를 표현하기 위한 실수값.

패딩

자연어 처리, 시계열 모델에서 길이가 다른 시퀀스를 동일한 길이로 맞추기 위해 비어있는 부분을 채우는 과정

  • 위에서 말했듯 행렬 연산으로 하기 위해 정규화
  • 이후 RNN, LSTM, Transformer같은 모델에 효율적으로 입력됨.
  • 실제 학습값에 영향을 주지 않도록 masking기법과 함께 사용된다.

'AI공부 > 자연어처리' 카테고리의 다른 글

5. RNN(Recurrent Neural Network)기초  (1) 2026.02.22
4. FastText  (0) 2026.02.21
3. NSMC를 활용한 단어 분류  (1) 2026.02.20
2. 자연어 처리(벡터화)  (1) 2026.02.16
0. 텐서플로우  (1) 2026.02.14