UD05 · Taller 1 — Simular un sistema experto con experta¶
Objetivo: construir un sistema experto que diagnostique un problema y compararlo con uno de clasificación, para comprobar que el mismo motor simula comportamientos de ámbitos distintos.
Rellena las celdas marcadas con # TU CÓDIGO y responde en las de texto marcadas con ✏️ Respuesta.
Fase 1 — Parche e importación¶
experta es de 2019 y collections.Mapping desapareció en Python 3.10. El parche va siempre antes de importar.
%pip install experta
import collections, collections.abc
if not hasattr(collections, 'Mapping'):
collections.Mapping = collections.abc.Mapping
collections.Iterable = collections.abc.Iterable
collections.MutableMapping = collections.abc.MutableMapping
from experta import *
✏️ Respuesta: ¿por qué el parche tiene que ir antes del import?
(escribe aquí)
Fase 2 — Sistema de diagnóstico: un coche que no arranca¶
Construye un motor con: un @DefFacts() que declare la acción inicial, una regla de arranque con salience=10 que declare los síntomas, una regla que deduzca la causa a partir de dos síntomas, y otra que imprima el resultado.
class DiagnosticoCoche(KnowledgeEngine):
# TU CÓDIGO: @DefFacts() con el hecho inicial
...
# TU CÓDIGO: regla de arranque con salience=10 que declare los sintomas
...
# TU CÓDIGO: regla que deduzca la causa
...
# TU CÓDIGO: regla que imprima el resultado
...
motor = DiagnosticoCoche()
motor.reset() # sin reset() no se cargan los DefFacts
motor.run()
✏️ Respuesta: anota la salida y explica qué reglas se dispararon y en qué orden.
(escribe aquí)
Fase 3 — Otro ámbito: clasificar animales¶
El mismo motor, otro dominio. Construye un sistema que, a partir de unos hechos sobre un animal (pelo, carnívoro, color, manchas), lo identifique.
class Animales(KnowledgeEngine):
# TU CÓDIGO
...
motor = Animales()
motor.reset() # sin reset() no se cargan los DefFacts
motor.run()
✏️ Respuesta: ¿qué has tenido que cambiar del motor entre la Fase 2 y la Fase 3? ¿Y qué has conservado? Esa es la idea de fondo del criterio.
(escribe aquí)
Fase 4 — El orden de disparo¶
Cambia la salience de la regla que deduce el tipo de animal (por ejemplo, salience=5) y vuelve a ejecutar.
# TU CÓDIGO: repite el motor de la Fase 3 con la salience cambiada
...
✏️ Respuesta: ¿qué cambia? Explica la resolución de conflictos: cuando varias reglas están activas a la vez, ¿cómo decide el motor?
(escribe aquí)
Fase 5 — Una regla con NOT y una pregunta al usuario¶
Ahora el sistema pregunta: pide por teclado si encienden las luces y decide en función de la respuesta. Añade además una regla con NOT que actúe cuando no exista un hecho.
class DiagnosticoConPregunta(KnowledgeEngine):
# TU CÓDIGO: usa input() en la regla de arranque y declara el hecho segun la respuesta
...
motor = DiagnosticoConPregunta()
motor.reset()
motor.run()
✏️ Respuesta: ¿qué aporta NOT que no se pueda hacer con una regla normal?
(escribe aquí)
Fase 6 — El umbral y la histéresis¶
Añade una regla con un umbral —por ejemplo, usuarios > 50 marca la carga como crítica— y pruébala con 40, 55 y 50.
# TU CÓDIGO: regla con umbral y las tres pruebas
# Pista: para comparar dentro de un Fact hace falta un constraint de predicado, P(...)
...
✏️ Respuesta: ¿qué ocurre justo en el umbral? ¿Cómo lo harías robusto con histéresis?
(escribe aquí)