전문가 시스템이란, 특정 분야 전문가의 지식을 모방하고, 이러한 지식을 컴퓨터 프로그램으로 구현한 것으로, 주어진 특정 문제를 해결하거나 조언을 제공하기 위해 사용된다.
전문가 시스템은 특정 영역 전문가 수준의 문제 해결 능력을 지닌 컴퓨터 프로그램이며, 이를 위해 전문가의 지식을 "규칙"이라는 형태로 지식 베이스에 저장하고, 이 규칙들을 통해 추론을 수행한다. 이는 기존의 절차적 코드가 아닌 규칙으로 표현되는 지식을 통해 추론함으로써 복잡한 문제를 해결하도록 설계되었으며, 인공지능 소프트웨어 최초의 성공적 형태이다.
이러한 전문가 시스템은 의료 진단, 주식 투자 조언, 기계 고장 진단 등에 활용된다.
전문가 시스템은 전문가의 지식을 모방해 비전문가도 전문가 수준의 결정을 내릴 수 있고, 일관된 판단을 제공하며 지식의 확산과 보존이 용이하다는 장점이 있다. 또한, IF THEN을 사용하는 규칙은 인간 전문가의 지식을 표현하는 자연스러운 방식이며, 지식 베이스와 추론 엔진이 분리되므로 다른 영역에도 쉽게 적용할 수 있다.
하지만, 복잡한 지식 베이스 작성이 필요하고, 전문가의 직관적인 판단을 완벽히 반영하기 어려우며, 환경 변화에 따른 지식 업데이트가 필요하다는 단점이 존재하기도 한다. 또한, 지식을 학습할 수 없고, 탐색이 비효율적이며, 규칙이 많아지면 유지보수가 어려워진다는 단점이 존재한다.
지식 베이스는전문가의 지식과 경험을 형식화하여 저장한다. 이때, 지식의 획득은 전문가로부터 직접적인 인터뷰나 문서 분석을 통해 이뤄질 수 있고, 시간이 지나면서 바뀌는 지식 또는 새로운 정보는 업데이트가 필요하다.
추론 엔진에서는 지식 베이스에 저장된 규칙과 팩트를 활용해 문제 해결을 위한 추론을 수행한다.
추론 엔진은 지식 베이스의 지식을 활용해 추론 및 결정을 수행하는 모듈로, 두 가지 구성 요소로 구성된다.
# 지식 베이스와 추론 엔진이 어떻게 설계되는지
class ExpertSystem: # 추론 엔진
def __init__(self):
self.knowledge_base = KnowledgeBase() # 지식 베이스 객체 초기화
# 진단 규칙을 평가하는 함수로, 규칙 조건이 사용자로부터 받은 증상과 일치하는지 검사
# 만약 조건이 AND나 OR로 연결된 여러 개의 증상들로 구성되어 있다면, check_condition 함수는 자신을 재귀적으로 호출하여 각 하위 조건을 평가함.
def check_condition(self, condition, selected_symptoms):
# "condition" : "stomach_pain" 와 같이 단일 증상인지 확인
if isinstance(condition, str): # condition이 문자열 인스턴스면
return condition in selected_symptoms # 사용자가 입력한 증상이 conditiion에 포함되는지 확인
op = condition.get("op") # 딕셔너리에서 op의 value만 추출
if op == "AND":
# "conds" : ["fever", "cough", "sore_throat"]과 같은 증상들
# 증상이 모두 있어야 True
return all(self.check_condition(sub_cond, selected_symptoms) for sub_cond in condition["conds"])
elif op == "OR":
# 증상 중 하나라도 있으면 True
return any(self.check_condition(sub_cond, selected_symptoms) for sub_cond in condition["conds"])
# 사용자로부터 입력받은 증상들을 바탕으로 check_condition 함수를 사용하여 가장 적합한 진단을 반환하는 함수
# True/False 결과 받아서 규칙에 맞는지 확인하고, 맞으면 진단명과 설명 return
def diagnose(self, selected_symptoms): # 증상에 따른 진단
for rule in self.knowledge_base.rules: # 규칙 하나씩 꺼내보면서 (독감, 감기, 위염, 편두통 등)
if self.check_condition(rule["condition"], selected_symptoms): # 사용자의 증상이 지식 베이스에 포함되는지 확인
return rule["diagnosis"], rule.get("explanation", "") # 진단명과 설명 return
return "No specific diagnosis.", "Consult a doctor." # 기본 답변 return
class KnowledgeBase: # 지식 베이스
def __init__(self):
# 질문 시에 활용할 거 (descriptions)
# 다시 말해, 증상들의 간략한 설명을 담고 있는 딕셔너리로, 이를 통해 사용자에게 어떤 증상을 물어볼지 결정함.
self.symptom_descriptions = {
"fever" : "a fever",
"cough" : "a cough",
"sore_throat" : "a sore throat",
"stomach_pain" : "stomach pain",
"headache" : "a headache",
"runny_nose" : "a runny nose",
"itchy_eyes" : "itchy eyes"
}
# rule 정의 - 진단 규칙 (AND, OR 조건을 포함한 복잡한 진단 규칙을 모델링함)
# 각 규칙은 특정 조건과 그 조건이 만족될 때의 진단, 설명으로 구성되며,
# 조건은 단순히 하나의 증상을 기반으로 할 수도 있고, AND, OR 등 논리 연산자를 포함해 여러 증상의 조합을 기반으로 할 수도 있음.
self.rules = [
{
"condition" : {"op": "AND", "conds" : ["fever", "cough", "sore_throat"]},
"diagnosis" : "You might have the flu (당신은 독감일 수 있습니다.)",
"explanation" : "Flu symptoms include fever, cough, and sore throat. (독감의 증상에는 발열, 기침, 목 아픔이 포함됩니다.)"
},
{
"condition" : {"op" : "AND", "conds" : ["runny_nose", "sore_throat"]},
"diagnosis" : "You might have a cold. (당신은 감기일 수 있습니다.)",
"explanation" : "Cold symptoms include runny nose and sore throat. (감기의 증상에는 콧물과 목 아픔이 포함됩니다.)"
},
{
"condition" : "stomach_pain",
"diagnosis" : "You might have gastritis. (당신은 위염일 수 있습니다.)",
"explanation" : "Pain in the stomach can be a sympotom of gastritis. (위의 통증은 위염의 증상일 수 있습니다.)"
},
{
"condition" : "headache",
"diagnosis" : "You might have a migraine. (당신은 편두통일 수 있습니다.)",
"explanation" : "A servere headache can be a symptom of migraine. (심한 두통은 편두통의 증상일 수 있습니다.)"
},
{
"condition" : "itchy_eyes",
"diagnosis" : "You might have an allergy. (당신은 알레르기일 수 있습니다.)",
"explanation" : "Itchy eyes can be a symptom of an allergy. (눈이 가렵다면 알레르기의 증상일 수 있습니다.)"
}
]
# 사용자에게 각 증상에 대해 직접 물어보고, 사용자의 응답을 바탕으로 선택된 증상들의 리스트를 반환
# 'yes'로 응답한 증상만 반환 리스트에 포함
def get_symptoms_from_user():
symptom_descriptions = KnowledgeBase().symptom_descriptions
selected_symptoms = []
print("Please answer the following (yes or no):")
for symptom, description in symptom_descriptions.items():
answer = input(f"Do you have {description}? ").lower()
if answer == 'yes':
selected_symptoms.append(symptom)
return selected_symptoms
if __name__ == "__main__":
selected_symptoms = get_symptoms_from_user() # 사용자가 증상 선택
system = ExpertSystem()
diagnosis, explanation = system.diagnose(selected_symptoms) # 진단 (진단명, 설명 or 기본 답변 return)
print(diagnosis)
print(explanation)