Недавно я обозначил четыре способа создания агентов ИИ. Агенты, основанные на правилах, были первым и самым элементарным агентом. Элементарность не означает, что такие агенты бесполезны или бесполезны. Наоборот, эти агенты являются общими решениями множества проблем. Давайте посмотрим, как получить представление об агентах на основе правил, используя сравнительный анализ возможностей рассуждений и примеры кода.

В области агентов, основанных на правилах, существуют вариации и различные типы, которые можно рассматривать на основе их характеристик и структур правил. Вот несколько типов агентов на основе правил. Примечание. Я говорю несколько, потому что доступно больше типов и гибридных комбинаций. Я выделяю то, что, по моему мнению, является наиболее распространенным или наиболее интересным.

(A) Правила условия-действия: это наиболее распространенный тип агента на основе правил. Правила состоят из условий (т. е. операторов if) и соответствующих действий (операторов then). Агент оценивает условия и выполняет соответствующее действие, когда условия удовлетворены. Каждое правило обычно работает независимо, и агент выбирает первое правило, условия которого выполняются.

Вот пример агента, основанного на правилах условий и действий. В этом примере подчеркивается:

Вывод и принятие решений: возможность выбрать наиболее подходящие правила, условия которых выполняются, и выполнить соответствующие действия.

Адаптируемость и обучение. Возможность обновлять или изменять правила на основе отзывов, новых данных или опыта.

class LumberjackAgent:
    def __init__(self):
        self.rules = [
            {'condition': 'tree_nearby', 'action': 'chop_tree'},
            {'condition': 'no_tree_nearby', 'action': 'explore'},
            {'condition': 'inventory_full', 'action': 'return_to_base'}
        ]
        self.inventory = []
    
    def make_decision(self, game_state):
        for rule in self.rules:
            if self.evaluate_condition(rule['condition'], game_state):
                action = rule['action']
                self.perform_action(action)
                break
    
    def evaluate_condition(self, condition, game_state):
        if condition == 'tree_nearby':
            return game_state['tree_nearby']
        elif condition == 'no_tree_nearby':
            return not game_state['tree_nearby']
        elif condition == 'inventory_full':
            return len(self.inventory) >= game_state['max_inventory']
        else:
            return False
    
    def perform_action(self, action):
        if action == 'chop_tree':
            self.chop_tree()
        elif action == 'explore':
            self.explore()
        elif action == 'return_to_base':
            self.return_to_base()
    
    def chop_tree(self):
        print("Chopping down the tree!")
        # Code for chopping down the tree goes here
        # Update inventory, score, or other relevant game state
        
    def explore(self):
        print("Exploring the area!")
        # Code for exploring the area goes here
        # Move to a new location, search for trees, etc.
        
    def return_to_base(self):
        print("Returning to base!")
        # Code for returning to the base goes here
        # Reset or perform necessary actions when inventory is full

# Simulation/Game State
game_state = {
    'tree_nearby': True,
    'max_inventory': 10
}

# Lumberjack Agent
lumberjack_agent = LumberjackAgent()
lumberjack_agent.make_decision(game_state)

В этом примере класс LumberjackAgent представляет игрового агента, который является лесорубом. Поведение агента регулируется набором правил, определенных в списке rules. Каждое правило имеет условие и связанное с ним действие.

Метод make_decision принимает текущее состояние игры в качестве входных данных и оценивает условие каждого правила. Если условие выполнено, соответствующее действие выполняется путем вызова метода perform_action.

Метод evaluate_condition сравнивает условие с состоянием игры и возвращает логическое значение. Метод perform_action выполняет соответствующее действие на основе ввода.

Агент предоставляет базовые действия, такие как срубание дерева, исследование местности или возвращение на базу, которые можно настроить с помощью соответствующей игровой логики.

Вот пример использования LumberjackAgent:

game_state = {
    'tree_nearby': True,
    'max_inventory': 10
}

lumberjack_agent = LumberjackAgent()
lumberjack_agent.make_decision(game_state)

В этом примере показано, как агент, основанный на правиле условного действия, может принимать решения на основе текущего состояния игры и выполнять соответствующие действия. Агент оценивает указанные в правилах условия и выбирает действие, связанное с первым выполненным условием. Однако такие правила довольно негибки. Если нам нужна гибкость, нам нужен агент другого типа, основанный на правилах.

