Open minjung00 opened 11 months ago
pip install fastapi
pip install uvicorn
FastAPI 앱 만들기 FastAPI를 테스트를 진행하려는 프로젝트로 이동하여 app.py를 생성한 후 FastAPI를 정의한다.
# 필요한 라이브러리 및 모듈 import
import os # 운영 체제와 상호 작용하기 위한 모듈
import pandas as pd # 데이터 조작 및 분석을 위한 라이브러리
import numpy as np # 수치 계산을 위한 라이브러리
from konlpy.tag import Okt # 한국어 형태소 분석을 위한 라이브러리
from gensim.models.word2vec import Word2Vec # 단어 임베딩을 위한 Word2Vec 모델
import re # 정규 표현식을 사용하기 위한 라이브러리
import html # HTML 엔터티를 변환하기 위한 라이브러리
from sklearn.metrics.pairwise import euclidean_distances # 유클리디언 거리 계산을 위한 라이브러리
from sklearn.preprocessing import StandardScaler # 데이터 스케일링을 위한 라이브러리
from fastapi import FastAPI # FastAPI 웹 프레임워크
# FastAPI 애플리케이션 초기화
app = FastAPI()
# Java 환경 변수 설정
os.environ["JAVA_HOME"] = "C:\Program Files\Java\jdk-11"
# 뮤지컬 데이터 파일 URL
file = "https://drive.google.com/uc?id=구글드라이브 해당 csv파일의 id값을 넣기"
# CSV에서 뮤지컬 데이터 불러오기
musical_data = pd.read_csv(file, encoding='utf-8')
# 모든 열에서 특수 문자와 HTML 엔터티 정제
for col in musical_data.columns:
musical_data[col] = musical_data[col].apply(lambda x: re.sub(r'[^\w\s]', '', html.unescape(str(x))))
# Konlpy를 사용한 텍스트 전처리
twitter = Okt()
# 텍스트 전처리 함수
def preprocessingText(synopsis):
stems = [] # 형태소 추출 결과를 저장할 리스트
tagged_review = twitter.pos(synopsis, stem=True) # 한국어 형태소 분석기를 사용하여 형태소 추출
# 각 단어와 형태소의 품사에 대해 반복
for word, pos in tagged_review:
# 명사(Noun) 또는 형용사(Adjective)인 경우에만 추출 리스트에 추가
if pos == "Noun" or pos == 'Adjective':
stems.append(word)
# 공백을 이용하여 추출한 형태소들을 하나의 문자열로 결합하여 반환
return " ".join(stems)
# 각 시놉시스에 대해 전처리 함수 적용
musical_data['synopsis_clear'] = musical_data['synopsis'].fillna('').apply(preprocessingText)
# 시놉시스 데이터를 리스트로 변환
sentences = musical_data['synopsis'].tolist()
# 시놉시스 열의 각 텍스트에 대해 앞서 정의한 전처리 함수(preprocessingText)를 적용하고 NaN 값은 빈 문자열로 대체
tokenized_data = musical_data['synopsis'].apply(lambda x: preprocessingText(str(x))).fillna('')
# 새로운 열 'synopsis_clear'에 전처리된 텍스트 추가 및 공백 추가
musical_data["synopsis_clear"] = musical_data['synopsis_clear'].astype(str) + " "
# 'synopsis_clear' 열의 각 텍스트를 공백을 기준으로 분할하여 리스트로 변환하여 'tokenized_data' 열에 추가
musical_data["tokenized_data"] = musical_data["synopsis_clear"].apply(lambda data: data.split(" "))
model = Word2Vec(musical_data["tokenized_data"],
vector_size=100,
window=3,
min_count=2,
sg=1)
model.save("word2vec_model2.bin")
# WordVector 단어를 문자열로 변환
word2vec_words = model.wv.key_to_index.keys()
# 시놉시스를 벡터화하고 문자열로 저장
string_array = []
# 데이터프레임의 행 수 만큼 반복
for index in range(len(musical_data)):
# 각 행에서 'musical_id', 'title', 'tokenized_data' 열의 데이터 추출
NUM = musical_data.loc[index, "musical_id"]
TITLE = musical_data.loc[index, "title"]
LINE = musical_data.loc[index, "tokenized_data"]
# 문장 벡터 초기화
doc2vec = None
# 해당 문장에 포함된 단어 수 초기화
count = 0
# 각 단어에 대해 Word2Vec 모델 적용
for word in LINE:
# 모델이 학습한 단어일 경우
if word in word2vec_words:
# 해당 단어의 벡터를 더함
count += 1
if doc2vec is None:
doc2vec = model.wv[word]
else:
doc2vec = doc2vec + model.wv[word]
# 문장의 벡터값 계산 (평균값)
if doc2vec is not None:
doc2vec = doc2vec / count
# 문자열로 변환하여 저장
string_array.append(doc2vec.tostring())
# 데이터프레임에 새로운 열 추가
musical_data["doc2vec_vec"] = string_array
# 날짜에서 start_date와 end_date 추출
musical_data['start_date'] = pd.to_datetime(musical_data['date'].str[:8], format="%Y%m%d")
musical_data['end_date'] = pd.to_datetime(musical_data['date'].str[:6], format="%Y%m")
# 열 재정렬
musical_data = musical_data[['musical_id', 'title', 'poster_url', 'genre', 'date', 'start_date', 'end_date', 'location',
'actors', 'age_rating', 'running_time', 'describe', 'synopsis', 'synopsis_clear',
'tokenized_data', 'doc2vec_vec']]
# 필요시 CSV로 저장
# musical_data.to_csv('../musical_data_vector.csv', index=False, encoding='utf-8')
# 추천 시스템
# doc2vec_vec을 numpy 배열로 변환
musical_data["doc2vec_numpy"] = musical_data["doc2vec_vec"].apply(lambda x: np.fromstring(x, dtype="float32"))
# 데이터 스케일 조정
scaler = StandardScaler()
scaler.fit(np.array(musical_data["doc2vec_numpy"].tolist()))
musical_data["doc2vec_numpy_scale"] = scaler.transform(np.array(musical_data["doc2vec_numpy"].tolist())).tolist()
# 유클리디언 거리 계산
sim_score = euclidean_distances(musical_data["doc2vec_numpy_scale"].tolist(), musical_data["doc2vec_numpy_scale"].tolist())
sim_df = pd.DataFrame(data=sim_score, index=musical_data["title"], columns=musical_data["title"])
# 예시: "빨간모자2"와 유사한 5개의 뮤지컬 가져오기
similar_musicals = sim_df["빨간모자2"].sort_values()[1:6]
# FastAPI 초기 엔드포인트용 route
@app.get("/")
def init():
return similar_musicals
=> 이전페이지에서 작성했던 컨텐츠 기반 추천 시스템 코드를 REST API에서 응답을 확인하기 위해 app.py로 이동한것.
1. 콘텐츠 기반 필터링
줄거리를 기반으로 유사도가 높은 순으로 (유클리드 거리가 가까운 순서) 작품 추천
musical_data_vector2.csv 데이터 사용
1. 모든 행의
doc2vec_vec
컬럼(줄거리를 벡터로 전환한 값을 다시 문자열로 저장한 컬럼)을 numpy 배열로 변환해서doc2vec_numpy
컬럼에 대입2. StandardScaler 객체를 적용한 후 리스트로 변환해서
doc2vec_numpy_scale
컬럼에 대입3. doc2vec_numpy_scale 컬럼의 유클리드 거리를 계산 → sim_df
결과
해당코드는 branch 0.0.3/work2vec_test → Model_test/Content_mock.ipynb 있습니다.