Saltar navegación

Árbores de decisión

Akinator

Xogo Akinator
Creación propia. Xogo Akinator (CC BY-SA)   🎥  Vídeo


Xoguemos unha partida con Akinator, o xenio que deduce calquera personaxe que teñamos en mente.

Abraiante, non ? Que hai detrás do seu funcionamento? Intenta imaxinar como consigue chegar ó resultado.

Como funciona?

Imos comprender como funciona unha árbore de decisión e algúns conceptos clave na IA cun exemplo simple e práctico.Se trata de implementar un sistema para clasificar animais. Empezamos só con tres Xirafa, Foca e Ovella.

Animais
Copilot . Animais (CC BY-SA)
  • Este é un programa en Python que podes executar en Google Colaboratory para cargar datos de animais que constan do tipo de animal e as súas características
  • O programa inclue explicacións detalladas nos comentarios para que comprendas cada paso.
  • Executandoo  en Colab, podes probar a crear 3 clases de animais e as características que os definen como tales.
  • Non te preocupes por comprender o programa totalmente, só de entender o que fai.

Código Python: Programa para crear 3 clases con 3 características que as distinguen

# Instalamos librarías necesarias para visualizar gráficos
!pip install matplotlib pandas

# Importamos as librarías necesarias
import pandas as pd
import matplotlib.pyplot as plt

# Creamos unha lista para gardar os datos
animais = []

# Explicación inicial ao usuario
print("Imos clasificar animais con base nas súas características.")
print("As características son:")
print("1. Ten pelo (1 = Si, 0 = Non)")
print("2. É doméstico (1 = Si, 0 = Non)")
print("3. Vive na auga (1 = Si, 0 = Non)")

# Preguntamos por varios animais e gardamos os datos
for i in range(3):  # Permitimos ao usuario introducir datos de 3 animais
    print(f"\nIntroduce as características do animal {i + 1}:")
    ten_pelo = int(input("¿Ten pelo? (1: Si, 0: Non): "))
    e_domestico = int(input("¿É doméstico? (1: Si, 0: Non): "))
    vive_na_auga = int(input("¿Vive na auga? (1: Si, 0: Non): "))
    clase = input("¿Que animal é? (Xirafa, Foca, Ovella): ")

    # Gardamos os datos como diccionario    
    animal = {
        "Ten pelo": ten_pelo,
        "É doméstico": e_domestico,
        "Vive na auga": vive_na_auga,
        "Clase": clase
    }
    animais.append(animal)

# Creamos un DataFrame a partir dos datos recollidos
df = pd.DataFrame(animais)

# Visualizamos os datos como gráfica
print("\nXerando gráfica das características...")
df.groupby("Clase")[["Ten pelo", "É doméstico", "Vive na auga"]].mean().plot(kind="bar")
plt.title("Características promedio por clase")
plt.ylabel("Valor (0: Non, 1: Si)")
plt.xticks(rotation=0)
plt.show()

# Mostramos os datos recollidos
print("\nDatos recollidos:")
print(df)
    
  • Este é un programa en Python que podes executar en Google Colaboratory para para clasificar os animais nunha das tres clases iniciais (xirafa, ovella e foca).
  • Se o modelo non acerta, pedirá á usuaria que introduza un novo animal, actualizará o DataFrame engadindo a nova clase e volverá adestrar o modelo.
  • Todo se realiza de forma iterativa ata que a usuaria decida rematar.
  • O programa inclue explicacións detalladas nos comentarios para que comprendas cada paso.
  • Executandoo  en Colab, podes probar a clasificar animais, crear novas clases e volver clasificar
  • Non te preocupes por comprender o programa totalmente, só de entender o que fai.

Código Python: Clasificar os animais nunha das tres clases iniciais (xirafa, ovella e foca).Incluir novas clases(novos animais).

# Instalamos as librarías necesarias (só se estás en Google Colaboratory)
!pip install pandas scikit-learn

# Importamos as librarías necesarias
import pandas as pd
from sklearn.tree import DecisionTreeClassifier