(B) Производственные системы. Производственные системы представляют собой более сложный тип агента, основанного на правилах. Эти агенты включают набор правил, организованных как рабочие правила. Думайте о производстве в смысле компьютерной науки контекстно-свободная грамматика.

В любом случае, каждое правило состоит из части условия (называемой левой частью или левой частью) и части действия (называемой правой частью или правой частью). Производственные системы часто используют механизм логического вывода для сопоставления условий с текущим состоянием агента и выполнения правил, условия которых выполняются.

Производственные системы подчеркивают:

Сопоставление правил. Рабочие системы отлично подходят для сопоставления правил с текущим состоянием системы или проблемной области.

Разрешение конфликтов. В ситуациях, когда несколько правил подходят для выполнения из-за перекрывающихся условий, рабочие системы используют стратегии разрешения конфликтов, чтобы определить, какие правила должны иметь приоритет.

Упорядочивание правил и поток управления. Механизмы упорядочивания правил и управления позволяют системе применять определенные последовательности срабатывания правил и выполнять действия в желаемом порядке.

class LumberjackAgent:
    def __init__(self):
        self.production_rules = [
            {'condition': ['tree_nearby'], 'action': 'chop_tree'},
            {'condition': ['no_tree_nearby'], 'action': 'explore'},
            {'condition': ['inventory_full'], 'action': 'return_to_base'}
        ]
        self.inventory = []
    
    def make_decision(self, game_state):
        for rule in self.production_rules:
            if self.evaluate_conditions(rule['condition'], game_state):
                action = rule['action']
                self.perform_action(action)
                break
    
    def evaluate_conditions(self, conditions, game_state):
        for condition in conditions:
            if condition not in game_state or not game_state[condition]:
                return False
        return True
    
    def perform_action(self, action):
        if action == 'chop_tree':
            self.chop_tree()
        elif action == 'explore':
            self.explore()
        elif action == 'return_to_base':
            self.return_to_base()
    
    def chop_tree(self):
        print("Chopping down the tree!")
        # Code for chopping down the tree goes here
        # Update inventory, score, or other relevant game state
        
    def explore(self):
        print("Exploring the area!")
        # Code for exploring the area goes here
        # Move to a new location, search for trees, etc.
        
    def return_to_base(self):
        print("Returning to base!")
        # Code for returning to the base goes here
        # Reset or perform necessary actions when inventory is full

# Simulation/Game State
game_state = {
    'tree_nearby': True,
    'max_inventory': 10
}

# Lumberjack Agent
lumberjack_agent = LumberjackAgent()
lumberjack_agent.make_decision(game_state)

В этом примере класс LumberjackAgent представляет агента дровосека, реализованного как производственная система. Поведение агента регулируется набором производственных правил, определенных в списке production_rules. Каждое производственное правило имеет условие и связанное с ним действие.

Метод make_decision принимает текущее состояние игры в качестве входных данных и оценивает условия каждого производственного правила. Если условия правила выполняются, соответствующее действие выполняется путем вызова метода perform_action.

Метод evaluate_conditions проверяет, выполняются ли все условия в правиле на основе состояния игры. Если какое-либо условие не выполняется, оценка возвращает False. В противном случае он возвращает True.

Метод perform_action выполняет соответствующее действие на основе введенной строки действия.

Вот пример использования LumberjackAgent:

game_state = {
    'tree_nearby': True,
    'max_inventory': 10
}

lumberjack_agent = LumberjackAgent()
lumberjack_agent.make_decision(game_state)

В этом примере агент получает состояние игры с соседним деревом и выполняет действие по срубанию дерева на основе продукционного правила, которое соответствует условию.

Производственная система для агента дровосека на самом деле является конкретной реализацией агента, основанного на правиле условного действия. Основное отличие заключается в представлении и организации правил.

Разумеется, и агенты Condition-Action, и агенты производственной системы имеют одни и те же ограничения. В основном, ни один из них не может надежно справляться с неопределенностью в своей среде. Проще говоря, если нет правила для обработки ввода, нет и действия. Агент на основе нечетких правил пытается обойти это ограничение.

(C) Системы на основе нечетких правил. Системы на основе нечетких правил используют нечеткую логику для обработки неточной или неопределенной информации. Системы, основанные на нечетких правилах, используют нечеткие множества и лингвистические переменные для захвата и анализа с степенями истины. Правила в этих системах содержат нечеткие функции принадлежности и используют механизмы нечеткого вывода для принятия решений.

