CLOVA Studio 운영자 Posted 16 hours ago 공유하기 Posted 16 hours ago 1. 임베딩이란 무엇인가요? 임베딩은 자연어 처리(NLP)와 기계학습의 핵심 개념으로, 텍스트 데이터를 인공지능이 이해할 수 있는 숫자 벡터로 변환합니다. 의미적으로 유사한 "멍멍이"와 "강아지" 같은 단어들은 벡터 공간에서도 가까운 위치에 배치됩니다. 임베딩의 가장 큰 특징은 단어나 문장의 의미적 관계를 수학적으로 표현할 수 있다는 점입니다. "왕 - 남자 + 여자 = 여왕"과 같은 벡터 연산이 가능하여 자연어의 의미 관계를 수치적으로 포착합니다. 단순한 단어 수준을 넘어 문장과 문단 전체의 의미까지 포착할 수 있는 임베딩은 검색 시스템, 추천 시스템, 감정 분석 등 다양한 자연어 처리 작업에서 핵심적인 역할을 합니다. 특히 최근 transformer 기반 사전학습 모델의 등장으로 더욱 정교한 임베딩이 가능해졌으며, 이는 기계 번역과 질의응답 시스템 같은 고도화된 AI 서비스의 성능 향상에 크게 기여하고 있습니다. CLOVA Studio의 임베딩 API(v2 포함)를 통해 텍스트 데이터를 1,024차원의 벡터로 변환할 수 있습니다. 이제 화장품 리뷰 데이터를 예시로 활용하여, CLOVA Studio 임베딩v2 API로 텍스트의 의미를 벡터 공간에 표현하고 분석하는 과정을 진행해보겠습니다. 분석 데이터 : review-cosmetic_raw.csv (데이터 출처 : AI Hub 속성기반 감정분석 데이터) 2. 임베딩 시각화를 통한 데이터 분포 확인 리뷰 텍스트 데이터 시각화는 다음 네 단계로 진행됩니다. 화장품 리뷰 텍스트 데이터를 수집하고 전처리합니다. 리뷰의 감정은 긍정(Positive), 중립(Neutral), 부정(Negative)으로 분류되어 있습니다. CLOVA Studio의 임베딩v2 API를 활용하여 각 리뷰 텍스트의 1,024차원 임베딩 벡터를 생성합니다. 고차원의 임베딩 벡터를 t-SNE 알고리즘을 통해 2차원으로 차원 축소합니다. 감정 분류에 따라 색상을 다르게 적용하여 시각화함으로써, 감정별 군집화 패턴을 확인할 수 있습니다. 이러한 과정을 통해 화장품에 대한 고객들의 감정적 반응이 벡터 공간에서 어떻게 분포하는지 파악할 수 있습니다. ① 필요한 모듈 import import time from tqdm import tqdm import pandas as pd from sklearn.manifold import TSNE import numpy as np import matplotlib.pyplot as plt from matplotlib import rcParams from sklearn.utils import resample ② 데이터 불러오기 df = pd.read_csv('review-cosmetic_raw.csv', encoding = 'utf-8-sig') # 같은 디렉토리 상의 데이터 불러오기 df.info() # 데이터 정보 확인 print(df.head()) # 데이터 상단 부분 출력 <class 'pandas.core.frame.DataFrame'> RangeIndex: 14835 entries, 0 to 14834 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Index 14835 non-null int64 1 Aspects 14835 non-null object 2 Domain 14835 non-null object 3 GeneralPolarity 14835 non-null int64 4 Text 14835 non-null object dtypes: int64(2), object(3) memory usage: 579.6+ KB Index Aspects Domain \ 0 1 [{'Aspect': '기능/효과', 'SentimentText': ' 거품이 풍부... 화장품 1 2 [{'Aspect': '기능/효과', 'SentimentText': '여드름 피부에... 화장품 2 3 [{'Aspect': '보습력/수분감', 'SentimentText': '유분기도 ... 화장품 3 4 [{'Aspect': '기능/효과', 'SentimentText': '이 제품 쓴다... 화장품 4 5 [{'Aspect': '향', 'SentimentText': '박하향이 처음에는 자... 화장품 GeneralPolarity Text 0 1 거품이 풍부해서 사용하기 편하고, 사용하기 편하고, 세정력도 좋습니다. 피부에 ... 1 0 여드름 피부에 잘 맞는 듯합니다. 좁쌀 여드름이 많이 좋아졌어요. 용량이 작고 사... 2 1 유분기도 여드름도 많이 좋아졌어요. 여드름도 많이 좋아졌어요. 세일할 때 구매하니 ... 3 1 이 제품 쓴다고 여드름이 안 생기는 건 아니지만 자극적이지 않아서 촉촉하지도 않지만... 4 1 박하향이 처음에는 자극적이라 생각했는데 풍부한 거품으로 부드럽게 잘 세정되는것 같아... Quote 데이터 구조확인 데이터셋은 화장품 리뷰 데이터로, 총 14,835개의 행과 5개의 열로 구성되어 있습니다. 데이터셋의 열에 대한 설명은 다음과 같습니다. Index : number of data , 정수형 데이터로 1 ~ 14835까지 데이터포인트 ID를 부여한 값입니다. Aspects : 리뷰 속성어(감정 분류 대상 텍스트별 점수 부여 내역), 텍스트 데이터를 쪼개서 감정 분석 점수를 부여한 정보 입니다. 본 데이터의 텍스트 부분만 합쳐서 사용했습니다. Domain : 리뷰 상품 , 화장품 리뷰 데이터이므로 "화장품" GeneralPolarity : 상품평 전체 감정 분류 정수형 데이터 (부정 -1, 중립 0, 긍정 1) Text : 리뷰 텍스트 데이터 (본 분석에서 임베딩을 구하는 타겟 데이터) 본 데이터는 화장품에 대한 텍스트 리뷰 데이터로 이미 감정분류(부정, 중립, 긍정), 리뷰 텍스트 데이터에 대한 분류가 완료된 데이터입니다. ③ 임베딩 구하기 본 분석에서는 빠르게 임베딩 값을 구하고 시각화하기 위해 240개의 데이터 포인트 (부정 -1, 중립 0, 긍정 1 : 각 80개씩)를 샘플링하여 사용합니다. def process_batch(batch, executor, max_retries, retry_delay_seconds): results = [] for text in tqdm(batch, desc="Processing Requests"😞 retries = 0 while retries <= max_retries: try: response = executor.execute({"text": text}) if isinstance(response, list😞 results.append(response) break raise ValueError(f"Unexpected response format: {response}") except Exception as e: retries += 1 if retries > max_retries: print(f"Skipping text: {text} due to repeated errors.") results.append(None) else: time.sleep(retry_delay_seconds) return results def main(): executor = CompletionExecutor( host='clovastudio.apigw.ntruss.com', api_key='****', # 올바른 값으로 변경해줘야합니다 api_key_primary_val='***', # 올바른 값으로 변경해줘야합니다 request_id='****' # 올바른 값으로 변경해줘야합니다. ) # 데이터 포인트 240개 샘플링 data = pd.concat([ resample(df[df['GeneralPolarity'] == 1], n_samples=80, random_state=0), resample(df[df['GeneralPolarity'] == 0], n_samples=80, random_state=0), resample(df[df['GeneralPolarity'] == -1], n_samples=80, random_state=0) ]).reset_index(drop=True) batches = [data['Text'][i:i + 60] for i in range(0, len(data), 60)] embeddings = [] for i, batch in enumerate(batches, start=1😞 print(f"Processing batch {i}/{len(batches)}") embeddings.extend(process_batch(batch, executor, max_retries=5, retry_delay_seconds=10)) if i < len(batches): time.sleep(30) # 429에러 발생 방지를 위한 딜레이, 필요시 조정 data['Embedding'] = embeddings print(data) if __name__ == '__main__': main() Processing batch 1/4 Processing Requests: 100%|██████████| 60/60 [00:08<00:00, 7.36it/s] Processing batch 2/4 Processing Requests: 100%|██████████| 60/60 [00:39<00:00, 1.52it/s] Processing batch 3/4 Processing Requests: 100%|██████████| 60/60 [00:44<00:00, 1.35it/s] Processing batch 4/4 Processing Requests: 100%|██████████| 60/60 [00:30<00:00, 1.95it/s] Index Aspects \ 0 3905 [{'Aspect': '자극성', 'SentimentText': '순하고 ', 'S... 1 13891 [{'Aspect': '기능/효과', 'SentimentText': '잡티, 멜라닌... 2 4789 [{'Aspect': '기능/효과', 'SentimentText': '세정력이 뛰어... 3 7049 [{'Aspect': '보습력/수분감', 'SentimentText': '얼굴에 너... 4 13036 [{'Aspect': '제형', 'SentimentText': '제형이 생크림 입자... .. ... ... 235 4639 [{'Aspect': '흡수력', 'SentimentText': '너무 무거운 느낌... 236 5757 [{'Aspect': '편의성/활용성', 'SentimentText': '사용하기 ... 237 9963 [{'Aspect': '기능/효과', 'SentimentText': '주름이 옅어지... 238 5514 [{'Aspect': '피부타입', 'SentimentText': '이 제품은 건성... 239 7696 [{'Aspect': '보습력/수분감', 'SentimentText': '촉촉함이 ... GeneralPolarity Text \ 0 1 순하고 저렴하고 양이 많아요. 촉촉함도 오래가고, 오래가고, 끈적이지 않아요. ... 1 1 잡티, 멜라닌 색소 억제 및 잡티 제거와 커버에도 도움이 되는 것 같아요. 잡티 ... 2 1 세정력이 뛰어난 것 같습니다. 세안하고 나면 뽀득거리면서도 자극적이지 않고 깨끗한 ... 3 1 얼굴에 너무 촉촉하고 ~~ 와~얼굴에 윤기가 광이 나요~~굿 4 1 제형이 생크림 입자 느낌으로 쫀쫀하게 피부에 문지르면 깨끗하게 잘 지워져요. .. ... ... 235 -1 너무 무거운 느낌이라 자주 손이 안가네요. 피부에 팩한 것 처럼 한꺼풀 덮여 있는 ... 236 -1 사용하기 불편합니다. 리프팅 효과도 없는 것 같고 피부에 트러블이 생깁니다. 237 -1 주름이 옅어지는 느낌 안 드네요. 피부는 약간 간질거리고, 붉은 트러블도 생겼어... 238 -1 이 제품은 건성인 분들에게는 뻑뻑하게 발리고 건조한 것 같습니다. 뻑뻑하게 발리고... 239 -1 촉촉함이 덜하고 끈적임이 있어 건조할때 OOO 바르고 건조함이 완화가 되기를 기대했... Embedding 0 [-1.0322266, 1.0615234, -1.0039062, 0.02919006... 1 [-0.70654297, 0.68603516, -1.1757812, -0.28100... 2 [-0.7182617, 1.0566406, -1.0390625, -0.2807617... 3 [0.38183594, 1.3720703, -1.1142578, -0.8857422... 4 [-0.5258789, 0.52441406, -1.1601562, -1.410156... .. ... 235 [0.22509766, 1.0605469, -1.3222656, -0.7373047... 236 [-0.87353516, 1.6015625, -1.5839844, -0.878417... 237 [-1.1142578, 0.8383789, -1.4892578, -0.6748047... 238 [-0.049591064, 1.4492188, -0.671875, -1.814453... 239 [-0.41479492, 1.0751953, -1.3623047, -0.305419... [240 rows x 5 columns] # 임베딩값을 포함한 데이터프레임 저장 data.to_csv('review-cosmetic_emb.csv', index=False, encoding='utf-8-sig') 리뷰데이터에 대해 임베딩 값을 추가하여 저장한 결과 파일은 다음과 같습니다. review-cosmetic_emb.csv matplot, t-SNE 차원 축소를 통해 임베딩 시각화하기 t-SNE(t-Distributed Stochastic Neighbor Embedding)는 고차원 데이터를 저차원으로 변환하여 시각화하는 데 매우 효과적인 비선형 차원 축소 기법입니다. 1024차원의 데이터 포인트의 임베딩값 간의 유사도 관계를 최대한 보존하여 2차원 공간으로 차원 축소하면 데이터 포인트들을 시각화할 수 있습니다. 비슷한 의미를 가진 데이터 포인트들은 2차원 평면상에서 서로 가깝게 위치하게 되어, 임베딩 공간의 구조를 직관적으로 이해할 수 있게 됩니다. 본 분석에서는 빠르게 임베딩 값을 구하고 시각화하기 위해 240개의 데이터 포인트 (부정 -1, 중립 0, 긍정 1 : 각 80개씩)를 샘플링하여 사용합니다. rcParams['font.family'] = 'AppleGothic' plt.rcParams['axes.unicode_minus'] = False embeddings = np.array(data['Embedding'].tolist()) tsne = TSNE(n_components=2, random_state=0, perplexity=30) # 2차원으로 시각화, perplexity는 데이터의 고차원 공간에서 가까운 이웃을 선택하는 방법과 관련이 있으며, 이 값이 크면 더 넓은 범위의 이웃을 고려한다는 의미이고, 작으면 더 국소적인 관계를 이웃으로 고려한다는 의미입니다 # 데이터포인트의 개수가 많을수록 큰 값을 사용하는 것이 일반적이며, 보통 5~50 사이의 값을 선택합니다. tsne_results = tsne.fit_transform(embeddings) data['t-SNE Dimension 1'] = tsne_results[:, 0] data['t-SNE Dimension 2'] = tsne_results[:, 1] polarity_to_color = {1: 'green', 0: 'blue', -1: 'red'} # 1: 긍정, 0: 중립, -1: 부정 colors = data['GeneralPolarity'].map(polarity_to_color) plt.figure(figsize=(10, 10)) plt.scatter( data['t-SNE Dimension 1'], data['t-SNE Dimension 2'], c=colors, alpha=0.5 ) plt.title('t-SNE 시각화: 임베딩 감성 분석') plt.xlabel('t-SNE 차원 1') plt.ylabel('t-SNE 차원 2') plt.legend(handles=[ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='green', markersize=10, label='긍정 (1)'), plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='blue', markersize=10, label='중립 (0)'), plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='red', markersize=10, label='부정 (-1)') ]) plt.show() 감정 별(긍정, 중립, 부정)로 t-SNE 시각화한 결과입니다. 긍정(1, 초록색)은 주로 하단부에 군집화되었고 부정(-1, 빨간색)은 상단부에 주로 분포한 것으로 확인할 수 있습니다. 또한 중립(0, 파란색)은 중앙에 넓게 분포하여 다른 감정들과 일부 겹치는 영역이 있습니다. 리뷰 텍스트가 감정 별로 구분이 되는 군집으로 형성되어 있고 CLOVA Studio의 임베딩 모델이 감정의 의미적 차이를 잘 포착했다는 것을 확인할 수 있습니다. 일부 영역에서 감정 간 겹칩이 발생하는 것은 리뷰 텍스트의 미묘한 감정표현이나 복잡한 표현이 포함된 경우로 해석할 수 있습니다. plotly, t-SNE 차원 축소를 통해 임베딩 시각화하기: 데이터포인트 내용 확인하기 import plotly.express as px import pandas as pd data['Text'] = data['Text'] df_tsne = pd.DataFrame({ 't-SNE Dimension 1': data['t-SNE Dimension 1'], 't-SNE Dimension 2': data['t-SNE Dimension 2'], 'GeneralPolarity': data['GeneralPolarity'], 'Text': data['Text'] }) df_tsne['GeneralPolarity'] = df_tsne['GeneralPolarity'].astype(str) fig = px.scatter( df_tsne, x='t-SNE Dimension 1', y='t-SNE Dimension 2', color='GeneralPolarity', hover_data=['Text'], color_discrete_map={ "-1": "red", # 부정 "0": "blue", # 중립 "1": "green" # 긍정 }, title='t-SNE 시각화: 감성 분석', width=1200, # 그래프 가로 길이, 필요시 조정 height=800 # 그래프 세로 길이, 필요시 조정 ) fig.update_layout( font=dict( family="AppleGothic", size=16 ), title=dict( font=dict(size=16) ), xaxis_title="t-SNE 차원 1", yaxis_title="t-SNE 차원 2" ) fig.show() plot에 표시된 데이터 포인트의 내용을 인터랙티브하게 바로 확인할 수 있도록 'plotly'를 이용하여 시각화하였습니다. 이를 통해 개별 데이터 포인트에 대한 자세한 정보 확인이 가능하여 실제 리뷰 텍스트의 내용이 어떤지 확인할 수 있습니다. 왼쪽 영역에 위치한 초록색 데이터 포인트를 확인해보니 "제품이 셋 세트라 완전 풍성합니다. 제형이 쫀쫀하게 성분이 콜라겐으로 더 행복한 시간 될 것 같아요"라는 내용의 긍정적인 리뷰 내용을 확인할 수 있습니다. 반면, 오른쪽 영역에 위치한 빨간색 데이터포인트를 확인해보면 "눈시림이 너무 심해서 얼굴에 바를 수가 없네요 자극이 너무 심하네요"라는 내용의 부정적인 리뷰 내용을 확인할 수 있습니다. 3. 임베딩 값을 활용한 분류기 구축과 성능평가 지금까지 우리는 이미 감정 분류가 되어있는, 즉 분류 레이블이 있는 데이터의 임베딩을 구하고 시각화를 해보았습니다. 하지만 실제 대부분의 데이터는 레이블이 없는 데이터를 다루게 되는데요, 이런 상황에서 텍스트 임베딩은 분석에 유용한 도구로 활용될 수 있습니다. 임베딩은 텍스트의 의미적 유사성을 수치화하여 표현된 값이기 때문에, 이를 기반으로 비슷한 의미를 가진 데이터들을 그룹화할 수 있습니다. 유사한 텍스트는 다차원의 임베딩 공간에서 가까운 거리에 위치하게 되기 때문입니다. 이러한 임베딩의 특성을 활용하여, K-means 클러스터링을 통해 비슷한 의미를 가진 텍스트 데이터들을 레이블 없이도 분류가 가능합니다. K-means 클러스터링은 다음과 같은 상황에서 특히 유용합니다. 텍스트로 이루어진 대량의 문서(ex. 고객 cs/리뷰 데이터)를 주제 별로 분류할 때 텍스트 데이터의 의미있는 패턴을 찾고 싶을 때 화장품 리뷰 데이터는 이미 분류 레이블(감정), 즉 분류에 대한 정답을 가지고 있지만 클러스터링 분석의 결과를 실제와 비교해보면서 임베딩 기반 클러스터링의 활용은 어떻게 할 수 있는지 알아보겠습니다. 임베딩 값을 활용한 분류기 구축/성능 평가 과정은 다음과 같습니다. K-means 클러스터링 클러스터링 성능평가하기 ① 필요한 모듈 import import numpy as np import pandas as pd from sklearn.cluster import KMeans from sklearn.feature_extraction.text import TfidfVectorizer import matplotlib.pyplot as plt from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score from scipy.stats import entropy from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report from xgboost import XGBClassifier from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay from sklearn.model_selection import GridSearchCV K-Means 클러스터링이란? 텍스트 데이터의 t-SNE 차원 축소 결과를 활용하여 K-Means 클러스터링을 수행하고, 클러스터별 카테고리(ex. 감정) 분포와 주요 키워드를 분석하겠습니다. 이를 통해 데이터의 특성별로 데이터를 나눠서 군집화하고 군집화된 데이터들의 내용으로 데이터의 특징을 파악할 수 있습니다. 코드 설명에 앞서, K-Means 클러스터링 알고리즘에 대해 알아봅시다. K-means는 데이터의 특징을 기반으로 하여 k개의 그룹으로 나누는 비지도 학습 알고리즘입니다. K-means 클러스터링 알고리즘을 도식화 하면 다음과 같습니다. 각 클러스터는 하나의 중심점을 가져야 합니다. 1. 초반에는 데이터 포인트 중 무작위로 k개의 중심점이 정해집니다. 이 초기 중심점들이 각 클러스터의 시작점이 됩니다. 2. 각 데이터 포인트들은 초반에 정해진 시작점을 기준으로 가장 가까운 클러스터에 할당됩니다. 3. 정해진 각 클러스터 내 평균을 계산하여 평균값이 새로운 중심값으로 설정됩니다. 4. 더이상 평균값에 변경이 없이 수렴할 때가지 클러스터를 재할당하는 과정을 거칩니다. ② K-Means 클러스터링 실행하기 앞서 t-SNE로 차원 축소한 데이터를 기준으로 3개의 클러스터를 생성합니다. 각 클러스터에서 부정(-1), 중립(0), 긍정(1) 감정이 얼마나 분포하는 확인해보고, 클러스터 별로 데이터의 특징이 어떻게 나타나는지 확인해보겠습니다. 클러스터링 실행 #1. t-SNE 결과 기반으로 클러스터링 kmeans = KMeans(n_clusters=3, random_state=42) data['Cluster'] = kmeans.fit_predict(data[['t-SNE Dimension 1', 't-SNE Dimension 2']]) # 2. 클러스터별 감성 비율 분석 sentiment_distribution = data.groupby('Cluster')['GeneralPolarity'].value_counts(normalize=True).unstack().fillna(0) print("클러스터별 감성 분포:") print(sentiment_distribution) # 3. 주요 키워드 분석 vectorizer = TfidfVectorizer(max_features=15) # 상위 15개 확인, 필요시 변경 가능 cluster_keywords = {} for cluster_id in data['Cluster'].unique(): cluster_texts = data[data['Cluster'] == cluster_id]['Text'] tfidf_matrix = vectorizer.fit_transform(cluster_texts) keywords = vectorizer.get_feature_names_out() cluster_keywords[cluster_id] = keywords print("클러스터별 주요 키워드:") for cluster_id, keywords in cluster_keywords.items(): print(f"Cluster {cluster_id}: {keywords}") Quote 다음은 KMeans()의 파라미터에 대한 설명입니다. n_clusters :군집화할 클러스터의 개수를 지정합니다. default = 8 random_state : 재현성을 위해 초기 중심점을 무작위로 선택할 때 사용되는 난수 생성을 위한 시드값을 설정합니다. ③ 결과 확인하기 클러스터별 감성 분포: GeneralPolarity -1 0 1 Cluster 0 0.076923 0.646154 0.276923 1 0.707547 0.283019 0.009434 2 0.000000 0.115942 0.884058 클러스터별 주요 키워드: Cluster 2: ['꾸준히' '너무' '만족합니다' '많이' '바르고' '얼굴에' '오래지속되어' '정말''좋네요' '좋습니다' '좋아요' '촉촉하고' '피부가' '피부에' '효과가'] Cluster 0: ['같습니다' '같아요' '느낌이' '들어요' '발림성' '발림성이' '않고' '오래' '좋고' '좋네요' '좋습니다' '좋아요' '향은' '향이' '효과는'] Cluster 1: ['가격대비' '가격도' '같아요' '구성이' '너무' '아쉽네요' '아직' '않네요' '않아요' '용량이' '촉촉하지' '피부가' '효과' '효과가' '효과는'] 클러스터 별 감성 분포 결과를 확인해보니, 각 Cluster 0,1,2마다 부정(-1), 중립(0), 긍정(1) 리뷰 내용이 모여있는 것을 확인할 수 있습니다. Cluster 부정(-1) 중립(0) 긍정(1) 0 7.7% 64.6% 27.7% 1 70.8% 28.3% 0.9% 2 0.0% 11.6% 88.4% Cluster 0는 중립, Cluster 1은 부정, Cluster 2는 긍정적인 리뷰가 다수로 차지하고 있습니다. 각 클러스터의 감정 비율을 통해, 화장품에 대한 리뷰가 부정, 중립, 긍정적으로 잘 나뉘는지를 알 수 있습니다. 클러스터 별 주요 키워드를 확인해보면, 긍정적인 리뷰가 많이 포함된 Cluster 2에서는 "좋아요", "촉촉하고"와 같은 단어가 많이 포함되었습니다. 반면, 부정적인 리뷰가 많이 포함된 Cluster 1에서는 "가격대비", "아쉽네요"와 같은 단어의 빈도가 많습니다. 이러한 결과를 확인해서 긍정적인 클러스터에 자주 언급되는 장점은 이를 강조한 마케팅과 같은 비즈니스 인사이트로 활용하거나 부정적인 클러스터에서 나타난 문제점은 개선점으로 인사이트를 얻을 수 있습니다. ④ 클러스터링 품질 평가하기 클러스터의 품질과 데이터 분포를 다양한 지표를 통해 평가하는 방법에 대해 설명하겠습니다. 먼저 데이터의 클러스터링이 잘 되었는지를 알 수 있는 양적 평가 지표에 대해 알아봅시다. Quote 지표 설명 Silhouette 점수 (-1~1) 각 데이터 포인트가 속한 클러스터와 다른 클러스터 간의 거리를 비교하는 지표, 값이 1에 가까울수록 클러스터링 간의 경계가 명확한 것을 의미합니다. Calinski-Harabasz 점수 클러스터 내 응집도와 클러스터 간 분산을 비교하는 지표, 값이 클수록 클러스터 간 거리가 크고, 클러스터 내 데이터가 밀집되어 있음을 의미합니다. Davies-Bouldin 점수 클러스터 간 거리와 클러스터 내부 분산의 비율을 평가하는 지표, 값이 낮을수록 좋은 클러스터링을 의미합니다. 정리하면 Silhouette 점수는 1에 가깝고, Calinski-Harabasz 점수는 높을수록 좋으며 Davies-Bouldin 점수는 낮을수록 좋은 클러스터를 의미합니다. Calinski-Harabasz 점수와 Davies-Bouldin 점수는 제한 범위가 없기 때문에 상대적 클러스터링 비교에 사용하기 적절합니다. # 지표 함수 정의 def evaluate_clustering(data): # 1. Silhouette silhouette_avg = silhouette_score(data[['t-SNE Dimension 1', 't-SNE Dimension 2']], data['Cluster']) print(f"Silhouette Score: {silhouette_avg}") # 2. Calinski-Harabasz ch_score = calinski_harabasz_score(data[['t-SNE Dimension 1', 't-SNE Dimension 2']], data['Cluster']) print(f"Calinski-Harabasz Score: {ch_score}") # 3. Davies-Bouldin db_score = davies_bouldin_score(data[['t-SNE Dimension 1', 't-SNE Dimension 2']], data['Cluster']) print(f"Davies-Bouldin Score: {db_score}") # 평가 실행 print("### Clustering Quality Evaluation ###") evaluate_clustering(data) ### Clustering Quality Evaluation ### Silhouette Score: 0.3865170180797577 Calinski-Harabasz Score: 262.519196880911 Davies-Bouldin Score: 0.9567987699215011 Silhouette 점수는 0.38로 클러스터링 품질이 양호한 수준입니다. 클러스터 내 데이터 포인트가 서로 밀접하게 모여있으면서 다른 클러스터와 적당히 분리된 상태를 의미하며, 점수가 0.5 이상일 경우 클러스터링 품질이 높다고 평가할 수 있습니다. Calinski-Harabasz 점수와 Davies-Bouldin 점수는 상대적 클러스터링 비교에 사용하기 적절하기 때문에 K값을 적절하게 바꿔가면서 비교하며 더 좋은 클러스터링을 찾는데 적절합니다. 3. 맺음말 1024차원의 임베딩 벡터를 2차원으로 시각화하면 리뷰 텍스트 간의 의미적 관계를 시각적으로 이해할 수 있습니다. 이를 통해 데이터 포인트들이 임베딩 벡터 공간에서 어떻게 분포하는지 파악할 수 있으며, 특정 라벨(긍정, 중립, 부정 등)로 분류된 데이터들이 서로 가깝게 위치하는 경향을 확인할 수 있습니다. 이 과정은 데이터의 라벨링 품질과 임베딩 모델의 성능을 확인하는 데 유용합니다. 예를 들어, 데이터 군집 간의 경계가 명확하지 않다면 임베딩 모델이 텍스트 간의 차이를 충분히 학습하지 못했거나, 라벨링된 데이터에 오류가 있을 가능성을 의미합니다. 이를 통해 오분류된 데이터 포인트를 탐지할 수 있으며, 잘못된 라벨링을 수정하거나 모델 성능을 개선하는 데 활용할 수 있습니다. 또한, K-Means 클러스터링과 XGBoost 모델을 활용하여 데이터를 정량적으로 분석했습니다. K-Means는 임베딩 벡터를 군집화하여 데이터 포인트 간의 유사성을 기준으로 각 클러스터의 특성을 파악하는 데 사용할 수 있습니다. 이 분석 방법은 감정 분석뿐만 아니라 다양한 도메인에서 분류 태스크를 정의하거나 데이터의 라벨링 품질을 확인하는 작업에도 활용될 수 있습니다. 예를 들어, 의료 데이터에서 질병 분류를 하거나 고객 리뷰 데이터를 기반으로 제품 추천을 할 때에도 데이터의 의미적 관계를 확인하고 모델 성능을 개선하는 데 기여할 수 있습니다. 따라서 도메인에 따라 임베딩 모델과 시각화 및 분류 방법을 적절히 조정하여 유용하게 활용할 수 있습니다. 지금까지 우리는 임베딩을 활용한 시각화와, 레이블이 없는 데이터를 가정하고 어떻게 분석하고 군집화할 수 있는지 K-means 클러스터링을 통해 알아봤습니다. 그러나, K-means 클러스터링말고도 더 정교한 분류가 필요할 수 있습니다. Quote 기존 레이블된 데이터를 학습하여 새로운 데이터를 더 정확하게 분류하고 싶을 때 클러스터링보다 더 세밀한 분류 경계가 필요할 때 분류 결과에 대한 확률값이나 신뢰도 점수가 필요할 때 이러한 요구사항을 충족하기 위해, 우리는 XGBoost와 같은 고급 머신러닝 알고리즘을 활용할 수 있습니다. 관련 내용은 "임베딩을 활용한 고급 분류 기법: XGBoost" 문서에서 자세히 다루도록 하겠습니다. 링크 복사 다른 사이트에 공유하기 More sharing options...
Recommended Posts
게시글 및 댓글을 작성하려면 로그인 해주세요.
로그인