Lecture/파이썬으로 만드는 AI 오델로 게임

5 랜덤시도를 통하여 순차 결정 문제 해결

작은별하나 2024. 11. 24. 02:03

1. MDP 문제 풀기

 

MDP(Markov Decision Process, 마르코프 의사결정 과정) 문제를 해결하기 위한 주요 방법들을 각각의 특징과 작동 원리를 중심으로 서술해 보겠습니다.

1) 몬테 카를로 기법(Monte-Carlo Method)

 

Monte-Carlo method



• 핵심 개념: 몬테 카를로 기법은 샘플링을 통해 MDP의 상태 가치나 행동 가치를 추정하는 방법입니다. 환경 모델에 대한 사전 지식이 필요하지 않고, 시뮬레이션을 통해 상태-행동 쌍에 대한 경험 데이터를 수집합니다.
• 작동 방식:
• 에피소드를 여러 번 시뮬레이션하여, 각 상태에 대한 평균 보상을 계산합니다.
• 에피소드 종료 후 얻은 보상 데이터를 기반으로 상태 가치나 행동 가치를 업데이트합니다.
• 주로 에피소드 단위로 학습이 이루어집니다.
• 장점:
• 환경의 모델이 없어도 사용 가능 (모델 프리 학습).
• 정책 평가 및 개선을 점진적으로 수행할 수 있음.
• 단점:
• 학습 과정에서 에피소드 종료까지 기다려야 하기 때문에 즉시 업데이트가 어렵고, 수렴 속도가 느릴 수 있음.

2) 시간차 학습 기법(Temporal Difference, TD Learning)

• 핵심 개념: TD 학습은 상태 또는 행동의 가치를 업데이트할 때 다음 상태에서 관찰된 가치를 즉시 사용하여 업데이트합니다. 이는 몬테 카를로 방법처럼 에피소드가 끝날 때까지 기다리지 않고도 학습을 진행할 수 있도록 합니다.
• 작동 방식:
• 현재 상태에서 취한 행동으로 얻은 보상과 다음 상태의 가치 평가를 결합하여 가치 함수를 갱신합니다.
• 대표적인 알고리즘: SARSA, Q-Learning.
• 장점:
• 에피소드 종료를 기다릴 필요 없이 즉각적인 업데이트 가능.
• 모델 프리 방식으로도 구현 가능.
• 실시간 학습에 적합.
• 단점:
• 초기에는 학습이 불안정할 수 있음.
• 학습률(learning rate) 및 탐험-활용 균형을 잘 설정해야 효과적임.

3) 동적 계획법(Dynamic Programming, DP)

• 핵심 개념: 동적 계획법은 상태 가치와 정책을 반복적으로 계산하여 최적의 정책을 도출하는 방법입니다. MDP의 환경에 대한 완전한 모델(전이 확률과 보상 정보)을 필요로 합니다.
• 작동 방식:
• 상태 가치 함수는 벨만 방정식을 이용하여 업데이트됩니다.
• 가치 반복(Value Iteration) 또는 정책 반복(Policy Iteration) 알고리즘이 대표적입니다.
• 환경 모델을 기반으로 모든 상태에 대해 가능한 상태 전이를 탐색합니다.
• 장점:
• 수렴 보장: 이론적으로 최적 정책을 보장.
• 계산 과정을 체계적으로 수행 가능.
• 단점:
• 환경 모델(전이 확률 및 보상 함수)이 반드시 필요.
• 상태 공간이 커질수록 계산량이 급격히 증가(차원의 저주).

4) 인공 신경망(Artificial Neural Network, ANN)

• 핵심 개념: 인공 신경망을 활용한 방법은 MDP 문제를 함수 근사(Function Approximation) 문제로 변환하여, 상태-행동 가치 함수나 정책을 근사합니다. 특히 딥러닝과 강화학습을 결합한 딥 Q-러닝(DQN) 등이 대표적입니다.
• 작동 방식:
• 상태를 입력으로 받아 상태-행동 가치 또는 행동 확률을 출력하는 신경망을 설계합니다.
• 경험 재현(Experience Replay)과 같은 기법으로 안정성을 향상시키고, 반복적인 학습으로 모델을 개선합니다.
• 장점:
• 대규모 상태 공간에서 효율적.
• 복잡한 환경에서도 좋은 성능 발휘 가능.
• 모델의 일반화 능력을 통해 비슷한 상태에 대해 유효한 행동을 도출 가능.
• 단점:
• 학습 과정이 복잡하며, 많은 데이터와 계산 자원이 필요.
• 하이퍼파라미터 설정 및 과적합 방지에 주의 필요.