Акцент в рассуждениях делается на:

Нечеткий вывод. Нечеткая логика допускает постепенные значения истинности от нуля до единицы. Механизмы нечеткого вывода, такие как нечеткое сопоставление и нечеткое рассуждение, используются для получения нечетких выводов на основе нечетких правил и нечетких множеств.

Лингвистические переменные и нечеткие множества: нечеткие системы, основанные на правилах, используют лингвистические переменные для обработки и выражения качественных понятий (например, температура: холодно, тепло, горячо), а нечеткие множества представляют функцию принадлежности, которая присваивает степени принадлежности каждому лингвистическому термину.

Агрегация нечетких правил. Системы, основанные на нечетких правилах, используют методы агрегации правил для объединения выходных данных нескольких правил. Методы агрегирования, такие как макс-минимум или взвешенное усреднение, агрегируют нечеткие выводы применимых правил для получения общего нечеткого вывода.

Дефаззификация. После объединения нечетких правил выполняется дефаззификация для получения четких результатов или решения. Методы дефаззификации, такие как методы на основе центроида или высоты, преобразуют нечеткий вывод в четкое значение на основе агрегированного нечеткого набора.

Опять же, системы на основе нечетких правил могут справляться с неопределенностью и неточностью, присущими реальным проблемам. Они моделируют и рассуждают с расплывчатой ​​или неопределенной информацией, что позволяет принимать решения в ситуациях, когда точные данные могут быть недоступны или их трудно получить. Вот пример:

import numpy as np
import skfuzzy as fuzz
from skfuzzy import control as ctrl

class FuzzyLumberjackAgent:
    def __init__(self):
        # Fuzzy input variables
        self.temperature = ctrl.Antecedent(np.arange(0, 101, 1), 'temperature')
        self.humidity = ctrl.Antecedent(np.arange(0, 101, 1), 'humidity')
        
        # Fuzzy output variable
        self.action = ctrl.Consequent(np.arange(0, 11, 1), 'action')
        
        # Fuzzy membership functions
        self.temperature['cold'] = fuzz.trimf(self.temperature.universe, [0, 0, 50])
        self.temperature['moderate'] = fuzz.trimf(self.temperature.universe, [0, 50, 100])
        self.temperature['hot'] = fuzz.trimf(self.temperature.universe, [50, 100, 100])
        
        self.humidity['low'] = fuzz.trimf(self.humidity.universe, [0, 0, 50])
        self.humidity['moderate'] = fuzz.trimf(self.humidity.universe, [0, 50, 100])
        self.humidity['high'] = fuzz.trimf(self.humidity.universe, [50, 100, 100])
        
        self.action['explore'] = fuzz.trimf(self.action.universe, [0, 0, 5])
        self.action['chop_tree'] = fuzz.trimf(self.action.universe, [0, 5, 10])
        
        # Fuzzy rules
        self.rules = [
            ctrl.Rule(self.temperature['cold'] | self.humidity['low'], self.action['explore']),
            ctrl.Rule(self.temperature['moderate'], self.action['chop_tree']),
            ctrl.Rule(self.temperature['hot'] | self.humidity['high'], self.action['explore'])
        ]
        
        # Fuzzy control system
        self.lumberjack_ctrl = ctrl.ControlSystem(self.rules)
        self.lumberjack_sim = ctrl.ControlSystemSimulation(self.lumberjack_ctrl)
    
    def make_decision(self, temperature_input, humidity_input):
        self.lumberjack_sim.input['temperature'] = temperature_input
        self.lumberjack_sim.input['humidity'] = humidity_input
        self.lumberjack_sim.compute()
        action_output = self.lumberjack_sim.output['action']
        
        return action_output
    
# Simulation
lumberjack_agent = FuzzyLumberjackAgent()

temperature_input = 70
humidity_input = 30

action_output = lumberjack_agent.make_decision(temperature_input, humidity_input)
print("Action output:", action_output)

В этом примере класс FuzzyLumberjackAgent представляет агента дровосека, реализованного как система на основе нечетких правил. Агент принимает нечеткие входные данные для температуры и влажности и обеспечивает нечеткие выходные данные для действия, которое необходимо предпринять.

Нечеткие входные данные (temperature и humidity) и нечеткие выходные данные (action) определяются с использованием классов Antecedent и Consequent из библиотеки skfuzzy. Нечеткие функции принадлежности определяются для каждой входной и выходной переменной с использованием fuzz.trimf, представляющих лингвистические термины, такие как «холодный», «умеренный», «горячий», «низкий», «умеренный», «высокий», «исследование» и «chop_tree». '.

