Project | Weather Tour Application

Table of Contents

[ Project ] 2021 Weather Tour Application ์˜ค๋Š˜ ์—ฌํ–‰ํ•˜๊ธฐ ๋”ฑ ์ข‹์€ ๊ตญ๋‚ด ๊ด€๊ด‘์ง€ ์ถ”์ฒœ ์•ฑ ๋งŒ๋“ค๊ธฐ

Project

2021-1 ์ „๊ณต์‹ฌํ™”ํ”„๋กœ์ ํŠธ

๐ŸŒฟ Background

(2021 4์›” ๊ธฐ์ค€) COVID 19๋กœ ์ธํ•ด ๊ตญ๋‚ด ์—ฌํ–‰์„ ๋– ๋‚˜๋ ค๋Š” ์‚ฌ๋žŒ์ด ๋Š˜์–ด๋‚˜๊ณ  ์žˆ๋‹ค. ์œ„์˜ ๊ทธ๋ฆผ์€ ํ•œ๊ตญ๋ฌธํ™”๊ด€๊ด‘์—ฐ๊ตฌ์›์—์„œ ์‹ค์‹œํ•œ 2020๋…„ 2~4์›”์— ๋Œ€ํ•œ ์‘๋‹ต๊ณผ 2021๋…„ 1~3์›”์˜ ์‘๋‹ต์— ๋Œ€ํ•œ ํ†ต๊ณ„์ž๋ฃŒ๋กœ, ์ฝ”๋กœ๋‚˜19 ์ดํ›„ 2021 1๋ถ„๊ธฐ์— ๊ตญ๋‚ด์—ฌํ–‰ ๋น„์œจ์ด 51.8%๋กœ ์ฆ๊ฐ€ํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์€ ํ•™์ƒ ๋˜๋Š” ์ง์žฅ์ธ์˜ ์‹ ๋ถ„์œผ๋กœ ์‹œ๊ฐ„/๊ณต๊ฐ„ ์ƒ์—์„œ ์ž์œ ๋กญ์ง€ ๋ชปํ•˜๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ด๋“ค์€ ์—ฌํ–‰์„ ๋– ๋‚  ์ˆ˜ ์žˆ๋Š” ๋‚ ์ด ํ•œ์ •์ ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ๊ตญ๋‚ด ๊ด€๊ด‘์ง€์˜ ๋‚ ์”จ๋ฅผ ๋ฏธ๋ฆฌ ์•Œ์•„๋‚ด์–ด ์›ํ•˜๋Š” ๋‚ ์งœ์— ๊ฐ€์žฅ ์—ฌํ–‰ํ•˜๊ธฐ ์•Œ๋งž์€ ๊ด€๊ด‘์ง€๋ฅผ ์ถ”์ฒœํ•ด์ฃผ๋Š” ์•ฑ์„ ๊ตฌ์ƒํ•˜์˜€๋‹ค.

๐Ÿ”Ž About Project

  • ๊ธฐ๊ฐ„ : 2021.04.26 ~ 2021.06.11
  • ์ „๊ณต์‹ฌํ™”๊ณต๋™์ฒด๋ฅผ ์ด๋ฃจ์–ด ์ „๊ณต์—์„œ ๋ฐฐ์šด ์ง€์‹์„ ์‹ฌํ™”ํ•˜์—ฌ ํ”„๋กœ์ ํŠธ ์ง„ํ–‰
    • ์ „๊ณต์‹ฌํ™”๊ณต๋™์ฒด : ์ „๊ณต ๊ด€๋ จ ๊ต๋‚ด์™ธ ๊ณต๋ชจ์ „ ๋ฐ ๋Œ€ํšŒ ์ค€๋น„, ์ „๊ณต ๊ด€๋ จ ์ž๊ฒฉ์ฆ ์ทจ๋“, ์ „๊ณต ์ง€์‹ ์‹ค๋ฌด ์—ฐ๊ตฌ ๋ฐ ๊ฐœ๋ฐœ, ์†Œ๋…ผ๋ฌธ ์ž‘์„ฑ ๋“ฑ์„ ์œ„ํ•œ ๋™์ผ ์ „๊ณต์ƒ์œผ๋กœ ๊ตฌ์„ฑ๋œ ํ•™์Šต๊ณต๋™์ฒด

