본문 바로가기
NLP

NLP_1

by Yonghip 2024. 9. 10.

Chapter2

  • 토큰화(tokenization):
    자연어는 문서(document)->문장(sentence)->단어(word)->문자(character?) 순서로 데이터를 쪼갤 수 있다.
    토큰화는 이 중 문장을 단어로 쪼개주는 과정을 의미한다. 주로 띄어쓰기나 품사 단위로 자르는데 한국어는 접미어로 다양한 형태를 가질 수 있으므로 형태소(말의 가장 작은 단위)로 잘라주어야 한다.
from nltk.tokenize import word_tokenize
print('단어 토큰화1 :',word_tokenize("Don't be fooled by the dark sounding name, Mr. Jone's Orphanage is as cheery as cheery goes for a pastry shop."))
단어 토큰화1 : ['Do', "n't", 'be', 'fooled', 'by', 'the', 'dark', 'sounding', 'name', ',', 'Mr.', 'Jone', "'s", 'Orphanage', 'is', 'as', 'cheery', 'as', 'cheery', 'goes', 'for', 'a', 'pastry', 'shop', '.']
from konlpy.tag import Okt
okt = Okt()
print('OKT 형태소 분석 :',okt.morphs("열심히 코딩한 당신, 연휴에는 여행을 가봐요"))
OKT 형태소 분석 : ['열심히', '코딩', '한', '당신', ',', '연휴', '에는', '여행', '을', '가봐요']
  • Cleaning: 노이즈 제거
  • Normalization: 형태가 다른걸 하나로 모음
  • Stemming: 어간을 자름(빠름)
  • lemmatization: 특정 룰에 따라 자름
  • 불용어: Cleaning해야할 쓸모 없다고 판단되는 데이터(it, the, "<HTML>"외에 특수문자 등)
from nltk.stem import WordNetLemmatizer
from nltk.stem import PorterStemmer
lemmatizer = WordNetLemmatizer()
stemmer = PorterStemmer()
sentence = "This was not the map we found in Billy Bones's chest, but an accurate copy, complete in all things--names and heights and soundings--with the single exception of the red crosses and the written notes."
words = sentence.split()

print('표제어 추출 후 :',[lemmatizer.lemmatize(word) for word in words])
print('어간 추출 후 :',[stemmer.stem(word) for word in words])
표제어 추출 후 : ['This', 'wa', 'not', 'the', 'map', 'we', 'found', 'in', 'Billy', "Bones's", 'chest,', 'but', 'an', 'accurate', 'copy,', 'complete', 'in', 'all', 'things--names', 'and', 'height', 'and', 'soundings--with', 'the', 'single', 'exception', 'of', 'the', 'red', 'cross', 'and', 'the', 'written', 'notes.']
어간 추출 후 : ['thi', 'wa', 'not', 'the', 'map', 'we', 'found', 'in', 'billi', "bones'", 'chest,', 'but', 'an', 'accur', 'copy,', 'complet', 'in', 'all', 'things--nam', 'and', 'height', 'and', 'soundings--with', 'the', 'singl', 'except', 'of', 'the', 'red', 'cross', 'and', 'the', 'written', 'notes.']

Chapter3

  • Language model: 다음 단어의 확률을 예측하는 모델(현재 거의 대부분의 Language model을 의미)
  • N-gram: 통계적 모델링 중 이전에 봐야할 sequence를 n개로 제한
  • Perplexity: NLP 평가지표 중 하나 모호함을 의미함

Chapter4

Local representation: 단어를 특정 인덱스로 매핑
Distributed representation: 분산해서 벡터 느낌으로 표현(관계, 늬앙스 표현 가능)

Local은 추가로 one-hot과 count based method로 나뉜다

  • BoW: defaultdict느낌으로 모든 문자 토큰화해서 빈도수 체크, 순서 상관x
  • DTM: BoW를 모든 문서에 실행해서 행렬 행태로 만듦
  • TF-IDF(term frequency, inverse document frequency):단어의 빈도(TF)와 문서에 얼마나 희소하게 등장하는지(IDF)를 사용하는 DTM 상위 알고리즘
from sklearn.feature_extraction.text import CountVectorizer

corpus = ['you know I want your love. because I love you.']
vector = CountVectorizer()

# 코퍼스로부터 각 단어의 빈도수를 기록
print('bag of words vector :', vector.fit_transform(corpus).toarray()) 

