역 퍼지화 (Defuzzification)
어떤 로직을 통해 퍼지 집합들의 소속도를 구했다고 가정하자. 소속도 그 자체는 사용하기 힘든 데이터이기 때문에 이걸 다시 쓸만한 데이터로 바꾸는 과정이 필요하다. 이 과정을 역 퍼지화(Defuzzification)라고 한다.
위와 같은 소속함수가 있다고 하자. 그리고 어떤 로직을 통해 퍼지 집합 {"기어가기", "걷기", "달리기"}에 대해 각각 0.2, 0.7, 0.5의 소속도를 얻어 냈다고 하자. 이걸 다시 '이동 속도'로 변환할 수 있을까?
적어도 위 소속함수 그래프에서 소속도를 다시 이동속도로 변환하기는 어려울 것 같다. 따라서 역퍼지화에는 이를 위한 여러가지 기법이 있으며 퍼지화와 달리 '이게 정답이다'하는 방법이 존재하지도 않는다.
다음은 역퍼지화 기법들이다.
가장 높은 소속도를 사용하기
말 그대로 가장 높은 소속도를 채용하는 것이다.
예를 들어, {"기어가기", "걷기", "달리기"}의 소속도가 각각 0.2, 0.7, 0.5라고 하자. 그러면 "걷기" 집합을 선택한다. 그러고 나서 "걷기" 집합의 소속함수를 가져와 그 중 한 점을 선택하면 된다. 보통은 다음 네 점중 하나를 선택한다.
- 소속도가 최대인 지점의 최솟값 (최댓값의 최솟값)
- 소속도가 최대인 지점의 최댓값 (최댓값의 최댓값)
- 소속도가 최대인 지점들의 평균값 (최댓값의 평균)
- 소속 함수의 면적을 이등분하는 지점 (넓이의 중간)
이런 방식은 굉장히 빠르지만 결과가 조잡하다. {"기어가기", "걷기", "달리기"}가 각각 0, 0, 1인 경우와 각각 0.33, 0.33, 0.34인 경우가 동일한 결과를 반환한다.
이 때, 넓이의 중간을 구하는 과정은 시간이 꽤 걸릴 수 있기 때문에 넓이의 중간값은 미리 구해놓는게 좋다. (어쩌피 불변함)
소속도를 잘 섞기(Blending)
위 방법과 비슷한데, 최대인 소속도를 가지는 집합을 선택하는 대신, 모든 집합을 선택하고 동일한 방법으로 결과를 얻어낸다. 그 다음 각각의 결과값에 소속도를 곱한뒤 더하여 최종 결과값을 얻어낸다. 이 때, 최종 결과값이 적절하게 normalize되어있도록 처리가 필요할 수 있다.
예를 들어, {"기어가기", "걷기", "달리기"}의 소속도가 각각 0.2, 0.7, 0.5라고 하자. 그러면 각각의 소속함수로 부터 적당한 값을 선택한다. 그 결과 나온 이동속도를 각각 $v_{creep}, v_{walk}, v_{run}$이라고 한다면 최종 결과값은 다음과 같다.
$$0.2v_{creep} + 0.7v_{walk} + 0.5v_{run}$$
위의 결과값으로 얻은 최종 이동속도가 달리기의 최대 이동속도보다 클 수 있으므로 이를 normalize하는 과정이 필요하다.
이건 딱히 중요한 건 아닌데, 영어 원문 참고용 각각의 방법의 명칭을 적자면
최댓값의 최솟값을 골라서 섞은 경우 : Smallest of Maximum method, Left of Maximum(LM)
최댓값의 최댓값을 골라서 섞은 경우 : Largest of maximum(LM), Right of Maximum(RM)
최댓값의 평균값을 골라서 섞은 경우 : Mean of Maximum (MoM)
무게 중심(Center of Gravity)
centroid of area라고도 불린다.
각각의 소속 함수에서 소속도 이하의 면적을 모두 색칠하여 더한 면적의 무게 중심을 기준으로 정한뒤 그 값을 반환한다.
예를 들어 {"기어가기", "걷기", "달리기"}의 소속도가 각각 0.2, 0.7, 0.5이라면 아래와 같이 색칠한 뒤 총 면적의 무게중심을 구한다. 그 무게중심이 위치한 x축의 값 (이동속도)를 반환한다.
굉장히 많이 쓰이는 방법이지만 시간이 오래걸린다.
IEEE에서 퍼지 로직을 컨트롤 하기 위한 비슷한 방법이 존재하는데, 이 방법에서는 각각의 소속 함수를 잘라내지 않고 그냥 소속 함수의 무게 중심을 사용한다. (따라서 무게 중심값을 미리 구할 수 있으므로 빠르다.) 그다음에 이걸 각각의 소속도와 blend한다.
역퍼지화 방법 고르기
무게 중심을 사용하는 방법이 많은 퍼지 로직에서 선택되는 방법이다. 그러나 이 방법은 구현이 복잡하고 느리며 새로운 소속 함수를 추가하기 까다로워 진다는 단점이 있다.
반면, 소속도를 blend하는 방법은 적당히 훌륭한 결과를 반환하면서 빠르다.
때로는 소속 함수를 아예 배제하고 그냥 값을 직접 리턴하는 방법도 있다. 즉, 별도의 역 퍼지화 전용 함수를 만들어서 빠르게 값을 리턴하는 것. 그다음 이를 blend하여 사용할 수 있다. 예를 들어 {"기어가기", "걷기", "달리기"}의 경우 소속도에 상관 없이 그냥 각각 1,4,20의 이동속도를 반환하도록 할 수 있다. 그리고 이를 소속도와 곱한 뒤 더한다음 normalize한다.
Boolean 값의 역퍼지화
만약 하나의 퍼지 셋이라면 그냥 기준값을 정한 뒤 이것을 넘으면 1 아니면 0을 반환하면 된다. 만약에 퍼지 셋이 여러 개가 있는 경우라면 아래 설명할 퍼지 규칙을 사용해야 한다.
Enum값의 역퍼지화
Enum값은 그 값에 순서를 정할 수 있느냐 없느냐로 방법이 나뉜다. 순서를 정할 수 있는 경우는 게임의 티어 (ex 브론즈, 실버, 골드, 플래티넘, 다이아) 같은 경우이고, 순서를 정할 수 없는 경우는 무기 종류(ex. 근접무기, 총, 수류탄)가 있다.
순서를 정할 수 있는 경우는 enum값을 순서대로 배치한 뒤 주어진 소속도가 어디 쯤에 위치하는지로 값을 정할 수 있다. 예를 들어 {브론즈, 실버, 골드, 플래티넘, 다이아} 같은 경우
위와 같이 정렬할 수 있다. 만약 "게임 실력"을 역퍼지화 해서 나온 값이 0.68이라면 플래티넘을 반환한다.
순서를 정할 수 없는 경우는 그냥 가장 높은 소속도를 지닌 값을 선택하면 된다.
퍼지 규칙(Fuzzy Rules)
전통적인 로직에서 지금 '비가온다'와 '춥다'가 참이라면 '비가 오고 춥다'역시 참이다. 그런데 퍼지 로직에서0.6만큼 비가 오고 있고 0.4만큼 추운 상황이라면 '비가 오고 춥다'라는 명제는 얼마나 참일까?
명제 조합하기
위 명제를 판단하기 전에 우선 퍼지 로직에서의 AND / OR / NOT 연산에 대해 알아야 한다. 전통적인 로직은 참/거짓 둘 중 하나만 판단하지만 퍼지 로직에서는 명제가 0.6만큼 참이거나 0.3만큼 참일 수 있다.
퍼지 로직에서 AND는 다음과 같다.
$$m_{A\&B} = min(m_A, m_B)$$
OR는 다음과 같다.
$$m_{A | B} = max(m_A, m_B)$$
NOT은 다음과 같다.
$$m_{not A} = 1 - m_A$$
위 세 가지를 조합하여 XOR, NOR, NAND도 표현 가능하다.
보통 퍼지 규칙에서는 위와 같이 AND/OR/NOT을 정의하는 게 국룰이라고 한다. 다른 버전을 사용하기도 하는데 그때는 명시적으로 알려준다고 하니 다른 아티클을 읽을 경우 참고하자.
다시 퍼지 규칙
이제 다음 질문에 대해 대답할 수 있다.
0.6만큼 비가 오고 있고 0.4만큼 추운 상황이라면 '비가 오고 춥다'라는 명제는 얼마나 참인가?
$$m_{raining\&cold} = min(m_{raining} , m_{icold})$$
즉 0.4만큼 참이다.
이런 식으로 만약 '브레이크를 밟는다'의 조건이 '코너에 가깝고' & '속도가 빠르다'라면 이 둘을 조합하여 '브레이크를 밟는다'의 소속도가 얼마인지 계산할 수 있다.
참고 : Ian Millington, AI for GAMES 3rd edition, CRC press, [Chapter 5.5]
'Game AI' 카테고리의 다른 글
퍼지 상태 머신 (Fuzzy State Machine) (2) | 2022.11.02 |
---|---|
퍼지 로직 의사 결정(Decision making) (0) | 2022.10.23 |
퍼지 로직(Fuzzy Logic) - 1 (2) | 2022.10.02 |
Behavior Tree(5) - 트리 생성, 한계 (0) | 2022.09.05 |
Behavior Tree (4) - 데이터 전달하기(Blackboard) (0) | 2022.09.05 |