์„ ํƒ ์ „๊ณต๊ณผ๋ชฉ

๐Ÿค– ๋จธ์‹ ๋Ÿฌ๋‹ (๊ต๊ณผ๋ชฉ : ๊ธฐ๊ณ„ํ•™์Šต) + ๐Ÿ“ก Socket programming (๊ต๊ณผ๋ชฉ : ์ปดํ“จํ„ฐ ๋„คํŠธ์›Œํฌ)

๋ฐ์ดํ„ฐ์…‹

  • ๊ธฐ์ƒ์ฒญ ์ง€์ƒ(์ข…๊ด€, ASOS) ๋ฐ์ดํ„ฐ

  • ๊ณต๊ณต๋ฐ์ดํ„ฐ ๊ธฐ์ƒ์ •๋ณด API (๊ธฐ์˜จ, ํ’์†, ํ•˜๋Š˜์ƒํƒœ, ์Šต๋„, ๊ฐ•์ˆ˜ํ™•๋ฅ )

    • ๊ด€๊ด‘์ฝ”์Šค๋ณ„ ๊ด€๊ด‘์ง€ ์ƒ์„ธ ๋‚ ์”จ ์กฐํšŒ์„œ๋น„์Šค

โžก๏ธ ๊ณ„์ ˆ๋งˆ๋‹ค ์กฐ๊ฑด ์„ธ๋ถ„ํ™” ํ›„ ์ ์ˆ˜ ์ฑ…์ •

๐Ÿ† ํ”„๋กœ์ ํŠธ ๊ฒฐ๊ณผ

์ตœ์šฐ์ˆ˜์ƒ

๋งก์€ ์—ญํ• 

  • ์ธ๊ณต์ง€๋Šฅ ์ฝ”๋“œ
  • ํŒŒ์ด์ฌ ์†Œ์ผ“ ํ†ต์‹ 
  • ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค ์ฝ”๋“œ ๊ตฌํ˜„

๐Ÿ—‚ Reference

Q-learning์„ ๊ตฌํ˜„ํ•  ๋•Œ๋Š” Open Source๋ฅผ ์ด์šฉํ•˜์˜€๋‹ค.





๐Ÿง ๊ฐœ๋… ์„ค๋ช…





๐Ÿ’ป ๊ตฌํ˜„ ย ย Implementation

1. ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

import io
import pandas as pd
data_spring = pd.read_csv('spring.csv',encoding='CP949')
data_summer = pd.read_csv('summer.csv',encoding='CP949')
data_fall = pd.read_csv('fall.csv',encoding='CP949')
data_winter = pd.read_csv('winter.csv',encoding='CP949')

2. ๊ฒฐ์ธก์น˜ ์ œ๊ฑฐ

df_spring = df_spring.fillna(0)
df_summer = df_summer.fillna(0)
df_fall = df_fall.fillna(0)
df_winter = df_winter.fillna(0)
df_spring_test = df_spring_test.fillna(0)
df_sp=df_spring.drop(['์ง€์ ','์ผ์‹œ'],axis=1)
df_su=df_summer.drop(['์ง€์ ','์ผ์‹œ'],axis=1)
df_fa=df_fall.drop(['์ง€์ ','์ผ์‹œ'],axis=1)
df_wi=df_winter.drop(['์ง€์ ','์ผ์‹œ'],axis=1)
df_spring_test=df_spring_test.drop(['์ง€์ ','์ผ์‹œ'],axis=1)
train_spring = df_sp.drop('์ง€์ ๋ช…', axis=1)
train_summer = df_su.drop('์ง€์ ๋ช…', axis=1)
train_fall = df_fa.drop('์ง€์ ๋ช…', axis=1)
train_winter = df_wi.drop('์ง€์ ๋ช…', axis=1)
test_spring = df_spring_test.drop('์ง€์ ๋ช…',axis=1)

3. ๊ณ„์ ˆ๋ณ„ ๊ธฐ์ƒ ๊ด€์ธก ๋ฐ์ดํ„ฐ์— ๋”ฐ๋ผ ์ ์ˆ˜ ๋งค๊ธฐ๊ธฐ