이 네 가지 방법은 MDP 문제를 푸는 다양한 상황에서 적합한 방식으로 활용됩니다.
• 환경의 모델 유무: 동적 계획법은 모델을 필요로 하지만, 나머지 방법들은 모델 없이도 사용 가능합니다.
• 계산량과 상태 공간 크기: 상태 공간이 작다면 동적 계획법이 효과적이며, 상태 공간이 클 경우 몬테 카를로, TD 학습, 또는 인공 신경망 기반 방법이 유리합니다.
• 즉각적 업데이트 가능성: TD 학습은 실시간 업데이트가 가능하며, 몬테 카를로 방법은 에피소드 단위 학습에 적합합니다.
• 대규모 문제: 인공 신경망은 복잡하고 큰 상태 공간에서도 효과적인 학습이 가능합니다.

이들 방법은 상황과 문제의 특성에 따라 조합되어 사용되기도 합니다. 예를 들어, 딥 Q-러닝은 시간차 학습과 신경망을 결합한 대표적인 사례입니다.

 

이번에 소개할 몬테카를로 기법의 특성과 자세한 설명을 하겠습니다.

1) 로직이 복잡한 모델에서도 적용 가능 (Model-Free)
몬테카를로 기법은 환경의 정확한 모델(전이 확률 및 보상 함수)을 요구하지 않는 모델 프리(Model-Free) 학습 방법입니다. 이는 복잡한 로직을 가진 시스템이나 환경에 대해 사전 지식 없이도 활용할 수 있음을 의미합니다.
• 실제 환경을 시뮬레이션하여 데이터를 수집하고, 경험을 바탕으로 상태 가치나 행동 가치를 추정합니다.
• 따라서 환경 모델이 없거나 정의하기 어려운 경우에도 유용하게 사용됩니다.

 

2) 에피소드 종료 후 보상을 적용 (Delayed Reward Application)
몬테카를로 기법은 에피소드(시뮬레이션의 한 단계부터 끝까지의 실행)가 종료된 후 얻은 최종 결과값을 기반으로 학습을 진행합니다.
• 중간 상태에서 학습하지 않고, 전체적인 에피소드 결과를 바탕으로 상태 가치나 행동 가치를 계산합니다.
• 이로 인해 시간차 학습(TD Learning)과 비교하면 즉각적인 업데이트가 어렵고, 에피소드의 완전한 실행이 필요합니다.

 

3) 기대값을 기반으로 한 낮은 편향 (Low Bias)
몬테카를로 기법은 많은 시행을 통해 최종 결과의 기대값을 계산하므로, 계산된 기대값이 실제 상태 가치나 행동 가치와 가까워질 가능성이 높습니다.
• 이는 몬테카를로 기법이 낮은 편향(Low Bias) 특성을 가지는 이유입니다.
• 시행 횟수가 적어도 결과 값이 비교적 안정적이고 평균적으로 신뢰할 수 있는 값을 도출합니다.

 

4) 무작위성으로 인해 높은 분산 (High Variance)
몬테카를로 기법은 샘플링에 의존하기 때문에 무작위성이 내재되어 있습니다. 이로 인해 같은 조건에서 시뮬레이션을 여러 번 수행하더라도 결과가 달라질 수 있습니다.
• 이러한 무작위성으로 인해 높은 분산(High Variance) 특성을 가지며, 예측의 정확도가 떨어질 가능성이 있습니다.
• 시행 횟수를 충분히 늘리거나, 결과값을 평균화하여 분산을 줄이는 방식으로 보완할 수 있습니다.

