본문 바로가기
유니티/mlAgents

유니티 머신러닝 개발 ML Agents 5편, 목표찻기 예제 제작.1 목표찻기 유니티 프로그램 제작

by NGVI 2021. 4. 6.

유니티 머신러닝 개발 ML Agents 5편, 목표 찾기 예제 제작. 1 목표 찾기 유니티 프로그램 제작

지난 편 까지는 유니티 mlAgent 환경을 구성하고,

해당 예제에서 재공하는 예제를 돌려보았습니다.

 

MlAgent Release8로 구성하였는데,

 

해당 설명부터는 Release15로 구성하여 진행합니다.

Release 15의 성치는 거의 8과 유사하니 앞의 과정을 성공하셨으면 쉽게 성공하실 수 있을 거라 생각합니다.

 

추후 포스팅 보시는 분들이 좀 생기면, 앞의 설명들도 15버전으로 바꿀 계획은 있습니다.

일단은 그냥 진행

 

해당 예지는 ml-agent relese15문서의 예제 문서를 참고하여 만들었습니다.

영문 설명이 부담 없으신 분은 그냥 

github.com/Unity-Technologies/ml-agents/blob/release_15_docs/docs/Learning-Environment-Create-New.md

 

해당 문서 가셔서 보고 하셔도 상관없을 듯 하지만,

 

여기에서는 목표 찾기로 끝내지 않고,

 

트레이닝을 다중으로 수행하는 방법

에이전트를 다중으로 설치하는 방법

에이전트 간 관계성을 만들어 보는 것까지 추가 진행할 계획이니

 

요런 것도 해보시고 싶으면 그냥 해당 페이지를 참고해주면 좋을 거 같습니다.

 

이전 4편 설명까지 환경 구축돼있다는 가정하에

 

새로운 씬을 하나 오픈합니다.

 

폴더 구성

같은 환경 구성이라면 다음과 같이 프로젝트 구성이 비슷할 것입니다.

저는 Exsmples 아래에 폴더 구성을 하도록 하겠습니다.

Test00이라고 구성하고 아래에 Gtest.scene로 새로 만들 신을 일단 저장하도록 하겠습니다.

 

요렇게 구성

Create the Floor Plane

  1. Right click in Hierarchy window, select 3D Object > Plane.
  2. Name the GameObject "Floor".
  3. Select the Floor Plane to view its properties in the Inspector window.
  4. Set Transform to Position = (0, 0, 0), Rotation = (0, 0, 0), Scale = (1, 1, 1).

위의 영어 설명 과정 진행합니다.

 

아래 바닥을 깔도록 할게요

 

Hierarchy 오른쪽 누구로 Plane 설치

Hierarchy 오른쪽 누구로 Plane 설치

 

이름 "Floor" 로 해주세요

 

해당 오브젝트를 선택하고 인스팩터를 봅시다.

Position =   (0, 0, 0), Rotation =   (0, 0, 0), Scale =   (1, 1, 1)

 

Position = (0, 0, 0), Rotation = (0, 0, 0), Scale = (1, 1, 1)

으로 세팅해줍니다.

Transform에서 마우스 오른쪽을 눌려  Reset 버튼을 눌려도 똑같은 동작을 보장합니다.

 

요렇게!

Add the Target Cube

  1. Right click in Hierarchy window, select 3D Object > Cube.
  2. Name the GameObject "Target".
  3. Select the Target Cube to view its properties in the Inspector window.
  4. Set Transform to Position = (3, 0.5, 3), Rotation = (0, 0, 0), Scale = (1, 1, 1).

목표가 되는 타겟를 설치할 것입니다.

Hierachy 창에서 마우스 오른쪽 누르고 cube 까지

이름은 Target 으로

 

트랜스폼 정보를

Transform to Position = (3, 0.5, 3), Rotation = (0, 0, 0), Scale = (1, 1, 1).

맞추어줍니다.

 

이렇게
대략 화면에는 이렇게 나오는 상태

이번에는 일을 수행할 Agent를 설치할 것입니다.

Add the Agent Sphere

  1. Right click in Hierarchy window, select 3D Object > Sphere.
  2. Name the GameObject "RollerAgent".
  3. Select the RollerAgent Sphere to view its properties in the Inspector window.
  4. Set Transform to Position = (0, 0.5, 0), Rotation = (0, 0, 0), Scale = (1, 1, 1).
  5. Click Add Component.
  6. Add the Rigidbody component to the Sphere.

스피어 설치

이름은 RollerAgent로

 

위치 정보를 

Position = (0, 0.5, 0), Rotation = (0, 0, 0), Scale = (1, 1, 1)으로

 

위치정보 세팅

Rigidbody component 부착

Rigidbody component 부착

add component 클릭

아래 rigidbody 검색

아래 나오는 rigidbody 클릭

설치됨

일단은 따로 속성 값 변경은 하지 않습니다.

 

위에서 제작한 아랫판과, 목표, 에이전트를 그룹화하겠습니다.

그룹화시켜두면 이후 강화 학습 시 학습 수량을 늘리는데 이용할 수도 있습니다.

 

빈 오프젝트 생성

이름은 TrainingArea

트랜스폼 리셋해줍니다.

Transform so that it is at (0,0,0) with Rotation (0,0,0) and Scale (1,1,1).

트랜스폼 정보와, 오브젝트 구성

Floor, Target, RollerAgent 모두 TrainingArea의 자식으로 붙입니다.

