Game Development

유니티를 통해 머신러닝을 해보자 본문

Unity/ML Agent( AI )

유니티를 통해 머신러닝을 해보자

Dev Owen 2021. 6. 26. 21:16


유니티를 통한 머신러닝 학습

오늘 부터 간단하게 유니티를 통해서 머신러닝을 해보고 앞으로도 머신러닝을 통해 여러가지 프로젝트를 진행하여 올려보도록 하겠습니다.

[ 셋팅 하기 ]

유니티에서 머신러닝을 하기위해선 PythonML Agents라는 패키지가 필요하게 됩니다.

먼저 Python3.7을 다운받고 기본적인 셋팅부터 진행하도록 하겠습니다. 파이썬을 다운받고 오시기 바랍니다.

1. 파이썬 셋팅

먼저 가상환경을 만들어 보도록 하겠습니다. 머신러닝을 진행할 프로젝트를 만들어주세요.

CMD창을 열어 해당 프로젝트 경로까지 이동해주시기 바랍니다.

 

cd "경로"

그 다음 새로운 가상환경을 만들어 보도록 하겠습니다.

가상환경이 필요한 이유는 타 프로젝트에 영향을 주지 않기 위해서 이기도합니다.

python -m venv "이름"
python -m venv venv

 저는 폴더이름을 vevn라고 설정했습니다.

이제 해당 아래의 명령어를 통하여 가상환경으로 들어가보도록 하겠습니다.

vevn\Scripts\activate

맥이 경우

source venv/bin/activate

pip 명령어를 최신 버전으로 업그레이드를 시키도록 하겠습니다.

python -m pip install --upgrade pip

그후 pyTorch라는 패키지를 다운받아줍니다.

pyTorch의 역활은 데이터 흐름을 사용하여 계산을 수행하기위한 오픈 소스입니다.

pip install torch==1.7.0 -f https://download.pytorch.org/whl/torch_stable.html

그다음 Ml Agent 패키지를 다운받아야합니다.

pip install mlagents

만약 오류가 발생하게 된다면 아래의 명령어를 통하여 다운을 받습니다.

pip install mlagents --use-feature-2020-resolver

정상적으로 ML Agents를 설치하였다면, 다음과 같은 명령어를 통해 확인할 수 있습니다.

mlagents-learn --help

해당 사진처럼 명령어가 보이게 된다면 올바르게 설치된것 입니다.

이제 유니티로 돌아가 인공지능을 만들어 보도록 하겠습니다.

 

2. 유니티 셋팅

유니티에선 크게할 셋팅 사항은없고, 패키지 매니저에서 ML Agent를 임포트 해주시기만 하면됩니다.

그럼이제 간단하게 인공지능학습을 해보도록 하겠습니다.


[ 머신러닝 시작하기 ]

이제 유니티를 통해 인공지능을 만들어 보도록 해봅시다!

 

1. 상속을 받아보자

MoveToGalAgent라는 스크립트를 하나 생성해주고, MlAgent를 사용할 수 있게 임포트를 해줍시다.

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

이렇게 두가지를 불러온 후 MoveToGoalAgent를 Agent라는 녀석을 상속 받게 하신 후 함수 하나를 오버라이드 합니다.

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

public class MoveToGoalAgent : Agent
{
    public override void OnActionReceived(ActionBuffers actions)
    {
        Debug.Log( actions.DiscreteActions[0] );
    }
}

이제 유니티로 돌아가 오브젝트를 하나 만든 후 해당 스크립트와 통신을 받을 수 있는 스크립트인 Decision Requester

스크립트 또한 추가해 줍니다.

 

2. 컨퍼넌트에 대해서 알아보자

학습에 들어가기전 간단하게 컨퍼넌트에 대해서 알아보도록 하겠습니다.

Behavior Parameters에 Branches Size는 데이터를 전송받는 사이즈라고 보시면 됩니다.

Space Type은 총 2가지로, Discrete, Continuous로 구성이 되어 있습니다.

Discrete는 0에서 ~ 값 까지의 값 중 하나를 랜덤으로 전송 받습니다.

