이번에는 3학년 1학기에 진행했던 전공 심화 프로젝트에 대해 포스팅해보고자 한다.
2학년까지 자료구조, 알고리즘 등 기본적인 프로그래밍 공부를 했다면,
이번 학기부터는 본격적으로 인공지능에 대해서 배우게 되었다.
이번에 "머신러닝"이라는 과목을 수강하게 되면서, 해당 과목에서 배운 머신러닝 기술을 적용한 실용가능한 앱을 구축하고자 했다.
<STEP 1> : 프로젝트 주제 정하기
같은 수업을 듣는 학과 친구들과 팀을 꾸려 먼저 주제에 대해 토의를 해보았다.
여러 가지 주제를 이야기해보고 각 주제 별로 필요한 데이터를 서칭해보았다.
공공데이터포털, AI-Hub, Kaggle 등 다양한 사이트에서 필요한 데이터를 서칭해보았는데, 생각보다 이 작업이 오래 걸렸다. 인공지능을 학습시키기 위해서 여러 feature들의 데이터가 필요한데, 우리의 목적에 딱 알맞는 데이터가 쉽게 찾아지지 않다. 그 가운데 '날씨 예보에 따른 놀러가기 좋은 관광지 추천'에 대한 주제를 가지고 데이터를 찾아보게 되었고, 기상청의 기상 데이터를 csv로 다운받을 수 있다는 점과, 공공데이터포털의 "기상청_관광코스별 관광지 상세 날씨 조회서비스"의 데이터에서 관광지별 날씨를 알 수 있다는 점을 고려하여 해당 주제를 프로젝트 주제로 선정하게 되었다. 자세한 아이디어 개요는 아래와 같다.
# 프로젝트 아이디어
- 데이터를 가공하여 주어진 날의 예보 정보에 따라 놀러가기 좋은 관광지를 추천해주는 인공지능을 구축한다.
- 사용자가 앱에 원하는 날짜와 시간을 입력하면, 입력받은 데이터를 인공지능에게 전달하여 해당 날짜와 시간에 놀러가기 좋은 관광지를 사용자에게 보여준다.
<STEP 2> : 프로젝트 구현 구체화
주제와 사용할 데이터가 정해졌으니, 이제는 프로젝트 구현을 어떻게 할 것인지 구체화를 해야한다.
[1] 데이터를 인공지능 학습에 사용할 수 있도록 가공한다. (feature과 label csv 파일 구축)
[2] 날씨 정보에 따라 해당 날씨가 놀러가기 좋은 날씨인지를 알려주는 인공지능을 구축한다.
(ex) 주어진 정보 [온도: 30도 / 강수확률: 50% / 강수량: 1mm 등] -> 5점의 날씨(10점 만점 기준)
주어진 정보 [온도: 25도 / 강수확률: 10% / 강수량: 0.5mm 등] -> 8점의 날씨(10점 만점 기준)
[3] 안드로이드 스튜디오에서 사용자로부터 원하는 날짜와 시간을 입력받고, 인공지능으로부터 추천받은 관광지를 보여줄 수 있 는 앱을 구축한다. 입력받은 날짜를 socket을 사용하여 파이썬 파일로 전송한다.
[4] 파이썬 파일에서 전달 받은 날짜의 모든 관광지에 대한 예보 데이터를 공공데이터포털에서 API를 사용하여 가져온다.
(ex) (가평)남이섬 [온도: 30도 / 강수확률: 50% / 강수량: 1mm 등]
(서울)월드컵공원 [온도: 25도 / 강수확률: 10% / 강수량: 0.5mm 등]
[5] 각 관광지의 날씨를 [2]의 인공지능에 넣어 입력받은 날짜의 관광지별 날씨 점수를 알아낸다.
(ex) (가평)남이섬 [온도: 30도 / 강수확률: 50% / 강수량: 1mm 등] -> 5점의 날씨(10점 만점 기준)
(서울)월드컵공원 [온도: 25도 / 강수확률: 10% / 강수량: 0.5mm 등] -> 8점의 날씨(10점 만점 기준)
[6] 가장 높은 날씨 점수를 받은 관광지명을 socket을 통해 안드로이드 스튜디오로 보내준다.
[7] 안드로이드 스튜디오에서 전달 받은 관광지명을 사용자가 볼 수 있게 화면에 띄워준다.
<STEP 3> : 프로젝트 구현
팀원들이 각자 구현할 부분을 나누었는데, 나는 데이터 가공과 인공지능 구축을 담당하였다.
# 학습 데이터 가공 (feature 추출)
우리는 공공데이터포털에서 제공되는 "기상청_관광코스별 관광지 상세 날씨 조회서비스"의 데이터를 사용했다. [링크] https://www.data.go.kr/data/15056912/openapi.do
기상청_관광코스별 관광지 상세 날씨 조회서비스
관광코스별 관광지의 동네예보, 기상지수예보, 시군구별 관광기후지수 정보를 조회하는 서비스
www.data.go.kr
위의 링크에 들어가서 참고문서를 확인하면, 제공하는 데이터에 대한 정보를 알려주는 '오픈API활용가이드'를 발견할 수 있다.
API와 JSON을 처음 접해본 나는 해당 내용을 잘 이해할 수 없어, 검색을 해보며 알아갔다.
아래의 링크는 내가 API와 JSON을 이해하는 데 도움을 준 링크이다.
API과 JSON 파일 보는 방법을 알고 오픈API활용가이드를 보니 어떤 구성으로 되어있으며 어떤 특징값들을 제공해주는 지 알 수 있었다.
[api 데이터 사용 설명링크] https://andjjip.tistory.com/108
[Python] 공공데이터 api로 데이터 가져오기
공공 데이터 활용 공공데이터 신청하기 공공데이터 포털은 공공기관이 생성 또는 취득하여 관리하고 있는 공공데이터를 한 곳에서 제공하는 통합 창구이다. 파일데이터, 오픈API, 시각화 등 다
andjjip.tistory.com
우리가 사용할 API에서는 '관광 테마', '관광지점 지역이름', '코스 지역이름' 등 다양한 정보를 제공하였지만, 우리는 그중에서 '예보시각(tm)', '관광지명(spotName)', '3시간 기온(th3)', '풍속(ws)', '하늘상태(sky)', '습도(rhm)', '강수확률(pop)'의 데이터만을 가져올 예정이다. 그 중에서도 '예보시각(tm)'값이 우리가 원하는 날짜와 시간대에 일치하는 데이터만 다시 골라낼 수 있게 코드를 작성하였다. 이렇게 골라낸 데이터 파일은 csv로 내 컴퓨터에 저장하였다.
학습데이터를 구축할 예정이므로 과거의 날씨들을 가져오기 위해 원하는 날짜를 과거로 정해줬다.
위의 코드에서 원하는 날짜를 2020년 2월 21일 15시로 지정해줬기 때문에 해당 날짜의 모든 관광지의 날씨 정보가 two.csv에 담겨 내 컴퓨터에 저장되었다.
위의 코드에서 날짜만 변경하여, 과거의 2020년 1월~12월의 관광지별 날씨 정보를 가져왔다.
(파일명은 1월은 one.csv, 2월은 two.csv ~ 12월은 twelve.csv로 정했다.)
# 학습 데이터 가공 (label 생성)
- label 생성 아이디어
관광지별 날씨 정보를 가져왔다면, 이제 날씨 정보에 따라 놀러가기 좋은 날씨인지를 알려주는 지표를 label로 생성시켜줘야 한다. 해당 데이터는 제공된 곳이 없기 때문에 직접 만들기로 했다.
이 때 고려해야할 점이 있는데, 계절마다 놀러가기 좋다고 생각되는 날씨가 다르다는 것이다.
예를 들어, 똑같은 7도라는 온도값이 주어졌을 때, 해당 계절이 겨울이였다면 따뜻한 편에 속하기에 놀러가기 좋은 온도이지만, 봄이였다면 추운 날씨에 속하기 때문에 놀러가기 좋은 온도는 아니다. 따라서 우리는 봄, 여름, 겨울, 가을마다 기준을 달리하여 날씨점수를 계산해주기로 하였고, 이에 따라 인공지능 모델도 4개를 구축하기로 했다.
각 계절마다 평균 온도, 평균 습도 등의 정보를 찾아본 후, 해당 값을 놀러가기 좋은 날씨를 결정짓는 지표로 삼았다.
예를 들면, 여름 계절(6월,7월,8월)에서 30도 이하이면 1점을 더하고, 27도 아래면 추가로 1점을 더한다. 또한 강수량이 20과 40사이라면 1점을 더하고 0과 20사이라면 추가로 1점을 더 더하는 방식이다. 이렇게 구해진 날씨 점수는 놀러가기 좋을 수록 높은 값을 나타낸다.
- label 데이터 생성 구현
위에서 구했던 1월부터 12월의 날씨 정보를 담고있는 csv를 파이썬에 불러온 뒤, 계절마다 데이터를 묶어준다.
3~5월 데이터를 묶어 봄 데이터로, 6~8월 데이터를 묶어 여름데이터로, 9월~11월 데이터를 묶어 가을 데이터로, 12월~2월 데이터를 묶어 겨울데이터로 만들어준다.
여기서 인공지능 학습에 '관광지명(spotName)'과 '예보시간(tm)'은 feature로 필요 없으므로 여기서 두 feature을 제거한다.
label 생성 아이디어에서 말한 것과 같은 기준으로 각 날씨 정보에 따른 날씨 점수를 label로 생성해준다.
# 인공지능 학습 & 모델 저장
학습시킬 feature와 label이 준비되었으므로, 이제 학습만 시키면 인공지능 모델이 완성된다.
기계학습에서 배운 sklearn의 학습모델은 knn, 로지스틱 회귀, Decision Tree, SVM 등 다양해서 각 방법으로 학습시켜보고, 성능을 확인해보도록 했다. 준비한 데이터를 train 데이터와 test 데이터로 나누고 train 데이터로 학습한 인공지능에 test 데이터를 넣어봄으로써 성능을 확인할 수 있었다.
다양한 시도 끝에 우리는 "RandomForestRegressor"가 95%정도로 높은 성능을 보이는 것을 확인해볼 수 있었고, 해당 학습방법으로 모델을 학습시킨 후, dump를 사용해서 인공지능 모델을 저장시켜줬다.
# Server Code
이제 안드로이드에서 사용자가 입력한 날짜와 시간을 socket으로 전송받아, 해당 날짜에 놀러가기 좋은 관광지를 다시 안드로이드 client로 보내주는 sever code를 작성해야 한다.
여기서 또 주의해야하는 점이 있다. 우리가 사용하는 데이터 API활용가이드를 확인해보면, 아래의 사진처럼 데이터가 업데이트된다는 점을 확인할 수 있었다. 따라서 우리는 모레까지의 예보 데이터만을 알 수 있기 때문에 사용자의 입력이 이보다 먼 시점을 가르킨다면 예외처리를 해주어야 했다.
아래의 코드까지가 socket으로 입력받은 날짜를 전달받고, 예외처리를 해준 것이다.
from socket import *
from datetime import datetime, timedelta
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')
while True:
#접속 승인
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) #원하는 날짜 정보
interval = (want_day_s - time1).days ## 오늘과 원하는 날짜의 차이 *2면 모레, 1이면 내일, 0이면 오늘 날씨 선택한 것
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()
예외처리되지 않은 날짜라면, 해당 날짜의 예보 정보를 API로부터 받아와야 한다.
이를 위해 필요한 형태로 입력받은 날짜를 바꾸어주었다.
pre_day_s = want_day + timedelta(days=-1)) #하루 전날 날짜 정보 받기
pre_day_s = pre_day_s[0:11]
pre_day_s = pre_day_s.replace('-','')
pre_day = pre_day_s + "00" #원하는 pre_day의 형태로 변환
want_day = want_day_s[0:17] #원하는 want_day 형태로 변환
알맞게 변형시킨 변수들을 사용하여 해당 날짜와 시간에 대한 관광지별 예보 정보 데이터를 입력받는다.
이는 위에서 학습데이터를 불러올때의 과정과 동일하다.
url = 'http://apis.data.go.kr/1360000/TourStnInfoService/getTourStnVilageFcst'
x_test = pd.DataFrame(columns=['tm','spotName','th3','wd','ws','sky','rhm','pop'])
for ID in range(1,439):
No = [29, 248, 249, 250]
if ID in No:
continue
course_id = str(ID)
queryString = "?" + \
"ServiceKey=" + "zrU%2F52hDqUJPfwfjNuG6P%2B2tv5%2BkSak2ejvJtORt8ZOm26oHVdqgoC0hL5wsAwo5xniSldSosXbSR6dD5St5Pw%3D%3D" + \
"&pageNo=" + "1"+ \
"&numOfRows=" + "140" + \
"&dataType=" + "JSON" + \
"&CURRENT_DATE=" + pre_day + \
"&HOUR=" + "24" + \
"&COURSE_ID=" + course_id
queryURL = url + queryString
response = requests.get(queryURL)
print(queryURL)
r_dict = json.loads(response.content)
data = json_normalize(r_dict['response']['body']['items']['item'])
#print(data.info())
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]
#print(data.info())
#오전 오후 저녁 시간선택에 맞는 데이터만 추출
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)
data = data.drop(['wd'],axis = 1)
#print(data.head())
x_test = x_test.append(data,ignore_index=True)
#print(x_test.head())
print(x_test.info())
이제 입력받은 날짜의 월에 따라 맞는 계절의 인공지능 모델을 불러온 후, 예보 데이터를 모델의 입력값으로 준다.
그럼 해당 인공지능은 예측된 날씨점수를 반환할 것이고, 그 중 가장 높은 점수를 보이는 관광지명을 socket을 통해 안드로이드로 전송시키면 된다.
x_test_spotName = x_test['spotName']
x_test = x_test.drop(['spotName','tm'],axis=1)
month = int(want_day[6:8])
spring_m = [3,4,5]
summer_m = [6,7,8]
fall_m = [9,10,11]
winter_m = [12,1,2]
if(month in spring_m):
automl = load('Spring.joblib')
y_predict = automl.predict(x_test)
if(month in summer_m):
automl = load('Summer.joblib')
y_predict = automl.predict(x_test)
if(month in fall_m):
automl = load('Fall.joblib')
y_predict = automl.predict(x_test)
if(month in winter_m):
automl = load('Winter.joblib')
y_predict = automl.predict(x_test)
Index = y_predict.index(max(y_predict))
res = x_test_spotName[Index]
##############################################
#수신한 데이터 컨트롤
#res = "학습 모델에 테스트 데이터 넣어서 나온 추천 관광지 보내기"
print("추천 지역 :" , res)
#클라이언트에게 답을 보냄
conn.sendall(res.encode("utf-8"))
#연결 닫기
conn.close()
s.close()
여기까지가 이번 프로젝트에서 내가 담당한 부분이다.
#후기
API, JSON 등 처음 접하는 것들이 많아서 공부가 많이 필요했다.
하지만 이로 인해 다양한 것을 사용해보고 알아갈 수 있어서 뿌듯하다.
이 프로젝트를 진행했을 때는 아직 머신러닝에 대해만 공부했던 시기라,
시간이 날 때 다른 인공지능 학습 방법으 적용시켜 보고싶다.
그리고 아쉬웠던 것은 좋은 날씨임을 알 수 있는 지표 데이터가 없어서 직접 만들어야 했다는 점이다.
우리가 나름 고심하여 기준을 세웠지만 더 명확한 기준이 있었으면 좋았을 것 같다.
더 좋은 프로젝트를 진행하기 위해 다양한 인공지능 기술들을 공부하고 데이터 가공방법을 생각해보자.
'2021년' 카테고리의 다른 글
[소프트웨어야 놀자] 대학생 멘토단 '딩가딩가' (0) | 2022.08.01 |
---|---|
<Q-learning> 세종 캠퍼스 내 최적 경로 안내 서비스 (0) | 2022.08.01 |
<CNN> 음성 인식을 통한 응급 상황 감지 AI 구현 (5) | 2022.07.31 |