주요 콘텐츠로 건너뛰기
AI 튜토리얼

Ultimate SFighterAI 튜토리얼: PPO로 《스트리트 파이터 2》를 클리어하는 에이전트 학습하기

이 튜토리얼에서는 Ultimate SFighterAI를 구성하고, 사전 학습된 NatureCNN 모델을 실행하며, 연속 클리어 능력을 평가하고, PPO로 재학습 또는 추가 학습을 진행한 뒤 TensorBoard로 학습 곡선을 분석하는 방법을 소개합니다.

Ultimate SFighterAI 튜토리얼: PPO로 《스트리트 파이터 2》를 클리어하는 에이전트 학습하기

프로젝트 개요

Ultimate SFighterAI는 《스트리트 파이터 2: 챔피언 에디션》을 대상으로 하는 심층 강화 학습 프로젝트입니다. 플레이어 캐릭터로 류를 사용하며, PPO 알고리즘으로 NatureCNN 모델을 학습하고 학습 범위를 전체 12개 스테이지로 확장합니다.

모델의 의사 결정 입력은 게임 화면의 RGB 픽셀에서만 가져오며, 캐릭터 위치, 동작 상태 또는 체력을 직접 읽지 않습니다. 학습 환경은 메모리 변수의 agent_hp와 enemy_hp만 사용해 보상을 계산하고 승패를 판단합니다.

프로젝트에는 학습이 완료된 모델 가중치와 학습 기록이 제공되므로, AI 대전을 바로 관람하거나 실험을 재현하고 병렬 규모를 조정하거나 기존 모델을 기반으로 추가 학습을 진행할 수 있습니다.

주요 기능 및 구현 특징

  • 전체 12개 스테이지 지원: 각 스테이지는 독립적인 에뮬레이터에서 실행되며 하나의 NatureCNN 모델을 함께 학습합니다.
  • 순수 시각 기반 의사 결정: 모델은 처리된 게임 화면을 바탕으로 이동, 공격 및 필살기를 선택합니다.
  • 27개 이산 동작: 중립, 이동, 일반 공격, 앉아 공격과 좌우 방향의 파동권, 용권선풍각, 승룡권 등의 동작을 포함합니다.
  • PPO 강화 학습: Stable-Baselines3의 PPO 알고리즘을 기반으로 학습합니다.
  • 다양한 평가 모드: 스테이지별 세이브 로드 테스트, 3판 2선승, 단일 KO 평가 및 첫 스테이지부터 연속 클리어를 지원합니다.
  • 사전 학습 모델: 기본 가중치는 logs/trained_models/ppo_ryu.zip에 있습니다.
  • 학습 시각화: TensorBoard로 보상 변화와 모델 업데이트 기록을 확인할 수 있습니다.
  • 다중 장치 지원: 학습 및 추론 매개변수는 auto, cpu, cuda, mps를 지원합니다.

화면 전처리

원본 게임 화면은 중앙 자르기, 움직이는 전경 추출 및 크기 조정을 거쳐 최종적으로 84×84×3 모델 입력으로 변환됩니다. 움직이는 전경은 t-16, t-8, t 세 시점의 그레이스케일 차분을 사용해 추출하며, 배경 밝기에 0.35를 곱한 뒤 R, G, B 세 채널을 조합합니다. 이 처리는 모델이 캐릭터의 이동과 공격을 인식하는 데 도움이 됩니다.

보상 메커니즘

보상은 주로 양측 체력 변화, KO 결과 및 시간 비용으로 구성됩니다. 피해 보상은 다음과 같이 계산합니다.

0.01 × (3 × 상대방이 잃은 체력 − 자신이 잃은 체력)

상대를 KO했을 때의 보상은 다음과 같습니다.

0.01 × (176 + 자신의 남은 체력)

자신이 KO되었을 때의 패널티는 다음과 같습니다.

0.01 × (176 + 상대방의 남은 체력)

또한 실제 동작을 실행할 때마다 시간 패널티가 차감되며, 기본값은 0.0005입니다.

