생각하는 지능

본 토픽은 현재 준비중입니다. 공동공부에 참여하시면 완성 되었을 때 알려드립니다.

문제 해결 에이전트의 예제

지능적 에이전트는 무엇인가를 스스로 할수있는 능력을 가진 어떤것입니다. 스스로 무엇을 한다는 것은 스스로 목적을 결정하고 올바른 행동이 무엇인지 판단합니다. 이번 문제 해결 에이전트는 스스로 목표나 목적을 판단하지 못하지만 어떻게 행동하는게 좋은지는 판단할 수 있습니다. 아직은 사람이 많이 개입하야하는 에이전트를 보게 될겁니다. 지금은 단계에서는 스스로 무엇인가를 할 수 있는 에이전트릉 보는것이 아닌 에이전트가 목표와 문제를 확인하고 어떤 행동을 해야하는지 결정하고 실행하는 전체 과정을 보는 것입니다. 스스로 무엇인가를 하는 능력은 나중에 다루게 될 것입니다. 아직은 스스로 하는 능력이 부족하지만 기본적인 작동 과정을 이해하고 나서 배우게 된다면 좋을것입니다. 

 

## 문제 해결 에이전트의 과정

가장 먼저 시작할 에이전트는 문제 해결 에이전트입니다. 에이전트마다 적합한 환경이 있는데 이번 에이전트는 목표를 먼저 선정하고 시작하는 구조입니다. 생각보다 간단하고 상식적인 구조로 되어있습니다.

 

문제 해결 에이전트는 먼저 목표를 선정하는 하고 그 목표를 해결하기 위해서 어떤 문제가 있는지를 확인합니다. 목표를 위한 문제가 무엇인지 어느 정도 정리가 되었다면 에이전트는 본격적인 검색을 시작합니다. 여기서 문제에 따라서 조금씩 다른 형태의 검색방법이 존재하는데 조금 변형된 형태이지 크게 달라지는건 아닙니다. 그 원리는 비슷하다는 의미입니다. 

 

목표 - 문제 - 검색 - 실행

이 과정이 상식적이지 않습니까?

어떤 목표(목표)가 있으면 어떻게 해결해가는게 좋은지 판단(검색)하고 실행(실행)하면 되는 일입니다. 그리고 문제는 현재 무슨 상황인지 정리하는 것을 이야기합니다. 내가 부산까지 차를 타고 가려고 한다면 적어도 내가 어디서 출발하는지 무엇을 타고 갈수있는지는 알아야 가능하겠죠. 현재의 상황과 예측을 해보는 것이 문제입니다.  

 

### 목표

문제 해결 에이전트가 작동하는 과정을 보겠습니다.

목표를 선정하는 것을 '목표 형식화'라고 합니다. 아주 간단합니다. 부산에 도착하는 것이 목표니까요. 지금배우는것이 지능을 가진 에이전트가 아니기때문에 사람이 목표를 선정합니다. 사람이 원하는것이 목표가 되니까요. 

 

### 문제

문제도 '문제 형식화'라고 합니다. 문제 형식화는 4가지 정보를 이용하면 현재 상황과 예측을 할 수 있습니다. 

초기상태 - 동작 - 전이모형 - 소요비용

지금상태와

할수있는 행동들과

그 행동을 하면 일어나는 일들

그리고 소요비용

 

점점 내용이 깊어지면서 새로운 용어들이 많이 등장합니다. 다 이해하기 싫다면 세부적인 내용은 패스하셔도 됩니다. 전체적인 흐름을 먼저 설명드릴테니까요.

 

여기서 함수를 이야기하면 조금 복잡할 수 있겠지만 생각해보겠습니다. 윗 글을 보면 이론적인 개념을 이야기했습니다. 그러나 이 개념을 항상 코딩할때 사용한다는 것을 알아야합니다. 목표 형식화도 결국 하나의 함수를 이용해서 목표를 형식화하며, 문제는 4가지 정보로 검색하는 과정에서 사용 가능하도록 저장소에 저장해둡니다. 나중에 검색하는 과정에서 저장된 내용을 이용하게 되는 것이죠. 

 

### 검색

아무튼 목표, 문제 형식화를 했으니 이제는 검색할 차례입니다. 미로를 푸는 과정을 생각해보면 검색하는 방법을 알 수 있습니다. 사람도 위에서 말한 검색을 통해서 미로를 풀게됩니다. 

시작점에서 출발하면 (1)갈래길이 나옵니다. 하나를 선택해서 가다보면 또 (2)갈래길이 나오죠. 그러다 막히면 돌아갑니다. 처음 나왔던 (1)갈래길에서 시작할까 아니면 (2)갈래길에서 시작할까요? 

목표나 문제에 따라서 검색방법이 조금 다르다고 말씀드린 부분이 이런겁니다. (1)이나 (2)나 지금 상황에서는 무엇을 선택하던 크게 상관없죠. 그리고 이정도 가지고 검색 방법이 조금 달라진다니 그런말할 이유도 없습니다. 그래서 이제 더 큰 상황으로 가보겠습니다. 

