Framework/Unity

[Unity] ML-Agent 구조 및 간단한 학습 진행

깜태 2021. 8. 26. 16:16
728x90

Unity ML-Agent 소개

 

 

구조 간단 소개

출처 : https://aifrenz.github.io/present_file/AI프렌즈세미나_ML-Agents.pdf

유니티의 ML-Agent 라이브러리와 python 딥러닝 라이브러리가 서로 통신하여 학습하는 구조

자세한 설명은

https://github.com/Unity-Technologies/ml-agents/blob/main/docs/ML-Agents-Overview.md,

https://aifrenz.github.io/present_file/AI프렌즈세미나_ML-Agents.pdf 참조하고,
간단한 설치방법은 이전 글에서 https://tw0226.tistory.com/92 에서 다루었으므로, 설치되었다는 가정으로 시작한다.

학습 방법

 

사실 학습 방법 이전에도 선행되어야 할 것이 유니티에서 게임을 만들어야 한다.

귀찮다면 누군가가 만들어놓은 강화학습 모델이 학습하기 좋을만한 게임을 다운받아써도 무방하다.

나는 2D 박스 공간을 만들어 에이전트가 목표물을 찾아가는 방식으로, 
https://game-dev.tistory.com/6?category=1212513 을 참조하여 만들었다.


게임이 만들어졌다는 가정 하에서는 ML-Agent 라이브러리를 이용해 강화학습에 필요한 설정들을 추가하고,

게임 설정이 끝난 뒤, cmd 창으로 mlagents-learn [게임명] 명령어로 실행시키고, 게임을 실행하여 통신시킨다.

ML-Agent 구현

구현에는 총 3가지 방식을 필요로 한다.

첫째로, Unity 상에서의 GUI를 설정해야 하고,
둘째로, 설정된 GUI를 바탕으로 C# 스크립트를 작성해서 Python과 연동할 수 있도록 만들어야 한다.
마지막으로, Python에서 모델 설정과 학습에 필요한 파라미터를 설정을 해줘야 한다.

Unity GUI

Scene을 만들고, 모델을 통해 움직이고자 하는 객체를 만든다.
객체가 생성되면 화면 우측에 Add Component가 있는데, ML-Agent 설치가 잘 되었다면 우측 그림처럼 ML-Agent에서 지원하는 컴포넌트를 추가할 수 있다.
이 때, New Script를 통해 새로운 스크립트를 생성하면 스크립트를 상속받은 객체가 된다.

추가한 Behavior Parameter에서는 스크립트에서 추가될 값들에 대해 명시해야 한다.
들어오는 값은 몇차원이고, 그에 따른 Actions, 내 행동은 Descrete인지, Continuous인지 적으면 된다.
(추가로 스크립트랑 연동하면서 생기거나 지워지기도 한다.)

C# Script

위에서 스크립트를 생성하였다면, 빈 스크립트의 상태를 볼 수 있다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveToGoalAgent : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

먼저 유니티에서 ML-Agent 라이브러리를 설치하였으므로 해당 라이브러리를 임포트하고,
MonoBehaviour가 아닌 Agent를 상속 받아야 한다.
이는 MoveToGoalAgent: MonoBehavior 가 아닌, SingleAgent : Agent 가 된다는 말이다.

추가로 기존에 있었던 Start()와 Update()는 지운다.

using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;

각각 설명하면 MLAgents 는 전체적인 라이브러리를 가져온 것이고,
Actuator는 Agent가 행동하는 부분의 라이브러리,
Sensor는 Agent가 받아들이는 상태에 대한 라이브러리다.

어떻게 사용되는지 예시를 들어보자.
(자세한 설명은 ML-Agents/Runtime/ 폴더에 들어가보면 확인할 수 있다.)

Sensor 예시

	public override void CollectObservations(VectorSensor sensor)
    {
        sensor.AddObservation(transform.position);
        sensor.AddObservation(target.position);
    }


위의 SingleAgent 클래스는 Agent를 상속받았으므로, Agent에서 정의된 CollectObservations 함수를 상속받아
sensor에 AddObservation 메소드로 관측 값을 추가한다.
위를 예로 들면 position은 (x,y,z)이라는 3차원 값이므로 3차원 값을 2개 추가해
sensor가 받아들인 값은 6차원의 벡터가 된다.

Actuator

마찬가지로 Unity 화면에서 ML-Agent 컴포넌트 중 DecisionRequester를 추가했다면,
해당 객체 내부에 ActionBuffers가 추가되어 강화학습의 모델 결과를 출력받아 움직일 수 있게 된다.
아래 코드는 ActionBuffer는 모델로부터의 결과를 받아서 transform.Translate 함수를 통해 유니티로 움직인 것이다.

    Vector3 nextMove;
    public override void OnActionReceived(ActionBuffers actions)
    {
        nextMove.x = actions.ContinuousActions[0];
        nextMove.z = actions.ContinuousActions[1];
        transform.Translate( nextMove * Time.deltaTime * speed );
    }

최종 코드는 다음과 같다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;

public class MoveToGoalAgent : Agent
{
    [ SerializeField ] Transform target;
    public override void OnEpisodeBegin()
    {
        transform.localPosition = new Vector3(0, 0.25f, 0);        
        target.localPosition = new Vector3( Random.Range(-4, 4) , 0.25f, Random.Range(-4, 4));
    }
    public override void CollectObservations(VectorSensor sensor)
    {
        sensor.AddObservation(transform.position);
        sensor.AddObservation(target.position);
    }

    public override void OnActionReceived(ActionBuffers actions)
    {
    	speed = 4;
        Vector3 nextMove = new Vector3( actions.ContinuousActions[0], 0, actions.ContinuousActions[1]);
        nextMove.x = actions.ContinuousActions[0];
        nextMove.z = actions.ContinuousActions[1];
        transform.Translate( nextMove * Time.deltaTime * speed );
    }

    private void OnCollisionEnter(Collision other) 
    {
        if  ( other.transform == target )
        {
            SetReward(+1);
            EndEpisode();
        }
        else
        {
            SetReward(-1);
            EndEpisode();
        }
    }    
}

Python

파이썬에서는 사실 간단하게 mlagents-learn 명령어로 하면 default로 설정된 모델로 실행되기 때문에
문제는 되지 않지만, 내가 config를 변경해 학습시키고 싶다면 yaml 파일로 만들어서 실행할 수 있다.
이런 경우에는 mlagents-learn [파일명.ymal] 을 실행하면 설정된 yaml 파일에 대한 설정값을 불러와 실행시키면 된다.

 

학습 과정

학습결과

우측 하단에서 Behavior Parameter 내부에 Model 부분에서 학습된 모델을 불러오면 확인할 수 있다.

 

 

참고자료 :
https://game-dev.tistory.com/6?category=1212513
https://aifrenz.github.io/present_file/AI프렌즈세미나_ML-Agents.pdf

유니티 mlagents-learn 사용법 : https://github.com/Unity-Technologies/ml-agents/blob/main/docs/Training-ML-Agents.md

728x90

'Framework > Unity' 카테고리의 다른 글

[Unity] 애니메이션 후 객체 삭제  (0) 2021.09.07