# Creación do conxunto de datos inicial con 3 clases (Xirafa, Foca, Ovella)
# Este é o DataFrame inicial coas características e clases dos animais
datos = {
    "Ten pelo": [0, 0, 1],       # 1: Si, 0: Non
    "É doméstico": [0, 0, 1],    # 1: Si, 0: Non
    "Vive na auga": [0, 1, 0],   # 1: Si, 0: Non
    "Clase": ["Xirafa", "Foca", "Ovella"]  # Clases dos animais
}

# Creamos un DataFrame para organizar os datos
df = pd.DataFrame(datos)

# Mensaxe inicial para a usuaria
print("\n\nBenvida ao clasificador de animais baseado nunha árbore de decisión.")
print("Iniciaremos coas seguintes clases: Xirafa, Foca e Ovella.")
print("Cada clase está definida polas seguintes características:")
print("- Ten pelo: 1 = Si, 0 = Non")
print("- É doméstico: 1 = Si, 0 = Non")
print("- Vive na auga: 1 = Si, 0 = Non\n")

# Creamos unha árbore de decisión inicial usando scikit-learn
X = df[["Ten pelo", "É doméstico", "Vive na auga"]]  # Características
y = df["Clase"]  # Etiquetas (clases)
modelo = DecisionTreeClassifier()  # Inicializamos a árbore de decisión
modelo.fit(X, y)  # Adestramos o modelo co DataFrame inicial

# Bucle principal para a clasificación
while True:
    # Paso 1: Preguntamos as características dun novo animal
    print("\nIntroduce as características do animal a clasificar:")
    ten_pelo = int(input("Ten pelo? (1 = Si, 0 = Non): "))
    e_domestico = int(input("É doméstico? (1 = Si, 0 = Non): "))
    vive_na_auga = int(input("Vive na auga? (1 = Si, 0 = Non): "))

    # Creamos un DataFrame coas características do novo animal
    novo_animal = pd.DataFrame(
    [[ten_pelo, e_domestico, vive_na_auga]],
    columns=["Ten pelo", "É doméstico", "Vive na auga"]  # Nomes das características
     )
   
    # Paso 2: Tentamos clasificar o animal utilizando a árbore de decisión
    predicion = modelo.predict([[ten_pelo, e_domestico, vive_na_auga]])[0]
    print(f"\nO modelo predi que o animal é: {predicion}")

    # Paso 3: Preguntar se a predición foi correcta
    correcto = input("O modelo acertou? (Si/Non): ").strip().lower()
    if correcto == "si":
        print("Perfecto! O modelo clasificou correctamente o animal.")
    else:
        # Paso 4: Engadir unha nova clase se o modelo errou
        nova_clase = input("Que animal é? (nome da nova clase): ")
        # Engadimos o novo animal ao DataFrame utilizando pd.concat
        novo_dato = pd.DataFrame({
            "Ten pelo": [ten_pelo],
            "É doméstico": [e_domestico],
            "Vive na auga": [vive_na_auga],
            "Clase": [nova_clase]
        })
        df = pd.concat([df, novo_dato], ignore_index=True)
        print(f"\nEngadimos a nova clase '{nova_clase}' ao conxunto de datos.")
        
        # Re-adestrar o modelo coa nova información
        X = df[["Ten pelo", "É doméstico", "Vive na auga"]]
        y = df["Clase"]
        modelo.fit(X, y)  # Re-adestramos o modelo
        print("O modelo foi actualizado e adestrado cos novos datos.")

    # Paso 5: Preguntar se a usuaria desexa continuar
    continuar = input("\n¿Queres clasificar outro animal? (Si/Non): ").strip().lower()
    if continuar != "si":
        print("Grazas por usar o clasificador de animais. Ata a próxima!")
        break
    

  • Este é un programa en Python que podes executar en Google Colaboratory para para clasificar os animais nunha das tres clases iniciais (xirafa, ovella e foca), crear novas clases para clasificar animais e cando dous vectores de características coinciden e non son o mesmo animal, pode incluir unha nova característica que os distinga.
  • Se o modelo non acerta, pedirá á usuaria que introduza un novo animal ou unha característica e actualizará o DataFrame engadindo a nova clase e/ou característica e volverá adestrar o modelo.
  • Todo se realiza de forma iterativa ata que a usuaria decida rematar.
  • O programa inclue explicacións detalladas nos comentarios para que comprendas cada paso.
  • Executandoo  en Colab, podes probar a clasificar animais, crear novas clases e características, e volver clasificar
  • Non te preocupes por comprender o programa totalmente, só de entender o que fai.

