프로젝트 개요
프로젝트 명 : 시를 잊은 그대에게 - 취향에 맞는 시집을 분류해 추천드립니다
프로젝트 기간 : 2022년 6월 22 ~ 2022년 6월 27일
사용 데이터 : 알라딘, DBPia에서 파싱한 데이터
사용 모델 : K-means Clustering
웹 : Flask, Google Data Studio
데이터 전처리 및 특성 공학
이전 장에서 알라딘과 DBPia를 통해 SQLite db에 저장한 파일들을 하나로 통합한 후, 분석에 사용하기 위해 전처리 및 특성 공학을 수행하였습니다.
1) DBPia 검색 결과로 만든 특성의 'None'을 '0'으로 변경
2) 출판사를 분석에 사용하기 위해 메이저 출판사(1: 창비, 문학과지성사, 문학동네, 민음사)와 기타 출판사(0)로 분류.
- 시집 출판 기간이 어느 정도 오래되고 시집을 판매하는 오프라인 서점에서도 기본적으로 구비되어 있는 출판사를 메이저 출판사로 선정하였는데, 이러한 정의 및 선별은 분석을 위해 편의상 진행한 다소 임의적인 구분입니다.
3) 저자명을 기반으로 단독저자와 공저자(선집?)을 분류
4) 기타 결측치 처리
그 결과 정리한 데이터셋: (정정: pub_unixtime은 실제 unixtime이 아니라 pub_data의 날짜에서 '-'를 제외한 값입니다.)
K-means Clustering
클러스터링 방식은 데이터가 가진 특성에 기반하여 유사한 그룹을 생성해 나가는 Unsupervised Machine Learning 방법입니다. 고객 데이터가 없어서 고객이 선호할만한 책을 추천해주는 모델을 제작할 수 없기에, 차선책으로 가지고 있는 시집의 데이터를 클러스터링 방법을 통해 분류한 후, 선호하는 시집을 입력하면 그 시집이 포함된 클러스터 안의 책을 추천해주는 방식의 서비스 모델을 고안했습니다.
이를 위해 사용한 클러스터링 방식이 K-means Clustering입니다. K-means clustering은 K개의 랜덤한 데이터를 클러스터의 중심점으로 설정한 후, 해당 클러스터에 인접해 있는 데이터를 같은 클러스트에 할당합니다. 다시 이렇게 할당된 각각의 클러스트를 기준으로 다시 K개의 중심점을 설정하고, 마찬가지로 해당 클러스터에 인접해 있는 데이터를 같은 클러스터로 다시 할당합니다. 이러한 과정을 클러스터 분할에 더이상 유의미한 변화가 없을 때까지 반복하여, 최종적으로 데이터를 K개의 클러스터로 분할한 결과를 도출하게 됩니다.
위에서 전처리한 데이터를 싸이킷런의 'StandardScaler'를 통해 표준화를 하고 K-means clustering을 진행하였습니다. (이때 k 값은 elbow methods를 통해 도출된 최적값인 10으로 설정하였습니다.) 이런 과정을 거쳐서 10개로 분류된 클러스터링 데이터를 만들었습니다.
Flask를 통해 웹으로 연결하기
이제 이렇게 만들어진 데이터를 db에 저장하고, Flask를 통해 웹으로 실행해보도록 하겠습니다.
우선, 현재 위치한 폴더에 하위 폴더를 만들고 거기에 flask를 작동할 파이썬 파일을 만듭니다. 그리고 시집 제목을 입력할 수 있는 입력창을 만든 간단한 화면을 구성해보겠습니다.
<html>
<body>
<form action="http://localhost:5000/result" method="Post">
<a> 시집을 추천해드립니다 </a>
<p> 시집 제목: <input type="text" name="Title" /></p>
<p> <input type="submit" value="입력" /></p>
</form>
</body>
</html>
이처럼 html문을 작성하고, render_templates을 통해 불러옵니다. 이후 터미널에 'flask run' 명령어를 입력하여 실행하면 아래와 같은 화면이 웹으로 출력됩니다.
다음으로 시집 제목을 입력하면, 검색한 시집이 포함되어 있는 클러스터의 salespoint 상위 다섯개 시집을 출력해주는 페이지를 구성하였습니다. flask 파이썬 파일에 다음과 같은 경로와 루트를 작성합니다.
@app.route('/result', methods=['POST'])
def show_result():
if request.method == 'POST':
title = request.form["Title"]
index_num = data.loc[data['Book_Title'] == title].index[0]
cluster_name = data.loc[index_num, 'clusters']
rec_book_list = data.loc[data['clusters'] == cluster_name]['Book_Title'][0:5].tolist()
rec_author_list = data.loc[data['clusters'] == cluster_name]['Author'][0:5].tolist()
rec_publisher_list = data.loc[data['clusters'] == cluster_name]['Publisher'][0:5].tolist()
rec_pubdate_list = data.loc[data['clusters'] == cluster_name]['Pub_date'][0:5].tolist()
rec1 = [rec_book_list[0], rec_author_list[0], rec_publisher_list[0], rec_pubdate_list[0]]
rec2 = [rec_book_list[1], rec_author_list[1], rec_publisher_list[1], rec_pubdate_list[1]]
rec3 = [rec_book_list[2], rec_author_list[2], rec_publisher_list[2], rec_pubdate_list[2]]
rec4 = [rec_book_list[3], rec_author_list[3], rec_publisher_list[3], rec_pubdate_list[3]]
rec5 = [rec_book_list[4], rec_author_list[4], rec_publisher_list[4], rec_pubdate_list[4]]
result = [rec1, rec2, rec3, rec4, rec5]
return render_template('result.html', result=result)
methods=['POST']로 설정하고 request를 통해 위의 입력창에 입력한 값을 받아올 수 있습니다. 이때 형식은 딕셔너리 형식이므로, key 값으로 지정한 "Title"을 입력하여 입력한 value를 받아옵니다. 이후 함수는 해당 클러스터를 저장한 데이터프레임에서 책 제목, 작가, 출판사, 출판일을 상위 5개 출력하는 명령어입니다.
<!doctype html>
<html>
<body>
<table border = 1>
{% for value in result%}
<tr>
<th> {{value[0]}} </th>
<td> {{value[1]}} </td>
<td> {{value[2]}} </td>
<td> {{value[3]}} </td>
</tr>
{% endfor %}
</table>
</body>
</html>
그리고 이를 웹으로 구현할 HTML입니다.
이제 웹 페이지를 구현하기 위해 검색창에 임의의 제목을 입력해보도록 하겠습니다.
시집 5권이 출력되는 것을 확인할 수 있습니다.
'Project' 카테고리의 다른 글
[Deep Learning] Gerhard Richter 소개하기 (자연어 처리, GAN) (0) | 2022.08.05 |
---|---|
[Machine Learning & Data Engineering] 시집 데이터를 분류해 추천하는 서비스를 웹으로 구현해보기 - 후기 (0) | 2022.06.28 |
[Machine Learning & Data Engineering] 시집 데이터를 분류해 추천하는 서비스를 웹으로 구현해보기 - 1 (0) | 2022.06.28 |
[Machine Learning] 무엇이 미량영양소의 결핍을 야기하는가? (RandomForestClassifier) -2 (0) | 2022.06.14 |
[Machine Learning] 무엇이 미량영양소의 결핍을 야기하는가? - 1 (0) | 2022.06.13 |