이 파일은 4WayBeacon_ppo 디렉토리에 있는 Policy_net.py와 같은 구조를 가지고 있으나 네트워크의 구성 부분이 다르기에 이 부분만 언급합니다.
먼저 이 코드에 대해 설명하기 전에 Deepmind에서 낸 첫 번째 스타크래프트2 관련 논문에서 사용한 네트워크 구조 설명을 하겠습니다. 딥마인드에서 사용한 네트워크 구조에는 Atari-net, FullyConv, FullyConvLSTM으로 3가지가 있습니다. Atari-net과 FullyConv의 구조는 다음의 그림과 같습니다.
Atari-net과 FullyConv의 차이점은 Minimap과 Screen을 합치기 전 Fully-Connected Layer를 거치느냐에 있습니다. 본 책에서는 Fully-Conv 네트워크 구조를 가지며 MoveToBeacon의 경우 Non-spatial features(미네랄, 가스, 인구 등등)에 대한 정보가 필요없으며 Screen과 Minimap의 특성이 갖으므로 다음과 같이 네트워크의 구조를 수정하였습니다.
화면을 이미지로 받아서 마린의 위치와 비콘의 위치를 각각 나타내는 이미지를 하나씩 전처리하여 쌓습니다. 그 후 여러개의 Convolutional Neural Network를 거쳐 Value, Non-spatial action policy, Spatial action policy를 출력합니다.
이러한 과정에 맞춰 PositionBeacon 내에 있는 Policy_net 클래스의 __init__은 다음과 같이 수정이 됩니다.
전처리한 이미지를 이미지의 형태를 가지도록 input을 넣어주지 않고 1행을 가지는 list로 만들어서 입력을 가집니다. 그 후 tf.reshape를 통해 원하는 이미지의 형태로 재변환합니다. 그 후 layer_2를 통해 128개의 kernel를 가지도록 Convolutional Neural Network에 통과시킵니다. 마지막으로 원하는 action_space에 맞게 self.action_probs를 출력합니다. 여기서 self.action_probs는 위 그림에서의 Non-spatial aciton policy입니다.self.spatial_probs는 위 그림에서의 Spatial action policy입니다. 이미지의 픽셀에 대한 정보를 얻어야 하기에 이미지의 사이즈 만큼(16x16) softmax로 출력합니다. 또한 위 그림에서의 Value에 해당하는 self.v_preds를 출력합니다.
먼저 이 코드에 대해 설명하기 전에 첫 번째 스타크래프트2 관련 논문 에서의 학습 방법을 설명하겠습니다. 앞에서 언급한 논문에서 전체 파라미터를 업데이트하는 방법은 일반적인 PPO와 같습니다. 하지만 일반적인 행동(상, 하, 좌, 우를 고르는 것과 같은)을 선택하는 방식과 달리 두 가지의 action policy(Non-spatial action policy, Spatial action policy)가 네트워크에서 출력되며 이를 합쳐서 한꺼번에 업데이트하는 방법을 취하고 있습니다. 수식으로 표현하자면 아래와 같습니다.
위의 식과 PPO에서 표현하고 있는 것이 다른 점은 Gt−vθ(st) 입니다. 하지만 PPO에서 advantage( A^t )는 실제로 다음 상태의 가치( Gt=Σk=0∞Rt+k+1 )와 현재 상태의 가치( vθ(st) )의 차이를 뜻하는 것이므로 표현법만 다를 뿐이지 실제로 의미는 같습니다.
중요한 것은 두가지의 action policy를 하나로 합치는 방법입니다. 논문에서 볼 수 있듯이 하나로 합쳐진 action policy는 아래와 같이 정의됩니다.
π(a∣s)=Ππ(al∣a<l,s)=π(a1∣s)π(a2∣s)⋯π(al∣s)
본 코드에서는 action policy는 두 가지를 하나로 합치게 되며 다음과 같이 표현될 수 있습니다.
π(a∣s)=π(a1∣s)π(a2∣s)
그리고 더 구체적으로 설명하자면 π(a1∣s) 는 policy_net.py에서의 self.act_probs이며 π(a2∣s) 는 policy_net.py에서 self.spatial_probs를 뜻합니다.
이제 실제 코드를 설명하겠습니다. 대부분은 4WayBeacon PPO에 있는 ppo.py와 같으나 다른점만 설명하도록 하겠습니다.
act_probs와 spatial_probs는 main 네트워크에서 상태에 대한 출력 값이므로 각각 π(a1∣s),π(a2∣s) 의 전체 확를 뜻합니다. 마찬가지로 act_probs_old와 spatial_probs_old는 target 네트워크에서 상태에 대한 출력 값이므로 전 πθold(a1∣s),πθold(a2∣s) 을 뜻합니다. 예를 들면 act_probs는 [0.2, 0.5, 0.3]을, spatial_probs_old는 [0.1 0.003 0.05 ..... 0.003]을 뜻합니다. 하지만 우리가 학습해야 하는 수치들은 실제로 선택한 행동에 대한 값을 이용하여야 하므로 이를 실제 행동에 대한 수치만 추출하는 과정을 거쳐야 합니다.
위에서 정의한 act_probs와 실제 선택한 non-spatial action을 조합하여 실제 행동에 대한 수치만을 추출하는 작업입니다. 예를들면 act_probs가 [0.2 0.5 0.3], non-spatial action이 1이라면 tf.reduce_sum을 거친 act_probs는 0.5가 됩니다. 이 작업을 거쳐 비로소 진정한 의미의 πθ(a1∣s) 이 됩니다. 그 후 마지막 줄의 action_probs는 πθ(a∣s)( πθ(a1∣s)πθ(a2∣s) )를 뜻하게 됩니다.