Código Python: Clasificar os animais nunha das tres clases iniciais (xirafa, ovella e foca).Incluir novas clases(animais) e novas características.

# Instalamos as librarías necesarias (só se estás en Google Colaboratory)
!pip install pandas scikit-learn

# Importamos as librarías necesarias
import pandas as pd
from sklearn.tree import DecisionTreeClassifier

# Creación do conxunto de datos inicial con 3 clases (Xirafa, Foca, Ovella)
datos = {
    "Ten pelo": [0, 0, 1],       # 1: Si, 0: Non
    "É doméstico": [0, 0, 1],    # 1: Si, 0: Non
    "Vive na auga": [0, 1, 0],   # 1: Si, 0: Non
    "Clase": ["Xirafa", "Foca", "Ovella"]  # Clases dos animais
}

# Creamos un DataFrame para organizar os datos
df = pd.DataFrame(datos)

# Mensaxe inicial para a usuaria
print("\n\nBenvida ao clasificador de animais baseado nunha árbore de decisión.")
print("\nIniciaremos coas seguintes clases: Xirafa, Foca e Ovella.")
print("\nCada clase está definida polas seguintes características:")
print("- Ten pelo: 1 = Si, 0 = Non")
print("- É doméstico: 1 = Si, 0 = Non")
print("- Vive na auga: 1 = Si, 0 = Non\n")

# Creamos unha árbore de decisión inicial usando scikit-learn
X = df.drop(columns=["Clase"])  # Seleccionamos todas as características excepto a "Clase"
y = df["Clase"]  # Definimos as etiquetas (clases)
modelo = DecisionTreeClassifier()  # Inicializamos a árbore de decisión
modelo.fit(X, y)  # Adestramos o modelo co conxunto de datos inicial

# Bucle principal para a clasificación
while True:
    # Paso 1: Preguntamos as características dun novo animal, incluíndo calquera nova característica
    print("\nIntroduce as características do animal a clasificar:")
    caracteristicas = {}

    # Preguntar polas características iniciais predefinidas
    caracteristicas["Ten pelo"] = int(input("Ten pelo? (1 = Si, 0 = Non): "))
    caracteristicas["É doméstico"] = int(input("É doméstico? (1 = Si, 0 = Non): "))
    caracteristicas["Vive na auga"] = int(input("Vive na auga? (1 = Si, 0 = Non): "))

    # Preguntar polas novas características engadidas ao conxunto de datos
    for columna in df.columns:
        if columna not in ["Ten pelo", "É doméstico", "Vive na auga", "Clase"]:
            pregunta = f"¿{columna}? (1 = Si, 0 = Non): "
            caracteristicas[columna] = int(input(pregunta))

    # Creamos un vector de entrada segundo a orde das columnas do DataFrame
    entrada = [caracteristicas[columna] for columna in df.columns if columna != "Clase"]

    # Paso 2: Clasificamos o animal empregando a árbore de decisión
    entrada_df = pd.DataFrame([entrada], columns=df.drop(columns=["Clase"]).columns)  # Formato válido para o modelo
    prediccion = modelo.predict(entrada_df)[0]
    print(f"\nO modelo predí que o animal é: {prediccion}")

    # Comprobamos se o vector de características coincide co vector predito
    vector_predito = df[df["Clase"] == prediccion].drop(columns=["Clase"]).values[0]
    if list(vector_predito) == entrada:
        # Paso 3: Preguntamos se a predición foi correcta
        correcto = input(f"O animal pertence realmente á clase '{prediccion}'? (Si/Non): ").strip().lower()
        if correcto == "non":
            # Engadimos unha nova característica para diferenciar este animal
            print("\nO vector de características coincide, pero non é o mesmo animal.")
            nova_caracteristica = input("Que característica diferencia este animal da clase predita? (nome): ")

            # Actualizamos o DataFrame engadindo a nova característica
            df[nova_caracteristica] = 0  # Inicializamos a nova columna con valor 0
            print(f"\nPrecisamos saber se cada clase existente ten a característica '{nova_caracteristica}':")
            for clase in df["Clase"].unique():
                valor = int(input(f"A clase '{clase}' ten '{nova_caracteristica}'? (1 = Si, 0 = Non): "))
                df.loc[df["Clase"] == clase, nova_caracteristica] = valor
            
            # Engadimos o novo animal ao conxunto de datos
            nova_clase = input("¿Que animal é? (nome da nova clase): ")
            novo_dato = {**caracteristicas, nova_caracteristica: 1, "Clase": nova_clase}
            df = pd.concat([df, pd.DataFrame([novo_dato])], ignore_index=True)
            print(f"\nEngadimos a nova clase '{nova_clase}' e a característica '{nova_caracteristica}' ao conxunto de datos.")
        else:
            print("Perfecto! O animal pertence á clase predita.")

        # Re-adestramos o modelo co conxunto de datos actualizado
        X = df.drop(columns=["Clase"])  # Actualizamos as características
        y = df["Clase"]  # Actualizamos as etiquetas
        modelo.fit(X, y)  # Re-adestramos o modelo
        print("O modelo foi actualizado coa nova clase e a nova característica.")
    else:
        print("O modelo errou completamente na predición.")

    # Paso 4: Preguntamos se a usuaria quere continuar
    continuar = input("\nQueres clasificar outro animal? (Si/Non): ").strip().lower()
    if continuar != "si":
        print("Grazas por usar o clasificador de animais. ¡Ata a próxima!")
        break
    
  • Este é un programa en Python que podes executar en Google Colaboratory para obter as árbores de decisión de cada clasificación do programa
  • O programa inclue explicacións detalladas nos comentarios para que comprendas cada paso.
  • Executandoo  en Colab, podes probar a crear máis clases de animais e as características que os definen como tales, e comprobar como crece a árbore de decisións.
  • Non te preocupes por comprender o programa totalmente, só de entender o que fai.

