😒 저 저 저 개념없는 나/⛓️ DL & ML

[문서 제목 자동 분류 작업 | Clustering] 5. 한국어 Text Clustering Word2Vec K-means | 인턴

우주수첩 2024. 1. 17. 16:29
728x90

 

주요 라이브러리

  • KoNLPy의 KKma 사용
  • gensim의 Word2Vec 사용
  • Sklearn의 K-Means 알고리즘 사용
pip install konlpy
pip install gensim
pip install scikit-learn

 

 

진행 순서

  1. 데이터 수집
  2. 형태소 분석 : 포스태깅
    -> KoNLPy의 kkm 사용
    -> morphs 사용
  3. gensim의 Word2Vec을 사용하여 벡터화 진행
  4. 클러스터링 진행

 

Word2Vec

단어를 N차원의 벡터로 만들어준다

텍스트만 tokenizing 해서 넣어주면 알고리즘을 통해 토큰 간의 상관관계를 찾아내고, 서로 유사한 공간에 배치하도록 만들어진다.

 

 

 

구현 코드

 

데이터 호출 및 전처리

import pandas as pd
from sklearn.cluster import KMeans
import numpy as np
from konlpy.tag import Kkma
import string
from gensim.models import Word2Vec
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE

csv_file_path = '../data/dataset_1.csv'

try:
    df = pd.read_csv(csv_file_path, encoding='utf-8')
except UnicodeDecodeError:
    print('utf-8으로 디코딩하는 중 오류 발생. 다른 인코딩 시도 필요.')


remove_punct_dict = dict((ord(punct), None) for punct in string.punctuation)
kkma_kor = Kkma() # 한국어 형태소 분석기 꼬꼬마

def KkmaLemNormalize_kor(text): # 형태소 분석 값 저장
    if '.' in text:
        text = text.rsplit('.', 1)[0] # 확장자 제거 후 군집화
    tokens = kkma_kor.morphs(text)
    return ','.join(tokens)

본인은 파일 이름을 가지고 클러스터링을 진행하기 때문에 문서의 확장자는 모두 제거 한 후 학습하였땨

 


Word to Vector

df['pos_tagging'] = df['CONTENT_TITLE'].map(KkmaLemNormalize_kor)

embedding_model = Word2Vec(df['pos_tagging'],  window = 2, min_count=50, workers=4,  sg=1)

 

  • pos_tagging : content_title을 형태소 분석 한 결과 값
  • gensim의 Word2Vec 함수를 사용하여 형태소 분석을 진행한 단어들을 vector로 변환한다.

Word Mean

def get_sentence_mean_vector(morphs):
    vector = []
    for i in morphs:
        try:
            vector.append(embedding_model.wv[i])
        except KeyError as e:
            pass
    try:
        return np.mean(vector, axis=0)
    except IndexError as e:
        pass

# 각 단어 벡터의 평균값을 word_mean에 저장한다.
df['word_mean'] = df['pos_tagging'].map(get_sentence_mean_vector)
  • Word2Vec을 통해 학습된 embedding_model을 사용하여 주어진 형태소 리스트에 대한 문장의 평균 벡터를 계산하는 역할을 한다.
  • word_mean : 각 단어 벡터의 평균 값

 