몬테카를로 기법은 복잡한 환경에서도 활용할 수 있는 모델 프리 기법으로, 기대값 계산의 편향은 낮지만, 무작위성으로 인해 분산이 높은 특성을 가집니다. 이 기법은 주로 많은 시행과 데이터를 통해 신뢰도 높은 기대값을 도출하거나, 복잡한 모델에서 사전 정보 없이 학습을 수행할 때 효과적입니다. 다만, 학습 과정에서 에피소드의 완료를 기다려야 하고, 높은 분산 문제를 해결하기 위해 충분한 시행이 요구됩니다.

 

2. 몬테카를로 기법

 

Python의 random 모듈은 난수를 생성하고 다양한 확률적 작업을 수행할 수 있도록 설계된 표준 라이브러리입니다. 시뮬레이션, 데이터 샘플링, 테스트 등의 작업에서 매우 유용하게 사용됩니다. 아래는 주요 함수와 특징에 대한 상세 설명입니다.

1) 모듈 설명

• random 모듈은 난수를 생성하거나 확률 기반 작업을 수행하기 위해 사용됩니다.
• 동일한 실행 결과를 반복적으로 얻고자 할 때는 시드(seed)를 설정하여 난수 생성의 초기값을 고정할 수 있습니다.

2) 주요 함수

2.1 seed(<시드값>)
• 난수 생성기의 초기값(시드값)을 설정하는 함수입니다.
• 특징:
• 동일한 시드값을 설정하면 항상 같은 난수 시퀀스가 생성됩니다.
• 디버깅이나 동일 환경에서의 반복 테스트 시 유용합니다.
• 사용 예:

import random

random.seed(42)
print(random.random())  # 동일한 시드값 설정 시, 항상 같은 결과
print(random.random())


2.2 randrange(stop)
• randrange(stop):
• 0부터 stop-1 사이의 정수 난수를 생성합니다.
• stop은 반드시 양의 정수여야 합니다.
• 사용 예:

print(random.randrange(10))  # 0~9 중 임의의 정수 반환


2.3 randrange(start, stop[, step])
• randrange(start, stop, step):
• start에서 stop-1까지의 범위에서 지정된 간격(step)으로 값을 생성합니다.
• step은 기본적으로 1이며, 지정하지 않으면 연속적인 숫자가 생성됩니다.
• 사용 예:

print(random.randrange(1, 10))      # 1~9 중 임의의 정수 반환
print(random.randrange(1, 10, 2))  # 1, 3, 5, 7, 9 중 임의의 정수 반환


2.4 choice(list)
• choice(list)는 전달받은 리스트(list)에서 임의의 요소를 하나 선택합니다.
• 리스트뿐만 아니라 튜플이나 문자열과 같은 시퀀스 자료형에도 사용할 수 있습니다.
• 사용 예:

items = ['apple', 'banana', 'cherry']
print(random.choice(items))  # 리스트에서 임의의 항목 선택


2.5 shuffle(list)
• shuffle(list)는 리스트의 요소를 무작위로 섞습니다.
• 주의:
• 입력으로 리스트 자료형만 허용합니다.
• 튜플이나 문자열과 같은 불변(immutable) 자료형에는 사용할 수 없습니다.
• 사용 예:

numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers)
print(numbers)  # 리스트가 섞인 결과 출력


3) 활용 예시
3.1 시뮬레이션
• 예를 들어, 주사위 굴리기 시뮬레이션:

import random

for _ in range(5):
    print(random.randint(1, 6))  # 1~6 사이의 정수 난수



3.2 데이터 샘플링
• 임의의 데이터 선택:

names = ['Alice', 'Bob', 'Charlie', 'Diana']
print(random.choice(names))  # 임의의 이름 선택



3.3 순서 섞기
• 카드 섞기 시뮬레이션:

deck = list(range(1, 53))  # 카드 번호 1~52
random.shuffle(deck)
print(deck)  # 섞인 카드 출력


4) 요약
• random 모듈은 난수를 기반으로 데이터 섞기, 샘플링, 범위 내 정수 생성 등을 간단히 수행할 수 있는 강력한 도구입니다.
• 동일한 결과를 반복적으로 얻고 싶다면 seed로 초기값을 설정합니다.
• 다양한 함수(randrange, choice, shuffle 등)를 통해 정수, 리스트 요소 등 여러 형태의 데이터를 다룰 수 있습니다.

 