๋ชจ๋“  ๊ณ„์ ˆ์— ๋Œ€ํ•ด ๊ฐ•์ˆ˜, ํ‰๊ท ๊ธฐ์˜จ, ์ƒ๋Œ€์Šต๋„, ํ‰๊ท ํ’์†๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ์ ์ˆ˜๋ฅผ ๋งค๊ฒจ์ฃผ์—ˆ๋‹ค. ์ด ๊ด€์ธก์น˜๋“ค์€ ๊ณ„์ ˆ๋งˆ๋‹ค ์ƒ์ดํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚˜๋ฏ€๋กœ ๊ณ„์ ˆ๋ณ„๋กœ ํ‰๊ท ๊ธฐ์˜จ์„ ๊ตฌํ•˜๊ณ  ์™ธ์ถœํ•˜๊ธฐ ์ข‹์€ ๊ธฐ์ƒ ์ •๋ณด๋ฅผ ๊ฐ๊ฐ ๊ตฌํ•ด์„œ ๊ธฐ์ค€์„ ์ •ํ•ด์ฃผ์—ˆ๋‹ค.

4. ๋ชจ๋ธ ํ•™์Šต ๋ฐ ์„ฑ๋Šฅ ๋น„๊ต

์ด๋ ‡๊ฒŒ ์ ์ˆ˜๋ฅผ ๋งค๊ฒจ์ค€ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ตํ•ฉํ•ด์„œ 7:3์˜ ๋น„์œจ๋กœ ๋ชจ๋ธ์— ํ•™์Šตํ•  ํ•™์Šต๋ฐ์ดํ„ฐ์™€ ํ‰๊ฐ€ ๋ฐ์ดํ„ฐ๋กœ ๋‚˜๋ˆ„์–ด์ฃผ์—ˆ๋‹ค.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(train_spring, y_label_spring, test_size=0.3, random_state=42)

์ด๋•Œ sklearn์˜ KNeighbors, SVM, Random Forest ๋ชจ๋ธ๋กœ ํ•™์Šตํ•ด๋ณด๊ณ  R2 score์„ ๊ธฐ์ค€์œผ๋กœ ์„ฑ๋Šฅ์„ ๋น„๊ตํ•˜์˜€๋‹ค.

ย  KNeighbors SVM Forest
R2 score 0.6986 0.6318 0.9558

โœ… Random Forest Regressor๊ฐ€ ๊ฐ€์žฅ ์„ฑ๋Šฅ์ด ๋†’์Œ

5. ์†Œ์ผ“ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

์›๋ž˜ ํ”„๋กœ์ ํŠธ์˜ ์ดˆ๊ธฐ ๋ชฉํ‘œ๋Š” 4๋ฒˆ๊นŒ์ง€์˜€๋‹ค. ํŒ€์›๋“ค๊ณผ ํ•จ๊ป˜ ์šฐ๋ฆฌ ์ƒํ™œ์— ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ์ฃผ์ œ๋ฅผ ๊ณจ๋ผ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ  ์ „์ฒ˜๋ฆฌ ํ›„, ๊ทธ๊ฒƒ์„ ์„ฑ๊ณต์ ์œผ๋กœ ์˜ˆ์ธกํ•ด์„œ ๊ด€๊ด‘์ง€๋ฅผ ์ถ”์ฒœํ•ด์ฃผ๋Š” ๊ฒƒ๊นŒ์ง€๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ง„ํ–‰์ด ๋๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์„œ ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  ํ•œ ๋ฒˆ ๋” ์ƒ๊ฐํ•˜๊ธฐ๋กœ ํ•˜์˜€๋‹ค.

ํ•ด๋‹น ํ•™๊ธฐ์— ์ปดํ“จํ„ฐ ๋„คํŠธ์›Œํฌ ๊ณผ๋ชฉ์—์„œ Socket Programming์˜ ๊ฐœ๋…์„ ๋ฐฐ์› ๋‹ค. ๋‚œ ๋ฐฑ์—”๋“œ๋ฅผ ๋ฐฐ์›Œ๋ณธ ์ ์€ ์—†์ง€๋งŒ ํ•ด๋‹น ํ†ต์‹  ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์•ฑ์œผ๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ๊ณ , ์ด๋ฅผ ๊ตฌํ˜„ํ•ด๋‚ด์—ˆ๋‹ค.

