자연어 처리 모델의 발전 과정
1970년: 단어가 얼마나 자주나오는지 기준으로 배열
1980 LSA 좌표평면에 배치해 비슷한 단어들을 같은 주제로 묶기 시작함.
2000 LDA 본격적인 토픽 모델링 기법이 등장해 비슷한 단어와 문서를 주제별로 연결함
2013 신경망 임베딩 Word2Vec, GloVe 등 단어를 벡터로 바꾼뒤 기준선을 정해 긍정/부정을 판별함.
2018 BERT, GPT 스스로 문맥을 이해하고 학습하는 모델이 등장함.
2020 - 추론능력이 강화되어 요약 및 복잡한 대화가 가능한 모델들이 발전함.
토픽 모델링
Word2Vec 등을 통해 비슷한 위치에 모인 단어와 문서를 같은 주제 Topic으로 묶는 기술.
단순한 긍정 부정 분류를 넘어 영화 내용등 주제별로 세밀하게 나누어 분석함.
https://standout.tistory.com/1836
토픽 모델링이란?: 비슷한 위치에 모인 단어와 문서를 같은 주제 Topic으로 묶는 기술.
토픽 모델링비슷한 위치에 모인 단어와 문서를 같은 주제 Topic으로 묶는 기술. 스포츠, 영화, 정치”라고 라벨을 달지 않아도, 알고리즘이 단어들의 분포와 동시 등장 패턴을 분석해서 문서를 몇
standout.tistory.com
워드임베딩 - 워드 벡터 Word Vector, Word2Vec
자연어를 컴퓨터가 이해할 수 있는 숫자 벡터로 변환하는 과정
고정된 차원의 벡터 공간에 단어를 표해 비슷한 의미를 가진 단어들은 벡터 공간상에서 가까운 위치에 자연스럽게 모이게 됨.
데이터 규모가 클수록 장점이 나타나며 대규모 데이터 분석에 강력함.
Word2Vec
단어를 백터로 변화시킨다. Word to Vector라는 의미. 단어를 숫자로 변환해 벡터 공간에 배치하는 밀집표현기술
환불, 취소를 완전히 다른 단어로 취급하는 기존 원핫인코딩과 달리 비슷한 맥락에서 사용된 단어들의 의미속성을 파악하여 유사도를 높게 묶을 수 있음.
https://standout.tistory.com/1834
문장을 숫자로 바꾸기 워드임베딩, 단어의 의미 벡터(embedding)를 데이터로부터 학습하는 신경망
빈도분석문장을 숫자로 바꾸는 가장 기초 방법은 빈도기반 방법이있다. 문장을 숫자로 바꾸는 가장 기초 방법은 빈도기반 방법이있다. Count, Frequency, Binary occurrence.https://standout.tistory.com/1833 빈도
standout.tistory.com
빈도분석
텍스트 데이터를 수치화하기 위해 단어가 등장하는 횟수를 세는 가장 기초적인 방법
감상문 등에서 긍정, 부정 단어가 몇 번 나왔는지 세어 점수를 매기는 방식의 단순 단어빈도방법으로 직설적인 부정표현이 드문 평가문일 경우 단순 빈도 분석만으로는 긍정적으로 해석될 수 있다.
https://standout.tistory.com/1833
빈도분석이란? Count, Frequency(count를 비율로 바꾼것), Binary occurrence(나왔는지, 안나왔는지만 보는
빈도분석문장을 숫자로 바꾸는 가장 기초 방법은 빈도기반 방법이있다. Count, Frequency(count를 비율로 바꾼것), Binary occurrence(나왔는지, 안나왔는지만 보는 방식).텍스트 데이터를 수치화하기 위해
standout.tistory.com
빈도분석 - TF-IDF, Term Frequency Inverse Document Frequency 단어빈도 역문서 빈도의 조합.
빈도가 높다는 것은 글을 대표한다라는 질문에서 시작됨. 빈도가 높다고 해서 무조건 중요한 것은 아니라는 한계를 극복하고자했다. IT문서내에서는 컴퓨터라는 단어가 빈도가 높지만 중요도가 낮고 , 초등학교 일기에서 '나는 오늘'이 가장 많이 나온다고 해서 일기의 핵심주제가 된다는 의미가 아니듯.
1958년 IBM의 한스피터 룬에 의해 재연된 아이디어이며 현재까지도 거의 모든 검색 엔진의 핵심 기술로 널리 사용되고있음.
https://standout.tistory.com/1832
빈도분석 - TF-IDF란? , Term Frequency Inverse Document Frequency 단어빈도 역문서 빈도의 조합.
빈도분석 - TF-IDF, Term Frequency Inverse Document Frequency 단어빈도 역문서 빈도의 조합. 빈도가 높다는 것은 글을 대표한다라는 질문에서 시작됨. 빈도가 높다고 해서 무조건 중요한 것은 아니라는 한계
standout.tistory.com
LDA 토픽 주제 모델링 분석
문서 - 주제 분포확인 - 주제 단어분포확인 - 주제선택 - 단어생성 순 진행
분석겨로가는 주제별로 어떤 단어들이 어떤 비율과 빈도로쓰였는지를 수치화된 키워드 묶음으로 보여준다.
주제들 간의 유사성을 2d 공간에 표현하여 가까울 수록 유사한 내용을 가룬다. intertopic Distance
https://standout.tistory.com/1835
비슷한것들끼리 묶어서 주제를 생성하는 토픽 군집화의 전통적인 방법: LDA Latent Dirichlet Allocation.
비슷한 맥락에서 등장하는 단어들은 비슷한 의미를 가진다는 분산가설 Distributional Hypothesis 에서 출발함“You shall know a word by the company it keeps”Word2Vec, BERT, GPT 전부의 철학. 단어를 여러 축 차원에
standout.tistory.com
단어유사도 측정 방법 : 코사인 유사도
각도가 0 에 가까워 동일한 방향을 가리키면 유사도가 높음 1
각도가 90도로 수직관계이면 서로 무관함. 0, 각도가 180도로 완전히 반대 방향이면 정반대의 의미임. -1
동의어, 반의어를 과학적으로 분류할 수 있음
"아이폰 - 스마트폰 + 태블릿 = 아이패드"와 같이 활용 할 수 있음.
https://standout.tistory.com/1831
단어유사도 측정 방법 : 코사인 유사도 Cosine Similarity 벡터 간 방향이 얼마나 비슷한가
단어유사도 측정 방법 : 코사인 유사도 Cosine Similarity 벡터 간 방향이 얼마나 비슷한가모든 벡터 기반 NLP에서 공통으로 쓰이는 표준 거리 함수Word Embedding 계열(Word2Vec, GloVe, FastText), TF-IDF 문서 비
standout.tistory.com
실습코드 분석 한국어_Word2Vec_사전학습_직접학습_통합실습 (1).ipynb
임베딩 모델 만들때 사용하는 라이브러리 gensim
java기반 형태소 분석기를 실행할때 필요한 연결 라이브러리 JPype1
한국어형태소 분석을 수행하기 위한 라이브러리 konlpy
Google Drive 공유차일을 colab에서 다운로드 할때 사용하는 라이브러리 gdown
# gensim은 Word2Vec, FastText 등 단어 임베딩 모델을 만들고 불러올 때 사용하는 라이브러리입니다.
!pip -q install gensim
# JPype1은 KoNLPy가 Java 기반 형태소 분석기를 실행할 때 필요한 연결 라이브러리입니다.
!pip -q install JPype1
# konlpy는 한국어 형태소 분석을 수행하기 위한 라이브러리입니다.
!pip -q install konlpy
# gdown은 Google Drive 공유 파일을 Colab에서 다운로드할 때 사용하는 라이브러리입니다.
!pip -q install gdown
import
정규표현식 re,
zipfile 압축 파일 해제
Word2Vec 문장 토큰 목록을 사용해 단어 벡터 모델을 직접 학습
KeyeVectors 단어 벡터만 저장된 파일을 불러오거나 저장할때
Okt 한국어 문장에서 명사, 동사, 형용사 등을 추룰하는 형태소 분석기
google.colab files Colab에서 사용자의 PC 파일을 직접 업로드할 때 사용.
# os는 폴더 생성, 파일 존재 여부 확인, 경로 결합 등 운영체제 관련 작업에 사용합니다.
import os
# re는 정규표현식을 사용하여 특수문자 제거 같은 텍스트 정제 작업을 할 때 사용합니다.
import re
# zipfile은 압축 파일을 해제할 때 사용합니다.
import zipfile
# pandas는 CSV 파일을 읽고 표 형태의 데이터프레임으로 처리할 때 사용합니다.
import pandas as pd
# numpy는 숫자 배열 계산에 사용합니다.
import numpy as np
# Word2Vec은 문장 토큰 목록을 사용하여 단어 벡터 모델을 직접 학습할 때 사용합니다.
from gensim.models import Word2Vec
# KeyedVectors는 단어 벡터만 저장된 파일을 불러오거나 저장할 때 사용합니다.
from gensim.models import KeyedVectors
# Okt는 한국어 문장에서 명사, 동사, 형용사 등을 추출할 수 있는 형태소 분석기입니다.
from konlpy.tag import Okt
# files는 Colab에서 사용자의 PC 파일을 직접 업로드할 때 사용합니다.
from google.colab import files
자업폴더 생성
# 데이터 파일을 저장할 폴더 이름을 지정합니다.
DATA_DIR = '/content/data'
# 모델 파일을 저장할 폴더 이름을 지정합니다.
MODEL_DIR = '/content/models'
# data 폴더가 없으면 새로 생성합니다.
os.makedirs(DATA_DIR, exist_ok=True)
# models 폴더가 없으면 새로 생성합니다.
os.makedirs(MODEL_DIR, exist_ok=True)
# 생성된 폴더 경로를 화면에 출력하여 확인합니다.
print('데이터 폴더:', DATA_DIR)
print('모델 폴더:', MODEL_DIR)
데이터준비
# news.csv 파일이 저장될 기본 경로를 지정합니다.
news_path = os.path.join(DATA_DIR, 'news.csv')
# news.csv 파일이 이미 있는지 확인합니다.
if False:
if os.path.exists(news_path):
# 파일이 있으면 그대로 사용합니다.
print('기존 news.csv 파일을 사용합니다:', news_path)
else:
# 파일이 없으면 사용자가 직접 업로드할지 선택할 수 있도록 안내합니다.
print('news.csv 파일이 없습니다. 파일 업로드 창에서 news.csv를 선택하세요.')
print('업로드하지 않아도 아래에서 실습용 예시 데이터가 자동 생성됩니다.')
try:
# 사용자의 PC에서 파일을 업로드합니다.
uploaded = files.upload()
# 업로드된 파일 목록을 하나씩 확인합니다.
for filename in uploaded.keys():
# 업로드된 파일명이 news.csv이면 data 폴더로 이동합니다.
if filename == 'news.csv':
# Colab 현재 경로에 업로드된 파일을 data 폴더 경로로 복사합니다.
os.replace(filename, news_path)
print('업로드한 news.csv 파일을 저장했습니다:', news_path)
except Exception as e:
# 업로드 과정에서 문제가 생겨도 실습용 예시 데이터를 만들 수 있도록 오류를 출력만 합니다.
print('파일 업로드를 건너뜁니다:', e)
# 업로드 후에도 news.csv가 없으면 실습용 예시 데이터를 생성합니다.
# if not os.path.exists(news_path):
if True:
# 토픽별 예시 뉴스 문장을 리스트로 작성합니다.
sample_rows = [
{'category': 1, 'news': '인공지능 기술이 산업 현장에 적용되면서 데이터 분석과 자동화 시스템의 활용이 확대되고 있다.'},
{'category': 1, 'news': '머신러닝 모델은 대량의 데이터를 학습하여 예측 정확도를 높이고 다양한 업무를 지원한다.'},
{'category': 1, 'news': '생성형 인공지능은 문서 작성 번역 요약 코딩 지원 등 여러 분야에서 활용되고 있다.'},
{'category': 2, 'news': '프로야구 경기에서 투수의 호투와 타선의 집중력이 승부를 결정했다.'},
{'category': 2, 'news': '축구 대표팀은 빠른 패스와 압박 전술을 앞세워 경기 주도권을 잡았다.'},
{'category': 2, 'news': '올림픽 선수들은 체력 훈련과 전략 분석을 통해 경기력을 끌어올리고 있다.'},
{'category': 3, 'news': '주식 시장은 금리 인상 우려와 기업 실적 발표의 영향을 받아 변동성이 커졌다.'},
{'category': 3, 'news': '환율 상승은 수입 물가와 소비자 가격에 영향을 미칠 수 있다.'},
{'category': 3, 'news': '정부는 경기 회복을 위해 투자 확대와 일자리 지원 정책을 추진하고 있다.'},
{'category': 4, 'news': '병원은 환자 진료 데이터를 분석하여 맞춤형 치료와 예방 관리를 강화하고 있다.'},
{'category': 4, 'news': '신약 개발 과정에서 인공지능을 활용한 후보 물질 탐색이 주목받고 있다.'},
{'category': 4, 'news': '건강 관리를 위해 규칙적인 운동과 균형 잡힌 식습관이 중요하다.'},
]
# 예시 데이터를 데이터프레임으로 변환합니다.
sample_df = pd.DataFrame(sample_rows)
# 예시 데이터를 news.csv 파일로 저장합니다.
sample_df.to_csv(news_path, index=False, encoding='utf-8-sig')
# 예시 데이터 생성 완료 메시지를 출력합니다.
print('실습용 예시 news.csv 파일을 생성했습니다:', news_path)
# 최종적으로 사용할 news.csv 경로를 출력합니다.
print('최종 news.csv 경로:', news_path)
csv 읽기
news라는 컬럼이있으면 본문 커럼으로 사용. 없으면 첫번째 컬럼을 본문 컬러므오 사용해 출력.
# news.csv 파일을 pandas 데이터프레임으로 읽습니다.
df_news = pd.read_csv(news_path)
# 데이터프레임의 상위 5개 행을 출력하여 데이터가 정상적으로 읽혔는지 확인합니다.
display(df_news.head())
# 데이터프레임의 컬럼 목록을 출력합니다.
print('컬럼 목록:', df_news.columns.tolist())
# news라는 컬럼이 있으면 해당 컬럼을 본문 컬럼으로 사용합니다.
if 'news' in df_news.columns:
text_col = 'news'
# news 컬럼이 없으면 문자열 데이터가 들어 있는 첫 번째 컬럼을 본문 컬럼으로 사용합니다.
else:
text_col = df_news.select_dtypes(include='object').columns[0]
# 실제로 사용할 본문 컬럼명을 출력합니다.
print('본문으로 사용할 컬럼:', text_col)
category news
0 1 인공지능 기술이 산업 현장에 적용되면서 데이터 분석과 자동화 시스템의 활용이 확대되...
1 1 머신러닝 모델은 대량의 데이터를 학습하여 예측 정확도를 높이고 다양한 업무를 지원한다.
2 1 생성형 인공지능은 문서 작성 번역 요약 코딩 지원 등 여러 분야에서 활용되고 있다.
3 2 프로야구 경기에서 투수의 호투와 타선의 집중력이 승부를 결정했다.
4 2 축구 대표팀은 빠른 패스와 압박 전술을 앞세워 경기 주도권을 잡았다.
clean_text() 한국어 텍스트 정제함수 만들기
pd.isna() 값이 비어있거나 결측치면 빈 문자열로 바꾼다.
입력값을 문자열 자료형으로 변환, re.sub() 정규화로 한글, 영어, 숫자, 공백을 제외 문자 공백으로 바꿈.
re.sub() 여러개의 공백을 하나의 공ㄱ백으로 줄임
text.strip() 앞 뒤 문장의불필요한 공백을 제거.
# 텍스트를 정제하는 함수를 정의합니다.
def clean_text(text):
# 입력값이 비어 있거나 결측치이면 빈 문자열로 바꿉니다.
if pd.isna(text):
return ''
# 입력값을 문자열 자료형으로 변환합니다.
text = str(text)
# 한글, 영어, 숫자, 공백을 제외한 문자는 공백으로 바꿉니다.
text = re.sub(r'[^가-힣a-zA-Z0-9\s]', ' ', text)
# 여러 개의 공백을 하나의 공백으로 줄입니다.
text = re.sub(r'\s+', ' ', text)
# 문장 앞뒤의 불필요한 공백을 제거합니다.
text = text.strip()
# 정제된 텍스트를 반환합니다.
return text
# 본문 컬럼에 정제 함수를 적용하여 cleaned 컬럼을 새로 만듭니다.
df_news['cleaned'] = df_news[text_col].apply(clean_text)
# 정제된 결과를 확인합니다.
display(df_news[[text_col, 'cleaned']].head())
news cleaned
0 인공지능 기술이 산업 현장에 적용되면서 데이터 분석과 자동화 시스템의 활용이 확대되... 인공지능 기술이 산업 현장에 적용되면서 데이터 분석과 자동화 시스템의 활용이 확대되...
1 머신러닝 모델은 대량의 데이터를 학습하여 예측 정확도를 높이고 다양한 업무를 지원한다. 머신러닝 모델은 대량의 데이터를 학습하여 예측 정확도를 높이고 다양한 업무를 지원한다
2 생성형 인공지능은 문서 작성 번역 요약 코딩 지원 등 여러 분야에서 활용되고 있다. 생성형 인공지능은 문서 작성 번역 요약 코딩 지원 등 여러 분야에서 활용되고 있다
3 프로야구 경기에서 투수의 호투와 타선의 집중력이 승부를 결정했다. 프로야구 경기에서 투수의 호투와 타선의 집중력이 승부를 결정했다
4 축구 대표팀은 빠른 패스와 압박 전술을 앞세워 경기 주도권을 잡았다. 축구 대표팀은 빠른 패스와 압박 전술을 앞세워 경기 주도권을 잡았다
Okt() 형태소 분석기 객체 생성
stopwords 세팅
extract_nouns() 명사만 추출해 한 글자 단어와 불용어를 제거.
확인
# Okt 형태소 분석기 객체를 생성합니다.
okt = Okt()
# 불필요한 일반 단어를 제거하기 위한 불용어 집합을 정의합니다.
stopwords = {'것', '수', '등', '및', '더', '이', '그', '저', '위해', '통해', '대한'}
# 문장에서 명사를 추출하는 함수를 정의합니다.
def extract_nouns(text):
# Okt 형태소 분석기로 문장에서 명사만 추출합니다.
nouns = okt.nouns(text)
# 한 글자 단어와 불용어를 제거합니다.
nouns = [word for word in nouns if len(word) > 1 and word not in stopwords]
# 정제된 명사 리스트를 반환합니다.
return nouns
# 각 뉴스 문장에 명사 추출 함수를 적용하여 tokens 컬럼을 만듭니다.
df_news['tokens'] = df_news['cleaned'].apply(extract_nouns)
# 토큰 추출 결과를 확인합니다.
display(df_news[['cleaned', 'tokens']].head())
cleaned tokens
0 인공지능 기술이 산업 현장에 적용되면서 데이터 분석과 자동화 시스템의 활용이 확대되... [인공, 지능, 기술, 산업, 현장, 적용, 데이터, 분석, 자동화, 시스템, 활용...
1 머신러닝 모델은 대량의 데이터를 학습하여 예측 정확도를 높이고 다양한 업무를 지원한다 [머신, 러닝, 모델, 대량, 데이터, 학습, 예측, 정확도, 높이, 업무, 지원]
2 생성형 인공지능은 문서 작성 번역 요약 코딩 지원 등 여러 분야에서 활용되고 있다 [성형, 인공, 지능, 문서, 작성, 번역, 요약, 코딩, 지원, 여러, 분야, 활용]
3 프로야구 경기에서 투수의 호투와 타선의 집중력이 승부를 결정했다 [프로야구, 경기, 투수, 호투, 선의, 집중, 승부, 결정]
4 축구 대표팀은 빠른 패스와 압박 전술을 앞세워 경기 주도권을 잡았다 [축구, 대표팀, 패스, 압박, 전술, 경기, 주도]
sentences 토큰이 2개 이상 있는 문장만 Word2Vec 학습에 사용한다.
# 토큰이 2개 이상 있는 문장만 Word2Vec 학습에 사용합니다.
sentences = [tokens for tokens in df_news['tokens'].tolist() if len(tokens) >= 2]
# 학습 문장 수를 출력합니다.
print('학습에 사용할 문장 수:', len(sentences))
# 첫 번째 학습 문장을 출력하여 데이터 형태를 확인합니다.
print('첫 번째 문장 토큰:', sentences[0] if sentences else '학습 가능한 문장이 없습니다.')
학습에 사용할 문장 수: 12
첫 번째 문장 토큰: ['인공', '지능', '기술', '산업', '현장', '적용', '데이터', '분석', '자동화', '시스템', '활용', '확대']
Word2Vec() 객체 생성.
- vector size 단어를 100차원의 벡터로 표현한다.
- window 중심 단어 주변 5개 단어까지 본다 .
- min_count 최소등장 횟수 작은 실습 데이터로 학습하기 위해 1로 설정한다 .
- workers 병렬 처리에 사용할 cpu 작업수
- sg skip-gram Word2Vec 에서 학습방식 두개중 선택, CBOW(주변단어를 보고 중심단어를 예측하기) sg = 0, Skip-gram (중심단어 하나를 보고 주변 단어를 예측하기 ) sg = 1
.save() 학습된 모델 파일로 저장.
# Word2Vec 모델을 학습합니다.
# vector_size는 단어를 몇 차원의 벡터로 표현할지 결정합니다.
# window는 중심 단어 주변 몇 개 단어까지 문맥으로 볼지 결정합니다.
# min_count는 최소 등장 횟수이며, 여기서는 작은 실습 데이터도 학습하기 위해 1로 설정합니다.
# workers는 병렬 처리에 사용할 CPU 작업 수입니다.
# sg=1은 Skip-gram 방식, sg=0은 CBOW 방식을 의미합니다.
trained_model = Word2Vec(
sentences=sentences,
vector_size=100,
window=5,
min_count=1,
workers=2,
sg=1,
epochs=100,
seed=42
)
# 직접 학습한 모델을 저장할 경로를 지정합니다.
trained_model_path = os.path.join(MODEL_DIR, 'news_word2vec.model')
# 학습된 Word2Vec 모델을 파일로 저장합니다.
trained_model.save(trained_model_path)
# 저장 완료 메시지를 출력합니다.
print('직접 학습한 Word2Vec 모델 저장 완료:', trained_model_path)
# 학습된 단어 수를 출력합니다.
print('학습된 단어 수:', len(trained_model.wv.index_to_key))
학습된 모델 확인.
wv.index_to_key[] 기준단어 선택해 topn5 5개를 출력.
이 학습단어가 2개 이상일 경우 코사인 유사도를 계산.wv.similarlity(a, b)
# 학습된 단어 목록 중 앞쪽 일부를 출력합니다.
print('학습된 단어 예시:', trained_model.wv.index_to_key[:20])
# 유사 단어를 확인할 기준 단어를 선택합니다.
target_word = trained_model.wv.index_to_key[0]
# 기준 단어와 가장 가까운 단어 5개를 출력합니다.
print(f'[{target_word}]와 유사한 단어:')
print(trained_model.wv.most_similar(target_word, topn=5))
# 학습 단어가 2개 이상이면 두 단어의 코사인 유사도를 계산합니다.
if len(trained_model.wv.index_to_key) >= 2:
# 첫 번째 단어를 선택합니다.
word1 = trained_model.wv.index_to_key[0]
# 두 번째 단어를 선택합니다.
word2 = trained_model.wv.index_to_key[1]
# 두 단어의 코사인 유사도를 계산합니다.
similarity = trained_model.wv.similarity(word1, word2)
# 유사도 결과를 출력합니다.
print(f'{word1} - {word2} 유사도:', similarity)
학습된 단어 예시: ['경기', '지원', '활용', '분석', '데이터', '지능', '인공', '관리', '영향', '확대', '습관', '균형', '운동', '규칙', '건강', '주목', '탐색', '물질', '후보', '과정']
[경기]와 유사한 단어:
[('예측', 0.7956401705741882), ('영향', 0.7854136824607849), ('지원', 0.7763903737068176), ('활용', 0.7644039392471313), ('실적', 0.7617887258529663)]
경기 - 지원 유사도: 0.77639043
google drive에 저장된 ko.bin 파일불러오기
# Google Drive 마운트를 사용할지 여부를 설정합니다.
USE_GOOGLE_DRIVE = False
# Google Drive 안의 ko.bin 파일 경로를 지정합니다.
ko_bin_drive_path = '/content/drive/MyDrive/data/ko.bin'
# Google Drive 사용 옵션이 True인 경우에만 Drive를 마운트합니다.
if USE_GOOGLE_DRIVE:
# Colab에서 Google Drive를 연결하기 위한 모듈을 불러옵니다.
from google.colab import drive
# Google Drive를 /content/drive 경로에 연결합니다.
drive.mount('/content/drive', force_remount=True)
# 지정한 경로에 ko.bin 파일이 있는지 확인합니다.
print('ko.bin 존재 여부:', os.path.exists(ko_bin_drive_path))
else:
# Drive를 사용하지 않는 경우 안내 메시지를 출력합니다.
print('현재는 Google Drive 사용을 끈 상태입니다. 사용하려면 USE_GOOGLE_DRIVE = True로 변경하세요.')
기존파일경로사용하기
# 로컬 업로드 방식으로 저장할 ko.bin 경로를 지정합니다.
ko_bin_local_path = os.path.join(MODEL_DIR, 'ko.bin')
# ko.bin 파일이 이미 models 폴더에 있는지 확인합니다.
if os.path.exists(ko_bin_local_path):
# 이미 파일이 있으면 다시 업로드하지 않습니다.
print('기존 ko.bin 파일을 사용합니다:', ko_bin_local_path)
else:
# 파일이 없으면 업로드 방식을 안내합니다.
print('ko.bin 파일이 없습니다. 필요하면 아래 files.upload() 주석을 해제하여 업로드하세요.')
# 아래 3줄은 실제 업로드가 필요할 때 주석을 해제해서 사용합니다.
# uploaded = files.upload()
# if 'ko.bin' in uploaded:
# os.replace('ko.bin', ko_bin_local_path)
# 최종 로컬 ko.bin 경로를 출력합니다.
print('로컬 ko.bin 경로:', ko_bin_local_path)
혹은 공개한국어 Word2Vec 모델 ko.zip를 자동 다운로드할 수 있다.
googleDrive 공유차일을 다운로드 gdown
zip 경로 지정, bin 경로지정
파일 id지정, url구성, 파일이 없을경우 다운로드 gdown.download() quiet 출력거의없이 다운로드 False일경우 진행상황을 화면에 출력한다. fuzzy 링크가 완전히 다운로드 링크가 아닐때도 자동으로실제 다운로드 링크로 변환해 다운받아라. False일경우 정확한 url만 가능.
os.path.exists() 파일존재 확인
exteractall() 압출풀기
# gdown은 Google Drive 공유 파일을 다운로드할 때 사용합니다.
import gdown
# 공개 한국어 Word2Vec 모델 파일이 저장될 zip 경로를 지정합니다.
ko_zip_path = os.path.join(MODEL_DIR, 'ko.zip')
# 압축 해제 후 ko.bin이 저장될 경로를 지정합니다.
ko_bin_download_path = os.path.join(MODEL_DIR, 'ko.bin')
# 공개 Google Drive 파일 ID를 지정합니다.
# 이 파일은 공개 한국어 Word2Vec 모델로 알려진 ko.zip 파일입니다.
ko_file_id = '0B0ZXk88koS2KbDhXdWg1Q2RydlU'
# gdown에서 사용할 다운로드 URL을 구성합니다.
ko_download_url = f'https://drive.google.com/uc?id={ko_file_id}'
# ko.bin 파일이 이미 있으면 다운로드하지 않습니다.
if os.path.exists(ko_bin_download_path):
print('이미 ko.bin 파일이 존재합니다:', ko_bin_download_path)
else:
try:
# Google Drive에서 ko.zip 파일을 다운로드합니다.
gdown.download(ko_download_url, ko_zip_path, quiet=False, fuzzy=True)
# 다운로드된 zip 파일이 실제로 존재하는지 확인합니다.
if os.path.exists(ko_zip_path):
# zip 파일을 열어 압축을 해제합니다.
with zipfile.ZipFile(ko_zip_path, 'r') as zip_ref:
# models 폴더에 압축을 풉니다.
zip_ref.extractall(MODEL_DIR)
# 압축 해제 후 파일 목록을 출력합니다.
print('압축 해제 후 models 폴더:', os.listdir(MODEL_DIR))
else:
# 다운로드가 실패한 경우 안내 메시지를 출력합니다.
print('ko.zip 다운로드에 실패했습니다. 수동 다운로드 후 업로드 방식을 사용하세요.')
except Exception as e:
# 다운로드 또는 압축 해제 중 오류가 발생하면 안내 메시지를 출력합니다.
print('자동 다운로드 중 오류가 발생했습니다:', e)
print('이 경우 12번 셀의 로컬 업로드 방식 또는 11번 셀의 Google Drive 방식을 사용하세요.')
# 최종 ko.bin 존재 여부를 출력합니다.
print('다운로드 방식 ko.bin 존재 여부:', os.path.exists(ko_bin_download_path))
모델객체 변수 초기화
ko.bin 후보 경로를 리스트로 구성해 실제로 존재하는 경로만 필터링해 하나이상 있을경우 로딩시도하고 첫번째로 발견된 ko.bin 파일을 사용한다
Word2Vec.load() 저장된 파일을 모델형식으로 불러온다.
Word2Vec.load() 반식이 실패할경우 KeyedVectors.load_wordvec_format() binary=true 바이너리 벡터형식으로 저장된 파일을 불러와 객체에 저장.
binary=true가 실패했을 경우 KeyedVectors.load_word2vec_fotmat() binary=False False로 다시 시도해 저장.
# 사전학습 모델 객체를 저장할 변수를 초기화합니다.
pretrained_model = None
# ko.bin 후보 경로를 리스트로 구성합니다.
candidate_paths = [
ko_bin_local_path,
ko_bin_download_path,
ko_bin_drive_path,
]
# 실제 존재하는 ko.bin 경로만 필터링합니다.
existing_paths = [path for path in candidate_paths if os.path.exists(path)]
# 찾은 경로를 출력합니다.
print('발견된 ko.bin 경로:', existing_paths)
# ko.bin 파일이 하나 이상 있을 때만 로딩을 시도합니다.
if existing_paths:
# 첫 번째로 발견된 ko.bin 파일을 사용합니다.
selected_path = existing_paths[0]
# 사용할 파일 경로를 출력합니다.
print('사용할 ko.bin 경로:', selected_path)
try:
# gensim Word2Vec 모델 형식으로 저장된 파일을 불러옵니다.
pretrained_model = Word2Vec.load(selected_path)
# Word2Vec 모델 형식으로 로딩 성공 메시지를 출력합니다.
print('Word2Vec.load 방식으로 로딩 성공')
except Exception as e1:
# Word2Vec.load 방식이 실패하면 오류를 출력합니다.
print('Word2Vec.load 실패:', e1)
try:
# word2vec 원본 binary 벡터 형식으로 저장된 파일을 불러옵니다.
kv = KeyedVectors.load_word2vec_format(selected_path, binary=True)
# KeyedVectors 객체를 pretrained_model에 저장합니다.
pretrained_model = kv
# KeyedVectors 방식 로딩 성공 메시지를 출력합니다.
print('KeyedVectors.load_word2vec_format(binary=True) 방식으로 로딩 성공')
except Exception as e2:
# binary=True 방식이 실패하면 오류를 출력합니다.
print('binary=True 로딩 실패:', e2)
try:
# 텍스트 벡터 형식으로 저장된 파일일 가능성을 고려하여 binary=False로 다시 시도합니다.
kv = KeyedVectors.load_word2vec_format(selected_path, binary=False)
# KeyedVectors 객체를 pretrained_model에 저장합니다.
pretrained_model = kv
# 텍스트 형식 로딩 성공 메시지를 출력합니다.
print('KeyedVectors.load_word2vec_format(binary=False) 방식으로 로딩 성공')
except Exception as e3:
# 모든 방식이 실패하면 오류를 출력합니다.
print('모든 로딩 방식 실패:', e3)
else:
# ko.bin 파일을 찾지 못한 경우 안내 메시지를 출력합니다.
print('ko.bin 파일을 찾지 못했습니다. 직접 학습 모델을 사용하거나 ko.bin을 업로드하세요.')
모델이 none이면 none을 반환하고 wv 단어벡터가 들어있다면 model.wv반환하는 함수를 생성
사전학습 모델의 벡터 저장소를 추출한다.
# 다양한 모델 객체에서 단어 벡터 저장소를 꺼내는 함수를 정의합니다.
def get_vectors(model):
# 모델이 None이면 None을 반환합니다.
if model is None:
return None
# Word2Vec 모델은 wv 속성 안에 단어 벡터가 들어 있습니다.
if hasattr(model, 'wv'):
return model.wv
# KeyedVectors 객체는 그 자체가 단어 벡터 저장소입니다.
return model
# 사전학습 모델의 벡터 저장소를 추출합니다.
pretrained_vectors = get_vectors(pretrained_model)
# 벡터 저장소가 있으면 단어 수를 출력합니다.
if pretrained_vectors is not None:
print('사전학습 모델 단어 수:', len(pretrained_vectors.index_to_key))
print('사전학습 모델 단어 예시:', pretrained_vectors.index_to_key[:20])
else:
print('사전학습 모델이 준비되지 않았습니다.')
검색기준 단어 지정
기존 단어가 모델 어휘에 있는지 확인. 유사한 단어 10개 검색
출력
# 검색할 기준 단어를 지정합니다.
query_word = '대회'
# 사전학습 벡터가 준비되었고 기준 단어가 모델 어휘에 있는지 확인합니다.
if pretrained_vectors is not None and query_word in pretrained_vectors:
# 기준 단어와 유사한 단어 10개를 검색합니다.
similar_words = pretrained_vectors.most_similar(query_word, topn=10)
# 검색 결과를 출력합니다.
print(f'[{query_word}]와 유사한 단어:')
for word, score in similar_words:
print(word, score)
else:
# 모델이 없거나 단어가 없을 때 안내 메시지를 출력합니다.
print(f'사전학습 모델이 없거나 [{query_word}] 단어가 모델 어휘에 없습니다.')
print('이 경우 9번 셀의 직접 학습 모델로 실습을 진행하세요.')
유사도 계산
# 유사도를 비교할 첫 번째 단어를 지정합니다.
word_a = '대회'
# 유사도를 비교할 두 번째 단어를 지정합니다.
word_b = '올림픽'
# 사전학습 벡터가 준비되었고 두 단어가 모두 어휘에 있는지 확인합니다.
if pretrained_vectors is not None and word_a in pretrained_vectors and word_b in pretrained_vectors:
# 두 단어의 코사인 유사도를 계산합니다.
score = pretrained_vectors.similarity(word_a, word_b)
# 유사도 결과를 출력합니다.
print(f'{word_a} - {word_b} 유사도:', score)
else:
# 모델이 없거나 단어가 없을 때 안내 메시지를 출력합니다.
print('사전학습 모델이 없거나 비교 단어가 모델 어휘에 없습니다.')
직접학습한 모델과 사전학습의 차이를 비교
# 비교할 단어를 지정합니다.
compare_word = '인공지능'
# 직접 학습 모델에 비교 단어가 있는지 확인합니다.
if compare_word in trained_model.wv:
# 직접 학습 모델의 유사 단어를 출력합니다.
print('[직접 학습 모델] 유사 단어')
print(trained_model.wv.most_similar(compare_word, topn=5))
else:
# 직접 학습 모델에 단어가 없을 때 안내합니다.
print('[직접 학습 모델] 해당 단어가 없습니다:', compare_word)
# 사전학습 모델이 준비되었고 비교 단어가 있는지 확인합니다.
if pretrained_vectors is not None and compare_word in pretrained_vectors:
# 사전학습 모델의 유사 단어를 출력합니다.
print('\n[사전학습 모델] 유사 단어')
print(pretrained_vectors.most_similar(compare_word, topn=5))
else:
# 사전학습 모델에 단어가 없거나 모델이 없을 때 안내합니다.
print('\n[사전학습 모델] 모델이 없거나 해당 단어가 없습니다:', compare_word)
직접학습 모델 벡터파일로저장
# 단어 벡터만 저장할 파일 경로를 지정합니다.
vector_path = os.path.join(MODEL_DIR, 'news_word2vec_vectors.txt')
# 직접 학습한 모델의 단어 벡터를 텍스트 형식으로 저장합니다.
trained_model.wv.save_word2vec_format(vector_path, binary=False)
# 저장 결과를 출력합니다.
print('단어 벡터 파일 저장 완료:', vector_path)
https://standout.tistory.com/1837
Model load error. Was model saved using code from an older Gensim Version? Python과 gensim의 버전문제 key_to_index 버전
실행하는데 어러가났다. Model load error. Was model saved using code from an older Gensim Version?발견된 ko.bin 경로: ['/content/models/ko.bin', '/content/models/ko.bin']사용할 ko.bin 경로: /content/models/ko.binERROR:gensim.models.word2
standout.tistory.com
다른 실습예제를 확인해보자 토픽_모델링_실습하기.ipynb
데이터 가져오기
# # Google Colab에서 로컬 PC의 파일을 업로드할 수 있게 해 주는 files 모듈을 불러옵니다.
# from google.colab import files
# # 운영체제의 폴더 생성, 경로 이동, 파일 존재 여부 확인 등에 사용하는 os 모듈을 불러옵니다.
# import os
# # 업로드한 데이터 파일을 저장할 폴더 이름을 문자열로 지정합니다.
# data_dir = 'data'
# # 현재 작업 위치에 data 폴더가 존재하지 않는지 확인합니다.
# if not os.path.exists(data_dir):
# # data 폴더가 없다면 새로 생성합니다.
# os.mkdir(data_dir)
# # 파일을 data 폴더 안에 저장하기 위해 현재 작업 위치를 data 폴더로 변경합니다.
# os.chdir(data_dir)
# # Colab 파일 업로드 창을 실행하여 사용자가 news.csv 파일을 업로드할 수 있게 합니다.
# files.upload()
# # 이후 코드에서 ./data/news.csv 경로로 파일을 읽을 수 있도록 작업 위치를 다시 상위 폴더로 변경합니다.
# os.chdir('..')
from google.colab import drive
drive.mount('/content/drive')
import pandas as pd
news_path = "/content/drive/MyDrive/data/news.csv"
df_news = pd.read_csv(news_path)
print(df_news.head())
Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).
num category category_name \
0 1001 0 정치
1 1002 0 정치
2 1003 0 정치
3 1004 0 정치
4 1005 0 정치
news
0 국회는 새로운 법안 심사를 진행하며 정부 정책 방향을 논의했다. 이번 보도에서는 정...
1 정부는 예산 편성과 개혁 과제를 중심으로 부처 회의를 열었다. 이번 보도에서는 정책...
2 대통령은 외교 일정에서 경제 협력과 안보 현안을 강조했다. 이번 보도에서는 개혁, ...
3 선거를 앞두고 각 정당은 공약 발표와 지역 방문을 확대했다. 이번 보도에서는 국회,...
4 국회는 새로운 법안 심사를 진행하며 정부 정책 방향을 논의했다. 이번 보도에서는 개...
뉴스 csv 파일 불러와 카테고리확인하기
# CSV 파일을 표 형태의 DataFrame으로 다루기 위해 pandas 라이브러리를 불러옵니다.
import pandas as pd
# ./data/news.csv 파일을 읽어서 df_news라는 DataFrame 변수에 저장합니다.
# 이 파일에는 뉴스 본문, 카테고리, 번호 등의 컬럼이 들어 있다고 가정합니다.
# df_news = pd.read_csv('./data/news.csv')
df_news = df_news
# 데이터가 정상적으로 불러와졌는지 확인하기 위해 전체 행과 열의 개수를 출력합니다.
print('데이터 크기:', df_news.shape)
# 데이터의 컬럼 이름을 확인하여 이후 코드에서 사용할 컬럼명을 점검합니다.
print('컬럼 목록:', df_news.columns.tolist())
데이터 크기: (160, 4)
컬럼 목록: ['num', 'category', 'category_name', 'news']
# category 컬럼 값이 7인 행만 필터링합니다.
# == 연산자는 category 값이 7인지 비교하여 True/False 결과를 만듭니다.
category_7_news = df_news[df_news.category == 7]
# 필터링된 데이터 중 앞쪽 5개 행을 출력하여 데이터 내용을 빠르게 확인합니다.
category_7_news.head()
num category category_name news
140 7001 7 IT 인공지능 기반 자연어 처리 기술이 뉴스 서비스와 검색 플랫폼에 빠르게 적용되고 있다...
141 1142 7 IT 클라우드 플랫폼 기업들은 보안 기능과 소프트웨어 개발 도구를 강화하고 있다. 이번 ...
142 1143 7 IT 반도체 업계는 인공지능 연산에 최적화된 칩과 데이터 처리 기술을 개발하고 있다. 이...
143 1144 7 IT 로봇 서비스는 알고리즘 고도화와 센서 데이터 학습을 통해 활용 범위를 넓히고 있다....
144 1145 7 IT 인공지능 서비스가 다양한 산업에 적용되면서 데이터 분석과 모델 성능 개선이 중요해졌...
한국어 형태소 분석 라이브러리 설치
KoNLPy가 Java 기반 형태소 분석기를 사용할 있도록 하는 JPype1
한국어 형태소 분석을 수행하기 위한 KoNLPy
# KoNLPy가 Java 기반 형태소 분석기를 사용할 수 있도록 JPype1 패키지를 설치합니다.
!pip install JPype1
# 한국어 형태소 분석을 수행하기 위한 KoNLPy 패키지를 설치합니다.
!pip install konlpy
catetory가 7이고 num이 7001인 뉴스의 news 컬럼 값 선택
values[0]는 조건에 맞는 결과 중 첫번째 뉴스 본문 문자열을 가져옴
# category가 7이고 num이 7001인 뉴스의 news 컬럼 값을 선택합니다.
# values[0]은 조건에 맞는 결과 중 첫 번째 뉴스 본문 문자열을 가져옵니다.
text = df_news[(df_news.category == 7) & (df_news.num == 7001)]['news'].values[0]
# 선택한 뉴스 본문이 어떤 내용인지 확인하기 위해 출력합니다.
print(text)
형태소 분석과 정규표현식 모듈 불러오기
konlpy, re
# 한국어 형태소 분석기를 사용하기 위해 konlpy 라이브러리를 불러옵니다.
import konlpy
# 정규표현식을 이용해 특수문자 제거, 패턴 검색 등을 할 수 있도록 re 모듈을 불러옵니다.
import re
konly.tag.Okt() 형태소 분석기로 품사 확인하기
okt.pos()
# KoNLPy에서 제공하는 Okt 형태소 분석기 객체를 생성합니다.
okt = konlpy.tag.Okt()
# 선택한 뉴스 본문 text를 형태소 단위로 분리하고 각 형태소의 품사를 함께 반환합니다.
# stem=True는 '했다', '합니다' 같은 표현을 '하다'처럼 기본형으로 정규화합니다.
morphs = okt.pos(text, stem=True)
# 형태소 분석 결과를 출력하여 단어와 품사가 어떻게 분리되었는지 확인합니다.
print(morphs)
get_words() 하나의 텍스트를 입력받아 토픽 모델링에 사용할 단어 문자열로 변환하는 함수 정의
입력한 텍스트를 okt.pos() 형태소 분석기로 분석.
for문으로 돌려 명사 noun, 형용사 Adjective, 동사 Verb는 주제를 파악하는데 중요한 품사임으로 선택.
한글자는 의미가 약하거나 노이즈일 수 있으니 두 글자 이상만 사용.
조건을 만족한 단어를 word_list에 추가하고 공백으로 연결해 .join() 정제된 단어 문자열을 반환함.
즉 주요 단어만 추출하는 것
# 하나의 텍스트를 입력받아 토픽 모델링에 사용할 단어 문자열로 변환하는 함수를 정의합니다.
def get_words(text):
# 입력된 텍스트를 Okt 형태소 분석기로 분석하여 (단어, 품사) 형태의 목록을 만듭니다.
morphs = okt.pos(text, stem=True)
# 토픽 모델링에 사용할 단어를 저장할 빈 리스트를 생성합니다.
word_list = []
# 형태소 분석 결과에서 단어와 품사를 하나씩 꺼내 반복합니다.
for word, pos in morphs:
# 명사, 형용사, 동사는 문서 주제를 파악하는 데 중요한 품사이므로 선택합니다.
if pos == 'Noun' or pos == 'Adjective' or pos == 'Verb':
# 한 글자 단어는 의미가 약하거나 노이즈일 가능성이 있으므로 두 글자 이상만 사용합니다.
if len(word) > 1:
# 조건을 만족한 단어를 word_list에 추가합니다.
word_list.append(word)
# 추출된 단어 리스트를 공백으로 연결하여 CountVectorizer가 처리할 수 있는 문자열로 만듭니다.
words = ' '.join(word_list)
# 최종적으로 정제된 단어 문자열을 반환합니다.
return words
news 본문에 추출함수 적용하기 및 확인
# df_news의 news 컬럼에 들어 있는 각 뉴스 본문마다 get_words 함수를 적용합니다.
# apply는 각 행의 텍스트를 하나씩 함수에 넣고 결과를 반환합니다.
df_news['words'] = df_news.news.apply(get_words)
# words 컬럼이 제대로 생성되었는지 앞쪽 5개 행으로 확인합니다.
df_news[['news', 'words']].head()
news words
0 국회는 새로운 법안 심사를 진행하며 정부 정책 방향을 논의했다. 이번 보도에서는 정... 국회 새롭다 법안 심사 진행 하다 정부 정책 방향 논의 하다 이번 보도 정부 국회 ...
1 정부는 예산 편성과 개혁 과제를 중심으로 부처 회의를 열었다. 이번 보도에서는 정책... 정부 예산 편성 개혁 과제 중심 부처 회의 열다 이번 보도 정책 대통령 정부 법안 ...
2 대통령은 외교 일정에서 경제 협력과 안보 현안을 강조했다. 이번 보도에서는 개혁, ... 대통령 외교 일정 경제 협력 안보 현안 강조 하다 이번 보도 개혁 정부 회의 국회 ...
3 선거를 앞두고 각 정당은 공약 발표와 지역 방문을 확대했다. 이번 보도에서는 국회,... 선거 앞두다 정당 공약 발표 지역 방문 확대 하다 이번 보도 국회 정부 정책 개혁 ...
4 국회는 새로운 법안 심사를 진행하며 정부 정책 방향을 논의했다. 이번 보도에서는 개... 국회 새롭다 법안 심사 진행 하다 정부 정책 방향 논의 하다 이번 보도 개혁 국회 ...
catetory가 7인 데이터에서 원문과 전처리된 단어 결과를 함께 확인한다.
# category 값이 7인 뉴스 데이터만 선택합니다.
category_7_news = df_news[df_news.category == 7]
# 선택된 데이터의 앞쪽 5개 행을 출력하여 words 컬럼의 전처리 결과를 확인합니다.
category_7_news.head()
텍스트를 숫자행렬로 바꾸기 위한 CountVectorizer 객체 생성.
LDA는 문자데이터를 직접 사용할 수 없어 단어 빈도 기반 숫자 데이터가 필요하다 .
CountVectorizer() 객체 생성.
max_df 전체 문서의 10%를 초과하여 너무 자주등장할 경우 제외한다.
max_features 빈도기준으로 최대 1000개의 단어특성만 사용한다.
min_df 최소 2개 문서 이상에 등장한 단어만 사용한다.
ngram_range 한단어 표현과 두단어 묶음 표현을 모두 사용한다. 한단어와 두단어 묶음을 둘다 사용하면 '기술이', 나 '기술이 빠르게'를 모두 사용해 단어 하나만 봤을때 놓칠 수 있는 의미를 함께 학습할 수 있다.
# 텍스트 데이터를 단어 빈도 행렬로 변환하기 위해 CountVectorizer를 불러옵니다.
from sklearn.feature_extraction.text import CountVectorizer
# CountVectorizer 객체를 생성합니다.
# max_df=0.1은 전체 문서의 10%를 초과하여 너무 자주 등장하는 단어를 제외한다는 의미입니다.
# max_features=1000은 빈도 기준으로 최대 1000개의 단어 특성만 사용한다는 의미입니다.
# min_df=2는 최소 2개 문서 이상에 등장한 단어만 사용한다는 의미입니다.
# ngram_range=(1, 2)는 한 단어 표현과 두 단어 묶음 표현을 모두 사용한다는 의미입니다.
count_vectorizer = CountVectorizer(
max_df=0.1,
max_features=1000,
min_df=2,
ngram_range=(1, 2)
)
전처리된 word 컬럼을 fit_transform(). 학습
첫번째 문서 0 의 단어 빈도 벡터를 출력한다.
# words 컬럼의 텍스트 데이터를 학습하여 단어 사전을 만들고, 동시에 문서-단어 빈도 행렬로 변환합니다.
feat_vect = count_vectorizer.fit_transform(df_news.words)
# 변환된 행렬의 크기를 출력합니다.
# 첫 번째 값은 문서 수, 두 번째 값은 선택된 단어 특성 수입니다.
print('문서-단어 행렬 크기:', feat_vect.shape)
# 첫 번째 문서의 단어 빈도 벡터를 출력합니다.
# 대부분의 값이 0인 희소 행렬 형태로 저장됩니다.
print(feat_vect[0, :])
문서-단어 행렬 크기: (160, 697)
<Compressed Sparse Row sparse matrix of dtype 'int64'
with 22 stored elements and shape (1, 697)>
Coords Values
(0, 92) 2
(0, 319) 1
(0, 229) 1
(0, 396) 1
(0, 570) 1
(0, 225) 1
(0, 131) 1
(0, 333) 1
(0, 451) 1
(0, 94) 1
(0, 320) 1
(0, 231) 1
(0, 397) 1
(0, 571) 1
(0, 646) 1
(0, 517) 1
(0, 522) 1
(0, 226) 1
(0, 133) 1
(0, 282) 1
(0, 515) 1
(0, 452) 1
countvector가 학습한 단어 목록을 가져와 get_feature_names_out()
# CountVectorizer가 학습한 단어 목록을 가져옵니다.
# get_feature_names_out은 최신 scikit-learn에서 사용하는 권장 메서드입니다.
feature_names = count_vectorizer.get_feature_names_out()
# 단어 목록 중 앞쪽 5개를 출력하여 어떤 단어들이 특성으로 사용되는지 확인합니다.
print(feature_names[:5])
['가족' '가족 관련' '가족 중심' '감독' '감독 경기']
LatentDirichletAllocation import
토픽변수 초기화
LatentDirichletAllocation 객체 생성.
n_components 토픽 갯수
시드고정
learning_method 토픽을 학습하는 방식 전체문서를 한번에 보고 학습하는 batch, 전체 데이터를 조금씩 나눠 학습하는 online이 있다. 성능은 batch가 좋고 메모리절약하기에는 online이 좋다 .
fit() 학습
# 토픽 모델링 알고리즘인 LatentDirichletAllocation을 불러옵니다.
from sklearn.decomposition import LatentDirichletAllocation
# 추출할 토픽의 개수를 지정합니다.
# 예를 들어 8이면 전체 뉴스 문서를 8개의 숨은 주제로 나누어 보겠다는 의미입니다.
topic_cnt = 8
# LDA 모델 객체를 생성합니다.
# n_components는 찾고자 하는 토픽 개수를 의미합니다.
# random_state는 실행할 때마다 비슷한 결과가 나오도록 난수 시드를 고정합니다.
lda = LatentDirichletAllocation(
n_components=topic_cnt,
random_state=42,
learning_method='batch'
)
# 문서-단어 빈도 행렬을 사용하여 LDA 모델을 학습합니다.
lda.fit(feat_vect)
확인하고싶은 토픽번호 set
lda.components_ 토픽별 단어 가중치
argsort()[;;-1] 작은 순서대로 정렬했을때 인덱스를 반환해 내림차순으로 바꿔 할당.
10개추출, 공백으로 연결해 print
# 확인하고 싶은 토픽 번호를 지정합니다.
# 토픽 번호는 0부터 시작하므로 topic_num=5는 여섯 번째 토픽을 의미합니다.
topic_num = 5
# lda.components_에는 각 토픽별 단어 가중치가 저장되어 있습니다.
# topic 변수에는 선택한 토픽의 모든 단어 가중치가 들어갑니다.
topic = lda.components_[topic_num]
# argsort는 값을 작은 순서대로 정렬했을 때의 인덱스를 반환합니다.
# [::-1]을 붙이면 큰 값부터 작은 값 순서로 인덱스를 뒤집습니다.
topic_word_indexes = topic.argsort()[::-1]
# 가중치가 가장 높은 상위 10개 단어의 인덱스만 선택합니다.
top_indexes = topic_word_indexes[:10]
# 상위 10개 인덱스에 해당하는 단어명을 feature_names에서 찾아 공백으로 연결합니다.
feature_name_list = ' '.join([feature_names[i] for i in top_indexes])
# 선택한 토픽을 대표하는 핵심 단어 목록을 출력합니다.
print(feature_name_list)
LDA 토픽 모델링 겨로가를 시각화하기 위한 pyLDAvis 패키지 설치
# LDA 토픽 모델링 결과를 인터랙티브하게 시각화하기 위한 pyLDAvis 패키지를 설치합니다.
!pip install pyLDAvis
버전이상이 있을 수 있음으로 try문에 넣어 import.
pyLDAvis.enable_notebook() colab에서 시각화 결과물을 화면에 바로 표시하도록 설정하는 함수
# pyLDAvis 기본 모듈을 불러옵니다.
import pyLDAvis
# scikit-learn 기반 LDA 모델 결과를 pyLDAvis 형식으로 변환하는 모듈을 불러옵니다.
# pyLDAvis 버전에 따라 sklearn 또는 lda_model 경로가 다를 수 있으므로 예외 처리를 사용합니다.
try:
# 일부 구버전 pyLDAvis에서 사용하는 import 방식입니다.
import pyLDAvis.sklearn as sklearn_lda
except ModuleNotFoundError:
# 최신 pyLDAvis에서 사용하는 import 방식입니다.
import pyLDAvis.lda_model as sklearn_lda
# 노트북 내부에서 pyLDAvis 시각화 결과가 표시되도록 설정합니다.
pyLDAvis.enable_notebook()
현재 pd 버전 확인
# 현재 설치된 pandas 버전을 출력합니다.
# pyLDAvis가 정상 작동한다면 pandas를 강제로 다운그레이드할 필요가 없습니다.
import pandas as pd
# 사용 중인 pandas 버전을 확인합니다.
print('현재 pandas 버전:', pd.__version__)
.prepare() 시각화 데이터 준비
.display() 시각화 결과 표시
# 학습된 LDA 모델과 문서-단어 행렬, CountVectorizer를 이용하여 시각화 데이터를 준비합니다.
# sklearn_lda는 pyLDAvis.sklearn 또는 pyLDAvis.lda_model 중 현재 환경에서 사용 가능한 모듈입니다.
vis = sklearn_lda.prepare(lda, feat_vect, count_vectorizer)
# 준비된 pyLDAvis 시각화 결과를 노트북 화면에 표시합니다.
pyLDAvis.display(vis)

components를 돌려 idx와 weight를 뽑아 내림차순으로 정렬한뒤 n개 선택
상위 단어출력
# 각 토픽에서 출력할 상위 단어 개수를 지정합니다.
top_n = 10
# lda.components_에는 토픽별 단어 가중치가 들어 있으므로 enumerate로 토픽 번호와 가중치를 함께 반복합니다.
for topic_idx, topic_weights in enumerate(lda.components_):
# 현재 토픽에서 가중치가 큰 단어의 인덱스를 내림차순으로 정렬한 뒤 상위 top_n개만 선택합니다.
top_word_indexes = topic_weights.argsort()[::-1][:top_n]
# 선택된 인덱스를 실제 단어 이름으로 변환합니다.
top_words = [feature_names[i] for i in top_word_indexes]
# 토픽 번호와 대표 단어들을 출력합니다.
print(f'Topic {topic_idx}:', ', '.join(top_words))
Topic 0: 인공, 지능, 인공 지능, 반도체, 기술 개발, 에너지, 실험, 되다 데이터, 선거, 처리 기술
Topic 1: 안전, 사회, 플랫폼, 클라우드, 교통, 보안, 우주, 기업 환율, 환율, 소프트웨어
Topic 2: 생활, 소비자, 취미, 주거, 날씨, 중심, 가족, 음식, 여행, 개혁
Topic 3: 사회, 노동, 창작, 문화, 논의, 환경 개선, 커지다, 통해, 요구, 노동 환경
Topic 4: 국회, 법안, 외교, 투자, 소비, 문화, 대통령, 선거, 회복, 모델
Topic 5: 경기, 훈련, 축구, 우승, 야구, 관심, 진행, 진행 하다, 훈련 진행, 대표팀 강도
Topic 6: 선수, 중요하다, 감독, 야구, 리그, 기후, 과학, 경기, 득점, 알고리즘
Topic 7: 전시, 공연, 축제, 영화, 금리, 음악, 관객, 안전, 보건, 복지
/usr/local/lib/python3.12/dist-packages/jupyter_client/session.py:203: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.utcnow().replace(tzinfo=utc)
/usr/local/lib/python3.12/dist-packages/jupyter_client/session.py:203: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.utcnow().replace(tzinfo=utc)
/usr/local/lib/python3.12/dist-packages/jupyter_client/session.py:203: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.utcnow().replace(tzinfo=utc)
/usr/local/lib/python3.12/dist-packages/jupyter_client/session.py:203: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.utcnow().replace(tzinfo=utc)
/usr/local/lib/python3.12/dist-packages/jupyter_client/session.py:203: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.utcnow().replace(tzinfo=utc)
/usr/local/lib/python3.12/dist-packages/jupyter_client/session.py:203: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.utcnow().replace(tzinfo=utc)
/usr/local/lib/python3.12/dist-packages/jupyter_client/session.py:203: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.utcnow().replace(tzinfo=utc)
/usr/local/lib/python3.12/dist-packages/jupyter_client/session.py:203: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.utcnow().replace(tzinfo=utc)
예시코드 분석 word2vec_모델_실습하기.ipynb
Word2Vec 실습에 필요한 라이브러리 설치
# Colab 또는 Jupyter 환경에서 필요한 패키지를 설치하기 위해 pip 명령을 실행합니다.
# -q 옵션은 설치 로그를 줄여 화면을 깔끔하게 유지합니다.
!pip install -q --upgrade pip
# gensim은 Word2Vec과 FastText 모델을 학습하고 사용할 때 필요한 핵심 라이브러리입니다.
!pip install -q gensim
# pandas는 CSV 파일을 읽고 데이터프레임 형태로 다룰 때 사용합니다.
!pip install -q pandas
# JPype1은 KoNLPy가 Java 기반 형태소 분석기를 사용할 때 필요한 연결 라이브러리입니다.
!pip install -q JPype1
# konlpy는 Okt 형태소 분석기를 통해 한국어 명사를 추출할 때 사용합니다.
!pip install -q konlpy
# scikit-learn은 뒤에서 단어 벡터를 2차원으로 줄여 시각화할 때 사용할 수 있습니다.
!pip install -q scikit-learn
# matplotlib은 학습 결과를 그래프로 시각화할 때 사용합니다.
!pip install -q matplotlib
import
gensim Word2Vec와 FastText모델을 제공하는 자연어 처리 라이브러리
Word2Vec 단어를 고정 길이의 숫자 베기터로 학습하는 모델 클래스
FastText Word2Vec 와 유사하지만 단어내부의 글자 n-gram까지 학습하는 모델 클래스, 즉 Word2Vec 의 발전형으로 단어를 하나의 독립된 토큰으로 취급해 사과, 사과를, 사과가 등이 다른 단어로 보게되지만 FastText는 단어 내부으 ㅣ글자 조각 subword도 함께 학습해 여러 조각으로 분해해 학습한다. 어미변화, 합성어, 파생어가많은 언어에서 강력해 한국어, 일본어, 독일어에 사용된다.
# 운영체제 경로 처리, 파일 존재 여부 확인, 폴더 생성 등에 사용하는 기본 모듈입니다.
import os
# 정규표현식을 사용하여 특수문자 제거, 공백 정리 등을 수행하기 위한 기본 모듈입니다.
import re
# CSV 파일을 읽고 표 형태의 데이터프레임으로 처리하기 위한 데이터 분석 라이브러리입니다.
import pandas as pd
# gensim은 Word2Vec과 FastText 모델을 제공하는 자연어 처리 라이브러리입니다.
import gensim
# Word2Vec은 단어를 고정 길이의 숫자 벡터로 학습하는 모델 클래스입니다.
from gensim.models import Word2Vec
# FastText는 Word2Vec과 유사하지만 단어 내부의 글자 n-gram까지 학습하는 모델 클래스입니다.
from gensim.models import FastText
# 설치된 gensim 버전을 출력하여 라이브러리가 정상 설치되었는지 확인합니다.
print('gensim version:', gensim.__version__)
# 현재 작업 폴더를 출력하여 파일을 어디에서 읽고 쓰는지 확인합니다.
print('현재 작업 폴더:', os.getcwd())
데이터준비
# 실습 데이터 파일을 저장할 폴더 경로를 지정합니다.
data_dir = './data'
# 실습 데이터 파일의 전체 경로를 지정합니다.
news_path = os.path.join(data_dir, 'news.csv')
# data 폴더가 없으면 자동으로 생성합니다.
os.makedirs(data_dir, exist_ok=True)
# news.csv 파일이 없는 경우 실습용 샘플 데이터를 자동 생성합니다.
if not os.path.exists(news_path):
# Word2Vec이 단어 간 문맥을 조금이라도 학습할 수 있도록 여러 주제의 한국어 예문을 준비합니다.
sample_news = [
{'category': 7, 'news': '인공지능 기술은 자연어 처리와 컴퓨터 비전 분야에서 빠르게 발전하고 있다.'},
{'category': 7, 'news': '머신러닝 모델은 데이터에서 패턴을 학습하고 예측 결과를 생성한다.'},
{'category': 7, 'news': '딥러닝은 신경망 구조를 사용하여 이미지 음성 텍스트 데이터를 분석한다.'},
{'category': 7, 'news': '자연어 처리에서는 형태소 분석 토큰화 임베딩 벡터화 과정이 중요하다.'},
{'category': 7, 'news': 'Word2Vec 모델은 비슷한 문맥에 등장하는 단어를 가까운 벡터로 표현한다.'},
{'category': 7, 'news': 'FastText 모델은 단어 내부의 글자 정보를 활용하여 미등록 단어 문제를 줄인다.'},
{'category': 7, 'news': '검색 엔진은 문서와 질의 사이의 의미 유사도를 계산하여 결과를 제공한다.'},
{'category': 7, 'news': '추천 시스템은 사용자 행동 데이터와 상품 정보를 분석하여 맞춤형 상품을 추천한다.'},
{'category': 7, 'news': '올림픽 대회에서는 선수들이 다양한 종목에서 경쟁하고 기록을 세운다.'},
{'category': 7, 'news': '국제 대회와 스포츠 경기는 선수 팀 감독 팬들에게 중요한 관심사이다.'},
{'category': 7, 'news': '스마트폰 시장에서는 아이폰 갤럭시 태블릿 노트북 같은 전자기기가 경쟁한다.'},
{'category': 7, 'news': '아이폰 사용자는 카메라 성능 배터리 화면 디자인을 중요하게 생각한다.'},
{'category': 1, 'news': '경제 시장에서는 금리 환율 물가 주식 투자 지표가 중요하게 다루어진다.'},
{'category': 2, 'news': '정치 뉴스에서는 정부 국회 선거 정책 법안 등이 주요 이슈로 등장한다.'},
]
# 샘플 데이터를 pandas 데이터프레임으로 변환합니다.
sample_df = pd.DataFrame(sample_news)
# 생성한 샘플 데이터를 news.csv 파일로 저장합니다.
sample_df.to_csv(news_path, index=False, encoding='utf-8-sig')
# 파일 생성 완료 메시지를 출력합니다.
print('news.csv 파일이 없어 실습용 샘플 파일을 생성했습니다:', news_path)
else:
# 파일이 이미 있으면 기존 파일을 그대로 사용합니다.
print('기존 news.csv 파일을 사용합니다:', news_path)
csv를 읽어
대표 컬럼명 후보를 준비해 선택한다.
후보 컬럼이 하나도 없으면 데이터가 가장 많은 컬럼을 사용한다.
이때 object 는 문자열컬럼임.
# news.csv 파일을 pandas 데이터프레임으로 읽어옵니다.
df_news = pd.read_csv(news_path)
# 데이터프레임의 행과 열 개수를 출력하여 파일이 정상적으로 읽혔는지 확인합니다.
print('데이터 크기:', df_news.shape)
# CSV 파일에 들어 있는 컬럼명을 출력하여 구조를 확인합니다.
print('컬럼 목록:', df_news.columns.tolist())
# 본문으로 사용할 수 있는 대표 컬럼명 후보를 순서대로 준비합니다.
text_column_candidates = ['news', 'text', 'content', 'article', '본문', '내용', 'title', '제목']
# 후보 컬럼 중 실제 데이터프레임에 존재하는 첫 번째 컬럼을 텍스트 컬럼으로 선택합니다.
text_col = next((col for col in text_column_candidates if col in df_news.columns), None)
# 후보 컬럼이 하나도 없으면 문자열 데이터가 가장 많은 컬럼을 자동으로 선택합니다.
if text_col is None:
# object 타입은 보통 문자열 컬럼이므로 문자열 컬럼 목록을 찾습니다.
string_columns = df_news.select_dtypes(include='object').columns.tolist()
# 문자열 컬럼이 하나도 없으면 텍스트 분석을 진행할 수 없으므로 오류를 발생시킵니다.
if not string_columns:
raise ValueError('텍스트로 사용할 수 있는 문자열 컬럼이 없습니다. news.csv 컬럼을 확인하세요.')
# 첫 번째 문자열 컬럼을 텍스트 컬럼으로 사용합니다.
text_col = string_columns[0]
# 최종 선택된 텍스트 컬럼명을 출력합니다.
print('사용할 텍스트 컬럼:', text_col)
# 데이터 앞부분을 출력하여 내용이 정상인지 확인합니다.
df_news.head()
데이터 크기: (12, 2)
컬럼 목록: ['category', 'news']
사용할 텍스트 컬럼: news
category news
0 1 인공지능 기술이 산업 현장에 적용되면서 데이터 분석과 자동화 시스템의 활용이 확대되...
1 1 머신러닝 모델은 대량의 데이터를 학습하여 예측 정확도를 높이고 다양한 업무를 지원한다.
2 1 생성형 인공지능은 문서 작성 번역 요약 코딩 지원 등 여러 분야에서 활용되고 있다.
3 2 프로야구 경기에서 투수의 호투와 타선의 집중력이 승부를 결정했다.
4 2 축구 대표팀은 빠른 패스와 압박 전술을 앞세워 경기 주도권을 잡았다.
category컬럼이 있고 categoty가 7인, 하나이상있는지를 확인해 복사한다.
만일 else라면 전체 데이터를 사용한다.
결측값을 str문자열로 바꾼뒤 astype, tolist.반환해 join 긴 문자열로 결합한다.
# category 컬럼이 있고 category 값이 7인 데이터가 하나 이상 있는지 확인합니다.
if 'category' in df_news.columns and (df_news['category'] == 7).sum() > 0:
# category 값이 7인 행만 선택합니다.
selected_df = df_news[df_news['category'] == 7].copy()
# 선택 기준을 출력합니다.
print('category == 7 데이터만 사용합니다.')
else:
# category가 없거나 category 7 데이터가 없으면 전체 데이터를 사용합니다.
selected_df = df_news.copy()
# 전체 데이터를 사용한다는 안내를 출력합니다.
print('category 7 데이터가 없거나 category 컬럼이 없어 전체 데이터를 사용합니다.')
# 선택된 데이터 개수를 출력합니다.
print('선택된 문서 수:', len(selected_df))
# 텍스트 컬럼의 결측값을 빈 문자열로 바꾼 뒤 문자열 타입으로 변환합니다.
selected_texts = selected_df[text_col].fillna('').astype(str).tolist()
# 여러 뉴스 문장을 하나의 긴 문자열로 결합합니다.
text = ' '.join(selected_texts)
# 결합된 텍스트 길이를 출력합니다.
print('결합된 텍스트 길이:', len(text))
# 결합된 텍스트 앞부분을 출력하여 실제 내용이 들어 있는지 확인합니다.
print(text[:500])
category 7 데이터가 없거나 category 컬럼이 없어 전체 데이터를 사용합니다.
선택된 문서 수: 12
결합된 텍스트 길이: 504
인공지능 기술이 산업 현장에 적용되면서 데이터 분석과 자동화 시스템의 활용이 확대되고 있다. 머신러닝 모델은 대량의 데이터를 학습하여 예측 정확도를 높이고 다양한 업무를 지원한다. 생성형 인공지능은 문서 작성 번역 요약 코딩 지원 등 여러 분야에서 활용되고 있다. 프로야구 경기에서 투수의 호투와 타선의 집중력이 승부를 결정했다. 축구 대표팀은 빠른 패스와 압박 전술을 앞세워 경기 주도권을 잡았다. 올림픽 선수들은 체력 훈련과 전략 분석을 통해 경기력을 끌어올리고 있다. 주식 시장은 금리 인상 우려와 기업 실적 발표의 영향을 받아 변동성이 커졌다. 환율 상승은 수입 물가와 소비자 가격에 영향을 미칠 수 있다. 정부는 경기 회복을 위해 투자 확대와 일자리 지원 정책을 추진하고 있다. 병원은 환자 진료 데이터를 분석하여 맞춤형 치료와 예방 관리를 강화하고 있다. 신약 개발 과정에서 인공지능을 활용한 후보 물질 탐색이 주목받고 있다. 건강 관리를 위해 규칙적인 운동과 균형 잡힌 식습관이 중
re.sub 불필요한 특수문자와 공백을 제거한다.
# 한글, 영문, 숫자, 공백을 제외한 특수문자를 공백으로 치환합니다.
cleaned_text = re.sub(r'[^가-힣a-zA-Z0-9\s]', ' ', text)
# 줄바꿈, 탭, 여러 개의 공백을 공백 한 칸으로 정리합니다.
cleaned_text = re.sub(r'\s+', ' ', cleaned_text).strip()
# 정제된 텍스트 길이를 출력합니다.
print('정제된 텍스트 길이:', len(cleaned_text))
# 정제된 텍스트 앞부분을 출력하여 결과를 확인합니다.
print(cleaned_text[:500])
# 정제 후 텍스트가 비어 있으면 원본 데이터 또는 컬럼 선택에 문제가 있으므로 명확한 오류를 발생시킵니다.
if len(cleaned_text) == 0:
raise ValueError('정제된 텍스트가 비어 있습니다. news.csv 내용과 텍스트 컬럼을 확인하세요.')
Okt 를 import해 객체생성을 하고 nouns명사만 추출해 저장한다. 10개보다 적으면 한글 두글자이상, 영문/숫자 2글자이상 단어후보로 추출한다 허용하지않던 것들도 조금 허용해 더 뽑아내는 것.
한글자 토큰은 의미가 약하니 2글자 이상 토큰만 남기고 return.
# 한국어 명사 추출을 안전하게 수행하는 함수를 정의합니다.
def extract_korean_tokens(input_text):
# 최종적으로 Word2Vec 학습에 사용할 토큰 리스트를 저장할 변수를 준비합니다.
tokens = []
# 먼저 KoNLPy의 Okt 형태소 분석기를 사용해봅니다.
try:
# Okt 형태소 분석기를 불러옵니다.
from konlpy.tag import Okt
# Okt 객체를 생성합니다.
okt = Okt()
# 입력 텍스트에서 명사만 추출합니다.
tokens = okt.nouns(input_text)
# Okt 방식으로 추출한 토큰 개수를 출력합니다.
print('Okt 명사 추출 개수:', len(tokens))
except Exception as e:
# Java, JPype, KoNLPy 문제로 Okt가 실패할 경우 오류 메시지를 출력하고 대체 방식을 사용합니다.
print('Okt 명사 추출 실패, 대체 토큰화를 사용합니다:', repr(e))
# Okt 결과가 너무 적으면 정규표현식 기반 대체 토큰화를 수행합니다.
if len(tokens) < 10:
# 한글 2글자 이상 또는 영문/숫자 2글자 이상 문자열을 단어 후보로 추출합니다.
fallback_tokens = re.findall(r'[가-힣]{2,}|[a-zA-Z0-9]{2,}', input_text)
# 대체 토큰화 결과를 최종 토큰으로 사용합니다.
tokens = fallback_tokens
# 대체 토큰화 사용 사실과 개수를 출력합니다.
print('대체 토큰화 개수:', len(tokens))
# 한 글자 토큰은 의미가 약한 경우가 많으므로 2글자 이상 토큰만 남깁니다.
tokens = [token for token in tokens if len(token) >= 2]
# 최종 토큰 리스트를 반환합니다.
return tokens
토큰이 20이하면 샘플토큰을 추가한다.
한문장에 넣을 토큰 개수를 지정한다. sentense_size
토큰 리스트를 잘라 여러 문장 리스트로 구성한다.
길이가 2 이상인 문장만 남겨 word2vec 학습 안정성을 높인다 .
# 정제된 텍스트에서 한국어 명사 또는 대체 토큰을 추출합니다.
noun2more = extract_korean_tokens(cleaned_text)
# Word2Vec 학습에 사용할 토큰이 너무 적으면 샘플 토큰을 추가하여 학습 실패를 방지합니다.
if len(noun2more) < 20:
# 실습용 기본 토큰을 여러 번 반복하여 최소 학습량을 확보합니다.
fallback_training_tokens = ['인공지능', '자연어', '처리', '모델', '학습', '데이터', '분석', '벡터', '임베딩', '유사도', '대회', '올림픽', '아이폰', '스마트폰'] * 5
# 기존 토큰 뒤에 실습용 기본 토큰을 추가합니다.
noun2more.extend(fallback_training_tokens)
# 토큰이 부족해 보강했다는 메시지를 출력합니다.
print('토큰 수가 부족하여 실습용 기본 토큰을 추가했습니다.')
# 추출된 토큰 앞부분을 출력합니다.
print('토큰 샘플:', noun2more[:50])
# 전체 토큰 개수를 출력합니다.
print('토큰 개수:', len(noun2more))
# 한 문장에 넣을 토큰 개수를 지정합니다.
sentence_size = 20
# 토큰 리스트를 sentence_size 단위로 잘라 여러 문장 리스트로 구성합니다.
sentences = [noun2more[i:i + sentence_size] for i in range(0, len(noun2more), sentence_size)]
# 길이가 2 이상인 문장만 남겨 Word2Vec 학습 안정성을 높입니다.
sentences = [sentence for sentence in sentences if len(sentence) >= 2]
# 생성된 문장 개수를 출력합니다.
print('학습 문장 개수:', len(sentences))
# 첫 번째 문장을 출력하여 입력 형태를 확인합니다.
print('첫 번째 학습 문장:', sentences[0])
학습 문장 개수: 6
첫 번째 학습 문장: ['인공', '지능', '기술', '산업', '현장', '적용', '데이터', '분석', '자동화', '시스템', '활용', '확대', '머신', '러닝', '모델', '대량', '데이터', '학습', '예측', '정확도']
WOrd2Vec 객체 생성.
sg skip-gram 중심단어 기준 주변단어 예측
vector_size 단어하나를 기본 100차원으로 표현
window 중심 단어 주변 3개 단어를 문맥으로 본다.
min_count 1번만 등장한 단어도 학습에 포함한다 .데이터양이 작은때 숫자를 낮춘다.
workers 학습에 cpu2개 사용
# Word2Vec 모델을 학습합니다.
model = Word2Vec(
# Word2Vec 학습에 사용할 문장 리스트를 입력합니다.
sentences=sentences,
# sg=1은 Skip-gram 방식으로, 중심 단어를 기준으로 주변 단어를 예측합니다.
sg=1,
# vector_size는 단어 하나를 몇 차원 벡터로 표현할지 정합니다.
vector_size=100,
# window는 중심 단어 주변 몇 개 단어를 문맥으로 볼지 정합니다.
window=3,
# min_count=1은 한 번만 등장한 단어도 학습에 포함한다는 의미입니다.
min_count=1,
# workers는 학습에 사용할 CPU 스레드 수입니다.
workers=2,
# epochs는 전체 데이터를 몇 번 반복 학습할지 정합니다.
epochs=100,
# seed는 실행할 때마다 비슷한 결과가 나오도록 난수값을 고정합니다.
seed=42
)
# 학습된 단어 사전 크기를 출력합니다.
print('Word2Vec 단어 사전 크기:', len(model.wv.index_to_key))
# 학습된 단어 일부를 출력합니다.
print('단어 사전 샘플:', model.wv.index_to_key[:30])
Word2Vec 단어 사전 크기: 92
단어 사전 샘플: ['경기', '지원', '활용', '분석', '데이터', '지능', '인공', '관리', '위해', '영향', '확대', '습관', '균형', '운동', '규칙', '건강', '주목', '탐색', '물질', '후보', '과정', '개발', '신약', '예방', '치료', '맞춤', '진료', '환자', '병원', '추진']
safe_most_similar() wv.key_to_index 입력단어가 모델의 단어사전에 존재하면 wv.most_similar() 유사단어를 계산한다. return
safe_similarity() 첫번째 단어가 사전에 없으면 안내하고 none을 반환.
두번째도. 모두 있으면 wv.similarity() 코사인 유사도 계산해 반환.
# Word2Vec 또는 FastText 모델에서 유사 단어를 안전하게 검색하는 함수를 정의합니다.
def safe_most_similar(trained_model, word, topn=10):
# 입력 단어가 모델의 단어 사전에 존재하는지 확인합니다.
if word in trained_model.wv.key_to_index:
# 단어가 존재하면 most_similar 함수로 유사 단어를 계산합니다.
return trained_model.wv.most_similar(word, topn=topn)
# 입력 단어가 없으면 안내 메시지를 출력합니다.
print(f'[{word}] 단어가 모델 사전에 없습니다.')
# 대신 사용할 수 있는 단어 사전 샘플을 출력합니다.
print('사용 가능한 단어 예시:', trained_model.wv.index_to_key[:30])
# 오류 대신 빈 리스트를 반환하여 다음 코드 실행이 중단되지 않게 합니다.
return []
# 두 단어 사이의 유사도를 안전하게 계산하는 함수를 정의합니다.
def safe_similarity(trained_model, word1, word2):
# 첫 번째 단어가 사전에 없으면 안내하고 None을 반환합니다.
if word1 not in trained_model.wv.key_to_index:
print(f'[{word1}] 단어가 모델 사전에 없습니다.')
return None
# 두 번째 단어가 사전에 없으면 안내하고 None을 반환합니다.
if word2 not in trained_model.wv.key_to_index:
print(f'[{word2}] 단어가 모델 사전에 없습니다.')
return None
# 두 단어가 모두 사전에 있으면 코사인 유사도를 계산하여 반환합니다.
return trained_model.wv.similarity(word1, word2)
테스트
# '대회'와 의미적으로 가까운 단어들을 안전하게 검색합니다.
similar_words = safe_most_similar(model, '대회', topn=10)
# 검색 결과를 출력합니다.
print(similar_words)
# '대회'와 '올림픽' 사이의 코사인 유사도를 안전하게 계산합니다.
similarity_score = safe_similarity(model, '대회', '올림픽')
# 계산 결과를 출력합니다.
print('대회-올림픽 유사도:', similarity_score)
# '아이폰'과 의미적으로 가까운 단어들을 안전하게 검색합니다.
iphone_similar_words = safe_most_similar(model, '아이폰', topn=10)
# 검색 결과를 출력합니다.
print(iphone_similar_words)
FastText() 객체 생성
sg 1 skip-gram 방식 사용
vector_size 단어의 차원수
window 중심단어에서 주변 문맥범위 3,
min_count 1이라도 단어가 제거되지않도록함
학습에 사용할 cpu 스레드 수2
# FastText 모델을 학습합니다.
f_model = FastText(
# FastText 학습에 사용할 문장 리스트를 입력합니다.
sentences=sentences,
# sg=1은 Skip-gram 방식을 사용한다는 의미입니다.
sg=1,
# vector_size는 단어 벡터의 차원 수입니다.
vector_size=100,
# window는 중심 단어 주변 문맥 범위입니다.
window=3,
# min_count=1은 실습 데이터가 적어도 단어가 제거되지 않게 합니다.
min_count=1,
# workers는 학습에 사용할 CPU 스레드 수입니다.
workers=2,
# epochs는 전체 데이터를 반복 학습하는 횟수입니다.
epochs=100,
# seed는 결과 재현성을 위한 난수 고정값입니다.
seed=42
)
# FastText 단어 사전 크기를 출력합니다.
print('FastText 단어 사전 크기:', len(f_model.wv.index_to_key))
마찬가지로 검색및 유사도계산
# FastText 모델에서 '대회'와 가까운 단어를 안전하게 검색합니다.
print('FastText 대회 유사 단어:', safe_most_similar(f_model, '대회', topn=10))
# FastText 모델에서 '대회'와 '올림픽'의 유사도를 안전하게 계산합니다.
print('FastText 대회-올림픽 유사도:', safe_similarity(f_model, '대회', '올림픽'))
# FastText 모델에서 '아이폰'과 가까운 단어를 안전하게 검색합니다.
print('FastText 아이폰 유사 단어:', safe_most_similar(f_model, '아이폰', topn=10))
os.makedirs()
path 지정
model.save() 모델 저장
Word2Vec.load() 불러오기
확인
# 학습된 모델을 저장할 폴더를 생성합니다.
os.makedirs('./models', exist_ok=True)
# Word2Vec 모델 저장 경로를 지정합니다.
word2vec_model_path = './models/korean_word2vec_practice.model'
# 학습된 Word2Vec 모델을 파일로 저장합니다.
model.save(word2vec_model_path)
# 저장된 Word2Vec 모델을 다시 불러옵니다.
loaded_model = Word2Vec.load(word2vec_model_path)
# 다시 불러온 모델의 단어 사전 크기를 출력하여 정상 저장 여부를 확인합니다.
print('다시 불러온 모델 단어 사전 크기:', len(loaded_model.wv.index_to_key))
BOW Bag of Words 단어의 순서는 고려하지않고 단어가 몇번 등장했는지에 집중하는 텍스트 수치화 방법
DTM Document Term Matrix 여러 문서의 BOW를 하나의 행렬로 모은것.
TF-IDF 특정 문서안에서 단어가 얼마나 자주 등장하는지, 전체 문서에서 흔한 단어가중치를 맞추고 흔하지않으면 가중치를 높임
Vocabulary(어휘집) 전체 문서에 등장한 고유 단어 목록
DTM(Document-Term Matrix) 문서별로 단어가 몇 번 등장했는지 기록한 표
TF(Term Frequency) 문서내 단어 등장 횟수
실습코드
import sys
import subprocess
from math import log
try:
from sklearn.feature_extraction.text import CountVectorizer
except ModuleNotFoundError:
raise ModuleNotFoundError("Please install the sklearn package.")
try:
from konlpy.tag import Okt
okt = Okt()
KONLPY_AVAILABLE = True
except Exception as e:
okt = None
KONLPY_AVAILABLE = False
KONLPY_ERROR = e
try:
import nltk
from nltk.corpus import stopwords
NLTK_AVAILABLE = True
except ModuleNotFoundError:
nltk = None
stopwords = None
NLTK_AVAILABLE = False
raise ModuleNotFoundError("Please install the nltk package.")
def print_section(title):
print('\n' + '='*80)
print(title)
print('='*80)
print_section('1. BOW 구현: 한국어 문장을 빈도 벡털 변환')
if not KONLPY_AVAILABLE:
print('[안내] konlpy.Okt 실행에 실패했습니다. 현재 코드는 공백기반 토큰화를 사용하여 계속 실행합니다. ')
# 한국어 문장을 토큰 리스트로 변환하는 함수
def tokenize_korean(document):
cleaned_document = document.replace('.', '')
cleaned_document = cleaned_document.replace(',', '')
if KONLPY_AVAILABLE:
return okt.morphs(cleaned_document)
return cleaned_document.split()
# 하나의 문서에서 BOW 사전과 빈도벡터를 만드는 함수
def build_bag_of_words(document):
tokenize_document = tokenize_korean(document)
word_to_index = {}
bow = []
for word in tokenize_document:
if word not in word_to_index:
word_to_index[word] = len(word_to_index)
bow.append(1)
else:
index = word_to_index[word]
bow[index] += 1
return word_to_index, bow
doc1 = "파이썬을 이용한 텍스트 빈도수 카운트 실습을 진행합니다 ."
vocab, bow = build_bag_of_words(doc1)
print("입력문장: ", doc1)
print("Vocab: ", vocab)
print('Vocab size: ', len(vocab))
print('BoW size: ', len(bow))
print("BOW: ", bow)
print_section("2. CountVectorizer를 이용한 BOW 생성")
corpus = ["you know i want your love. I love you"]
vec = CountVectorizer()
bow_matrix = vec.fit_transform(corpus)
print("입력코퍼스: ", corpus)
print("bag of words: ", bow_matrix.toarray())
print("Vocab: ", vec.vocabulary_)
print_section("3. 사용자가 직접 정의한 불용어 제거")
text = ["Family is not an important thing."]
custom_stop_words = ['the', 'a', 'an', 'is', 'not']
vect_custom = CountVectorizer(stop_words=custom_stop_words)
custom_matrix = vect_custom.fit_transform(text)
print("입력문장: ", text)
print("bow vector: ", custom_matrix)
print("Vocab: ", vect_custom.vocabulary_)
print_section("4. DTM과 TF-IDF을 위한 전처리 단계")
docs = [
"배우고 싶은 자연어",
"딥러닝 머신러닝 배우고 싶은 강화학습",
"자연어 처리 좋아요",
"배우고 싶은 딥러닝"
]
vocab = sorted(set(word for doc in docs for word in doc.split()))
N = len(vocab)
print("문서목록")
for idx, doc in enumerate(docs, start=1):
print(f'문서{idx} : {doc}')
print("vocab: ", vocab)
print("문서개수 N: ", N)
================================================================================
1. BOW 구현: 한국어 문장을 빈도 벡털 변환
================================================================================
입력문장: 파이썬을 이용한 텍스트 빈도수 카운트 실습을 진행합니다 .
Vocab: {'파이썬': 0, '을': 1, '이용': 2, '한': 3, '텍스트': 4, '빈': 5, '도수': 6, '카운트': 7, '실습': 8, '진행': 9, '합니다': 10}
Vocab size: 11
BoW size: 11
BOW: [1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
================================================================================
2. CountVectorizer를 이용한 BOW 생성
================================================================================
입력코퍼스: ['you know i want your love. I love you']
bag of words: [[1 2 1 2 1]]
Vocab: {'you': 3, 'know': 0, 'want': 2, 'your': 4, 'love': 1}
================================================================================
3. 사용자가 직접 정의한 불용어 제거
================================================================================
입력문장: ['Family is not an important thing.']
bow vector: <Compressed Sparse Row sparse matrix of dtype 'int64'
with 3 stored elements and shape (1, 3)>
Coords Values
(0, 0) 1
(0, 1) 1
(0, 2) 1
Vocab: {'family': 0, 'important': 1, 'thing': 2}
================================================================================
4. DTM과 TF-IDF 실습
================================================================================
문서목록
문서1 : 배우고 싶은 자연어
문서2 : 딥러닝 머신러닝 배우고 싶은 강화학습
문서3 : 자연어 처리 좋아요
문서4 : 배우고 싶은 딥러닝
vocab: ['강화학습', '딥러닝', '머신러닝', '배우고', '싶은', '자연어', '좋아요', '처리']
문서개수 N: 8'Personal > SK 네트웍스 AI 캠프' 카테고리의 다른 글
| [SK네트웍스 Family AI 캠프] 32기 9주차 회고: Day32 ~ Day34 (0) | 2026.06.26 |
|---|---|
| SK 네트웍스 AI 캠프 - 3_초거대언어모델(LLM) - Day34_자연어 처리를 위한 딥러닝 모델 (0) | 2026.06.26 |
| SK 네트웍스 AI 캠프 - 3_초거대언어모델(LLM) - Day32_자연어 데이터 준비 자연어 처리 절차와 형태소 분석 (0) | 2026.06.24 |
| [SK네트웍스 Family AI 캠프] 32기 8주차 회고: Day27 ~ Day31 (0) | 2026.06.20 |
| SK 네트웍스 AI 캠프 - 2 _데이터 분석과 머신러닝 / 딥러닝 - Day31_AI 모델 검증을 통한 고도화 (0) | 2026.06.19 |