NIRVANA

[Unity] 유니티에서 머신러닝 모델 사용하기 본문

Unity

[Unity] 유니티에서 머신러닝 모델 사용하기

녜잉 2024. 2. 24. 17:00

 

원래는  Barracuda 사용하려고 했는데 모델을 .onnx로 변경하지 못함 이슈가 발생하여서

api를 사용해서 머신러닝 모델 사용을 해보기로 했다

 

간단한 로직?을 살펴보면

 

유니티: UnityWebRequest 클래스를 사용, POST로 모델 예측에 필요한 데이터를 전송

머신러닝 모델 API: GET으로 필요한 데이터 읽기, POST로 예측 결과를 생성 → 예측값 반환 

 

요런 방향이 된다. 

 

사용한 머신러닝 모델은 XGBoostRegressor이다. 

 


코드 

 

📌유니티 코드(webre.cs)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;


[Serializable]
public class TimeData
{
    public int month;
    public int dayofWeek;
    public int day;
    public int hour;
    public int minute;
}


public class webre : MonoBehaviour
{
    public Text resultText;
    private string [] requestResult;
    //private char[] separators = { ":", "}" };
    public int subWayPeople = 0;

    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(SendTimeRequest());
    

    }

    IEnumerator SendTimeRequest()
    {
        DateTime utcTime = DateTime.UtcNow;
        DateTime koreanTime = utcTime.AddHours(9);

        TimeData timeData = new TimeData();

        int day = (int)koreanTime.DayOfWeek;

        string jsonData = "{\"month\": " + koreanTime.Month + ", " +
                  "\"dayofweek\": \"" + day + "\", " +
                  "\"day\": " + koreanTime.Day + ", " +
                  "\"hour\": " + koreanTime.Hour + ", " +
                  "\"minute\": " + koreanTime.Minute + "}";


        //데이터를 전송할 url 
        string url = "http://localhost:8000/predicts/";

        //웹 요청 생성
        using (UnityWebRequest request = UnityWebRequest.Post(url, "POST"))
        {
            byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonData);

            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            request.SetRequestHeader("Content-Type", "application/json");

            yield return request.SendWebRequest();


            // 응답 처리
            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("Error sending request: " + request.error);
            }
            else
            {
                Debug.Log("Request successful! Response: " + request.downloadHandler.text);

                requestResult = request.downloadHandler.text.Split(new char[] { ':', '}' });


            }

            if (int.TryParse(requestResult[1], out subWayPeople))
            {
                // 변환에 성공한 경우 countAsInt 변수에 저장
                Debug.Log("Converted to int: " + subWayPeople);
            }

            else
            {
                // 변환에 실패한 경우
                Debug.LogError("Failed to convert to int: " + requestResult[1]);
            }
        }

      }

 

 

📌 파이썬 코드 - 머신러닝 api (XGModel.py)

# -*- encoding: euc-kr-*-
from fastapi import FastAPI, Request
import xgboost as xgb
from pydantic import BaseModel 
import pandas as pd
import pickle


app = FastAPI()

#XGBoost model load
xg_filename ="모델 경로"
model = xgb.Booster(model_file=xg_filename)

#요청 데이터를 받을 클래스 정의 
#'month', 'dayofweek', 'day', 'hour', 'min'가 들어가야 함 
class Data(BaseModel):
    month: int
    dayofweek: int
    day: int
    hour: int
    minute: int 



@app.post('/predicts')
async def predicts(data: Data):
    month = data.month
    dayofweek = data.dayofweek
    day = data.day
    hour = data.hour
    minute = data.minute
    
    #유니티에서 받은 데이터로 데이터 프레임 생성 
    df = pd.DataFrame({
        'month': [month],
        'dayofweek':[dayofweek],
        'day': [day],
        'hour' : [hour],
        'minute': [minute]
        })
    
    #넘파이 배열로 나오므로 int로 반환하기 위해 인덱스 사용
    result =int(model.predict(xgb.DMatrix(df))[0]) 
    
    return {"result": result}

 

 


에러 

 

처음 유니티 → API로 웹 요청을 보낼 때 422 에러가 발생했었다. 

FastAPI를 사용할 때, pydantic으로 정의한 형식에 맞지 않으면 발생하는 오류라고 한다.

변수명, 순서 다 똑같아야 함을 명심 또 명심!! (이걸로 두시간 헤맴...)

[Fast API] Endpoint Validation (422 Error: Unprocessable Entity) (tistory.com)

 

[Fast API] Endpoint Validation (422 Error: Unprocessable Entity)

Fast API 애플리케이션 개발 시에 422 Error가 발생할 경우가 있다. 보통 API 요청 시 pydantic으로 정의되어 있는 Request Model에 어긋나기 때문에 발생하는데 그 외에도 endpoint, router 선언 기준/선언 순서

do-hyeon.tistory.com

 

 

FastAPI로 API 서버 만드는 거는 처음이었고 머신러닝 모델 배포도 처음 해보는 거여서 FastAPI 서버 만들 때가 진짜 고생 많았었다... 처음에는 joblib 사용해서 불러왔는데 머신러닝 모델 로드가 아예 안되어서..진짜 너무 많이 헤맴

pickle에 원래 XGBoost 사용하는 방식으로 가는게 정답이었다는 거! 

 

일단 유니티는 using 사용 안하고 webrequest 한 거여서 보안적으로 안좋을 듯 하니.. 이거 수정하고

진짜 꼭꼭 클라우드로 배포해봐야지...!!! 

너무 재미있을듯.. 대충 설계도 구상은 다 해놨다 V^_^V