word_mean 예시 값

 [-0.03963488  0.0562488   0.12559599  0.18853712 -0.11144651 -0.22676721
  0.25350776  0.40121943 -0.05900029 -0.38926458 -0.04434485 -0.46354598
  0.07621433  0.13625236  0.08149165  0.01368343 -0.00563234  0.00104974
  0.09237216 -0.25832137  0.1711869   0.1663731   0.35206586 -0.15955646
 -0.13816425  0.07335179 -0.23451555  0.06883837 -0.25656733 -0.10069612
  0.2604331  -0.20582983  0.12017339 -0.30541965 -0.10755094  0.01330901
  0.01289757  0.25516656 -0.27447587 -0.05738288  0.06369495  0.16284803
 -0.21038178 -0.07707428  0.06543393 -0.134137    0.01083146 -0.3203792
  0.00138586  0.04119883  0.02148912 -0.02113771 -0.04401416 -0.0745329
  0.17022403 -0.17828026  0.10029115 -0.07868389 -0.03901556  0.12809992
  0.01650007 -0.00709657  0.17983808 -0.1431954  -0.10177233  0.13732056
 -0.206829   -0.12785664 -0.15516965 -0.18829031 -0.00631164  0.1141054
  0.06517173  0.02908249  0.23753299 -0.21832423  0.03050529 -0.07775839
 -0.22351442 -0.20505099 -0.0773908  -0.10928757  0.0066435   0.10738466
 -0.161667   -0.27250093 -0.05145412 -0.09048307  0.02951686  0.21962707
  0.15904815 -0.10457265 -0.04895057 -0.14961243  0.19503383 -0.0778031
 -0.22608301  0.18543425  0.09902657 -0.0099283 ]

Clustering

word_vectors = df.word_mean.to_list()

kmeans_clustering = KMeans(n_clusters=3, max_iter=10000, random_state=42, n_init=10)
idx = kmeans_clustering.fit_predict( word_vectors )

df['category'] = idx
  • n_clusters : 3개의 클러스터로 데이터 군집화를 진행한다
  • max_iter : 알고리즘이 수렴할 때 까지 최대 10000번의 반복을 수행한다.
  • random_state : 무작위성을 제어하기 위한 시드값으로 큰 의미 없음
  • n_init : 초기 클러스터 중심을 설정 시도를 10번 한다.

 

  • idx : 군집화를 진행한 결과를 담고 있는 리스트
  • 데이터 프레임의 'category' feature에 클러스터링 결과값 저장

 

결과

category
2 4446
0 4066
1 3113
Name: count, dtype: int64

시각화

word_vectors = df.word_mean.to_list()
word_vectors = np.array(word_vectors)

tsne = TSNE(n_components=2, random_state=42)
word_vectors_2d = tsne.fit_transform(word_vectors)


df['tsne_x'] = word_vectors_2d[:, 0]
df['tsne_y'] = word_vectors_2d[:, 1]

# Plot the scatter plot with different colors for each cluster
plt.figure(figsize=(10, 8))
plt.scatter(df['tsne_x'], df['tsne_y'], c=df['category'], cmap='viridis', alpha=0.7)
plt.title('t-SNE Visualization of Clusters')
plt.xlabel('t-SNE Dimension 1')
plt.ylabel('t-SNE Dimension 2')
plt.colorbar()
plt.show()

 

 

cluster 3개

 

 

cluster 4개

 


데이터 프레임 정리, 저장

del df['word_mean']
del df['pos_tagging']
del df['cluster_kor']

new_file_path = '../result_data/UL_clustering_result_1.csv'
df.to_csv(new_file_path, index=False)
  • 안쓰는 feature 정리

 

참고 url:

https://ratsgo.github.io/natural%20language%20processing/2017/03/08/word2vec/

 

Word2Vec으로 문장 분류하기 · ratsgo's blog

이번 포스팅에선 요즘 인기를 끌고 있는 단어 임베딩 방법론 가운데 하나인 Word2Vec을 활용해서 문장을 분류하는 방법에 대해 이야기해보려고 합니다. 우선은 뽐뿌, 클리앙, 세티즌 등 휴대폰 리

ratsgo.github.io

https://beomi.github.io/2020/01/05/Clustering_Twitter_Users/

 

NLP 튜토리얼: 라벨링 없이 트위터 유저들을 자동으로 나누어보기 - Beomi's Tech blog

트위터에는 굉장히 다양한 유저들이 있다. 그리고 트위터 유저들은 “BIO”라고 부르는 자기소개 페이지에 자신에 대한 정보를 적어둔다. 위 스크린샷과 같이, 자신의 계정이 어떤 계정인지를

beomi.github.io

 

 

 

 

 

 

728x90