# 각 단어의 인덱스가 어떻게 부여되었는지를 출력
print('vocabulary :',vector.vocabulary_)
bag of words vector : [[1 1 2 1 2 1]]
vocabulary : {'you': 4, 'know': 1, 'want': 3, 'your': 5, 'love': 2, 'because': 0}

Chapter9

Word2vector:

단어를 dense하게 일정 차원으로 만드는 모든 알고리즘(cbow, skip-gram, MLP,...)

  • center word: 예측하고 싶은 단어
  • context word: 그 주변 n개 단어
  • window: 위에서 언급한 n


CBOW: 중심단어 예측을 위해 주변 단어 n개씩 2n개 입력
입력 벡터는 one hot vector 사용, 이걸 2n번 반복하고 더한 뒤 2n으로 나눈 뒤 W'과 softmax를 거쳐 확률 계산
loss로는 cross entropy 사용


Skip-gram은 그 반대 느낌 W'이 동일한 가중치를 사용하는지 궁금
CBoW, skip-gram의 모든 과정에 활성화 함수는 없음

import re
import urllib.request
import zipfile
from lxml import etree
from nltk.tokenize import word_tokenize, sent_tokenize
# 데이터 다운로드
# urllib.request.urlretrieve("https://raw.githubusercontent.com/ukairia777/tensorflow-nlp-tutorial/main/09.%20Word%20Embedding/dataset/ted_en-20160408.xml", filename="ted_en-20160408.xml")
targetXML = open('ted_en-20160408.xml', 'r', encoding='UTF8')
target_text = etree.parse(targetXML)

# xml 파일로부터 <content>와 </content> 사이의 내용만 가져온다.
parse_text = '\n'.join(target_text.xpath('//content/text()'))

# 정규 표현식의 sub 모듈을 통해 content 중간에 등장하는 (Audio), (Laughter) 등의 배경음 부분을 제거.
# 해당 코드는 괄호로 구성된 내용을 제거.
content_text = re.sub(r'\([^)]*\)', '', parse_text)

# 입력 코퍼스에 대해서 NLTK를 이용하여 문장 토큰화를 수행.
sent_text = sent_tokenize(content_text)

# 각 문장에 대해서 구두점을 제거하고, 대문자를 소문자로 변환.
normalized_text = []
for string in sent_text:
     tokens = re.sub(r"[^a-z0-9]+", " ", string.lower())
     normalized_text.append(tokens)

# 각 문장에 대해서 NLTK를 이용하여 단어 토큰화를 수행.
result = [word_tokenize(sentence) for sentence in normalized_text]
from gensim.models import Word2Vec
from gensim.models import KeyedVectors

model = Word2Vec(sentences=result, vector_size=100, window=5, min_count=5, workers=4, sg=0)

벡터가 아래와 같이 연관성을 포함하게 된다

model.wv.most_similar("man")
[('woman', 0.8600590825080872),
 ('guy', 0.8178783655166626),
 ('lady', 0.7964988350868225),
 ('boy', 0.7851755619049072),
 ('girl', 0.7616583704948425),
 ('gentleman', 0.7232996821403503),
 ('kid', 0.7047719359397888),
 ('soldier', 0.6957467198371887),
 ('poet', 0.681509256362915),
 ('king', 0.6633133292198181)]

Glove

word2vec알고리즘 중 하나

 

$w_m^T, w_n$가 center word, context word이며 편향은 보지말고 $logX_{mn}$ 을 보면 둘 사이의 등장 횟수 임을 알 수 있다
즉 GloVe는 둘의 내적과 등장 횟수를 동등하게 만드는걸 목적으로 한다

09-06 패스트텍스트(FastText)

각 단어를 n-gram으로 다시 쪼개서 워드 임베딩 하는 방식(N-gram 모델의 그거랑 다름)
n = 3인 경우: <ap, app, ppl, ple, le>
여기서 하나의 단어를 쪼갠 단위를 subword라고 한다
subword를 사용하면 OOV 문제에 더 유연하게 대처할 수 있게된다

09-09 엘모(Embeddings from Language Model, ELMo)

단어들의 다의성 문제를 해결하기 위한 embedding 방법, Langeuage model의 은닉층을 word embeddeing으로 사용하는 느낌
실제로는 biLM, weighted sum of all layers 등 사소한 변형이 있는듯 그리고 biLSTM이 실행단에 들어가는 것이니 당연히 느리다

 

출처: https://wikidocs.net/book/2155

'NLP' 카테고리의 다른 글

NLP_2  (2) 2024.09.10