프로젝트 디렉터리 설명

  • data/: 12개 스테이지의 시작 세이브, 게임 메모리 변수 정의 및 장면 설정을 저장합니다.
  • main/train.py: 전체 스테이지 병렬 학습 및 이어서 학습을 담당합니다.
  • main/test.py: 스테이지별 테스트 및 연속 클리어 평가를 담당합니다.
  • main/env_utils.py: ROM 설정 및 환경 구성을 처리합니다.
  • main/custom_wrappers.py: 화면 처리, 동작 매핑 및 보상 계산을 구현합니다.
  • logs/trained_models/ppo_ryu.zip: 프로젝트에서 제공하는 학습 완료 모델입니다.
  • logs/: 학습 과정의 TensorBoard 기록을 포함합니다.
  • requirements.txt: Python 의존성 목록입니다.

설치 및 환경 설정

1단계: Python 환경 준비

프로젝트는 Python 3.10 사용을 권장합니다. README에 기록된 검증 환경은 macOS, Apple Silicon 및 Python 3.10.20이며 CPU와 Apple MPS 경로를 모두 검증했습니다. 다른 플랫폼에서는 Stable-Retro와 PyTorch의 공식 설치 안내를 참고해야 합니다.

프로젝트 루트 디렉터리에 가상 환경을 만들고 활성화한 다음 의존성을 설치합니다.

python3.10 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt

Windows 사용자는 다음 명령으로 가상 환경을 활성화할 수 있습니다.

.venv\Scripts\activate

Anaconda로 Python 3.10 환경을 만든 다음 requirements.txt의 의존성을 설치할 수도 있습니다. 프로젝트의 주요 의존성은 Gymnasium, Stable-Retro, Stable-Baselines3입니다.

2단계: 게임 ROM 준비

Stable-Retro는 게임 ROM을 제공하지 않으며, 이 프로젝트에도 ROM이 포함되어 있지 않습니다. 합법적인 경로를 통해 지원되는 《스트리트 파이터 2: 챔피언 에디션》 미국판 ROM을 구해야 합니다.

ROM을 준비한 후 환경 변수로 절대 경로를 지정할 수 있습니다. macOS 또는 Linux에서는 다음을 실행합니다.

export SF2_ROM_PATH="/absolute/path/to/your/rom.md"

Windows PowerShell에서는 다음을 사용합니다.

$env:SF2_ROM_PATH = "C:\path\to\your\rom.md"

다른 방법으로는 ROM을 프로젝트의 기본 위치에 저장할 수 있습니다.

data/street-fighter-ii-special-champion-edition-usa.md

학습 및 테스트 프로그램이 ROM을 자동으로 가져옵니다. 현재 Python 환경의 Stable-Retro에 해당 ROM이 이미 가져와져 있다면 바로 실행할 수 있습니다.

3단계: 스테이지 데이터 확인

data/ 디렉터리의 12개 .state 파일은 각각 1스테이지부터 12스테이지까지의 시작 상태를 저장합니다. data.json과 scenario_full_frame.json은 게임 메모리 변수와 장면 설정을 정의합니다. 프로그램은 이 파일을 직접 읽으므로 Stable-Retro 설치 디렉터리에 복사할 필요가 없습니다.

사전 학습 모델 실행

전체 12개 스테이지별 테스트

환경 설정을 완료한 후 프로젝트 루트 디렉터리에서 실행합니다.

python -m main.test --episodes 1

프로그램은 1스테이지부터 12스테이지까지의 시작 세이브를 순서대로 불러오며, 각 스테이지는 기본적으로 3판 2선승으로 진행됩니다. --episodes 1은 전체 평가를 1회 진행한다는 의미입니다. 이 매개변수를 생략하면 기본적으로 10회 테스트합니다.

특정 스테이지에서 실패해도 프로그램은 이후 스테이지 테스트를 계속합니다. 터미널에는 각 스테이지의 승패, 보상, 스테이지 승률 및 한 번의 평가에서 12개 스테이지를 모두 이긴 비율이 출력됩니다.

화면을 끄고 평가 결과에 집중

대전을 볼 필요가 없다면 렌더링을 끄고 CPU 추론을 명시적으로 사용할 수 있습니다.

