4 분 소요

이 포스트는 AWS Deepracer 강의를 바탕으로 공부한 내용을 정리하였습니다.

Reward Function

기본 구조

  • 입력: 딕셔너리 객체
    • 시뮬레이션에서 일어나는 상태에 대한 정보가 담겨있다.

        def reward_function(params):
        	reward = ...
        	return float(reward)
      
  • 보상함수 예시

      import math
        
      def reward_function(params):
      # 1. 생존 보상 reward_survived 
          ########## [reward_survived] survived ########## 
          reward_survived = 1
            
      # 2. 트랙 위 안착 보상 reward_wheels 
           ########## [reward_wheels] all_wheels_on_track ########## 
          all_wheels_on_track = params['all_wheels_on_track']
          if all_wheels_on_track :
              reward_wheels = 1 
          else:
              reward_wheels = 0
            
      # 3. 속도 보상 reward_speed 
          ############## [reward_speed] speed #############
          speed = params['speed']
          reward_speed = speed / 4 
            
      # 4. 방향 보상 reward_direction 
          ############## [reward_direction] direction_diff #############
          waypoints = params['waypoints'] # 경로 좌표
          closest_waypoints = params['closest_waypoints']
          heading = params['heading']
            
          # 현재 에이전트와 가장 가까운 waypoint의 위치를 가져옵니다.
          next_point = waypoints[closest_waypoints[1]]
          prev_point = waypoints[closest_waypoints[0]]
        
          # track_direction 을 계산 
          track_direction = math.atan2(next_point[1] - prev_point[1], next_point[0] - prev_point[0])
          track_direction = math.degrees(track_direction)  
        
      	# 각의 차이 (direction_diff) 계산
          direction_diff = abs(track_direction - heading)
          if direction_diff > 180:
              direction_diff = 360 - direction_diff
            
          # 보상 결정
          direction_diff_rad = math.radians(direction_diff)
          reward_direction = math.cos(direction_diff_rad)
        
      # 4. 방향 보상 다른 버전
          x = params['x']
          y = params['y']
            
          steering_angle = params['steering_angle']
          steering_angle_rad = math.radians(steering_angle)
            
          heading = params['heading']
          heading_rad = math.radians(heading)
            
          closest_waypoints = params['closest_waypoints']
          waypoints = params['waypoints']
          waypoints_len = len(waypoints) - 1
            
          # 타켓 웨이포인트 좌표 구하기
          closest_previous, closest_next = closest_waypoints
          target_waypoint_idx = (closest_next + 4) % waypoints_len
          target_waypoint = waypoints[target_waypoint_idx]
          x_target, y_target = target_waypoint
            
          # 현재 위치에서 타켓 웨이포인트로의 벡터의 라디안 각 구하기
          x_target_vector = x_target - x
          y_target_vector = y_target - y
          target_rad = math.atan2(y_target_vector, x_target_vector)
            
          # 정답값
          target_steering_angle_rad = target_rad - heading_rad
            
          # 손실과 보상
          loss = math.sin(target_steering_angle_rad - steering_angle_rad) ** 2
          reward_direction = (1 - loss*2)*2
        
                
      # 보상 합계 reward        
          ########### [reward weight sum] ############ 
          reward = 1*reward_survived + 1*reward_wheels + 1*reward_speed + 1*reward_direction
            
          return float(reward)
    


1. Params

image

  1. x, y
    • x축과 y축에 따른 agent의 중앙 위치
    • type: float
    • 원점: 왼쪽 하단 모서리

    image

  2. speed
    • type: float
    • 범위: 0~4
    • Agent의 속도
  3. distance_from_center
    • type: float
    • 범위: 0~(트랙의 너비) / 2
    • Agent의 중앙과 트랙의 중앙 사이의 거리
    • Agent의 한 쪽 바퀴가 트랙의 흰색 경계선을 벗어났을 때 최대
      • (트랙의 너비) / 2

        image

  4. track_width
    • type: float
    • 트랙의 너비. 트랙의 흰색 경계선 사이의 거리
  5. all_wheels_on_track
    • type: boolean
    • Agent의 트랙 이탈 여부를 확인

      image

  6. heading
    • type: float
    • 범위: -180~180
    • 트랙의 x축에 대한 agent의 진행 방향(각도)

      image

  7. steering_angle
    • type: float
    • 범위: -30~30
    • agent의 진행 방향에 대한 앞바퀴의 각도
    • 앞바퀴가 오른쪽으로 꺾여 있으면 음수, 왼쪽으로 꺾여 있으면 양수
  8. steps
    • type: int
    • 완료한 step 개수
      • step: agent가 state 정보를 입력 받고, 현재의 정책에 따라 취할 하나의 행동을 결정하는 일련의 과정 한 번
  9. progress
    • type: float
    • 범위: 0~100
    • 트랙을 얼만큼 주행했는지 퍼센트로 반환 (100이면 완주)
  10. track_length
    • type: float
    • 트랙의 시작점으로부터 중앙선을 따라 다시 시작점으로 돌아가기까지의 거리
  11. is_offtrack
    • type: boolean
    • agent가 종료 시점에 트랙을 벗어났다면 True, 벗어나지 않았다면 False
  12. is_left_of_center
    • type: boolearn
    • Agent가 트랙 중앙에서 왼쪽에 있으면 True, 오른쪽에 있으면 False
  13. is_reversed
    • type: boolean
    • Agent의 바퀴가 시계 방향으로 주행하면 True, 시계 반대방향으로 주행하면 False
  14. waypoints
    • type: [[float, float], [float, float], …]
    • 트랙 중앙을 따라 정해진 waypoint의 위치를 순서대로 나열한 리스트
    • 순환 트랙의 경우 시작과 끝 지점의 waypoint는 같다.

      image

  15. closest_waypoints
    • type: [int, int]
    • Agent의 현재 위치에서 가장 가깝게 위치한 두 waypoint의 index
    • Agent와의 거리: 유클리드 거리 계산법 이용 (앞바퀴 기준)
    • 첫 번째 값은 agent의 뒤에서 가장 가까운 waypoint, 두 번째 값은 agent의 앞에서 가장 가까운 waypoint
  16. closest_objects
    • type: [int, int]
    • Agent의 현재 위치에서 가장 가깝게 위치한 두 object의 index
    • 첫 번째 값은 agent의 뒤에서 가장 가까운 object, 두 번째 값은 agent의 앞에서 가장 가까운 object
    • object가 하나만 있는 경우 두 값은 모두 0
  17. is_crashed
    • type: boolean
    • Agent와 다른 object와의 충돌 여부. (충돌 True, 충돌X False)
  18. objects_distance
    • type: [float, …]
    • 트랙의 시작점으로부터 object들의 거리
    • i번째 요소는 i번째 object의 시작점으로부터의 거리
  19. objects_left_of_center
    • type: [boolean, …]
    • object들이 중앙선을 기준으로 왼쪽에 있는지 오른쪽에 있는지 (왼쪽 True, 오른쪽 False)
  20. objects_heading
    • type: [float, …]
    • object들의 x축에 대한 object의 진행 방향(각도) (움직이지 않는 object는 0)
  21. objects_location
    • type: [[float, float], [float, float], …]
    • object들의 위치값(x, y)
  22. objects_speed
    • type: [float, …]
    • object들의 speed (움직이지 않는 object는 0)


