본문 바로가기

카테고리 없음

ML: Learning From Text Data

Text Data에 ML 적용하기

  • Preprocessing texts: 토크나이징, 스테밍, 형태소 분석
  • Representation texts: Bag-of-Words(document-term matrix), Tf-Idf
  • Classification of texts
  • Word embedding: Word2Vec
  • Text processing using deep leaning models: CNN, RNN 등등

 

Preprocessing Text

정규표현을 이용해 텍스트를 전처리할 수 있다.

특정 문자를 삭제하거나 대문자, 소문자를 변환하거나  등등 텍스트를 원하는 형태로 전처리하는 작업이다.

 

1) Tokenizing

nltk.tokenize.word_tokenize() 함수를 사용한다.

from nltk.tokenize import word_tokenize
text_tokens = word_tokenize(text_prep)

띄어쓰기를 기준으로 텍스트가 토크나이징된다.

 

2) Stemming

어형이 변형된 단어로부터 접사 등을 제거하고 그 단어의 어간을 분리해내는 것을 의미한다.

예를 들면 shining -> shine, likes -> like, running -> run

from nltk.stem.porter import PorterStemmer

stemmer = PorterStemmer()

def tokenizer_stemmer(text):
	text_tokens = word_tokenize(text)
    return [stemmer.stem(word) for word in text_tokens]
    
text_stems = tokenizer_stemmer(text_prep)

 

 

3) Removing Stop-words

불용어를 삭제한다. 불용어란 분석에 큰 의미가 없는 단어이다. 예를 들어 the, a, an, is, I, my 등과 같이 문장을 구성하는 필수 요소지만 문맥적으로 큰 의미가 없는 단어가 이에 속한다. 문장에 자주 등장하여 중요한 단어같지만 자연어처리시 의미분석에 큰 의미가 없으므로 미리 삭제해준다.

NLTK에서는 영어 불용어리스트를 제공한다.

from nltk.corpus import stopwords
nltk.download('stopwords')
stop = stopwords.words('english')

def remove_stopwords(text):
	return [w for w in text if w not in stop]
text_stems = remove_stopwords(tokenizer_stemmer(text_prep))

 

ex) ['the', 'sun', 'is', 'shine'] ->(불용어 처리 후) -> ['sun', 'shine']

 

4) Morphological Analysis

형태소 분석은 텍스트를 가장 작은 의미 단위인 형태소로 분리하는 과정이다.

한국어같이 굴절어나 복합어를 많이 사용하는 언어에서 중요하다. 형태소분석을 하지 않는다면,  '가다'와 '가는'이 실질적으로는 같은 의미를 가진 어근이지만 컴퓨터는 다른 의미를 가진 별개의 언어로 인식한다.

 

5) POS tagging

품사 태깅은 말 그대로 단어들마다의 품사를 태깅해주는 것이다.

텍스트 내의 각 단어에 품사(명사, 동사, 형용사 등)를 할당하는 과정이 필요한 이유는 문장의 구조적 이해에 필수적이기 때문이다. 

ex) [('the', 'DT'), ('SUN', 'NN'), ('is', 'VBZ'), ...]

 

 

KoNLPy

코엔엘파이는 한국어 자연어 처리 작업에 필요한 전처리 작업을지원하는 파이썬 패키지이다.

형태소분석, 명사 추출, POS tagging같은 작업들을 지원한다.

 

KoNLPy: 파이썬 한국어 NLP — KoNLPy 0.6.0 documentation

KoNLPy: 파이썬 한국어 NLP KoNLPy(“코엔엘파이”라고 읽습니다)는 한국어 정보처리를 위한 파이썬 패키지입니다. 설치법은 이 곳을 참고해주세요. NLP를 처음 시작하시는 분들은 시작하기 에서 가

konlpy.org

KoNLPy를 이용해 진행할 수 있는 텍스트 전처리 작업들은 아래와 같다.

 

1)Tokenizing + stemming

Okt를 이용해 토크나이징 + 스테밍을 진행해보자.

konlpy.tag.Okt.morph()

okt = Okt() 
#'하늘을 나는 아름다운 꿈을 꾸었습니다!'

#형태소 분석
# ['하늘', '을', '나', '는', '아름답다', '꿈', '을', '꾸다', '!']
okt.morphs(text, norm=True, stem=True)

#명사 추출
# ['하늘', '나', '꿈']
okt.nouns(text) #[]

 

konlpy에서 지원하는 파이썬 패키지가 100%의 정확성으로 전처리 작업들을 수행해주지는 않는다.

위에서도 볼 수 있듯 '나는'의 '나'는 동사이지만, 명사로 추출한 모습을 볼 수 있다.

 

PoS tagging을 위한 라이브러리로는 Okt, Kkma 등을 사용할 수 있는데 정교성 대비 시간의 트레이드 오프를 적절히 고려하여 작업에 최적화된 파이썬 패키지를 적절히 사용하는 것이 필요하다.

 

Bag-of-Words Model

컴퓨터가 자연어를 이해하기 위해서는 텍스트 전처리 후 이를 숫자로 변환해주는 작업이 필요하다.

