최종 프로젝트로 소개팅 코스를 추천해주는 소개팅 앱을 만들기로 하였다.
이용자가 어떤 키워드를 제시하면 이와 가장 유사한 소개팅 장소 등을 추천해주고, 이용자가 선택(체크)한 것들을 카카오 API 를 이용해서 최단경로를 추천해주는 것이 핵심 기능이다.
우리팀은 우선적으로 카카오의 블로그 검색 API를 활용하여 우리 프로그램에 사용될 데이터를 확보하기로 하였다.
from sklearn.feature_extraction.text import CountVectorizer # sklearn 설치, CountVectorizer : 문서를 token count matrix로 변환하는 클래스.
from sklearn.metrics.pairwise import cosine_similarity # sklearn 설치, cosine_similarity : 코사인 유사도를 계산해주는 클래스.
import pandas as pd # pandas 임포트
import json # json 임포트
from random import * # 랜덤 숫자를 위한 random 임포트
import requests # 웹 요청 임포트
from flask import Flask, request, jsonify, Response
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
@app.route('/contents')
def Contents_Based_Filtering():
input1 = request.args.get('region', "이문동")
input2 = request.args.get('theme', "음식점")
input3 = request.args.get('special', "일식")
theme = ['CT1', 'AT4', 'FD6', 'CE7'] # 테마 리스트 (CT1=문화시설,AT4=관광명소,FD6=음식점,CE7=카페)
# search = input('Please put keyword') # 지역 임시 인풋 값
realList = list() # 지역 인풋값 결과 json을 list에 저장하기 위해 초기화
for j in range(len(theme)): # 테마 4개 반복
for z in range(3): # 페이지 3개 반복
headers = {'Authorization': '', } # 내 다음 API KEY
params = (
('page', z + 1),
('size', '15'),
('sort', 'accuracy'),
('query', '서울 ' + input1), # '이문동'대신 안드로이드에서 검색한 값을 넣을 예정
('category_group_code', theme[j]),
) # rest API 파라미터
response = requests.get('https://dapi.kakao.com/v2/local/search/keyword.json', headers=headers,
params=params) # API 사용
realResult = response.json() # 출력 값 json화
# print(realResult)
if realResult['meta']['total_count'] == 0: # 결과 값이 없을때
continue # 페이지를 넘겨라
if realResult['meta']['is_end'] == True: # 페이지가 끝났을 때
del realResult['meta']
# realResult.pop('meta') # meta라는 key를 지우고
realResult = realResult.pop('documents') # document에 있는 value 값들을 꺼낸다
for k in range(len(realResult)):
del realResult[k]['distance'] # distance 키는 필요 없으니 제거
realList.append(realResult[k]) # 초기화 한 realList에 하나씩 추가
break # 페이지 끝났음으로 break
else: # 페이지가 안끝났다면
del realResult['meta']
# realResult.pop('meta') # meta라는 key를 지우고
realResult = realResult.pop('documents') # document에 있는 value 값들을 꺼낸다
for k in range(len(realResult)):
del realResult[k]['distance'] # distance 키는 필요 없으니 제거
realList.append(realResult[k]) # 초기화 한 realList에 하나씩 추가
for t in realList:
if t['category_group_name'] == input2: # 음식점에 대한 json만 추출
themeList.append(t) # themeList에 결과 json 추가
blogContentList = list() # 블로그 내용을 담아 감성 분석 처리를 하기위해 list 초기화
for nmList in placeNmList: # 장소 이름 개수로 돌림
headers = {'Authorization': 'KakaoAK e00921ac7c78ceabb295eec543d574f6', } # 내 다음 API KEY
params = (
('sort', 'accuracy'),
('page', '1'),
('size', '3'),
('query', input1 + " " + nmList), # '이문동'대신 안드로이드에서 검색한 값을 넣을 예정
) # rest API 파라미터
response = requests.get('https://dapi.kakao.com/v2/search/blog', headers=headers, params=params) # API 사용
blogAPI = response.json() # 출력 값 json화
del blogAPI['meta']
blogAPI = blogAPI.pop('documents') # document에 있는 value 값들을 꺼낸다
for blist in blogAPI: # contents와 title 컬럼만을 남기고 모두 제거
del blist['blogname']
del blist['datetime']
del blist['thumbnail']
del blist['url']
blogContentList.append(blist) # 초기화한 blogContentList에 json 추가
blogContentList.append('perforat1on')
dict_example = json.dumps(blogContentList, ensure_ascii=False)
result = str(dict_example)
result=result.replace(result[0], "", 1)
result=result[:-1]
result=result.replace(', "perforat1on"',"perforat1on")
result = result.replace("perforat1on, ", "perforat1on")
return result
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)
카카오 API를 활용하여 데이터들을 가져오는 코드
이를 통해 약 10만개에 가까운 숫자의 가게/블로그 게시글을 확보할 수 있었고 초기 계획은 이를 FireBase에 업로드하여 이용자가 검색하면 그 결과를 반환해주는 것이었다.
하지만 Firebase에 데이터들을 올리고 활용해본 결과, 검색 한번에 1분이상 걸렸기에 실제 사용은 불가능하단 판단을 내렸다.
다른 방법으로 자연어 처리를 통해 상호명과 해당 가게가 가지는 특징들을 연관지어 줄 수 있으면 좋겠다는 생각이 들었고 그러기 위해 우선적으로 토큰화를 시킬 필요가 있었고 0KT 형태소 분석기를 사용하기로 했다. 그전에 불용어 처리를 할 필요가 있었는데 안타깝게도 한국어에 대한 불용어가 정확하게 정의되어 있지 않는 상태이다. 인터넷에 나오는 불용어들도 서로서로 복사해가는 경우가 많아서 수집한 불용어들의 중복을 제거하고 나니 약 1500여개의 불용어 리스트가 만들어졌다. 그리고 데이터 사이사이에 있는 온갖 이모티콘들을 제거하는 것도 고된작업이었으나 확실히 이모티콘을 제거해야만 보다 정확도 높은 모델을 만들 수 있었다.
from konlpy.tag import Okt
import json
import numpy as np
import pandas as pd
train_data = pd.read_pickle("readDfMk05.pkl")
# 불용어 정의
stopwords = np.load('krStopword02.npy')
# 형태소 분석기 OKT를 사용한 토큰화 작업 (다소 시간 소요)
print('형태소 분석 시작')
okt = Okt()
tokenized_data = []
for sentence in train_data['contents']:
temp_X = okt.morphs(sentence, stem=True) # 토큰화
temp_X = [word for word in temp_X if not word in stopwords] # 불용어 제거
tokenized_data.append(temp_X)
with open("newStop_word01.json", "w") as f:
json.dump(tokenized_data, f, ensure_ascii=False)
이모티콘을 제거한 데이터를 readDfMk05 라는 피클 파일로 저장을 해두었고 불용어는 numpy 타입으로 krStopword02 로 저장해두었다.이 둘을 이용해서 한글 자연어 처리 패키지인 KoNLPy의 0kt 형태소 분석 툴을 이용해서 토큰화를 하였으며 이를 newStop_word01.json 파일로 저장하였다.
최종적으로 자연어 처리를 위한 오픈소스 라이브러리인 Gensim을 활용하여 word2Vec 모델을 만들었다.
Word2Vec란, 신경망 모델을 사용해서 단어간의 연관성을 학습하는 자연어 처리기술을 뜻하며, 상호를 중점으로 상관도가 높은 단어들을 학습시키기 위해 사용하였다.
import json
with open('newStop_word02.json', 'r') as f:
tokenized_data = json.load(f)
print(tokenized_data)
from gensim.models import Word2Vec
model = Word2Vec(sentences = tokenized_data, vector_size = 100, window = 5, min_count = 5, workers = 4, sg = 0)
model.wv.save_word2vec_format('modelMk03') # 모델 저장
Gensim의 word2vec 모델을 사용은 매우 간단하게 할 수 있으며 최종 모델을 modleMk03이란 이름으로 저장하였다.
이후에는 modelMk03만 불러와서 작업을 하였다.
'빅데이터교육과정 > Python' 카테고리의 다른 글
최종프로젝트 - AWS (0) | 2021.07.01 |
---|---|
최종 프로젝트 - 이미지 학습(1) (0) | 2021.07.01 |
DATA 긁어오기 (0) | 2021.05.25 |
파이썬 - 성적처리 (0) | 2021.04.24 |