Skip to content

유사한 경주 관광지를 추천하는 Android App

Notifications You must be signed in to change notification settings

Na-Jinji/proj_130

Repository files navigation

1. Introduction

이짝워뗘

  • 개발기간 : 2020.12.26 ~ 2021.03.30
  • 개발인원 : 3명

[ 프로그램 소개 ]

이짝워뗘는 경주 관광지에 대한 정보 제공 및 추천 시스템을 제공해주는 애플리케이션입니다.

사용자는 카카오계정을 통해서 로그인과 로그아웃을 진행할 수 있고, 검색 시스템을 통해 입력한 키워드가 포함된 관광지 결과를 얻을 수 있습니다. 관광지를 선택하게 되면 해당 관광지와 유사한 5개의 관광지를 추천받을 수 있고 각 관광지에 대한 관련 정보를 볼 수 있습니다. 그리고 관광지에 대한 북마크를 진행할 수도 있고 이를 북마크 탭에서 따로 볼 수 있습니다.

이 외에도 사용자 정보 편집 기능과 관광지에 대한 정보를 공유하는 기능을 제공하고 있습니다.

[ 프로그램 흐름도 ]

image

2. Development Stack

  • Python 3.7
  • Flask
  • Android Studio
  • Docker
  • Spring Boot
  • MySQL
  • Nginx

3. Features

Search & Display

처음 화면에서 경주 관광지를 검색하면 다음과 같이 관련 관광지 목록이 뜹니다.

관광지와 유사한 관광지 5곳을 추천합니다.

관광지 중 한 곳을 선택하면 다음과 같이 관광지 관련 정보를 볼 수 있습니다.

관광지 페이지에서 공유 버튼을 클릭하면 다음과 같이 공유할 수 있고, 공유 화면은 앱 내의 관광지 정보를 그대로 담은 웹 페이지입니다.

Bookmark

관광지 페이지에서 북마크 등록 및 해제를 할 수 있습니다.

북마크를 등록하게 되면 북마크 탭에서 북마크 등록 현황을 확인할 수 있습니다. 북마크를 2초 이상 꾹 누르면 북마크 탭에서도 북마크를 해제할 수 있습니다.

MyPage

마이 페이지 탭을 클릭하면 내 정보를 볼 수 있습니다. My 편집을 클릭하면 나이, 주소, 성별을 수정할 수 있습니다.

4. Recommendation System

경주 관광지 추천 시스템은 사용자가 하나의 관광지명을 입력하면 이와 유사한 5개의 경주 관광지들을 추천해주는 추천 시스템입니다.

[ 추천 시스템 서버 ]

추천 시스템 서버는 Flask로 개발하였고, 앱 서버로 관광지 추천 요청이 들어오면 앱 서버가 추천 시스템 서버에 요청하도록 구현하였습니다.


[ 추천 시스템 로직 ]