python -m main.test --episodes 1 --no-render --device cpu

렌더링을 끄면 일괄 평가에 적합하며 화면 표시로 인한 추가 오버헤드를 줄일 수 있습니다.

첫 스테이지부터 연속 클리어

AI가 게임의 진행 방식에 따라 다음 상대에게 도전하는 모습을 보려면 다음을 실행합니다.

python -m main.test --episodes 1 --no-load-level-saves

이 모드에서는 시작 시 1스테이지 세이브만 불러오고, 이후에는 게임이 정상적으로 스테이지를 진행합니다. 한 번이라도 실패하면 해당 시도는 종료됩니다. 프로그램은 도전한 스테이지의 승률과 전체 클리어율을 출력합니다.

스테이지별 테스트에서 ‘전체 승리’는 모델이 12개의 독립적인 스테이지 세이브에서 모두 평가를 통과했다는 의미입니다. ‘전체 클리어율’은 한 번의 연속 진행으로 12개 스테이지를 모두 클리어해야 하므로 두 지표의 의미는 다릅니다.

자주 사용하는 테스트 매개변수

  • --model-path PATH: PPO 모델을 지정합니다. 기본값은 logs/trained_models/ppo_ryu.zip입니다.
  • --episodes N: 스테이지별 평가 횟수 또는 연속 클리어 시도 횟수를 설정합니다. 기본값은 10입니다.
  • --no-render: 게임 화면을 끕니다.
  • --no-load-level-saves: 스테이지별 세이브를 불러오지 않고 첫 스테이지부터 연속으로 도전합니다.
  • --reset-round: 스테이지별 테스트에서 기본 3판 2선승 대신 단일 KO를 평가 단위로 사용합니다.
  • --device auto/cpu/cuda/mps: 모델 추론 장치를 선택합니다. 기본값은 auto입니다.
  • --speed N: 표시 프레임 수를 줄여 시각화 속도를 높입니다. 기본값은 4입니다.

직접 모델 학습

소규모 설정으로 시작

기본 학습 설정은 매우 많은 자원을 필요로 합니다. 처음 실행할 때는 각 스테이지에 에뮬레이터 하나만 실행하고 작은 배치 크기를 사용하는 것이 좋습니다.

python -m main.train --envs-per-level 1 --batch-size 256 --log-dir runs/ryu

프로젝트에는 12개 스테이지가 있으므로 --envs-per-level 1은 총 12개의 병렬 에뮬레이터를 실행한다는 의미입니다. ROM, 환경 구성, 장치 및 로그 출력이 모두 정상인지 확인한 후 병렬 수를 점진적으로 늘리십시오.

기본 학습 규모 이해

python -m main.train을 직접 실행하면 각 스테이지에 기본적으로 64개의 에뮬레이터가 실행되어 총 768개의 병렬 환경이 구성됩니다. 기본 n-steps=128과 함께 한 번의 PPO 업데이트에서 98,304개의 샘플을 수집하며, 전체 학습 목표는 7억 스텝입니다.

기본 설정은 충분한 CPU와 메모리를 필요로 하므로 일반 컴퓨터에서 처음 테스트하기에는 적합하지 않습니다. 실제 하드웨어에 맞춰 --envs-per-level, --batch-size 또는 전체 학습 스텝 수를 줄여야 합니다.

자주 사용하는 학습 매개변수

  • --envs-per-level N:각 레벨의 병렬 환경 수입니다. 지정하지 않으면 레벨당 64개입니다.
  • --total-timesteps N:이번 학습의 총 스텝 수입니다. 이어서 학습할 때는 추가 스텝 수를 의미하며, 기본값은 700000000입니다.
  • --n-steps N:각 시뮬레이터가 한 번의 업데이트 전에 수집하는 스텝 수이며, 기본값은 128입니다.
  • --batch-size N:PPO 업데이트 배치 크기이며, 기본값은 8192입니다.
  • --n-epochs N:각 배치 샘플 데이터의 학습 반복 횟수이며, 기본값은 3입니다.
  • --learning-rate N:학습률이며, 기본값은 0.0002입니다.
  • --device auto/cpu/cuda/mps:학습 장치를 선택하며, 기본값은 mps입니다.
  • --log-dir PATH:모델과 학습 곡선의 출력 디렉터리이며, 기본값은 logs/ALL_MOTION_SIMULTANEOUS입니다.

