- 사용자의 요청을 GCP(클라우드)의 Flask로 받고, Pretrained AI Model로 구간별 미래 속도 데이터를 추론합니다.
- 동적 환경에서 최단 경로를 찾을 수 있도록 구현한 A* 알고리즘과 구간별 미래 속도 데이터를 활용하여
최단 시간 경로와최단 ETA를 구할 수 있습니다. 최단 시간 경로와최단 ETA를 json 형태로 사용자에게 응답을 보냅니다.
다음의 인공지능 모델은 추론 요청 전 1시간 동안의 구간별 속도 데이터를 통해 미래의 1시간 속도 데이터를 구할 수 있습니다.
해당 인공지능 모델을 AI-Based-ETA 캡스톤 프로젝트에 사용한 이유는 다음과 같습니다.
- 32-layer의
TCN 모듈,GCN 모듈그리고Residual connection을 사용하여 빠른 학습과 빠른 추론이 가능합니다. - 시간적 의존관계와 공간적 의존관계를 포착하기 때문에 다른 인공지능 모델에 비해 높은 성능을 갖고 있습니다.
- 인기있는 모델이기 때문에 참고할 수 있는 자료가 많아서 트러블슈팅에 유리합니다.
This is the original pytorch implementation of Graph WaveNet in the following paper: [Graph WaveNet for Deep Spatial-Temporal Graph Modeling, IJCAI 2019] (https://arxiv.org/abs/1906.00121). A nice improvement over GraphWavenet is presented by Shleifer et al. paper code.
구간별 속도는 시간에 따라 동적으로 변화합니다. 따라서 동적 환경에서 최단 시간 경로와 ETA를 구하기 위해 A* 알고리즘을 직접 구현하였습니다.
A* 알고리즘의 핵심 로직의 다음 3가지 입니다.
첫 번째는 heurisitc함수를 통한 경로 탐색 보정 입니다.
Dijkstra, BFS, DFS 등을 사용한 경로탐색은 목적지까지 원하는 노드에 도달하기 위해, 방향과 상관없는 노드를 탐색하지만, heuristic함수를 사용한 A*는 그렇지 않습니다.
출발지와 목적지의 위도와 경도를 사용한 heuristic함수를 통해, 출발지에서 목적지까지 원하는 방향의 노드들만 탐색해 경로를 찾을 수 있습니다.(유클리드 distance 사용)
### 휴리스틱 함수
def heuristic(node1, node2, node_info):
lat1, lng1 = node_info[node1]
lat2, lng2 = node_info[node2]
return math.sqrt((lat1 - lat2) ** 2 + (lng1 - lng2) ** 2)
두 번째는 시간에 따라 변화는 속도를 current_time을 기준으로 vms_timetable_df에서 찾고, 구간별 거리에 나눠서 경과 시간(동적 가중치)를 구합니다.
# 통행 시간 계산
speed = get_speed_data_for_time(current_time, vms_timetable_df, current_node)
distance_km = distance / 1000 # 단위 맞추기
time_a = distance_km / speed # 시간 = 거리 / 속도(속력)
time_elapsed = time_a * 3600 # 초로 변환
next_time = current_time + timedelta(seconds=time_elapsed)
next_time = round_time_to_nearest_5_minutes(next_time)
세 번째는 Sliding Window 기법을 활용하여, 미래 속도 데이터가 추가로 필요할 때마다 인공지능으로 구하였습니다.
if current_time - last_request_time >= timedelta(hours=1) + timedelta(minutes=5):
last_request_time += timedelta(hours=1)
vms_timetable_df = request_speed_data(last_request_time)
사용자의 요청인 출발지, 도착지, 시각을 받고, 인공지능과 A* 알고리즘으로 구한 최단 시간 경로와 ETA를 json 형태로 응답을 반환합니다.
@app.route('/find_path', methods=['POST'])
def find_path():
요청 받은 노드 정보들을 json 형태로 가져 옵니다.
@app.route('/get-node-info', methods=['POST'])
def get_node_info():
인공지능 모델이 구간 별로 horizon(5분 단위) 1 ~ 12까지 총 60분 추론하였습니다.
A* 알고리즘을 통해 구한 최단 시간 ETA와 경로는 다음과 같고, total_hours: 0, total_minutes: 55, total_seconds: 0으로 총 55분 거렸습니다.
다음은 동일 시각의 네이버 길찾기를 통해 구한 결과입니다.
인공지능 모델은 한번에 구간 별로 horizon(5분 단위) 1 ~ 12까지 총 60분 추론까지 추론하는데, 서울시청 ~ 부산시청는 4시간 이상 걸리기 때문에 총 5번 추론하였습니다.
1번째 추론
5번째 추론
첫 번째 추론과 마지막 추론을 비교하면, 추론을 길게 할 수록 정확도가 낮아지는 것을 알 수 있습니다.
A* 알고리즘을 통해 구한 최단 시간 ETA와 경로는 다음과 같고, total_hours: 4, total_minutes: 10, total_seconds: 0으로 총 4시간 10분 걸렸습니다.
다음은 동일 시각의 네이버 길찾기를 통해 구한 결과입니다.
AI 개발환경의 python3 version은 3.6, ubuntu 20.0.4의 deafult python3 version은 3.8로 version이 상이함
때문에, flask를 실행시킬 가상환경 내부에서는 3.8이 아닌, 3.6을 사용해야 하므로, 3.6을 default로 설정함
각 팀원이 Flask에 접근할 수 있게 공유할 수 있는 폴더를 chmod 2775로 생성
폴더 생성 후 group 생성 하여 팀원의 user ID 추가 후, 공유 폴더의 소유자를 group으로 변경함
flask Server를 Run 시킬 때, virtual Enviroment 없이 실행시키는 경우 fatal error가 발생하는 경우 대처가 어려울 수 있어 virtual enviroment를 source /home/shared/venv/bin/activate를 통해 가상 환경 활성화 후 flask 실행
이후, deactivate를 통해 가상 환경 종료