Código Python: Visualizando as árbores de decisión en cada clasificación 

# Instalamos as librarías necesarias (só se estás en Google Colaboratory)
!pip install pandas scikit-learn graphviz

# Importamos as librarías necesarias
import pandas as pd
from sklearn.tree import DecisionTreeClassifier, export_graphviz
import graphviz
from IPython.display import display, Image

# Creación do conxunto de datos inicial con 3 clases (Xirafa, Foca, Ovella)
datos = {
    "Ten pelo": [0, 0, 1],       # 1: Si, 0: Non
    "É doméstico": [0, 0, 1],    # 1: Si, 0: Non
    "Vive na auga": [0, 1, 0],   # 1: Si, 0: Non
    "Clase": ["Xirafa", "Foca", "Ovella"]  # Clases dos animais
}

# Creamos un DataFrame para organizar os datos
df = pd.DataFrame(datos)

# Mensaxe inicial para a usuaria
print("\n\nBenvida ao clasificador de animais baseado nunha árbore de decisión.")
print("\nIniciaremos coas seguintes clases: Xirafa, Foca e Ovella.")
print("\nCada clase está definida polas seguintes características:")
print("- Ten pelo: 1 = Si, 0 = Non")
print("- É doméstico: 1 = Si, 0 = Non")
print("- Vive na auga: 1 = Si, 0 = Non\n")

# Creamos unha árbore de decisión inicial usando scikit-learn
X = df.drop(columns=["Clase"])  # Seleccionamos todas as características excepto a "Clase"
y = df["Clase"]  # Definimos as etiquetas (clases)
modelo = DecisionTreeClassifier()  # Inicializamos a árbore de decisión
modelo.fit(X, y)  # Adestramos o modelo co conxunto de datos inicial

# Función para mostrar o gráfico da árbore de decisión
def mostrar_arvore_decision(modelo, X, y):
    dot_data = export_graphviz(
        modelo,
        out_file=None,
        feature_names=X.columns,
        class_names=modelo.classes_,
        filled=True,
        rounded=True,
        special_characters=True
    )
    graph = graphviz.Source(dot_data)
    graph.render("arvore_decision", format="png", cleanup=True)  # Xera un ficheiro PNG
    display(Image("arvore_decision.png"))  # Mostra o ficheiro PNG

# Mostramos a árbore de decisión inicial
print("\nAquí tes a árbore de decisión inicial:")
mostrar_arvore_decision(modelo, X, y)