사전 학습 가중치를 사용한 이어서 학습

프로젝트는 제공된 PPO 가중치에서 이어서 학습하는 기능을 지원합니다. 아래 명령은 100만 스텝을 추가로 학습하고 결과를 새 디렉터리에 저장합니다.

python -m main.train \
  --resume-model logs/trained_models/ppo_ryu.zip \
  --envs-per-level 1 --batch-size 256 \
  --total-timesteps 1000000 --log-dir runs/ryu-resume

이어서 학습할 때 --total-timesteps는 이전 모델의 학습량을 포함한 누적 목표가 아니라, 이번에 추가로 실행할 학습 스텝 수를 의미합니다.

TensorBoard로 학습 곡선 확인

프로젝트에는 학습 기록 기능이 내장되어 있습니다. TensorBoard를 시작합니다.

tensorboard --logdir=logs

그런 다음 브라우저에서 http://localhost:6006/을 열면 보상 변화와 모델 업데이트 관련 곡선을 확인할 수 있습니다.

직접 학습하여 생성한 로그를 확인하려면 디렉터리만 바꾸면 됩니다.

tensorboard --logdir=runs/ryu

고급 사용 권장 사항

  1. 먼저 검증한 후 확장하세요. 먼저 레벨당 하나의 환경으로 짧게 학습하여 ROM 가져오기, 저장 데이터 읽기, 로그 기록이 정상인지 확인한 다음 병렬 시뮬레이터 수를 늘리세요.
  2. 플랫폼에 맞는 장치를 지정하세요. Apple Silicon에서는 mps를 시도할 수 있고, 호환되는 NVIDIA GPU 환경에서는 cuda를 선택할 수 있습니다. 그렇지 않으면 cpu 또는 auto를 사용하세요. README는 macOS Apple Silicon 환경에서 검증되었으며, 다른 플랫폼에서는 PyTorch와 Stable-Retro의 요구 사항에 맞춰 구성해야 합니다.
  3. 두 가지 평가를 구분하세요. 레벨별 저장 데이터 테스트는 각 상대의 성능을 분석하는 데 적합하고, 연속 클리어는 전체 게임 흐름에 더 가깝습니다. 결과를 보고할 때 사용한 모드를 명시해야 합니다.
  4. 렌더링 없이 일괄 평가를 진행하세요. 여러 차례 통계를 낼 때는 --no-render를 추가하고, 전략의 동작을 확인할 때만 화면을 활성화하세요.
  5. 실험 결과는 독립 디렉터리에 저장하세요. --log-dir를 사용해 서로 다른 매개변수 조합마다 디렉터리를 만들면 학습 기록이 서로 덮어쓰이는 것을 방지하고 TensorBoard에서 쉽게 비교할 수 있습니다.
  6. 전체 명령 옵션을 확인하세요. 학습 및 테스트 스크립트는 모두 도움말을 제공합니다.
python -m main.train --help
python -m main.test --help

모듈 방식 외에도 프로젝트는 스크립트를 직접 실행할 수 있습니다.

python main/train.py
python main/test.py

맺음말

Ultimate SFighterAI는 픽셀 입력, 동작 매핑, 보상 설계, PPO 및 여러 레벨의 병렬 환경을 하나의 완전한 격투 게임 에이전트로 결합하는 방법을 보여 줍니다. 가장 안정적인 시작 방법은 먼저 ROM을 구성하고 사전 학습 모델을 실행한 다음, 낮은 병렬도로 학습을 재현하고, 마지막으로 이어서 학습, 장치 선택 및 TensorBoard 분석을 통해 실험 규모를 단계적으로 확장하는 것입니다.

이 프로젝트는 Apache License 2.0에 따라 배포되며 Gymnasium, Stable-Retro 및 Stable-Baselines3 등의 오픈 소스 구성 요소를 사용합니다.