8/5 NLP
이 포스팅은 위의 강의와 자료를 보고 정리한 게시글입니다..
정수 인코딩
- 자연어를 컴퓨터가 이해할 수 있는 형태로 인코딩하는 과정
패딩(padding)
- 자연어를 컴퓨터가 이해할 수 있는 숫자 형태로 인코딩하는 과정에서 문장들의 길이를 모두 동일하게 맞추는 작업
-
컴퓨터는 길이가 동일한 문장을 하나의 행렬로 만들어 병렬적으로 계산할 수 있다.(계산 속도가 매우 빨라짐)
- 보통 0을 추가해 길이를 맞추는 제로패딩 방식을 사용한다.
원 핫 인코딩(One-Hot Encoding)
- 정수로 표현되었지만 실제로는 문자인 이 데이터를 기계가 인식할 수 있도록 바꿔주는 방법
- 정수 인코딩을 했을 때 단어에 숫자가 부여되는데, 이러한 숫자는 대소관계를 가지므로 인코딩방법으로 적합하지 않다.
- 원 핫 인코딩은 1차원 벡터의 형태로 인코딩하는 방식으로, 표현하고자 하는 단어의 자리는 1, 나머지는 0으로 채워넣은 벡터로 인코딩
- 하지만 단어와 문장의 개수가 많아지면, 필요한 공간이 엄청나게 늘어나고 0의 개수가 많아지므로 희소 데이터(sparse data)가 된다.
백오브 워즈(Bag of Words, BoW)
- bag은 원소의 순서를 고려하지 않고 중복 원소를 허용하는 집합을 의미한다.
- 단어의 등장 순서를 고려하지 않고, 문서 내 단어의 등장 빈도를 고려한다.
문서 단어 행렬(Document Term Matrix, DTM)
- 각 문서에 대한 BoW 표현 방법을 그대로 갖고 와서, 서로 다른 문서들의 BoW들을 결합한 표현방법
- 원 핫 인코딩과 마찬가지로 공간적 낭비를 일으킬 수 있다.
TF-IDF
- 단어의 빈도(TF, term frequency)와 역 문서 빈도(Inverse Document Frequency)를 사용하여 DTM 내의 각 단어들 마다 중요한 정도를 가중치로 주는 방법이다.
- TF, IDF을 곱한 값으로 점수가 높을수록 해당 문서에서만 자주 등장하는 단어이다.
- tf(d, t) : 단어의 빈도, DTM에서 각 단어들이 가진 값
- df(t) : 특정 단어 t가 등장한 문서의 수, 문서에서 몇번 등장했는지는 고려하지 않는다.
- idf(d, t) = log(\frac{n}{1 + df(t)})
- idf(d, t) = log(n / (1 + df(t)))
- log 사용 이유 : n이 커질수록 IDF 값이 급격하게 증가하는 것 방지
- 1 더한 이유 : 0되는 것 방지
파이썬 활용
불용어 제거 및 빈도수 측정
from nltk.tokenize import sent_tokenize
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
text = """
분석하고자 하는 문장 입력
"""
sent_text = sent_tokenize(text) # text를 문장 토큰화
nltk.download('stopwords') # 불용어 다운로드
vocabulary = {}
sentences = []
stop_words = stopwords.words('english')
for sent in sent_text :
sentence = word_tokenize(sent)
result = []
for word in sentence :
word = word.lower()
if (word not in stop_words) & (len(word) > 2) : # 불용어가 아니거나 길이가 3 이상인 단어
result.append(word)
if word not in vocabulary :
vocabulary[word] = 0 # key값을 word로 가지는 dictionary 생성
vocabulary[word] += 1 # 등장횟수
sentences.append(result)
2번 이상 등장한 단어 빈도수 측정, 정수값 부여
sorted_vocabulary = sorted(vocabulary.items(), key = lambda x : x[1], reverse = True) # lambda x : x[1] 은 value값을 의미
# 정수 임베딩
integer_embedding = {}
i = 0
for (word, frequency) in sorted_vocabulary :
if frequency > 1 :
i += 1
integer_embedding[word] = 1
integer_embedding["oov"] = len(integer_embedding) + 1 # 상위 4개의 단어를 제외한 단어들
encoded = []
for s in sentences :
temp = []
for w in s :
try : # integer_embedding의 key값은 monkey, banana, jungle, food 4가지만 있음
temp.append(integer_embedding[w])
except KeyError : # 4가지 이외의 경우(KeyError)의 경우 'oov'의 value값으로 할당
temp.append(integer_embedding["oov"])
encoded.append(temp)
Counter 활용
빈도수 측정
import numpy as np
from Collections import Counter
words = np.hstack(sentences) # hstack은 ndarray 형식의 배열 수평으로 결합할 때 사용하는 함수
# hstack은 행의 개수가 같고 열의 개수가 다른 두 행렬을 합칠 때 사용
# vstack은 열의 개수가 같고 행의 개수가 다른 두 행렬을 합칠 때 사용
vocabulary = Counter(words)
정수 인코딩
vocab_size = 4
common_vocabulary = vocabulary.most_common(vocab_size)
integer_embedding = {}
i = 0
for (Word, frequency) in common_vocabulary :
i = i + 1
integer_embedding[word] = i
NLTK Freqdict 활용
정수 인코딩
from nltk import FreqDist
vocabulary = FreqDist(np.hstack(sentences))
vocab_size = 4
common_vocabulary = vocabulary.most_common(vocab_size)
integer_embedding = {word[0] : index + 1 for index, word in enumerate(common_vocabulary)}
Tensorflow Keras 활용
빈도수를 기준으로 정수 부여
from tensorflow.keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer()
tokenizer.fit_on_texts(sentences)
tokenizer.word_counts
integer_encoding = tokenizer.texts_to_sequences(sentences)
Padding
파이썬 활용
max_len = max(len(encode) for encode in integer_encoding)
for encode in integer_encoding :
while len(encode) < max_len :
encode.append(0)
padding = np.array(integer_encoding)
keras 활용
from tensorflow.keras.preprocessing.sequence import pad_sequences
integer_encoding = tokenizer.texts_to_sequences(sentences)
padding = pad_sequences(integer_encoding) # 앞에서부터 제로패딩
padding = pad_sequences(integer_encoding, padding = 'post', maxlen = 6) # 뒤에서부터 패딩, 열의 개수 설정
padding = pad_sequences(integer_encoding, padding = 'post', value = -1) # 패딩값 변경
TF-IDF
import math
documents = [
"배가 너무 너무 아프다",
"배가 너무 고프다",
"저기 저기 배가 지나간다",
"비가 와서 다리가 아프다"
]
vocabulary = list(set(w for doc in documents for w in doc.split()))
num_documents = len(documents)
TF, IDF 계산하는 함수
def tf(t, d) :
return d.count(t)
def idf(t) :
df = 0
for doc in documents :
df += t in oc
return math.log(num_documents / (1 + df))
def tfidf(t, d) :
return tf(t, d) * idf(t)
계산하기
TF
import pandas as pd
result = []
for i in range(num_documents) :
result.append([])
d = documents[i]
for j in range(len(vocabulary)) :
t = vocabulary[j]
result[-1].append(tf(t, d))
term_frequency = pd.DataFrame(result, columns = vocabulary)
IDF
result = []
for i in range(len(vocabulary)) :
t = vocabulary[i]
result.append(idf(t))
inverse_df = pd.DataFrame(result, index = vocabulary, columns = ["IDF"])
TF-IDF
result = []
for i in range(num_documents) :
result.append([])
d = documents[i]
for j in range(len(vocabulary)) :
t = vocabulary[i]
result[-1].append(tfidf(t, d))
tf_idf = pd.DataFrame(result, columns = vocabulary)
댓글남기기