Continuous는 -1 ~ 1 까지의 값 중 하나를 랜덤하게 전송 받습니다.

해당 스크립트는 일정 시간 마다 CMD에서 전송되는 값을 받기위해 존재하는 스크립트라고 생각하시면 됩니다.

 

3. 학습을 시작해 보자

이제 학습을 시작해 보도록 하겠습니다. CMD 창으로 돌아가준뒤, mlagents-learn 이라는 명령어를 입력해줍니다.

다음과 같은 화면으로 변경이되며 인공지능 학습의 준비는 시작되었고, 이제 게임으로 돌아가 플레이 버튼을 눌러봅니다.

정상적으로 잘 따라오셨다면 이처럼 값들이 들어오는 모습을 볼 수 있습니다.

다시 학습을 할려고 CMD에 명령어를 입력하게 된다면 에러가 발생하게 될것입니다.

그 이유는 같은 태그로 학습을 시작할려고 하기 때문인데요. 이러한 에러를 막는 방법은 2가지가 있습니다.

mlagents-learn --force
mlagents-learn --run-id="이름"

이렇게 2가지 방법으로 다시 시작할 수 있게 됩니다.

이제 거이다 왔습니다. 지금부턴 오브젝트가 골인 지점까지 가도록 학습을 시켜보도록 하겠습니다.


[ 오브젝트를 찾아다니는 인공지능 ]

지금부터 특정 오브젝트를 찾아다니는 인공지능을 만들어 보도록 하겠습니다.

그러기 위해선 현재 오브젝트의 위치와 우리가 찾아가야하는 오브젝트의 위치에 대한 기본적인 정보를 보내줘야합니다.

using Unity.MLAgents.Sensors;

선언 후 아래의 함수를 오버라이드 하신 후 자신의 위치와 타겟의 위치를 넣어주시면 됩니다.

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

그리고 이제 오브젝트를 움직이게 하기 위해서 값을 받는 곳을 수정해보도록 하겠습니다.

[ SerializeField ] float speed = 1;
Vector3 nextMove;
public override void OnActionReceived(ActionBuffers actions)
{
    nextMove.x = actions.ContinuousActions[0];
    nextMove.z = actions.ContinuousActions[1];

    transform.Translate( nextMove * Time.deltaTime * speed );
}

코드를 수정한뒤 해당 컨퍼넌트의 Space Type과 사이즈를 변경한 후, 실행해보도록 하겠습니다.

이렇게 랜덤으로 블럭이 타겟을 향해서 움직이는걸 볼 수 있습니다. 이제 조금만 남았습니다.

이제 점수를 부여해보도록 하겠습니다.

음수 값을 넣으면 점수가 줄어들게 됩니다.

SetReward(+1);

해당 함수를 통하여 첫 번쨰 학습이 종료됬다는걸 알려줍니다.

EndEpisode();

학습이 종료 됬을 때 호출되는 함수 입니다. 

public override void OnEpisodeBegin() {}

이제 전체적인 코드를 보여드리도록 하겠습니다.

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.position = Vector3.zero;
}
    public override void CollectObservations( VectorSensor sensor )
    {
        sensor.AddObservation( transform.position );
        sensor.AddObservation( target.position );
    }

    [ SerializeField ] float speed = 1;
    Vector3 nextMove;
    public override void OnActionReceived(ActionBuffers actions)
    {
        nextMove.x = actions.ContinuousActions[0];
        nextMove.z = actions.ContinuousActions[1];

        transform.Translate( nextMove * Time.deltaTime * speed );
    }

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

이런 원리로 개발한 인공지능들이 공을 찾아 움직이는 모습입니다.

전체적인 프로젝트는 깃헙을 통해서 배포하도록 하겠습니다.


마무리

생각보다 간단해서 놀라웠습니다... 이걸 활용해서 많은 것들을 한번 만들어 봐야 겠다는 생각이 들었습니다.

최정적으로 학습된 친구들입니다.

 

 

Dev-Owen-Git/Unity-Ai-FindBall

Contribute to Dev-Owen-Git/Unity-Ai-FindBall development by creating an account on GitHub.

github.com

 

Comments