์•„๋ž˜์— ์ผ๋ถ€ ์ฝ”๋“œ๋ฅผ ์˜ฌ๋ ค๋†“๊ฒ ๋‹ค.


[ Server ]

from socket import *
from datetime import datetime, timedelta
import numpy as np
HOST = ""
PORT = 12000
s = socket(AF_INET, SOCK_STREAM)
print ('Socket created')
s.bind((HOST, PORT))
print ('Socket bind complete')
s.listen(1)
print ('Socket now listening')
#์ ‘์† ์Šน์ธ
conn, addr = s.accept()
print("Connected by ", addr)

#๋ฐ์ดํ„ฐ ์ˆ˜์‹ 
rc = conn.recv(1024)
rc = rc.decode("utf8").strip()
if not rc: break
print("Received: " + rc)
date=rc[0:8]
time=rc[8:]
print('date:',date)
print('time:',time)
#ํ˜„์žฌ ๋‚ ์งœ ์ •๋ณด
time1 = datetime.now() 
#์›ํ•˜๋Š” ๋‚ ์งœ ์ •๋ณด 
want_day_s = datetime(int(rc[0:4]),int(rc[4:6]),int(rc[6:8]),int(rc[8:10]),0,0) 

# ์˜ค๋Š˜๊ณผ ์›ํ•˜๋Š” ๋‚ ์งœ์˜ ์ฐจ์ด 
# 2๋ฉด ๋ชจ๋ ˆ, 1์ด๋ฉด ๋‚ด์ผ, 0์ด๋ฉด ์˜ค๋Š˜ ๋‚ ์”จ ์„ ํƒํ•œ ๊ฒƒ
interval = (want_day_s - time1).days 

#๋ชจ๋ ˆ๋ฅผ ์„ ํƒํ–ˆ๋Š”๋ฐ ํ˜„์žฌ ์‹œ๊ฐ์ด ์ƒˆ๋ฒฝ ์—ฌ์„ฏ์‹œ ์ „์ด๋ฉด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ
if(interval == 2) and (int(time1[12:14]) <= int(6)): 
    res = "์ƒˆ๋ฒฝ 6์‹œ ์ดํ›„ ๋ชจ๋ ˆ ๋‚ ์”จ ์ •๋ณด๊ฐ€ ์—…๋ฐ์ดํŠธ ๋ฉ๋‹ˆ๋‹ค!"
    conn.sendall(res.encode("utf-8"))
    conn.close()
    s.close()
    exit()

#์˜ค๋Š˜, ๋‚ด์ผ, ๋ชจ๋ ˆ ์ด์™ธ์˜ ์„ ํƒ์„ ํ–ˆ์„ ์‹œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ธฐ
if(interval != 1) and (interval != 0) and (interval != 2): 
    res = "์˜ค๋Š˜, ๋‚ด์ผ, ๋ชจ๋ ˆ์˜ ์˜ˆ๋ณด๋งŒ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค!"
    conn.sendall(res.encode("utf-8"))
    conn.close()
    s.close()
    exit()

#ํ•˜๋ฃจ ์ „๋‚  ๋‚ ์งœ ์ •๋ณด ๋ฐ›๊ธฐ
pre_day_s = want_day_s + timedelta(days=-1) 

pre_day_s=str(pre_day_s)
pre_day_s=pre_day_s[:11]
pre_day_s=pre_day_s.replace('-','')

want_day_s=str(want_day_s)

#์›ํ•˜๋Š” pre_day์˜ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
pre_day = pre_day_s + "00" 
print('pre_day_s',pre_day_s)

#์›ํ•˜๋Š” want_day ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
want_day = want_day_s[:16] 
print('want_day', want_day)

๋‹ค์Œ์€ ๊ธฐ์ƒ์ž๋ฃŒ๊ฐœ๋ฐฉํฌํ„ธ์—์„œ Open API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ

import pandas as pd
from pandas import json_normalize
import json
import requests
from bs4 import BeautifulSoup

url = 'http://apis.data.go.kr/1360000/TourStnInfoService/getTourStnVilageFcst'