갈래길이 나오면 무조건 오른쪽으로 이동하는 겁니다. 그러다가 막히면 바로 직전의 갈래길에서 왼쪽으로 가는겁니다. 그리고는 또 다시 오른쪽으로만 이동합니다. 이렇게 오다보니 (146) 갈래길을 만났습니다. 막다른 길이네요. 직전으로 돌아갔더니 가본 길입니다. 그렇게 전부 단 가본길만 나와서 계속 되돌아갔습니다. 그러다보니 (5)갈래길까지 왔습니다. (5)갈래길에서 왼쪽으로 가봅니다. 그렇게해서 갔더니 이번에는 (234)갈래길까지 갔는데도 원하던 목표가 안보입니다. 어떻게 된걸까요? 목표는 어디죠? 사실 목표는 (1)갈래길에서 왼쪽으로 가야 나옵니다. 지금까지 오른쪽으로만 다녔으니 (1)갈래길에서부터 헛고생한거죠. 

그럼 이제 생각이 바뀌어서 갈래길이 나오면 오른쪽 왼쪽 한번씩 다 가봅니다. 출발점을 기준으로 항상 같은 거리까지만 가봅니다. 이해가 잘안되죠? 그림이 필요합니다. 이번 검색의 문제는 갈래길을 500번을 지나야 목표를 발견할 수있었는데 거기까지 가는 모든 곳을 다 찾아본겁니다. 

하나만 더 보죠. 100개의 도시를 한번씩 다 갔다와야하는데 이 와중에서도 최적의 길을 찾아야합니다. 전에 이야기한 방식과는 조금 다릅니다. 아까는 단순히 목표만 찾으면 되었는데 이번에는 모든 곳을 다 가보라고 합니다. 그전에도 갔던 곳을 기억하는건 했습니다. 그러나 오른쪽으로 갔다 왼쪽으로 갔다하는 정보만 저장해두면 되는 상황이였습니다. 다시 되돌아가도 어느쪽으로 갔는지 안갔는지만 알면되니까요. 

그런데 이번에는 좀 다릅니다. 갔던 장소를 기억해둬야합니다. 그리고 갔던 순서를 기억해야합니다. 거기에 최적의 길을 찾아야합니다. 비슷한듯 다른 문제릉 보고 있는겁니다. 

 

지금 무슨 이야기를 하는지 감이 오시나요? 상황에 따라서 조금씩 다르다는 겁니다. 그렇다면 어떤 검색 방법을 사용하는게 가장 좋을지 판단하는 녀석도 필요하지 않을까요? 당연히 컴퓨터 과학자들이 만들어두었죠. 일단 이건 그냥 넘어가도록 하죠. 어쨋든 위에 3가지 검색과정을 보면 다르다는것을 알수있죠. 이걸 만든 사람들이 이름을 정했는데 '깊이 우선 검색', '너비 우선 검색' 등등이 있습니다. 이름이 어려워서 처음에 이름만 접하면 이해하기가 싫어집니다. 그렇다고해서 이름을 몰라야되는건 아닙니다. 사회적 동물이라 타인과 소통을 하야하니까요. 

 

### 실행

다음으로는 실행을 해야합니다. 실행이라는것을 설명할때는 항상 동작열이라는 개념을 이해해야합니다. 새로운 용어의 등장을 별로 좋아하지 않지만 이 표현이 제일

적합한거같아서 그냥 쓰겠습니다. '동작열'이라는게 행동들을 순서대로 모아둔 것입니다. 실행을 할때 동작열의 행동대로 실행하면 된다는 뜻이죠. (245)갈래길에서 오른쪽으로 가면 목표가 있다고 한다면, (245)갈래길까지 이동하는 것을 동작열이라고 합니다. (1)에서 왼쪽, (2)에서 오른쪽, (3)에서 오른쪽 ..... (245)에서 오른쪽 이렇게 행동들의 순서의 집합입니다. 즉, 검색한 결과가 '해답'이라는 이름으로 나왔으면 해답을 가지고 동작열을 만듭니다. 이때 해답을 동작열로 바꾸는 이유는 해답이 동작을 추천해주면 선택은 에이전트가 하면 되는거라고 생각하시면 됩니다. 검색은 목표를 위한 하나의 도구일 뿐입니다. 선택은 에이전트가 하는거죠. 

 

그렇게 하여 모든 과정이 끝났습니다. 문제 해결 에이전트는 이렇게 목표와 문제를 형식화해서 검색을 합니다. 나오는 해답으로 동작열을 만들어서 실행하는거죠. 

 

## 프로그램 예제

아래 보이는 내용은 앞에서 말한 내용 중 하나를 프로그램 언어로 작성해두었습니다. 이 내용은 책에서 그대로 발취한 내용입니다.

----

function SIMPLE-PROBLEM-SOLVING-AGENT(percept) returns 하나의 동작

   지속 변수: seq, 동작열, 초기에는 비어 있음

          state, 현재 세계 상태에 대한 어떤 서술

          goal, 목표, 초기에는 무(null)

          problem, 형식화된 문제