Нечеткие правила определяются с использованием ctrl.Rule и представляют лингвистические отношения между входными и выходными данными. В этом примере правила определяют условия и действия на основе входных данных о температуре и влажности, например: «Если температура низкая или влажность низкая, действие — исследование».

Нечеткая система управления создается с помощью ctrl.ControlSystem, а симуляция инициализируется с помощью ctrl.ControlSystemSimulation. Метод make_decision принимает входные данные температуры и влажности, устанавливает их в моделировании, вычисляет выходное действие и возвращает нечеткое выходное действие.

Вот пример использования FuzzyLumberjackAgent:

lumberjack_agent = FuzzyLumberjackAgent()

temperature_input = 70
humidity_input = 30

action_output = lumberjack_agent.make_decision(temperature_input, humidity_input)
print("Action output:", action_output)

В этом примере агент получает ввод температуры 70 и ввод влажности 30. На основе определенных нечетких правил агент вычисляет нечеткое выходное действие как 7,5, что можно интерпретировать как умеренный уровень действия «chop_tree».

В нечетких системах, основанных на правилах, условия и выводы правил выражаются с использованием нечетких множеств и лингвистических переменных. Условия оценивают степень принадлежности входных переменных для определения применимости правила, в то время как выводы определяют нечеткий результат или действие, которое необходимо предпринять на основе степени удовлетворения условий правила. Это отличается от бинарной структуры ввода-действия двух предыдущих агентов, основанных на правилах.

Недостатком является накладные расходы на нечеткое принятие решений. Каждое взаимодействие, проходящее через систему на основе нечетких правил, является новым, поэтому влечет за собой те же накладные расходы на обработку. Кроме того, эти агенты могут стать стохастическими при определенных обстоятельствах, что может быть нежелательно. К счастью, у нас остался один тип агента, основанного на правилах, для обсуждения, который подходит для таких ситуаций.

(D) Системы рассуждений на основе прецедентов: агенты рассуждений на основе прецедентов хранят и рассуждают на основе набора ранее решенных прецедентов. Правила в этом типе агента обычно имеют форму сопоставления текущей ситуации или проблемы с аналогичными случаями в базе данных. Затем агент применяет соответствующее решение или действие. Это достигается за счет таких способностей рассуждения, как:

Поиск дел: системы CBR превосходно извлекают соответствующие дела из библиотеки дел или базы знаний. Учитывая новую проблему или ситуацию, системы CBR ищут похожие случаи, которые соответствуют характеристикам или контексту текущей проблемы. Процесс поиска включает в себя сопоставление атрибутов проблемы с сохраненными случаями с использованием таких методов, как метрики подобия или сопоставление с образцом.

Адаптация обращения: после извлечения соответствующего обращения системы CBR адаптируют или изменяют действие полученного обращения в соответствии с текущей проблемой. Механизмы адаптации анализируют различия между полученным случаем и текущей проблемой и применяют соответствующие модификации, чтобы сделать решение более подходящим или эффективным.

Оценка сходства. Методы оценки сходства учитывают различные особенности проблемы и решения. К ним относятся числовые значения, категориальные переменные или даже сложные структуры. Это позволяет системе идентифицировать случаи, наиболее релевантные текущей проблеме. Вспомните Расстояние Левенштейна.

Объяснение. Крайне важно, чтобы CBR-системы объясняли процесс принятия решений, связывая текущую проблему с соответствующими извлеченными случаями. Объяснения помогают пользователям понять, почему было выбрано то или иное действие.

Эти желаемые возможности рассуждений делают системы рассуждений на основе прецедентов (CBR) ценными в проблемных областях, где прошлый опыт и решения могут направлять принятие решений. Давайте посмотрим, как наш лесоруб может извлечь выгоду из этого типа архитектуры агента.

class Case:
    def __init__(self, temperature, humidity, action):
        self.temperature = temperature
        self.humidity = humidity
        self.action = action