2. 기본 보상함수 예제

중앙선 따라가기

image

두 경계선 안에서 움직이기

image

지그재그로 움직이는 것 방지하기

image

장애물 피하기 & 부딪히지 않고 한 줄로 가기

image

image

3. 보상함수 실험

  • 보상을 항상 1로 준다 Discount factor 0.999⇒ 완주율 100%
    • 생존하면 1이고 미래 보상 가치도 크기 때문에 오래 살아남을 수 있어 완주률이 높다.
  • 보상을 항상 1로 준다. Discount factor 0으로 준다. ⇒ 전혀 학습 안된다.
    • 미래 보상 가치가 없기 때문에 당장 현재 생존만 하면 되므로 완주율이 매우 낮다.
  • 보상을 항상 -1로만 준다. Discount factor 0.999 ⇒ 완주율이 줄어든다.
    • 생존할 가치가 없기 때문에 완주율이 줄어든다.


4. Track 시각화

  • 트랙 시뮬레이션 공간을 시각화하였다.

image

https://drive.google.com/file/d/1tR6NCXrD56Hc5IvgtlMl8C5J6HsqHGVT/view?usp=sharing



Log Analysis

1. Reward graph

  • 모델 성능을 개선하기 위해 로그 기록을 분석해보자
  • 훈련에 대한 결과를 확인할 수 있다.

    image

    • 모두 우상향을 그려야 정상적인 그래프이다.
    • 보상 축 스케일은 계속 변하며 완주율 축 스케일은 고정이다.
    • 그래프
      • 초록색 - 한번 iteration 시에 얻을 수 있는 평균 보상
      • 파란색 - 훈련 시 평균 완주율 : 트랙 전반적인 부분에서의 완주율을 알 수 있다.
      • 빨간색 - 평가 시 평균 완주율 : 트랙 시작점에서 출발했을 때의 완주율을 알 수 있다.
    • 초록색은 상승 & 파란색은 하강
      • 안정성을 버리고 보상을 추구한다는 의미 ⇒ 보상 체계 잘못됨, 보상 함수에서 안정성에 더 높은 보상을 줄 필요가 있다.
    • 빨간색과 파란색은 함께 상승하며, 빨간색이 파란색 보다 더 위쪽에 있는 것이 일반적이다.
      • Training은 트랙 여러군데서 출발점을 가지지만, Evaluation은 트랙 시작점에서만 출발한다.
    • 점 하나 - 업데이트 한번
      • 점 하나는 에피소드가 20개씩 담겨있는 하나의 iteration이다. (이탈하면 에피소드 끝)
      • iteration 5에서의 보상은 에피소드 20개의 평균(에피소드의 보상 합 / 에피소드 개수 나누기)인 120 이다.


2. download logs

  1. 시뮬레이션을 통해
  2. 그래프를 통해
  3. 모델의 로그를 통해 분석할 수 있다.
    • [Download logs] 클릭

      image


logs/…/~~-sagemaker.log

  • 훈련 중 에러 발생 시, 이 파일의 하단의 에러 메시지를 확인하여 해결하기

logs/…/~~-robomaker.log

  • 보상함수의 print 내용은 이 곳에 출력된다.

metrics/…~~.json

  • Metrics에 대한 로그 기록들이 담겨있다.

    image

sim-trace/…/n-iteration.csv

  • 각각의 iteration마다 시뮬레이션 상태 값에 대한 기록들이 담겨있는 csv 파일
  • 데이터가 밀려있는 경우가 있으므로 주의하기!


3. iteration csv 파일 다루기

  • 자취 분포, 속도 분포, reward 분포, 위험 구간 시각화를 해보았다.

image

https://drive.google.com/file/d/1tRCSMSFR9_Y5SCerCFGuP-yl0XSOHInR/view?usp=sharing

4. 모든 params 출력하기

https://drive.google.com/file/d/1tevvBHmGi3XjdnC8PDv_I6muHCDu45Yt/view?usp=sharing

댓글남기기