state <-- UPDATE-STATE(state, percept)

   if seq가 비었음 then 

    goal <-- FORMULATE-GOAL(state, goal)

    problem <-- FORMULATE-PROBLEM(state, goal)

    seq <-- SEARCH(problem)

    if seq = failure then return 무 동작

   action <-- REST(seq)

   return action

----

 

앞에서 설명한 함수가 이제 나옵니다.

가장 먼저 function이라는 단어로 시작하죠. 

단어 뒤에 ( ) 있다면 이게 함수입니다

SEARCH(problem)

이것도 SEARCH 함수입니다.

에이전트가 문제를 형식화하면 그 다음에 문제를 가지고 검색을 한다고 했는데 그 말이 실제로 함수를 사용한다는 뜻입니다. 

괄호 안이 있는 problem이 정보를 넣어주는것이고 

그 정보를 가지고 SEARCH라는 함수를 실행하면 해답이 나옵니다.

 

''분명 어렵습니다. 함수를 아해하는것도 어려운데 그 전이 배운 내용을 응용해야하는 것이 분명 어려운 일입니다. 만약 쉽게 이해가 되지 않는다면 프로그래밍에 대한 기초를 알고 있어야합니다. 파이썬을 먼저 배워보시길 바랍니다. 그러나. 설명해봅니다. 잘 알고 계시는 분들은 그냥 무시하고 넘어가주세요.

 

앞에 function으로 시작하는 단락이 있죠

그리고 state로 시작하는 단락이 있습니다

앞의 function부분은 정보를 입력하는 작업이고

뒤의 state부분은 입력된 정보로 함수를 동작시켜 원하는 결과가 나오게하는 작업입니다.

<--  이게 들어가있는 줄을 보면 항상 함수가 있죠

함수에서 만들어진 결과를 앞에 전달해주는 겁니다

~~ seq <-- SEARCH(problem)

문제problem를 가지고 검색SEARCH하는 함수를 작동 합니다

검색을 통해서 해답이 나오면 seq에다가 저장해두는 겁니다.

그리고 

~~ if seq가 비었음 then 

이 줄의 의미는 만약에 seq에 아무런 정보도 없다면 then 이하를 실행하면 된다는 뜻입니다. 

UPDATE-STATE 함수로 현재 상태를 파악하고

FORMULATE-GOAL로 목표를 선정합니다(목표 형식화).

FORMULATE-PROBLEM으로 문제를 형식화합니다.

SEARCH로 검색을 합니다.

REST함수로 해답을 실제 동작으로 바꾸는거죠.

 

위에 나와있던 코딩이 하나의 함수라고 말씀드렸죠?

우리는 지금까지 하나의 함수를 뜯어보고 있었습니다

위에 나온 여러가지 함수는 결국 SIMPLE-PROBLEM-SOLVING-AGENT를 작동시키기 위해서 필요했던 함수이죠.

우리가 원하는 것은 SIMPLE-PROBLEM-SOLVING-AGENT함수를 통해서 나오는 결과값이였죠.

SIMPLE-PROBLEM-SOLVING-AGENT함수안에 많은 함수들이 들었있다고 하더라도 원하는 결과만 나오면 됩니다. 

그럼 이 함수의 결과물은 어떻게 나가는 걸까요?

SEARCH함수를 사용해서 나오는 결과값을 seq에 넣어주는 것은 SEARCH함수 안에서 모든 계산을 다 끝내고 난 후 return이라는 코드로 그 정보를 밖으로 내보내줍니다. 그 값이 seq에 들어가는거죠. 

그래서 SIMPLE-PROBLEM-SOLVING-AGENT함수의 제일 마지막에 return action이 적혀있죠.

결과적으로 무수히 많은 함수를 써서 action에 정보를 담아두고, 마지막에는 action에 들어있는 정보를 밖으로 내보내는거죠. 밖으로 나온 action은 seq <-- 를 만나서 seq로 값이 들어갑니다. 그리고 REST함수에 의해서 action에 있던 정보들이 동작열로 바뀌게 됩니다. 

 

* 파이썬으로 작성한 것도 보여드리겠습니다.

class SimpleProblemSolvingAgent(agents.Agent):

    def __init__(self):

        Agent.__init__(self)

        state = []

        seq = []

        def program(percept):

            state = self.update_state(state, percept)

            if not seq:

                goal = self.formulate_goal(state)

                problem = self.formulate_problem(state, goal)

                seq = self.search(problem)

            action = seq[0]

            seq[0:1] = []

            return action

        self.program = program

 

함수를 구성하고 있는 구조는 같습니다. 

다만, 프로그래밍 언어마다 작성하는 방법이 조금씩 다른거죠.

파이썬이라는 언어를 사용해서 작성하면 저렇게 작성할 수 있습니다.

그러니까 언어가 중요한게 아니라 함수가 어떤 방식으로 작동하는지 만들거나 이해하는게 중요합니다.

 

처음 보여준 코드는 수도코드(pseudocode)로 작성한 것이며

다음 보여준 코드는 파이썬(python)으로 작성한 것입니다.

  • 봤어요 (0명)

댓글

댓글 본문
작성자
비밀번호
버전 관리
Braden
현재 버전
선택 버전
graphittie 자세히 보기