그 중 하나의 방법론이 Bag-of-Words 모델이다.

핵심 아이디어는 문장이나 문서의 구조를 무시하고, 오직 단어의 출현 빈도만을 기반으로 텍스트를 수치화하는 것이다.

 

  • 어휘사전 생성: 모든 문서에서 사용되는 단어들의 집합을 만들어, 이를 어휘사전으로 사용한다.
  • 문서 벡터 생성: 각 문서에 대해, 어휘사전의 단어가 해당 문서에 몇 번 나타나는지 세어서 벡터를 만든다. 벡터의 각 요소는 특정 단어의 빈도를 나타낸다.

 

ex) 'the dog is on the table' 

0 0 1 1 0 1 1 1
are cat dog is now on table the

 

 

docs = np.array([
	'The sun is shining',
    'The weather is sweet',
    'The sun is shining, the weater is sweet, and she likes running!'
])

count = CountVectorizer()
bag = count.fit_transform(docs)

 

[the, sun, is, shining, weather, sweet, and, she, likes, running]

첫번째 문장의 경우 -> [1, 1, 1, 1, 0, 0, 0, 0, 0, 0]

두번째 문장의 경우 -> [1, 0, 1, 0, 1, 1, 0, 0, 0, 0]

세번째 문장의 경우 -> [2, 1, 2, 1, 1, 1, 1, 1, 1, 1]

 

 

TF-IDF

TF-IDF는 문서 내에서 단어의 중요도를 평가하는 수치화 방법으로, 자연어 처리 및 정보 검색 분야에서 널리 사용된다.

  • TF(Term Frequency): 문서 d 내에서 단어 t가 등장하는 횟수 (-> t가 많이 등장할 수록 중요한 단어로 인식)
  • IDF(Inverse Document Freuency): 전체 문서 집합에서 단어 t가 포함된 문서의 비율의 역수를 로그 스케일로 취한 값(-> 단어 t가 포함된 문서가 적을수록 TF-IDF 값이 높아진다.) 

한 문서 내에서 등장하는 t의 빈도가 높다고 하더라도 해당 단어가 문서에 보편적으로 어디나 존재하면, 문서를 구분하기 위한 중요한 특성으로 인식하기는 어렵기 때문이다.

IDF = log(nd/1+DF(t))
TF-IDF(t, d) = TF(t, d) * IDF(t)

 

docs = np.array([
	'The sun is shining',
    'The weather is sweet',
    'The sun is shining, the weather is sweet, and she likes RUNNING!'
])

tfidf = TfidfVectorizer()
docs_vector = tfidf.fit_transform(docs)

 

 

N-gram Model

N-gram은 주어진 텍스트 샘플에서 연속적으로 이어지는 'n'개의 아이템을 의미한다.

Bag-of-words는 일반적으로 1-gram을 사용하여 단어간의 시퀀스를 전혀 고려하지 않지만, N-gram을 사용하면 문장의 순서와 구조를 더 잘 포착할 수 있다.

특히 자연어 처리에서는 단어의 연속성과 문맥을 고려할 수 있으므로, 단순한 1-gram보다 더 정확한 언어 모델을 만들 수 있다.

  • 1-gram: "the", "sun", "is", "shining"
  • 2-gram: "the sun", "sun is", "is shining"

scikit-learn 라이브러리에 있는 CounterVectorizer클래스를 사용해 n-gram 모델을 구현할 수 있다.

'ngram_range = (2,2)'

 

 

Sentimental Analysis

영화 리뷰 텍스트 데이터셋으로 감정분석을 수행하는 코드의 예시이다.

#Transform text to TF-IDF feature vector
tfidf = TfidfVectorizer(strip_accents=None,
	lowercase=False,
    preprocessor=preprocessor,
    max_df=0.1,
  	min_df=10
    )
X_train_vector = tfidf.fit_transform(X_train)
X_test_vector = tfidf.fit_transform(X_test)

#data dimension
X_train_vector = X_train_vector.toarray()
X_test_vector = X_test_vector.toarray()
X_train_vector.shape

#Training a logistic regression model
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(penalty = "l2", verbose = 1)
lr.fit(X_train_vector, y_train)

lr.score(X_train_vector, y_train)

#Sentiment prediction
tweets = ["this movie is garbage",
	"what a fantastic film!"]
tweets_tfidf = tfidf.transform(tweets)
lr.predict(tweets_tfidf)

#Training decision tree model
from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier(max_depth = 20)
tree.fit(X_train_vector, y_train)

tree.score(X_train_vector, y_train)


# Most important terms(features)
importances = tree.feature_importances_
indices = np.argsort(importrances)[::-1]

 

 

Vector Similarity

Cosine Similarity

문장 혹은 문서 사이의 유사도를 계산한다.

벡터간의 거리가 아닌 벡터간의 각도 기반으로 유사도를 측정한다.

ex) A = (0, 5), B = (2,4)일 때,

cosθ = (0*2 + 5*4)/(루트(0*0+5*5)*루트(2*2+4*4)) = 20/5*루트(20)  = 2*루트(5)/5

 

 

Word Embedding