# Bucle principal para a clasificación
while True:
    # Paso 1: Preguntamos as características dun novo animal, incluíndo calquera nova característica
    print("\nIntroduce as características do animal a clasificar:")
    caracteristicas = {}

    # Preguntar polas características iniciais predefinidas
    caracteristicas["Ten pelo"] = int(input("Ten pelo? (1 = Si, 0 = Non): "))
    caracteristicas["É doméstico"] = int(input("É doméstico? (1 = Si, 0 = Non): "))
    caracteristicas["Vive na auga"] = int(input("Vive na auga? (1 = Si, 0 = Non): "))

    # Preguntar polas novas características engadidas ao conxunto de datos
    for columna in df.columns:
        if columna not in ["Ten pelo", "É doméstico", "Vive na auga", "Clase"]:
            pregunta = f"¿{columna}? (1 = Si, 0 = Non): "
            caracteristicas[columna] = int(input(pregunta))

    # Creamos un vector de entrada segundo a orde das columnas do DataFrame
    entrada = [caracteristicas[columna] for columna in df.columns if columna != "Clase"]

    # Paso 2: Clasificamos o animal empregando a árbore de decisión
    entrada_df = pd.DataFrame([entrada], columns=df.drop(columns=["Clase"]).columns)  # Formato válido para o modelo
    prediccion = modelo.predict(entrada_df)[0]
    print(f"\nO modelo predí que o animal é: {prediccion}")

    # Comprobamos se o vector de características coincide co vector predito
    vector_predito = df[df["Clase"] == prediccion].drop(columns=["Clase"]).values[0]
    if list(vector_predito) == entrada:
        # Paso 3: Preguntamos se a predición foi correcta
        correcto = input(f"O animal pertence realmente á clase '{prediccion}'? (Si/Non): ").strip().lower()
        if correcto == "non":
            # Engadimos unha nova característica para diferenciar este animal
            print("\nO vector de características coincide, pero non é o mesmo animal.")
            nova_caracteristica = input("Que característica diferencia este animal da clase predita? (nome): ")

            # Actualizamos o DataFrame engadindo a nova característica
            df[nova_caracteristica] = 0  # Inicializamos a nova columna con valor 0
            print(f"\nPrecisamos saber se cada clase existente ten a característica '{nova_caracteristica}':")
            for clase in df["Clase"].unique():
                valor = int(input(f"A clase '{clase}' ten '{nova_caracteristica}'? (1 = Si, 0 = Non): "))
                df.loc[df["Clase"] == clase, nova_caracteristica] = valor
            
            # Engadimos o novo animal ao conxunto de datos
            nova_clase = input("Que animal é? (nome da nova clase): ")
            novo_dato = {**caracteristicas, nova_caracteristica: 1, "Clase": nova_clase}
            df = pd.concat([df, pd.DataFrame([novo_dato])], ignore_index=True)
            print(f"\nEngadimos a nova clase '{nova_clase}' e a característica '{nova_caracteristica}' ao conxunto de datos.")
        else:
            print("Perfecto! O animal pertence á clase predita.")

        # Re-adestramos o modelo co conxunto de datos actualizado
        X = df.drop(columns=["Clase"])  # Actualizamos as características
        y = df["Clase"]  # Actualizamos as etiquetas
        modelo.fit(X, y)  # Re-adestramos o modelo
        print("O modelo foi actualizado coa nova clase e a nova característica.")
    else:
        print("O modelo errou completamente na predición.")

    # Mostramos a árbore de decisión actualizada
    print("\nAquí tes a árbore de decisión actualizada:")
    mostrar_arvore_decision(modelo, X, y)

    # Paso 4: Preguntamos se a usuaria quere continuar
    continuar = input("\nQueres clasificar outro animal? (Si/Non): ").strip().lower()
    if continuar != "si":
        print("Grazas por usar o clasificador de animais. ¡Ata a próxima!")
        break
    

Inicio e presentación: O programa comeza cunha mensaxe de benvida dirixida á usuaria.

Infórmaa sobre o obxectivo do programa: clasificar animais baseándose nas súas características.

Presenta as clases iniciais dispoñibles (Xirafa, Foca, Ovella) e explica as características principais que definen os animais:

  • Se teñen pelo: 1 (Si) ou 0 (Non).
  • Se son domésticos: 1 (Si) ou 0 (Non).
  • Se viven na auga: 1 (Si) ou 0 (Non).