반드시 트랜스폼 데이터 초기화 후 붙이도록 합시다.

 

스크립트 파일 제작

GRollerAgent.cs

씬이 저장된 폴더에 C# 스트립트 파일을 하나 만들도록 합시다.

풀 소스를 주석과 함께 첨부해 올리도록 하겠습니다.

문법이 어쩌고 이런 설명보다는 기능별로 간략하게 주석을 달아두겠습니다.

 

이전에 알아두면 좋은 내용

 

Episode

에피소드란 계념은 어떤 사건, 게임에서는 하나의 스테이지라고 보시면 됩니다.

해당 예제에서는 목표 찾는 에피소드를 진행하며

목표를 찾거나, 완전히 실패하면 에피소드가 종료되게 구성되어 있습니다.

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

using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
//mlAgent 사용시 포함해야 됨

public class gRollerAgent : Agent
{
    Rigidbody rBody;
    void Start()
    {
        rBody = GetComponent<Rigidbody>();
    }

    public Transform Target;
    public override void OnEpisodeBegin()
    {
        //새로운 애피소드 시작시, 다시 에이전트의 포지션의 초기화
        // If the Agent fell, zero its momentum
        if (this.transform.localPosition.y < 0) //에이전트가 floor 아래로 떨어진 경우 추가 초기화
        {
            this.rBody.angularVelocity = Vector3.zero;
            this.rBody.velocity = Vector3.zero;
            this.transform.localPosition = new Vector3(0, 0.5f, 0);
        }

        //타겟의 위치는 에피소드 시작시 랜덤하게 변경된다.
        // Move the target to a new spot
        Target.localPosition = new Vector3(Random.value * 8 - 4,
                                           0.5f,
                                           Random.value * 8 - 4);
    }

    /// <summary>
    /// 강화학습 프로그램에게 관측정보를 전달
    /// </summary>
    /// <param name="sensor"></param>
    public override void CollectObservations(VectorSensor sensor)
    {
        //타겟과 에이전트의 포지션을 전달한다.
        // Target and Agent positions
        sensor.AddObservation(Target.localPosition);
        sensor.AddObservation(this.transform.localPosition);

        //현재 에이전트의 이동량을 전달한다.
        // Agent velocity
        sensor.AddObservation(rBody.velocity.x);
        sensor.AddObservation(rBody.velocity.z);
    }

    /// <summary>
    /// 강화학습을 위한, 강화학습을 통한 행동이 결정되는 곳
    /// </summary>
    public float forceMultiplier = 10;
    public override void OnActionReceived(ActionBuffers actionBuffers)
    {
        //학습을 위한, 학습된 정보를 해석하여 이동을 시킨다.

        // Actions, size = 2
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = actionBuffers.ContinuousActions[0];
        controlSignal.z = actionBuffers.ContinuousActions[1];
        rBody.AddForce(controlSignal * forceMultiplier);

        // Rewards
        float distanceToTarget = Vector3.Distance(this.transform.localPosition, Target.localPosition);

        //타겟을 찻을시 리워드점수를 주고, 에피소드를 종료시킨다.
        // Reached target
        if (distanceToTarget < 1.42f)
        {
            SetReward(1.0f);
            EndEpisode();
        }

        //판 아래로 떨어지면 학습이 종료된다.
        // Fell off platform
        else if (this.transform.localPosition.y < 0)
        {
            EndEpisode();
        }
    }

    /// <summary>
    /// 해당 함수는 직접조작 혹은 규칙성있는 코딩으로 조작시키기 위한 함수
    /// </summary>
    /// <param name="actionsOut"></param>

    public override void Heuristic(in ActionBuffers actionsOut)
    {
        var continuousActionsOut = actionsOut.ContinuousActions;
        continuousActionsOut[0] = Input.GetAxis("Horizontal");
        continuousActionsOut[1] = Input.GetAxis("Vertical");
    }
}

 

코드를 작성하여

hierarchy의 Rolleragent에 부착한다. 

아래 그림 참고

 

부착하면 오른쪽과 같이 컴포넌츠가 추가된다.

Decision Requester 컴포넌트도 추가해준다.

Decision Requester 컴퍼넌트도 추가

각 컴퍼넌트 설정값

 

Behavior Parameters

 

  • Behavior Name: RollerBall //행위의 이름
  • Vector Observation > Space Size = 8 //우리가 보고할 데이터 사이즈
  • Actions > Continuous Actions = 2 //우리가 보고 받을 데이터 사이즈
    • //이산적이지 않은 연속된 값 사용

세팅 참고

 

GRollerAgent

우리가 많든 타겟 연결

Decision Requester

설정참고

요기까지 작업하고 유니티를 플래이 시켜본다.

별다른 에러 없이 구동되는 것을 확인할 수 있다.

 

물론 아무것도 되지 않는 모습..

실행화면의 모습

 

Heuristic

위에 Agent코드 중 Heuristic함수를 이용해서 우리가 직접 조작해 볼 수 있다.

 

Behavior parameters 속성의 Behavior Type속성을 Heuristic Only으로 변경하고 실행하여 키보드의 화살표를 눌려보자.

 

요렇게 하고 플래이

이후 다시 Default로 돌려두자.

우리는 ml을 하고 싶은 것이니

 

요기까지 하면 유니티 프로젝트는 어느 정도 준비가 된 상황이다.

 

다음에는 학습 프로그램을 구동시켜서 학습을 시켜보자.

댓글