class CBRlumberjackAgent:
    def __init__(self):
        self.case_library = [
            Case(65, 40, 'chop_tree'),
            Case(70, 35, 'chop_tree'),
            Case(80, 50, 'explore'),
            Case(60, 45, 'chop_tree')
        ]
    
    def retrieve_similar_cases(self, temperature, humidity):
        similar_cases = []
        for case in self.case_library:
            if self.similarity_measure(temperature, humidity, case.temperature, case.humidity):
                similar_cases.append(case)
        return similar_cases
    
    def similarity_measure(self, temperature1, humidity1, temperature2, humidity2):
        # Implement your similarity measure here
        # This can be based on distance metrics, fuzzy similarity, or any other relevant measure
        # Return True if similar, False otherwise
        return abs(temperature1 - temperature2) < 5 and abs(humidity1 - humidity2) < 5
    
    def adapt_solution(self, similar_cases):
        if similar_cases:
            # Select a similar case (you can use more sophisticated selection strategies)
            selected_case = similar_cases[0]
            return selected_case.action
        else:
            return 'explore'  # Default action if no similar case is found
    
    def make_decision(self, temperature, humidity):
        similar_cases = self.retrieve_similar_cases(temperature, humidity)
        action = self.adapt_solution(similar_cases)
        return action

# Simulation
lumberjack_agent = CBRlumberjackAgent()

temperature = 67
humidity = 42

action = lumberjack_agent.make_decision(temperature, humidity)
print("Action:", action)

В этом примере класс Case представляет случай в библиотеке случаев. Каждый случай имеет такие атрибуты, как temperature, humidity и action. Класс CBRlumberjackAgent представляет агента дровосека, реализованного в виде системы рассуждений на основе прецедентов (CBR).

Библиотека случаев состоит из экземпляров класса Case, представляющих прошлые случаи с соответствующей температурой, влажностью и действиями. Метод retrieve_similar_cases ищет в библиотеке случаев похожие случаи на основе меры сходства. В этом примере мера подобия основана на простом пороге разности для температуры и влажности.

Метод adapt_solution адаптирует решение или действие из найденных похожих случаев. В данном примере используется простейшая стратегия, где в качестве адаптированного решения выбирается действие из первого подобного случая.

Метод make_decision использует в качестве входных данных текущую температуру и влажность. Он извлекает похожие случаи, адаптирует решение и возвращает адаптированное действие для текущей проблемы.

Вот пример использования CBRlumberjackAgent:

lumberjack_agent = CBRlumberjackAgent()

temperature = 67
humidity = 42

action = lumberjack_agent.make_decision(temperature, humidity)
print("Action:", action)

В этом примере агент получает температуру 67 и влажность 42. Он извлекает аналогичные случаи из библиотеки случаев, находит аналогичный случай с температурой 65 и влажностью 40 и адаптирует действие для этого случая, что приводит к решению « рубить_дерево».

В целом агент рассуждений на основе прецедентов делает упор на поиск и адаптацию прошлых прецедентов для решения текущих проблем. Он использует библиотеку случаев для поиска похожих случаев, адаптации их решений и предоставления индивидуальных рекомендаций или действий. Ориентация на повторное использование прошлого опыта и его адаптацию к текущему контексту отличает системы CBR от других типов агентов, которые полагаются на предопределенные правила, служебные функции или алгоритмы поиска.

Вот и все, распространенные типы агентов, основанных на правилах. Помните, что каждый тип способен решать проблемы. Агенты, основанные на правилах условий и действий, и агенты правил производства полагаются на явные правила «если-то» для принятия решений или выполнения действий на основе текущего состояния или входных данных. Системы, основанные на нечетких правилах, используют нечеткую логику для обработки неточной или неопределенной информации, используя нечеткие условия и выводы для рассуждений и принятия решений. Системы рассуждений на основе прецедентов извлекают и адаптируют решения из прошлых прецедентов, хранящихся в библиотеке прецедентов, для решения текущих проблем, используя сходство между прецедентами.

Однако есть некоторые проблемы, когда необходим другой тип агента. Мы рассмотрим поисковые агенты в ближайшем будущем. А пока удачного кодирования и будьте добры к своим агентам!

Имея это в виду, если вам понравилась эта история и вы хотите прочитать больше, вот три действия, которые вы можете предпринять прямо сейчас, чтобы поддержать мою работу:

1. Похлопайте истории 👏 и оставьте КОММЕНТАРИЙ 📫 со своими мыслями

2. СЛЕДУЙТЕ за мной, чтобы получать уведомления о новых историях ⏰

3. ПОДЕЛИТЕСЬ и порекомендуйте эту историю в социальных сетях 🐦