x_test = pd.DataFrame(columns=['tm','spotName','th3','wd','ws','sky','rhm','pop'])

๋ฐœ๊ธ‰๋ฐ›์€ API ํ‚ค๋Š” ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์—…๋กœ๋“œํ•˜์˜€๋‹ค.

for ID in range(1,439):
    No = [29, 248, 249, 250]
    if ID in No:
        continue
    course_id = str(ID)
    queryString = "?" + \
      "ServiceKey=" + "0000000000000000" + \
      "&pageNo=" + "1"+ \
      "&numOfRows=" + "140" + \
      "&dataType=" + "JSON" + \
      "&CURRENT_DATE=" + pre_day + \
      "&HOUR=" + "24" + \
      "&COURSE_ID=" + course_id
      
    queryURL = url + queryString
    response = requests.get(queryURL)

    r_dict = json.loads(response.content)
    data = json_normalize(r_dict['response']['body']['items']['item'])

    li = ['tm','spotName','th3','wd','ws','sky','rhm','pop']
    
    #tm : ์„ ํƒํ•œ ์‹œ๊ฐ์œผ๋กœ ๋ถ€ํ„ฐ 3์‹œ๊ฐ„ ๊ธฐ์˜จ (์˜ˆ : 09๋ฉด 09-12)
    #wd : ํ’ํ–ฅ
    #ws : ํ’์†
    #sky: ํ•˜๋Š˜ ์ƒํƒœ
    # 1: ๋ง‘์Œ, 2: ๊ตฌ๋ฆ„ ์กฐ๊ธˆ, 3: ๊ตฌ๋ฆ„๋งŽ์ด, 4:ํ๋ฆผ, 5: ๋น„, 6:๋น„๋ˆˆ, 7:๋ˆˆ๋น„, 8:๋ˆˆ
    #rhm: ์Šต๋„
    #pop: ๊ฐ•์ˆ˜ํ™•๋ฅ 

    #ํ•„์š”ํ•œ column๋งŒ data์— ์ €์žฅ
    data = data.loc[:,li]
    
    #์˜ค์ „ ์˜คํ›„ ์ €๋… ์‹œ๊ฐ„์„ ํƒ์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋งŒ ์ถ”์ถœ
    List = []
    for i in range(0,len(data['tm'])):
        if want_day not in data.loc[i,'tm']:
                List.append(i)
    data = data.drop(List,axis = 0)
    x_test = x_test.append(data,ignore_index=True)
x_test = x_test.drop_duplicates(['spotName'], keep='first')


[ Client ]

์ด์ „ ๋žฉํƒ‘์— ์žˆ๋Š” ์ฝ”๋“œ๋Š” ์ถ”ํ›„ ์ž‘์„ฑํ•˜์—ฌ ์—…๋กœ๋“œํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.






์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ




โžก๏ธ ย ํ”„๋กœ์ ํŠธ๋ฅผ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ..

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ๋Š” ๊ธฐ๊ณ„ํ•™์Šต๊ณผ ์ปดํ“จํ„ฐ๋„คํŠธ์›Œํฌ ์ˆ˜์—…์„ ์ˆ˜๊ฐ•ํ•˜๋ฉด์„œ ํŒ€์›๋“ค๊ณผ ์Šค์Šค๋กœ ์‹ฌํ™”ํ•ด๋ณธ ํ”„๋กœ์ ํŠธ์˜€๊ธฐ ๋•Œ๋ฌธ์— ๋” ์˜๋ฏธ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

์ด๋ฏธ์ง€ ๋ฐ ์ž๋ฃŒ ์ถœ์ฒ˜

[์‹ค์‹œ๊ฐ„ ์ „๊ตญ ๋‚ ์”จ] ์˜คํ›„ 5์‹œ ํ˜„์žฌ ๋Œ€์ฒด๋กœ ํ๋ฆฌ๊ณ  ๊ณณ์— ๋”ฐ๋ผ ๋น„

ํ•œ๊ตญ๋ฌธํ™”๊ด€๊ด‘์—ฐ๊ตฌ์›

 

Related Posts



๐Ÿ’™ You need to log in to GitHub to write comments. ๐Ÿ’™
If you can't see comments, please refresh page(F5).