본문 바로가기
Lecture/파이썬으로 만드는 AI 오델로 게임

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

by 작은별하나 2024. 11. 24.
반응형

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
728x90

댓글