퍼지 추론 (Fuzzy Inference): 기계에게 회색조의 사고를 가르치기
요약
고전 논리의 이분법적 참/거짓을 넘어 0과 1 사이의 신념의 정도를 다루는 퍼지 추론(Fuzzy Inference)의 개념을 설명합니다. 퍼지 사실, 퍼지-OR 연산, 그리고 규칙(Rules)을 통해 불확실성을 처리하는 기계적 사고 방식을 다룹니다.
핵심 포인트
- 퍼지 논리는 0과 1 사이의 신념의 정도(degree of belief)를 사용함
- 퍼지-OR 연산은 동일 사실에 대해 더 높은 확신 값을 유지함
- 퍼지 규칙은 조건부 사실로부터 새로운 사실을 추론하는 기반이 됨
- 도수 변수를 통해 사실의 불확실성을 추론 과정에 반영함
사실과 정도 (Facts and Degrees)
고전 논리 (Classical logic)에서 어떤 것은 참(True)이거나 거짓(False)입니다. 고양이가 매트 위에 있거나, 있지 않거나 둘 중 하나입니다. 환자가 열이 나거나, 나지 않거나 마찬가지입니다. 중간 지대는 없습니다.
퍼지 논리 (Fuzzy logic)는 다이얼을 추가합니다.
참/거짓 대신, 모든 문장은 0과 1 사이의 숫자인 **신념의 정도 (degree of belief)**를 가집니다. 1.0의 정도는 확실함을 의미합니다. 0.0의 정도는 신념이 전혀 없음을 의미합니다. 그리고 그 사이의 모든 것은 허용됩니다.
가장 단순한 형태의 퍼지 사실 (fuzzy fact)은 다음과 같습니다:
# 퍼지 사실: 85%의 확신을 가진 "Rex는 털이 있다"
engine.add_fact("has-hair", ["rex"], 0.85)
술어 (Predicate)는 has-hair입니다. 인자 (Argument)는 rex입니다. 정도 (Degree)는 0.85입니다. 아마도 멀리서 Rex를 관찰했거나, 사진이 흐릿했을 수도 있습니다. 우리는 Rex가 털이 있다는 것을 꽤 확신하지만, 확실하지는 않습니다.
이것은 다음에 이어질 모든 것의 기본 구성 요소입니다. 퍼지 지식 베이스 (Fuzzy knowledge base)는 각자 고유한 정도를 가진 이러한 사실들의 집합일 뿐입니다. 어떤 사실은 우리가 확신하지만 (deg=1.0), 어떤 사실은 잠정적인 추측입니다 (deg=0.3). 엔진은 이들을 모두 동일하게 취급하며, 단지 그 숫자에 주의를 기울일 뿐입니다.
한 가지 중요한 세부 사항은, 두 소스가 서로 다른 정도로 동일한 사실을 주장할 때 엔진은 더 높은 값을 유지한다는 것입니다. 이를 **퍼지-OR (fuzzy-OR)**라고 부릅니다. 만약 한 센서가 has-hair(rex)를 0.85라고 말하고 다른 센서가 0.92라고 말한다면, 엔진은 0.92를 저장합니다. 낙관적이지만 합리적입니다. 더 강력한 증거가 승리하는 것입니다.
engine.add_fact("has-hair", ["rex"], 0.85)
engine.add_fact("has-hair", ["rex"], 0.92) # fuzzy-OR: 0.92를 유지함
아래 위젯에서 퍼지 사실을 생성하고 정도 슬라이더를 드래그하여 정도가 시각적 표현을 어떻게 변화시키는지 확인할 수 있습니다. 1.0의 사실은 견고하고 밝습니다. 0.1의 사실은 흐릿하여 거의 보이지 않습니다. 이것은 단순한 장식이 아닙니다. 엔진의 불확실성 (uncertainty)을 시각화한 것입니다.
규칙 (Rules)
사실만으로는 비활성 상태입니다. 추론을 하기 위해서는 기존의 사실로부터 새로운 사실을 생성하는 if-then 문인 **규칙 (rules)**이 필요합니다.
퍼지 규칙은 다음과 같습니다: "만약 X가 털을 가지고 있다면, X는 포유류이다." 코드로 표현하면 다음과 같습니다:
engine.add_rule(
name="mammal-rule",
conditions=[{"pred": "has-hair", "args": ["?x"], "degVar": "?d"}],
...
여기에는 많은 내용이 포함되어 있으므로, 하나씩 풀어보겠습니다.
패턴 변수 (Pattern variables). 조건 내의 ?x는 변수입니다. 이는 어떤 인자(argument)와도 일치합니다. 엔진이 has-hair(rex, 0.85)를 찾으면, ?x를 rex에 바인딩(bind)합니다. 동일한 ?x가 이후 액션(action)에도 나타나므로, 엔진은 is-mammal(rex, ...)을 추가합니다.
도수 변수 (Degree variables). ?d는 매칭된 사실(fact)의 도수(degree)를 포착합니다. 만약 has-hair(rex)의 도수가 0.85라면, ?d는 0.85로 바인딩됩니다.
도수 표현식 (Degree expressions). 액션의 도수는 ["*", 0.95, "?d"]입니다. 즉, ?d가 무엇이든 그 값에 0.95를 곱합니다. 따라서 Rex의 털 보유도가 0.85라면, 그의 포유류 정도는 0.95 * 0.85 = 0.8075가 됩니다. 0.95라는 계수는 규칙 자체의 신뢰도(confidence)를 나타냅니다. 털이 있다는 것은 포유류라는 강력한 증거이지만, 완벽하지는 않습니다. 일부 비포유류도 털과 유사한 구조를 가지고 있기 때문입니다.
우선순위 (Priority). 규칙에는 우선순위가 있습니다. 우선순위가 높은 규칙이 먼저 실행됩니다. 기본 분류 규칙(포유류, 조류, 육식동물)은 우선순위 60으로 실행됩니다. 중간 단계의 클래스는 50으로 실행되며, 종(species) 식별은 40으로 실행됩니다. 이를 통해 엔진은 특정 종을 식별하려고 시도하기 전에 중간 개념들을 먼저 구축할 수 있습니다.
규칙은 여러 개의 조건을 요구할 수도 있습니다. 다음은 육식동물 규칙입니다:
engine.add_rule(
name="carnivore-rule",
conditions=[
...
두 개의 조건과 두 개의 도수 변수가 있습니다. 도수 표현식은 두 입력 도수 중 최솟값 (minimum) — 즉, 가장 약한 연결 고리 — 을 취한 다음 0.9를 곱합니다. 만약 어떤 대상이 고기를 먹는다는 것에 90% 확신하지만 발톱이 있다는 것에는 60%만 확신한다면, 육식동물 도수는 0.9 * min(0.9, 0.6) = 0.54가 됩니다. 연쇄(chain)는 오직 가장 약한 증거만큼만 강합니다.
아래 위젯에서 조건을 전환하고 도수를 조정하여 규칙이 어떻게 실행되고 전파되는지 확인해 보세요.
전방 추론 (Forward Chaining)
개별 규칙도 유용하지만, 진정한 힘은 규칙들을 서로 연결 (chaining) 하는 데서 나옵니다. 엔진은 루프(loop)를 돌며 실행됩니다:
- 모든 규칙을 스캔합니다. 각 규칙에 대해, 그 조건(conditions)을 만족하는 모든 변수 바인딩(variable bindings)을 찾습니다.
- 각 일치 항목에 대해, 이 (규칙, 바인딩) 쌍이 이전에 실행(fired)된 적이 있는지 확인합니다. 실행된 적이 없다면, 액션(actions)을 실행합니다.
- 새로운 사실(facts)이 추가되거나 변경되었다면, 1단계로 돌아갑니다.
- 더 이상 변화가 없거나, 최대 반복 횟수에 도달하면 중단합니다.
이것을 **전방 추론 (forward chaining)**이라고 부릅니다. 알려진 사실로부터 시작하여, 더 이상 결론을 도출할 수 없을 때까지 규칙을 통해 앞으로 연결해 나가는 방식입니다. 엔진은 새로운 것을 더 이상 배울 수 없을 때까지 계속 작동합니다.
다음은 전체 엔진입니다. 약 100줄의 Python 코드로 작성되었습니다:
"""Python 약 100줄로 구현한 전방 추론 퍼지 추론 엔진 (Forward-chaining fuzzy inference engine)."""
from __future__ import annotations
...
이것이 전부입니다. 의존성(dependencies)도, 프레임워크(frameworks)도 없습니다. _match_condition 메서드는 사실 저장소(fact store)를 대상으로 단일화 방식(unification-style)의 패턴 매칭을 수행합니다. _satisfy_all 메서드는 여러 조건을 함께 연결하며 변수 바인딩을 전달합니다. 그리고 run은 고정점(fixpoint)에 도달할 때까지 루프를 돕니다.
_fired 집합(set)에 주목하세요. 각 (규칙, 바인딩) 쌍은 최대 한 번만 실행됩니다. 이것이 없다면 "만약 포유류라면 온혈 동물이다"와 같은 규칙이 동일한 동물에 대해 계속해서 실행되어 무한 루프를 생성할 것입니다. 이 이력 집합(history set)이 루프를 종료시키는 역할을 합니다.
또한 정도(degrees)가 어떻게 전파되는지 주목하세요. _satisfy_all이 여러 조건을 결합할 때, 최솟값 (minimum) 정도를 취합니다. 이는 가장 약한 연결의 원리(weakest link principle)입니다. 그 후 규칙의 액션은 자신의 정도 표현식(degree expression)을 통해 그 정도를 더욱 감쇄(attenuate)시킬 수 있습니다. 사실이 세 단계의 규칙 층을 거쳐 도출될 때쯤이면, 그 정도는 원래 입력값으로부터 계속 곱해져 낮아진 상태가 됩니다. 확신 있는 입력은 확신 있는 결론을 낳고, 불확실한 입력은 잠정적인 결론을 낳습니다.
아래의 위젯은 이 과정을 단계별로 시각화합니다. 루프의 각 반복, 어떤 규칙이 실행되는지, 어떤 사실이 추가되는지, 그리고 정도가 체인을 통해 어떻게 전파되는지를 확인할 수 있습니다.
동물 분류기 (The Animal Classifier)
구체적인 예시인 동물 분류기 (Animal Classifier)를 통해 이 모든 것을 종합해 보겠습니다. 우리는 세 개의 계층에 걸쳐 10개의 규칙을 정의합니다.
계층 0 -- 특성 (Traits). 가공되지 않은 관찰 값들입니다: has-hair (털이 있음), has-feathers (깃털이 있음), eats-meat (고기를 먹음), has-claws (발톱이 있음), has-hooves (발굽이 있음), has-stripes (줄무늬가 있음), cannot-fly (날 수 없음), has-long-neck (목이 김), is-aquatic (수생 동물임). 이것들은 당신이 주장하는 사실 (Facts)입니다.
계층 1 -- 클래스 (Classes). 특성으로부터 도출된 중간 카테고리입니다: is-mammal (포유류임, has-hair로부터), is-bird (조류임, has-feathers로부터), is-carnivore (육식동물임, eats-meat + has-claws로부터), is-ungulate (유편류임, is-mammal + has-hooves로부터).
계층 2 -- 종 (Species). 최종 식별 결과입니다: 얼룩말 (zebra), 펭귄 (penguin), 독수리 (eagle), 호랑이 (tiger), 기린 (giraffe), 돌고래 (dolphin).
다음은 Python으로 작성된 10개의 규칙이 포함된 전체 지식 베이스 (Knowledge Base)입니다:
engine = FuzzyEngine()
# --- 계층 1: 기본 분류 (우선순위 60) ---
...
얼룩말 (zebra) 분류 과정을 추적해 보겠습니다. 우리는 세 가지 사실로 시작합니다:
engine.add_fact("has-hair", ["mystery"], 0.9)
engine.add_fact("has-hooves", ["mystery"], 0.85)
engine.add_fact("has-stripes", ["mystery"], 0.95)
...
반복 1회차 (Iteration 1) (우선순위 60): mammal-rule이 실행됩니다. has-hair(mystery, 0.9)가 일치하므로, is-mammal(mystery)가 0.95 * 0.9 = 0.855의 정도 (Degree)로 추가됩니다.
반복 2회차 (Iteration 2) (우선순위 50): ungulate-rule이 실행됩니다. 이 규칙은 is-mammal (현재 0.855로 존재)과 has-hooves (0.85)를 필요로 합니다. 정도 (Degree): 0.9 * min(0.855, 0.85) = 0.765.
반복 3회차 (Iteration 3) (우선순위 40): zebra-rule이 실행됩니다. 이 규칙은 is-ungulate (0.765)와 has-stripes (0.95)를 필요로 합니다. 정도 (Degree): 0.9 * min(0.765, 0.95) = 0.689.
엔진은 species(mystery, zebra)를 0.689의 정도로 결론짓습니다. 확실하지는 않지만, 상당히 확신할 수 있는 수준입니다. 정도 (Degree)는 세 개의 규칙 계층을 거치며 감쇄되었으며, 각 단계에서 신뢰도 계수 (Confidence factor)를 곱하고 가장 약한 연결 고리인 최솟값 (Minimum)을 취했습니다. 최종 숫자는 전체 체인에 축적된 불확실성을 반영합니다.
아래의 생물 제작기 (Creature Builder)에서 특성들을 켜거나 꺼서 자신만의 동물을 만들어 보세요. 엔진이 규칙을 통해 체인을 형성하며 종을 식별함에 따라 추론 트리 (Inference tree)가 성장하는 모습을 관찰할 수 있습니다.
LLM을 통한 확장 (Scaling with LLMs)
여기 큰 문제가 하나 있습니다. 우리의 10개 규칙 지식 베이스 (knowledge base)로는 이 코끼리를 분류할 수 없습니다.
이것이 바로 고전적 AI (classical AI)에 대한 근본적인 비판이자, 이 분야에서 **지식 습득 병목 현상 (knowledge acquisition bottleneck)**이라 부르는 문제입니다. 수작업으로 제작된 전문가 시스템 (expert systems)은 확장성 (scale)이 없습니다. 우리의 작은 동물 분류기는 얼룩말, 펭귄, 독수리는 처리하지만, 천산갑 (pangolin)에 대해 물으면 어쩔 줄 몰라 합니다. 아르마딜로요? 전혀 모릅니다. 모든 깔끔한 분류를 무너뜨리는 예외 사례 (edge case)인 오리너구리요? 가능성이 없습니다.
GOFAI (Good Old-Fashioned AI, 전통적 AI) 커뮤니티는 수십 년 동안 이 벽에 부딪히며 시간을 보냈습니다. 지식 표현 (knowledge representation)은 장난감 수준의 도메인 (toy domains)에서는 아름답게 작동합니다. 하지만 예외 사례를 커버하는 데 필요한 규칙의 수가 전문가 팀이 작성할 수 있는 속도보다 더 빠르게 증가하는 현실 세계에서는 무너집니다. 이것이 신경망 (neural networks)이 승리한 이유입니다. 신경망은 수작업으로 만든 규칙이 필요하지 않습니다. 데이터로부터 직접 학습하기 때문입니다.
그렇다면 왜 우리는 2026년에 퍼지 추론 엔진 (fuzzy inference engine)을 만들고 있는 걸까요?
무언가가 변했기 때문입니다. 우리에게는 이제 LLM (Large Language Models)이 있습니다.
LLM은 무엇보다도 놀라울 정도로 효과적인 지식 컴파일러 (knowledge compiler)입니다. LLM은 인류 지식의 상당 부분을 흡수했으며, 당신이 요청하는 어떤 구조화된 형식으로든 지식을 출력할 수 있습니다. 퍼지 추론 규칙 (fuzzy inference rules)을 포함해서 말이죠.
다음은 우리의 확장된 지식 베이스를 생성한 프롬프트 (prompt)입니다:
동물 분류를 위한 퍼지 추론 규칙을 생성하라.
각 규칙은 다음을 포함한다: 이름, 조건 (pred/args, ?variables 및 degVar 포함),
...
이것을 LLM에 입력하면 곤충 (has-exoskeleton + has-six-legs), 거미류 (has-eight-legs + has-exoskeleton), 영장류 (is-mammal + has-opposable-thumbs), 서식지 기반 추론 (사막, 북극, 정글, 사바나), 행동 특성 (굴을 파는, 나무를 타는, 밤에 사냥하는), 그리고 까다로운 사례를 처리하는 모호성 해소 규칙 (disambiguation rules)을 포함하는 구조화된 규칙 세트를 얻을 수 있습니다.
10개의 규칙 지식 베이스는 25개가 됩니다. 그다음은 100개, 그다음은 500개가 됩니다.
25개의 규칙이 되면, 시스템은 파충류, 양서류, 그리고 뱀, 악어, 고래, 박쥐와 같은 몇몇 종을 더 추가합니다. 100개의 규칙이 되면, 곤충, 거미류, 영장류, 개과 동물, 고양이과 동물, 그리고 총 약 30개의 종을 처리할 수 있습니다. 이 시스템은 천산갑(pangolin)과 아르마딜로(armadillo)를 구분할 수 있습니다 (천산갑은 비늘이 있지만 포유류이며, 아르마딜로는 골판 갑옷을 가지고 있습니다). 500개의 규칙이 되면, 아홀로틀(axolotls), 오리너구리(platypuses), 일각고래(narwhals), 고...
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기