몬테 카를로 기법을 사용하여 원주율(π)을 추정하는 방법은 4분원의 면적을 계산하는 데 기초합니다. 이를 프로그램으로 구현한 과정을 풀어서 설명하겠습니다.

문제 접근 방법

1) 4분원의 면적과 원주율의 관계
• 원의 방정식. \(  x^2 + y^2 = r^2 \) 에서, 반지름이 1인 원을 고려하면 \(  x^2 + y^2 \leq 1 \) 이 4분원의 조건이 됩니다.
• 이 4분원은 한 변의 길이가 1인 정사각형의 안에 위치합니다.
• 정사각형의 면적은 \(  1 \times 1 = 1  \) 이고, 4분원의 면적은 \(  \pi \times r^2 / 4 = \pi / 4 \) 입니다.
• 따라서, 정사각형 내에 난수를 생성해 점을 찍고, 이 점 중에서 4분원 안에 들어간 점의 비율을 계산하면 이를 통해 원주율을 추정할 수 있습니다.
2) 난수 생성
• [0, 1) 범위에서 x와 y 좌표를 무작위로 생성합니다.
• 생성된 (x, y) 좌표가 \(  x^2 + y^2 \leq 1 \) 을 만족하면, 해당 점은 4분원 안에 위치합니다.
3) 비율 계산
• 생성된 점 중에서 4분원 안에 포함된 점의 수를 총 점의 수로 나누면, 4분원의 면적 비율이 됩니다.
• 이를 4배하면, 원주율(π)을 추정할 수 있습니다.

 

원주율 구하기



이 방법은 난수 생성과 샘플링을 이용해 복잡한 수학적 계산 없이 원주율을 추정할 수 있는 몬테 카를로 기법의 대표적인 예입니다. 이는 컴퓨터 시뮬레이션과 난수 생성의 힘을 보여주는 사례로, 실제 문제의 해결이나 추정 작업에서도 유용하게 사용됩니다.

 

1. 몬테 카를로 기법의 기본 개념

• 몬테 카를로 기법은 무작위(random) 값을 활용해 문제를 해결하거나 근사값을 추정하는 방법입니다.
• 이 기법은 시뮬레이션을 통해 가능한 결과를 무작위로 탐색하고, 이를 바탕으로 평균값이나 확률을 계산합니다.
• 특히, 사전 지식 없이 환경을 탐색하면서 데이터를 축적하므로 모델 프리(Model-Free) 학습 방법으로 분류됩니다.

2. 탐색 방식

• 무작위로 행동을 선택하거나 샘플링을 수행하여 목표 상태에 도달합니다.
• 목표 상태에 도달했을 때 얻는 보상(reward)을 기록하여 학습의 기초 자료로 활용합니다.
• 이는 특정 상태나 행동이 얼마나 좋은지를 측정하고, 학습 과정을 통해 최적의 경로나 행동을 찾도록 돕습니다.

3. 절차 보상

• 몬테 카를로 기법은 특정 상태에서 시작해 목표 지점에 도달할 때까지의 과정을 시뮬레이션합니다.
• 목표 상태에 도달했을 때 얻는 보상값(예: 점수, 성공 여부)을 기반으로 상태에 대한 평가를 수행합니다.
• 전체 에피소드(시뮬레이션 과정)가 종료된 후, 각 상태나 행동에 대해 그 상태에서 시작했을 때 기대할 수 있는 평균 보상을 계산합니다.

4. 상태 공간과 보상값

• 몬테 카를로 기법은 상태 공간(state space)에서 발생한 보상값을 각 상태에 저장합니다.
• 저장된 값은 단순히 해당 상태에서 관찰된 보상의 평균이며, 이를 통해 상태의 가치를 추정합니다.
• 이렇게 상태 공간에서의 가치를 점진적으로 업데이트하여, 결국 최적 경로 또는 정책을 도출합니다.

5. 요약 특성

1. 무작위성을 활용:
• 몬테 카를로 기법은 무작위적으로 다양한 시뮬레이션을 수행하면서 데이터를 축적합니다.
2. 에피소드 단위 학습:
• 에피소드(한 번의 시뮬레이션)가 완료된 후, 그 결과를 바탕으로 상태 가치나 행동 가치를 갱신합니다.
3. 평균 보상 저장:
• 특정 상태에서의 보상값을 누적하여 평균을 계산하며, 이는 상태의 기대 가치를 나타냅니다.
4. 단점:
• 에피소드가 완료될 때까지 기다려야 학습이 진행되므로 실시간 업데이트가 어렵습니다.
• 무작위성이 높아 초기에는 학습이 불안정할 수 있습니다.

6. 응용 사례

• 몬테 카를로 기법은 게임 플레이, 경로 최적화, 추정 문제 등에서 사용되며, 강화학습(특히 정책 평가 및 정책 개선)에서도 중요한 역할을 합니다.

 

격자 세계의 구조

1. 격자 세계 정의:
• 격자 세계는 셀(cell)로 이루어진 정사각형 공간입니다. 각 셀은 에이전트가 이동할 수 있는 상태(state)를 나타냅니다.
• 상태 공간은 격자의 크기에 따라 정의되며, 예를 들어  격자에서는 총 25개의 상태가 존재합니다.
2. 특정 요소:
• 에이전트(★): 격자 내에서 이동하며 목표에 도달하기 위해 경로를 찾는 주체입니다.
• 장애물(■): 에이전트가 통과할 수 없는 셀로, 경로를 제한합니다.
• 목표(○): 에이전트가 도달해야 하는 최종 지점으로, 보상을 얻는 상태입니다.

 


격자 세계에서의 문제 정의

• 에이전트(★)는 시작 지점에서 목표 지점(○)까지 이동하는 경로를 찾아야 합니다.
• 에이전트는 다음과 같은 규칙에 따라 행동합니다:
1. 가능한 행동:
• 에이전트는 상, 하, 좌, 우로 이동할 수 있습니다.
• 격자 밖으로 나가거나 장애물(■)이 있는 셀로 이동할 수 없습니다.
2. 목표:
• 가능한 최단 경로나 보상이 최대인 경로를 선택하여 목표(○)에 도달하는 것이 목적입니다.

몬테 카를로 기법을 활용한 경로 학습

1. 초기 조건:
• 에이전트는 환경(격자 세계)에 대한 사전 지식 없이 무작위로 행동을 시작합니다.
• 각 상태에 대한 보상이나 가치 정보를 축적하면서 최적 경로를 학습합니다.
2. 탐색 과정:
• 에이전트는 무작위로 이동하며, 장애물(■)을 피하고 목표(○)에 도달할 수 있는 여러 경로를 탐색합니다.
• 목표 지점에 도달하면 해당 에피소드가 종료됩니다.
3. 보상 계산:
• 목표 상태(○)에서는 높은 보상을 부여합니다(예: +1).
• 그 외의 상태에서는 0 또는 작은 보상을 부여할 수 있습니다.
• 장애물에 닿거나 격자를 벗어나려는 시도는 불가능하며, 보상이 주어지지 않습니다.
4. 상태 가치 업데이트:
• 에피소드가 종료된 후, 각 상태에서 얻어진 보상을 평균적으로 계산하여 상태 가치를 갱신합니다.
• 에이전트는 시간이 지남에 따라 높은 보상을 얻을 가능성이 큰 상태를 선택하는 경향을 학습합니다.

격자 세계에서의 상태변수 선택과 상태 공간 생성

1. 상태변수 선택

• 상태변수란?
상태변수는 현재 상태를 정의하는 요소로, 에이전트가 처한 상황이나 환경을 표현하는 데 사용됩니다.
격자 세계에서 상태변수는 에이전트의 위치를 나타냅니다.
• 격자 세계의 상태변수 정의
• 격자가  크기라면, 상태변수는 에이전트의 위치를  좌표로 나타낼 수 있습니다.
• 예를 들어, 격자 세계가 라면 상태변수는 와 같이 정의됩니다.
• 특정 위치에 장애물이나 목표 지점이 있더라도, 에이전트의 상태는 단순히 위치로 표현됩니다.
• 왜 상태변수가 중요할까?
• 상태변수는 에이전트의 학습에서 핵심입니다.
• 각 상태에 대해 가치(value)나 보상(reward)을 계산하며, 이는 에이전트가 최적의 행동을 선택하는 기준이 됩니다.
• 잘못된 상태변수 정의는 학습을 방해하거나 성능을 저하시킬 수 있습니다.

2. 상태 공간 생성

• 상태 공간이란?
상태 공간은 가능한 모든 상태변수의 집합으로, 격자 세계에서는 에이전트가 이동할 수 있는 모든 위치를 포함합니다.
\( n \times m \) 크기의 격자에서는 \( n \times m \) 개의 상태가 존재합니다.
• 상태 공간 초기화
• 각 상태는 초기에 학습되지 않았기 때문에, 모든 상태의 가치를 0으로 설정합니다.
• 이는 학습이 진행되며 각 상태에 대한 평균 보상이 업데이트될 준비 상태를 의미합니다.

 

격자 세계에서 에이전트가 이동할 수 있는 위치를 무작위로 선택하는 과정을 서술하겠습니다.

1. 에이전트 이동의 전제

• 에이전트는 상, 하, 좌, 우로 이동할 수 있습니다.
• 이동 가능한 조건:
1. 격자의 경계를 벗어나지 않아야 함: 에이전트는 격자 세계 내부에만 머물러야 하며, 경계를 넘을 수 없습니다.
2. 장애물(■)이 있는 칸으로 이동 불가: 특정 위치에 장애물이 있을 경우, 해당 방향으로의 이동이 허용되지 않습니다.

2. 이동 가능한 위치의 결정 과정

1. 현재 위치 확인:
• 에이전트의 현재 위치를 (x, y) 로 설정합니다.
2. 이동 가능한 방향 계산:
• 에이전트가 이동할 수 있는 상, 하, 좌, 우의 좌표를 계산합니다.
• 상(up): (x, y-1)
• 하(down): (x, y+1)
• 좌(left): (x-1, y)
• 우(right): (x+1, y)
• 이 때, 경계를 벗어나거나 장애물이 있는 위치는 제외합니다.
3. 무작위 선택:
• 이동 가능한 위치들 중 하나를 무작위로 선택합니다.
• 이를 위해 Python의 random.choice를 사용할 수 있습니다.

에이전트가 격자 세계에서 목적지에 도달할 때까지의 과정을 반복하며, 그동안의 상태를 저장하고, 목적지에 도달하면 에피소드를 완료하는 과정을 서술하겠습니다.

에피소드 종료:
• 에이전트가 목적지에 도달하면 에피소드가 완료됩니다.
• 에피소드 동안 기록한 상태와 행동은 학습에 활용됩니다.
보상 계산:
• 에피소드가 종료되면 에이전트가 기록한 상태들을 기반으로 보상을 계산합니다.
• 예를 들어, 목적지에 도달한 상태에는 높은 보상(예: 0)을, 다른 상태에는 낮은 보상(예: -1)을 부여합니다.

3. 구현

클래스 이름 : GridWorld
멤버 변수
map : 격자세계의 세계 정보를 저장
agent : 격자세계를 여행할 에이전트
start : 시작 위치
end : 도착 위치

 

import random  # 몬테 카를로 기법에서 사용할 무작위 수 모듈

# 격자세계를 읽고 프로세스할 클래스
class GridWorld:
    # 생성자: 격자 환경 초기화
    def __init__(self, fname):
        """
        파일에서 격자 정보를 읽어 초기화.
        - fname: 격자 환경 파일 이름
        """
        # 비어있는 맵으로 초기화
        self.map = []
        # fname으로 파일을 열어서 처리
        with open(fname) as f:
            # 첫 줄: 격자 크기 (행 개수 n, 열 개수 m)
            self.n, self.m = map(int, f.readline().split())
            # 두 번째 줄: 에이전트 시작 위치 (행, 열)
            self.start = tuple(map(int, f.readline().split()))
            # 세 번째 줄: 목표 위치 (행, 열)
            self.end = tuple(map(int, f.readline().split()))
            # 나머지 줄: 격자 맵 정보
            for _ in range(self.n):
                # 0은 이동 가능, 1은 장애물
                self.map.append(
                    [0 if k == '0' else 1 for k in f.readline()
                         if k == '0' or k == '1'])

    # 환경을 초기화
    def init(self):
        """
        환경 초기화 함수: 에이전트를 시작 지점으로 이동.
        """
        # 에이전트 위치를 시작 지점으로 설정
        self.agent = self.start
        return self.agent

    # 에이전트를 움직인다.
    def move(self, dir):
        """
        에이전트를 주어진 방향으로 이동.
        - dir: 0=상, 1=우, 2=하, 3=좌 (방향)
        """
        # 방향에 따른 이동 벡터 (상, 우, 하, 좌)
        dxy = [ (0, 1), (1, 0), (0, -1), (-1, 0) ]
        # 이동 후의 새로운 위치 계산
        nr, nc = self.agent[0]+dxy[dir][0], self.agent[1]+dxy[dir][1]
        # 이동 가능한 위치인지 확인
        if nr<0 or nr>=self.n or nc<0 or nc>=self.m or self.map[nr][nc]!=0:
            # 이동 불가능한 경우, 위치 유지
            nr, nc = self.agent
        # 에이전트의 위치 업데이트
        self.agent = (nr, nc)
        return self.agent

    # 목적지 도착 여부 검사
    def isFinish(self):
        """
        현재 위치가 목표 지점인지 확인.
        - 반환값: True(목적지 도달), False(아직 도달하지 않음)
        """
        return self.agent == self.end

    # 결과값 출력하기
    def print(self, ss):
        """
        격자 상태를 시각적으로 출력.
        - ss: 각 상태의 [평균 보상, 방문 횟수]를 저장한 2D 배열
        """
        # 맵의 가로 경계선 출력
        print("-"*(9*self.m))
        for r in range(self.n):
            line = ""
            for c in range(self.m):
                # 장애물은 #####로 표시
                if self.map[r][c] == 1: 
                    line += " [#####] "
                # 방문하지 않은 상태는 빈칸으로 표시
                elif ss[r][c][1] == 0: 
                    line += "         "
                # 방문한 상태는 평균 보상을 출력
                else: 
                    line += "{:^9.2f}".format(ss[r][c][0]/ss[r][c][1])
            print(line)
        # 맵의 가로 경계선 출력
        print("-"*(9*self.m))

 

이 프로그램은 격자 세계(Grid World)를 정의하고, 몬테 카를로 기법을 통해 에이전트의 이동 및 학습을 처리하는 구조로 작성되었습니다. 이를 통해, 에이전트는 시작 지점에서 목표 지점까지 이동하는 시뮬레이션을 반복하며 상태를 학습할 수 있습니다.

아래에 이 프로그램의 구성과 동작 원리를 단계별로 설명하겠습니다.

1. 프로그램 구성

이 프로그램은 GridWorld라는 클래스를 중심으로 동작하며, 다음과 같은 주요 기능을 포함합니다:
1. 격자 세계 초기화 (__init__)
• 격자의 크기(n x m), 시작 지점, 종료 지점, 격자 맵(장애물 포함)을 파일에서 읽어 초기화합니다.
• 맵에서 0은 이동 가능한 위치를 의미합니다.  1은 장애물로, 이동할 수 없는 위치입니다.
2. 환경 초기화 (init)
• 에이전트의 초기 위치를 시작 지점으로 설정하고 반환합니다.
3. 에이전트 이동 (move)
• 에이전트가 상, 하, 좌, 우로 이동할 수 있습니다.
• 이동하려는 위치가 격자의 경계를 벗어나거나 장애물이 있는 경우, 에이전트는 움직이지 않습니다.
• 에이전트의 새로운 위치를 반환합니다.
4. 목적지 도착 여부 확인 (isFinish)
• 에이전트가 현재 위치에서 목표 지점에 도달했는지 확인합니다.
• 목표에 도달하면 True를 반환하고, 그렇지 않으면 False를 반환합니다.
5. 결과 출력 (print)
• 격자 상태와 학습 정보를 보기 좋게 출력합니다.
• 각 격자 셀에 학습된 평균 보상을 시각화합니다.

테스트 맵

4 4
0 0
2 2
0000
0010
0100
0000

 

실행 결과

9 7
0 2
8 6
0000000
1011110
0010000
0110111
0010000
1011110
0000000
0101010
0001000
반응형