각각 경주 관광지의 특징들을 명사(noun), 대명사(pronoun), 동사(verb)로 표현한 특징 리스트를 생성하여 data.csv 파일로 저장하였습니다. 추천 시스템을 생성할 때 csv 파일에서 '카테고리(category)', '관광지명(title)', '특징 리스트(tag)'를 추출합니다. 관광지마다 해당 카테고리와 특징 리스트를 하나의 text 문장으로 합친 뒤에 Scikit-Learn의 CountVectorizer를 통하여 문장 간 유사도를 구합니다. CountVectorizer는 문서 목록에서 각 문서의 feature (문장의 특징) 노출수를 가중치로 설정한 BOW(Bag Of Words) 벡터를 생성하는 API입니다. CountVectorizer의 fit_tranform을 호출하여 각 관광지의 문장에서 노출되는 feature 수를 합한 DTM(Document Term Matrix)를 생성합니다. 여기서 경주 관광지들의 DTM은 shape가 (330, 878)입니다. 이 DTM을 이용하여 코사인 유사도(cosine similarity)를 구하면 get_recommendations이 호출될 때마다 코사인 유사도 중 해당 관광지명 인덱스에 해당하는 값에서 추천 개수만큼 뽑아냅니다. 이때 본인 관광지는 제외됩니다.

    class Model:
        def __init__(self, tokenizer=None):
            gyeongju_data = pd.read_csv('model/data.csv')
            self.metaData = gyeongju_data[['category', 'title', 'tag']].drop_duplicates()
            self.metaData['soup'] = self.metaData.apply(create_soup, axis=1)

            # 이름:index - 예) 로라커피:0, 이스트앵글:1
            self.indices = pd.Series(self.metaData.index, index=self.metaData['title']).drop_duplicates()

            # BOW 인코딩
            if tokenizer:
                count = CountVectorizer(analyzer='word', tokenizer=tokenizer.morphs)
            else:
                count = CountVectorizer(analyzer='word')
            count_matrix = count.fit_transform(self.metaData['soup'])

            # 코사인 유사도 구하기
            self.cosine_sim2 = cosine_similarity(count_matrix, count_matrix)

            # index 초기화
            self.metaData = self.metaData.reset_index()
            self.indices = pd.Series(self.metaData.index, index=self.metaData['title'])

get_recommendations의 기본 로직은 이렇습니다.

  1. 관광지명이 들어오면 관광지 이름을 가지고 있는 index를 뽑아냅니다.
  2. 코사인 유사도 중 관광지 이름에 해당하는 리스트인 sim_scores를 추출합니다.
  3. sim_scores를 내림차순으로 정렬합니다.
  4. sim_scores에서 본인을 제외한 상위 5개를 뽑아낸 뒤 해당 score의 관광지명들을 리턴합니다.
   # 5개의 추천리스트 가져오기
    def get_recommendations(self, title):
        title = self.set_exact_title(title)
        if len(title) <= 0 or title == '':
            return []

        idx = self.indices[title]
        sim_scores = list(enumerate(self.cosine_sim2[idx]))  # 유사도 측정
        sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)  # 내림차순

        sim_scores = sim_scores[1:6]  # 5개
        attraction_indices = [i[0] for i in sim_scores]     # 장소 index
        scores = [i[1] for i in sim_scores]     # 유사도

        # debug
        for i in scores:
            print(i)

        result_data = self.metaData[['title', 'tag']].iloc[attraction_indices]
        result_data['scores'] = np.array(scores)
        return result_data['title'].values.tolist()

5. Server

애플리케이션 서버는 Spring Boot로 개발하였고, MySQL을 사용하였습니다. AWS EC2, RDS, S3를 이욯하고 있으며, Docker로 서버를 배포하였습니다. 이미지의 경우 s3에 저장해서 외부 접근을 허용하였습니다.

서버 구조는 아래의 [ 애플리케이션 서버 구조 ]와 같고 애플리케이션 서버에서 처리하는 주된 기능은 다음과 같습니다.

추천 시스템 서버은 [ 추천 시스템 서버 ]를 참고하세요.

[ 사용자 ]

  • 사용자 회원가입 및 로그인
  • 사용자 정보 업데이트

[ 관광지 ]

  • 추천 관광지 목록 요청
  • 관광지 목록 가져오기 및 관광지 정보 표시

[ 북마크 ]

  • 북마크 저장 및 삭제

[ 애플리케이션 서버 구조 ]

6. Source

  • 경주 관광지의 이미지들은 구글 썸네일 이미지로부터 수집하였습니다.
  • 경주 관광지의 카테고리(카페,명소,음식), 관광지명, 주소, 위치 정보(위도,경도), 전화번호, 홈페이지주소, 상세정보는 경주시청에서 운영하는 경주문화관광 웹사이트에서 수집하였습니다.

경주문화관광 : https://www.gyeongju.go.kr/tour/index.do

7. Youtube

유튜브 링크 : https://youtu.be/gbRaGe59YAo

8. People

About

유사한 경주 관광지를 추천하는 Android App

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages