-
[NLP processing] 자연어 데이터를 전처리해보자!ML&DL 이야기/ML 2024. 2. 23. 19:09
자연어 처리과정
자연어처리 과정은 아래의 단계를 거친다.
1. Preprocessing: 자연어를 정리하는 과정, token화가 포함됨
불용어 제거(Stopwords removing), 형태소 분석(Stemming), 표제어 추출(Lemmatization)
2. Vectorization: 정수 인코딩으로 변형하는 과정(임베딩 시키기 위한 전과정)
One-hot Encoding, Count vectorization, Tfidf, Padding
3. Embedding(실제 측정 차원으로 임베딩 시키는 과정)
Word2vec, Doc2vec, Glove, Fasttext
4. Modeling(자연어를 입력하고 원하는 task를 수행하는 과정)
GRU, LSTM, Attention
Preprocessing & Tonkenize
자연어 데이터 전처리에는 정해진 정답은 없지만, 불용어, 특수문자, 언어 통일(여러 언어로 작성된 경우) 등을 하는 단계이다. 예시를 보면 아래와 같을 것이다.
1. 불용어, 특수문자 제거: 특수문자, 조사 등을 제거(list화를 하거나 기존의 불용어 데이터를 이용)
이때 cleaning과 normalize과정을 거치는데, 이는 불용어 제거와 표현방법이 다른 단어를 하나로 통합시켜 같은 단어로 만드는 과정(대소문자, 동의어 등)을 말한다.
2. 정규표현식을 사용하여 한글과 영어 소문자를 제외한 모든 글자 제거
3. 한국의 경우 형태소 분석을 기반으로 토큰화, 영어 데이터의 경우 단어 기반으로 토큰화를 진행
영어의 경우 대다수 띄어쓰기를 기준으로 token화를 하며, 한국어는 형태소 단위로 토큰화를 하는 경우가 많다.
한국어 토큰화 라이브러리는 주로 konlpy(코엔엘파이)를 사용하며, 내부엔 여러 서브 모듈(Kkma, Hannanum, Komoran, Mecab, Twitter)이 존재한다.이때, 내가 설정한 불용어들을 결과로 반환해주는 형태소 분석기를 사용하셔야 합니다. 예를 들어 조사를 불용어로 설정하였는데 조사를 분리해주지 못하는 형태소 분석기는 후보에서 제외하시면 됩니다. -데이콘 lyung@dacon.io
4. 해당 토큰을 기반으로 리스트에 저장된 불용어 제거
이런 단계를 거친 코드 예시는 아래와 같다(출처: 데이콘 NLP 언제까지 미룰래?)
def text_preprocessing(text_list): stopwords = ['을', '를', '이', '가', '은', '는', 'null'] #불용어 설정 tokenizer = Okt() #형태소 분석기 token_list = [] for text in text_list: txt = re.sub('[^가-힣a-z]', ' ', text) #한글과 영어 소문자만 남기고 다른 글자 모두 제거 token = tokenizer.morphs(txt) #형태소 분석 token = [t for t in token if t not in stopwords or type(t) != float] #형태소 분석 결과 중 stopwords에 해당하지 않는 것만 추출 token_list.append(token) return token_list, tokenizer #형태소 분석기를 따로 저장한 이유는 후에 test 데이터 전처리를 진행할 때 이용해야 되기 때문입니다. train['new_article'], okt = text_preprocessing(train['content'])
위의 코드 예시는 단어가 아닌 문장기반 토큰화를 적용할때의 예시로, 현재 내가 작업하는 부분에서는 전처리에 언어를 통일하는 부분 + 대소문자 통일만 작업하였다(문장기반이 아닌 단어 데이터여서)
Vectorization
NLP, 즉 자연어를 숫자로 변환하는 과정을 의미한다. 간단히 말해 단어에 특정 벡터를 붙여주어, 구분하는 단계이다.
특정 단어에 숫자를 부여하고, 해당 단어에 해당하는 숫자로 문장을 표시, 이후에 encoding을 해당단어를 표시한다.
keras의 text_to_sequence를 이용한 예시는 아래의 코드와 같다.
from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences def text2sequence(train_text, max_len=100): tokenizer = Tokenizer() #keras의 vectorizing 함수 호출 tokenizer.fit_on_texts(train_text) #train 문장에 fit train_X_seq = tokenizer.texts_to_sequences(train_text) #각 토큰들에 정수 부여 vocab_size = len(tokenizer.word_index) + 1 #모델에 알려줄 vocabulary의 크기 계산 print('vocab_size : ', vocab_size) X_train = pad_sequences(train_X_seq, maxlen = max_len) #설정한 문장의 최대 길이만큼 padding return X_train, vocab_size, tokenizer train_X, vocab_size, vectorizer = text2sequence(train['text'], max_len = 100)
Embedding
앞서 이름을 붙인 단어 데이터에를 그대로 적용하면 단어간 유사도를 고려하지 못한다는 치명적인 단점이 있다.
(그냥 순서대로 번호를 붙여준거라고 생각해도 된다)
이를 위해 유사도를 반영한 벡터화를 위해 word2vec등의 다양한 방법론들이 나오게 되었다.
임베딩 또한 하나의 모델을 의미하며 훈련을 통해 학습됨으로 데이터가 충분하고 시간이 많으면 소지한 데이터에 특화된 임베딩 모델을 학습시킬 수 있다.
하지만 보통은 pre_trained embedding model을 가져와서 사용한다.
대표적으로 word2vec, gloce, fasttext등 다양한 방법들이 존재하지만, 최근에는 hugging face을 통해 쉽게 사용가능한 transfomer 기반의 Bert나 GPT를 사용하기도 한다.
word2vec을 이용한 예시코드를 보면 아래와 같다.
#model load import gensim word2vec = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin.gz', binary = True) #vocabulary에 있는 토큰들의 벡터를 가져와 embedding matrix에 저장 embedding_matrix = np.zeros((vocab_size, 300)) #300차원의 임베딩 매트릭스 생성 for index, word in enumerate(vocabulary): #vocabulary에 있는 토큰들을 하나씩 넘겨줍니다. if word in word2vec: #넘겨 받은 토큰이 word2vec에 존재하면(이미 훈련이 된 토큰이라는 뜻) embedding_vector = word2vec[word] #해당 토큰에 해당하는 vector를 불러오고 embedding_mxtrix[i] = embedding_vector #해당 위치의 embedding_mxtrix에 저장합니다. else: print("word2vec에 없는 단어입니다.") break #keras embedding layer에 embedding_matrix를 가중치로 주어 이용 #Embedding 최소 2개의 매개변수(입력 차원(보통 단어의 수), 출력 차원)으로 정의된다 model = Sequential() model.add(Embedding(vocab_size, 300, weights = [embedding_matrx], input_length = max_len))
추가적으로 Keras의 Embedding 층을 추가로 사용하는 이유는 앞서 말한 pretrained된 데이터들은 해당 모델에서 정의한 벡터의 차원을 가지는데, 이를 우리가 필요한만큼의 차원으로 다시 재축소(dense vector로 변환) 하기 위해서이다.
(pretrained 된 벡터를 주어줌으로서 학습이 더 용이하게 이루어지게 한다)
Test시 유의점
- train에 사용했던 형태소 분석기를 객체로 저장하여 test에도 이용해야 한다.
- train에 사용했던 vectorizer를 객체로 저장하여 test에도 이용해야 한다.
- train에 사용했던 Embedding matrix를 객체로 저장하여 test에도 이용해야 한다.
Reference
https://www.dacon.io/competitions/official/235670/codeshare 실습 코드 참고
https://monetd.github.io/python/nlp/Word-Embedding-Word2Vec-%EC%8B%A4%EC%8A%B5/ 실습 코드 참고
영어 실습 참고
https://limelbe.tistory.com/138
'ML&DL 이야기 > ML' 카테고리의 다른 글
[Time-series] Time-series Analysis, 시계열 알아보기 (2) 2024.03.22 [Graph] Graph Neural Networks 개론(개념정리) (4) 2024.03.04 [NLP] BLEU Score(Bilingual Language Evaluation Understudy) (0) 2024.02.16 Beam Search in NLP (1) 2024.02.16 [NLP] RNN, LSTM과 NLP 개론 (0) 2024.02.13