Configuración inicial: Utiliza un conxunto de datos predefinido (DataFrame) que contén as características iniciais dos animais mencionados.

Crea un modelo de árbore de decisión (DecisionTreeClassifier) usando as librarías de scikit-learn.

Este modelo é adestrado empregando os datos iniciais.

Bucle principal do programa: O programa entra nun bucle que se repite ata que a usuaria decida rematar.

En cada iteración, realízanse os seguintes pasos:

  • Preguntar polas características dun novo animal: Solicítase á usuaria que introduza os valores das características do animal a clasificar.Estas características inclúen as iniciais (pelo, doméstico, vive na auga) e calquera outra característica engadida en interaccións previas.As respostas son almacenadas nun dicionario chamado caracteristicas.
  • Xerar o vector de entrada: Constrúese un vector (entrada) coas características introducidas pola usuaria, mantendo o mesmo formato e orde que o modelo espera.
  • Clasificación: Empregando o modelo de árbore de decisión, realízase a predición da clase do animal (por exemplo, Xirafa ou Foca). Isto baséase nas características proporcionadas. O programa mostra a predición á usuaria.
  • Comprobación da predición: Compara as características introducidas coa clase predicida polo modelo. Pregunta á usuaria se a predición é correcta:
    • Se é correcta: Confírmase a predición, e o modelo segue sendo o mesmo.
    • Se non é correcta:
      • Solicítase á usuaria unha nova característica que diferencie o animal da clase predicida.
      • Engadir unha nova característica e clase: A nova característica proposta pola usuaria é engadida ao conxunto de datos.
      • Pregúntase se as clases existentes teñen ou non esa nova característica.
      • A nova clase do animal introducido pola usuaria é engadida xunto coas súas características.
  • Re-adestramento do modelo: O modelo de árbore de decisión é re-adestrado empregando o conxunto de datos actualizado, que inclúe as novas características e clases introducidas.
  • Continuar ou rematar: Pregúntase á usuaria se desexa clasificar outro animal. Se responde "Si": O bucle continúa, e realízase outra clasificación. Se responde "Non": O programa remata cunha mensaxe de despedida.
  • Esta secuencia garante que o programa aprenda de maneira iterativa, adaptándose ás novas informacións proporcionadas pola usuaria. Deste xeito, mellora a súa capacidade de clasificación co tempo.

Datos iniciais: Creamos un DataFrame inicial con tres animais (xirafa, foca e ovella) definidos polas súas características: Ten pelo, É doméstico, Vive na auga.

Exemplo:

Xirafa: [0, 0, 0]

Foca: [0, 0, 1]

Ovella: [1, 1, 0]

Adestramento inicial do modelo: Utilizamos DecisionTreeClassifier de scikit-learn(librería) para crear e adestrar unha árbore de decisión usando o DataFrame inicial.

Clasificación: Preguntamos as características dun novo animal á usuaria. Usamos o modelo para predicir a clase deste animal baseado nas súas características.

Verificación: Se a predición é correcta, mostramos unha mensaxe de confirmación. Se a predición é incorrecta, pedimos á usuaria que introduza o nome do novo animal e engadímolo como unha nova clase ao DataFrame.

Actualización: Engadimos o novo animal ao DataFrame e re-adestramos o modelo para que inclúa a nova clase.

Iteración: O proceso repítese ata que a usuaria decida rematar.

Interpretación Esta táboa é útil para entender como se diferencian os animais utilizando características clave.

Por exemplo: Podemos observar que só a Ovella é doméstica e que só a Foca vive na auga.

Este tipo de representación permite identificar patróns nos datos, facilitando o uso para modelos de intelixencia artificial.

Tarefa

Duración:
20 min
Agrupamento:
2

Analiza esta árbore de decisión obtida co exemplo de clasificación de animais cunha clase máis. Explica a secuencia de decisión que fan clasificar unha entrada como peixe e como xirafa.

Rexistra no teu portafolio as respostas e conclusións

Árbore de decisión 4 clases
Creación propia. Árbore de decisión 4 clases (CC BY-SA)

Reflexión

Lista de Cotexo

Árbores de decisión

Esta lista axúdache a organizar e verificar o progreso no teu portafolio.