Presentación - Universidad Veracruzana

Anuncio
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Metodologı́as de Programación II
Arboles de Decisión en Lisp
Dr. Alejandro Guerra-Hernández
Departamento de Inteligencia Artificial
Facultad de Fı́sica e Inteligencia Artificial
[email protected]
http://www.uv.mx/aguerra
Maestrı́a en Inteligencia Artificial 2012
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Arboles de Decisión
I
Los árboles de decisión representan hipótesis sobre una
clase, como una conjunción de disyunciones de atributos
proposicionales.
I
Buen dı́a para jugar tenis [1]:
Atributo
Cielo
Clase
Valor
nublado
lluvioso
soleado
Húmedad
alta
no
si
Viento
fuerte
normal
si
no
débil
si
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Ejemplos de entrenamiento
I
La hipótesis explica un conjunto de casos conocido como
ejemplos de entrenamiento.
I
Dı́as donde juego o no al tenis:
dı́a
ej1
ej2
ej3
ej4
ej5
ej6
ej7
ej8
ej9
ej10
ej11
ej12
ej13
ej14
cielo
soleado
soleado
nublado
lluvia
lluvia
lluvia
nublado
soleado
soleado
lluvia
soleado
nublado
nublado
lluvia
temperatura
calor
calor
calor
templado
frı́o
frı́o
frı́o
templado
frı́o
templado
templado
templado
calor
templado
humedad
alta
alta
alta
alta
normal
normal
normal
alta
normal
normal
normal
alta
normal
alta
viento
débil
fuerte
débil
débil
débil
fuerte
fuerte
débil
débil
débil
fuerte
fuerte
débil
fuerte
jugar-tenis
no
no
si
si
si
no
si
no
si
si
si
si
si
no
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Clasificación
1: function CLASIFICA(E: ejemplo, A: árbol)
2:
Clase ← valor-atributo(raı́z(A),E);
3:
if es-hoja(raı́z(A)) then
4:
return Clase
5:
else
6:
clasifica(E, sub-árbol(A,Clase));
7:
end if
8: end function
I
Dado el árbol de la página anterior, el caso:
hCielo = soleado, Temperatura = caliente, Humedad = alta, Viento = fuertei
no clasifica como un buen dı́a para jugar tenis.
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
ID3 [2] Inducción de árboles de decisión
1: function ID3(E: ejemplos, A: atributos, C: clase)
2:
AD ← ∅; Clase ← clase-mayoritaria(C,E);
3:
if E = ∅ then return AD;
4:
else if misma-clase(E,C) then return AD ← Clase;
5:
else if A = ∅ then return AD ← Clase;
6:
else
7:
Mejor-Partición ← mejor-partición(E, A);
8:
Mejor-Atributo ← primero(Mejor-Partición);
9:
AD ← Mejor-Atributo;
10:
for all Partición ∈ resto(Mejor-Partición) do
11:
Valor-Atributo ← primero(Partición);
12:
Sub-E ← resto(Partición);
13:
agregar-rama(AD, Valor-Atributo, ID3(Sub-E, {A \ Mejor-Atributo}, C));
14:
end for
15:
end if
16: end function
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Entropı́a
I
Si los posibles n valores del atributo v , ocurren con
probabilidades P(vi,...,n ), entonces el contenido de
información, o entropı́a, E está dado por:
E(P(vi ), . . . , P(vn )) =
n
X
−P(vi ) log2 P(vi )
i=1
I
En nuestro caso, de 14 ejemplos 9 son positivos y 5 son
negativos:
9 5
E( , ) = 0,940
14 14
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Ganancia de información
I
Es la reducción de la entropı́a causada por particionar un
conj. de entrenamiento S, con respecto a un atributo
a ∈ A:
ganancia(S, a) = E(S) −
X |Sv |
v ∈a
|S|
E(Sv )
I
Observen que el segundo término de ganancia/2, es la
entropı́a con respecto al atributo a.
I
Para nuestro ejemplo:
ganancia(S, cielo) = 0,24674976
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Mejor atributo
I
1
2
3
4
5
Aquel que maximiza la ganancia de información:
Information gain of
Information gain of
0.029222548
Information gain of
Information gain of
Highest information
attribute CIELO : 0.24674976
attribute TEMPERATURA :
attribute HUMEDAD : 0.15183544
attribute VIENTO : 0.048126936
gain: 0.24674976
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Arboles de Decisión
I
Podemos representarlos como una lista de listas:
CL-USER> (setq arbol ’(cielo
(soleado (humedad
(normal si)
(alta no)))
(nublado si)
(lluvia (viento
(fuerte no)
(debil si)))))
(CIELO (SOLEADO (HUMEDAD (NORMAL SI) (ALTA NO))) (
NUBLADO SI) (LLUVIA (VIENTO (FUERTE NO) (DEBIL SI
))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Funciones de acceso sobre árboles
CL-USER>
CIELO
CL-USER>
(HUMEDAD
CL-USER>
SI
CL-USER>
NIL
CL-USER>
T
(root arbol)
(sub-tree arbol ’soleado)
(NORMAL SI) (ALTA NO))
(sub-tree arbol ’nublado)
(leaf (sub-tree arbol ’soleado))
(leaf (sub-tree arbol ’nublado))
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Implementación funciones de acceso al árbol
1
2
(defun root(Tree)
(car Tree))
3
4
5
(defun sub-tree(Tree Attribute-Value)
(second (assoc Attribute-Value (cdr Tree))))
6
7
8
(defun leaf(Tree)
(atom Tree))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
¿Cómo funciona assoc?
CL-USER> (assoc
(UNO 1)
CL-USER> (assoc
(DOS 2)
CL-USER> (assoc
(LLUVIA (VIENTO
’uno ’((uno 1) (dos 2) (tres 3)))
’dos ’((uno 1) (dos 2) (tres 3)))
’lluvia (cdr arbol))
(FUERTE NO) (DEBIL SI)))
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Imprimiendo el árbol
CL-USER> (print-tree arbol)
CIELO
- SOLEADO
HUMEDAD
- NORMAL -> SI
- ALTA -> NO
- NUBLADO -> SI
- LLUVIA
VIENTO
- FUERTE -> NO
- DEBIL -> SI
NIL
Carga de Archivos
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Definiendo print-tree
1
2
3
4
5
6
7
8
9
10
11
(defun print-tree (tree &optional (depth 0))
(mytab depth)
(format t "˜A˜ %" (first tree))
(loop for subtree in (cdr tree) do
(mytab (+ depth 1))
(format t "- ˜A" (first subtree))
(if (atom (second subtree))
(format t " -> ˜A˜ %" (second subtree))
(progn
(terpri)
(print-tree (second subtree) (+ depth
5))))))
12
13
14
(defun mytab (n)
(loop for i from 1 to n do (format t " ")))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Ejemplos de entrenamiento
I
Aunque los ejemplos también pueden representarse como
una lista de listas, esto no es buena idea.
I
Necesitamos una representación que nos permita
relacionar un ejemplo dado, con el valor de un atributo
dado. Supongan que *examples* es mi repositorio de
ejemplos:
CL-USER> (get-value ’cielo (car *examples*))
LLUVIA
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Ejemplos, atributos y valores
1
2
(defun put-value (attr inst val)
(setf (get inst attr) val))
3
4
5
(defun get-value (attr inst)
(get inst attr))
CL-USER> (put-value ’nombre ’ej1 ’alejandro)
ALEJANDRO
CL-USER> (get-value ’nombre ’ej1)
ALEJANDRO
CL-USER> (setq *ejemplos* nil)
NIL
CL-USER> (push ’ej1 *ejemplos*)
(EJ1)
CL-USER> (get-value ’nombre (car *ejemplos*))
ALEJANDRO
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Archivos de ejemplos: ARFF y CSV
I
Un archivo tenis.arff:
@RELATION jugar-tenis
@ATTRIBUTE
@ATTRIBUTE
@ATTRIBUTE
@ATTRIBUTE
@ATTRIBUTE
cielo {soleado,nublado,lluvia}
temperatura {calor,templado,frio}
humedad {alta,normal}
viento {debil,fuerte}
jugar-tenis {si,no}
@DATA
soleado, calor, alta, debil, no
soleado, calor, alta, fuerte, no
nublado, calor, alta, debil, si
lluvia, templado, alta, debil, si
...
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
With a little help from your friends
I
ASFD2 (Another System Definition Facility 2) es una
herramienta para describir como están organizados los
archivos fuente de un sistema Lisp.
I
En particular sus dependencias.
I
Quiklisp es una herramienta que nos permite instalar
librerı́as que han sido definidas usando ASDF2.
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Instalando ASDF2
I
http://common-lisp.net/project/asdf/
I
Descargar la fuente asdf.lisp ó el tarball con la
distribución completa del sistema.
I
Compilar éste archivo
I
Agregar la siguiente lı́nea al archivo .lispworks o el
archivo de inicialización de cualquier otro Lisp:
#-:asdf (load "˜/lisp/asdf/asdf")
1
I
Si el sı́mbolo ASDF no está definido, Lisp cargará el
sistema.
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Instalando Quicklisp
I
http://www.quicklisp.org/beta/
I
Descargar el archivo quicklisp.lisp
I
Cargarglo en Lisp, evaluar: (ql:add-to-init-file)
I
Quicklisp se cargará cada vez que llamemos a Lisp!
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Instalando librerı́as: trivial-shell
1
2
3
4
5
6
7
8
9
10
11
12
CL-USER> (ql:quickload "trivial-shell")
To load "trivial-shell":
Install 1 Quicklisp release:
trivial-shell
; Fetching #<QL-HTTP:URL "http://beta.quicklisp.org/archive
/trivial-shell/2011-05-22/trivial-shell-20110522-http.
tgz">
; 13.61KB
==================================================
13,937 bytes in 0.00 seconds (13610.35KB/sec)
; Loading "trivial-shell"
[package com.metabang.trivial-timeout]............
[package trivial-shell]..
("trivial-shell")
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
GUI
Ejecutando comandos shell: grep
1
2
3
4
5
6
7
8
9
CL-USER> (trivial-shell:shell-command "egrep \"@ATTR\" tenis.arff")
"@ATTRIBUTE cielo {soleado,nublado,lluvia}
@ATTRIBUTE temperatura {calor,templado,frio}
@ATTRIBUTE humedad {alta,normal}
@ATTRIBUTE viento {debil,fuerte}
@ATTRIBUTE jugar-tenis {si,no}
"
NIL
0
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Partiendo cadenas: split-sequence
1
2
3
4
5
6
7
8
9
10
11
12
13
CL-USER> (ql:quickload "split-sequence")
To load "split-sequence":
Install 1 Quicklisp release:
split-sequence
; Fetching #<QL-HTTP:URL "http://beta.quicklisp.org/archive/
split-sequence/2011-08-29/split-sequence-1.0.tgz">
==================================================
2,580 bytes in 0.00 seconds (2519.53KB/sec)
; Loading "split-sequence"
[package split-sequence]
("split-sequence")
CL-USER> (split-sequence:split-sequence #\, "hola, que, tal")
("hola" " que" " tal")
14
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Ensamblando cajitas
1
2
3
4
5
CL-USER> (split-sequence:split-sequence #\Newline
(trivial-shell:
shell-command
"egrep \"@ATTR\"
tenis.arff"))
("@ATTRIBUTE cielo {soleado,nublado,lluvia}" "@ATTRIBUTE
temperatura {calor,templado,frio}" "@ATTRIBUTE humedad
{alta,normal}" "@ATTRIBUTE viento {debil,fuerte}" "
@ATTRIBUTE jugar-tenis {si,no}" "")
184
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Variables globales
1
2
3
4
5
(defvar
(defvar
(defvar
(defvar
(defvar
*attributes* nil "The attributes of the problem")
*domains* nil "The domain of the attributes")
*target* nil "The target concept")
*examples* nil "The training set")
*trace* nil "Trace the computations")
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Datos crudos
1
2
3
4
5
6
7
8
9
10
11
(defun get-data (arff)
(mapcar #’(lambda(x)
(mapcar #’read-from-string
(split-sequence:split-sequence #\, x)))
(butlast
(split-sequence:split-sequence
#\Newline
(trivial-shell:shell-command
(concatenate ’string
"egrep -v \"ˆ$|[@ %]\" "
arff))))))
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
get-data
CL-USER> (get-data "tenis.arff")
((SOLEADO CALOR ALTA DEBIL NO) (SOLEADO CALOR ALTA FUERTE
NO) (NUBLADO CALOR ALTA DEBIL SI) (LLUVIA TEMPLADO ALTA
DEBIL SI) (LLUVIA FRIO NORMAL DEBIL SI) (LLUVIA FRIO
NORMAL FUERTE NO) (NUBLADO FRIO NORMAL FUERTE SI) (
SOLEADO TEMPLADO ALTA DEBIL NO) (SOLEADO FRIO NORMAL
DEBIL SI) (LLUVIA TEMPLADO NORMAL DEBIL SI) (SOLEADO
TEMPLADO NORMAL FUERTE SI) (NUBLADO TEMPLADO ALTA
FUERTE SI) (NUBLADO CALOR NORMAL DEBIL SI) (LLUVIA
TEMPLADO ALTA FUERTE NO))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Clase a predecir
1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
(defun get-target (arff)
(read-from-string
(car
(cdr (split-sequence:split-sequence
#\Space
(car
(butlast
(split-sequence:split-sequence
#\Newline
(trivial-shell:shell-command
(concatenate ’string
"egrep \"@rel|@REL\" "
arff))))))))))
CL-USER> (get-target "tenis.arff")
JUGAR-TENIS
11
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Dominios
1
2
3
(defun get-domain (attribute)
(nth (position attribute *attributes*)
*domains*))
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Todo junto
1
2
3
4
5
6
7
8
9
10
11
12
13
14
(defun id3-load (arff)
(let ((data (get-data arff))
(attribs-doms (get-attribs-doms arff)))
(setf *gensym-counter* 1)
(setf *attributes* (mapcar #’car attribs-doms))
(setf *domains* (mapcar #’cadr attribs-doms))
(setf *target* (get-target arff))
(loop for d in data do
(let ((ej (gensym "ej")))
(setf *examples* (cons ej *examples*))
(loop for attrib in *attributes*
as v in d do
(put-value attrib ej v))))
(format t "Training set initialized")))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Ejecución
1
2
3
4
5
6
7
8
9
CL-USER> (id3-load "/Users/aguerra/Desktop/Dropbox/2012mpii/codigo/clase06/tenis.arff")
Training set initialized
NIL
CL-USER> *examples*
(#:|ej14| #:|ej13| #:|ej12| #:|ej11| #:|ej10| #:|ej9| #:|
ej8| #:|ej7| #:|ej6| #:|ej5| #:|ej4| #:|ej3| #:|ej2|
#:|ej1|)
CL-USER> *attributes*
(CIELO TEMPERATURA HUMEDAD VIENTO JUGAR-TENIS)
CL-USER> *domains*
((SOLEADO NUBLADO LLUVIA) (CALOR TEMPLADO FRIO) (ALTA
NORMAL) (DEBIL FUERTE) (SI NO))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Y el reseteo
1
2
3
4
5
6
7
8
(defun id3-reset ()
(setf *examples* nil
*target* nil
*attributes* nil
*domains* nil
*trace* nil
*root* nil)
(format t "The ID3 setting has been reset."))
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Definición de un sistema ASDF: cl-id3.asd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(asdf:defsystem :cl-id3
:depends-on (:split-sequence)
:components ((:file "cl-id3-package")
(:file "cl-id3-algorithm"
:depends-on ("cl-id3-package"))
(:file "cl-id3-load"
:depends-on ("cl-id3-package"
"cl-id3-algorithm"))
(:file "cl-id3-classify"
:depends-on ("cl-id3-package"
"cl-id3-algorithm"
"cl-id3-load"))
(:file "cl-id3-cross-validation"
:depends-on ("cl-id3-package"
"cl-id3-algorithm"
"cl-id3-load"
"cl-id3-classify"))
(:file "cl-id3-gui"
:depends-on ("cl-id3-package"
"cl-id3-algorithm"
"cl-id3-load"
"cl-id3-classify"
"cl-id3-cross-validation"))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Definiendo un paquete: cl-id3-package
1
2
3
4
5
6
7
8
9
(defpackage :cl-id3
(:use :cl :capi :split-sequence)
(:export :load-file
:induce
:print-tree
:classify
:classify-new-instance
:cross-validation
:gui))
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Leyendo archivos: cl-id3-load
1
(in-package :cl-id3)
2
3
;;; Auxiliar functions
4
5
6
7
8
9
10
(defun read-lines-from-file (file)
"It reads the FILE into a list of strings"
(remove-if (lambda (x) (equal x ""))
(with-open-file (in file)
(loop for line = (read-line in nil ’end)
until (eq line ’end) collect line))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
GUI
Portabilidad: Bye, bye grep
1
2
3
4
5
6
7
8
(defun arff-get-data (lines)
"It extracts the value for *data* from the lines of a ARFF file"
(mapcar #’(lambda(x)
(mapcar #’read-from-string
(split-sequence #\, x)))
(remove-if
(lambda (x) (string-equal "@" (subseq x 0 1)))
lines)))
9
10
11
12
13
14
(defun csv-get-data (lines)
"It extracts the value for *data* from the lines of a CSV file"
(mapcar #’(lambda(x)
(mapcar #’read-from-string
(split-sequence #\, x))) (cdr lines)))
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Ejemplo arff-get-data
1
2
CL-ID3> (arff-get-data (read-lines-from-file "tenis.
arff"))
((SOLEADO CALOR ALTA DEBIL NO) (SOLEADO CALOR ALTA
FUERTE NO) (NUBLADO CALOR ALTA DEBIL SI) (LLUVIA
TEMPLADO ALTA DEBIL SI) (LLUVIA FRIO NORMAL DEBIL
SI) (LLUVIA FRIO NORMAL FUERTE NO) (NUBLADO FRIO
NORMAL FUERTE SI) (SOLEADO TEMPLADO ALTA DEBIL
NO) (SOLEADO FRIO NORMAL DEBIL SI) (LLUVIA
TEMPLADO NORMAL DEBIL SI) (SOLEADO TEMPLADO
NORMAL FUERTE SI) (NUBLADO TEMPLADO ALTA FUERTE
SI) (NUBLADO CALOR NORMAL DEBIL SI) (LLUVIA
TEMPLADO ALTA FUERTE NO))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Load
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
(defun load-file (file)
"It initializes the learning setting from FILE"
(labels ((get-examples (data)
(loop for d in data do
(let ((ej (gensym "ej")))
(setf *examples* (cons ej *examples*))
(loop for attrib in *attributes*
as v in d do
(put-value attrib ej v))))))
(if (probe-file file)
(let ((file-ext (car (last (split-sequence #\. file))))
(file-lines (read-lines-from-file file)))
(reset)
(cond
((equal file-ext "arff")
(let ((attribs-doms (arff-get-attribs-doms file-lines)))
(setf *attributes* (mapcar #’car attribs-doms))
(setf *domains* (mapcar #’cadr attribs-doms))
(setf *target* (arff-get-target file-lines))
(setf *data* (arff-get-data file-lines))
(get-examples *data*)
(format t "Training setting initialized after ˜s.˜ %" file)))
((equal file-ext "csv")
(let ((attribs-doms (csv-get-attribs-doms file-lines)))
(setf *attributes* (mapcar #’car attribs-doms))
...
(t (error "File’s ˜s extension can not be determined." file))))
(error "File ˜s does not exist.˜ %" file))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Cargando un archivo
1
2
3
4
5
6
7
8
9
10
CL-ID3> (load-file "tenis.arff")
The ID3 setting has been reset.
Training setting initialized after "tenis.arff".
NIL
CL-ID3> *target*
JUGAR-TENIS
CL-ID3> *attributes*
(CIELO TEMPERATURA HUMEDAD VIENTO JUGAR-TENIS)
CL-ID3> *examples*
(#:|ej14| #:|ej13| #:|ej12| #:|ej11| #:|ej10| #:|ej9|
#:|ej8| #:|ej7| #:|ej6| #:|ej5| #:|ej4| #:|ej3|
#:|ej2| #:|ej1|)
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Algoritmo principal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(defun id3 (examples attribs)
"It induces a decision tree runing ID3 over EXAMPLES and ATTRIBS)"
(let ((class-by-default (get-value *target* (car examples))))
(cond
;; Stop criteria
((same-class-value-p *target*
class-by-default
examples) class-by-default)
;; Failure
((null attribs) (target-most-common-value examples))
;; Recursive call
(t (let* ((partition (best-partition attribs examples))
(node (first partition)))
(cons node
(loop for branch in (cdr partition) collect
(list (first branch)
(id3 (cdr branch)
(remove node attribs))))))))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Todos somos de la misma clase?
1
2
3
4
5
6
1
2
3
4
(defun same-class-value-p (attrib value examples)
"Do all EXAMPLES have the same VALUE for a given ATTRIB ?"
(every #’(lambda(e)
(eq value
(get-value attrib e)))
examples))
CL-ID3> (same-class-value-p *target* ’si *examples*)
NIL
CL-ID3> (same-class-value-p *target* ’no *examples*)
NIL
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Valor mayoritario de Clase
1
2
3
4
5
6
7
8
9
1
2
(defun target-most-common-value (examples)
"It gets the most common value for *target* in EXAMPLES"
(let ((domain (get-domain *target*))
(vals (mapcar #’(lambda(x) (get-value *target* x))
examples)))
(caar (sort (loop for v in domain collect
(list v (count v vals)))
#’(lambda(x y) (>= (cadr x)
(cadr y)))))))
CL-ID3> (target-most-common-value *examples*)
SI
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Partición
1
2
3
4
5
6
7
8
9
10
11
12
1
2
(defun get-partition (attrib examples)
"It gets the partition induced by ATTRIB in EXAMPLES"
(let (result vlist v)
(loop for e in examples do
(setq v (get-value attrib e))
(if (setq vlist (assoc v result))
;;; value v existed, the example e is added
;;; to the cdr of vlist
(rplacd vlist (cons e (cdr vlist)))
;;; else a pair (v e) is added to result
(setq result (cons (list v e) result))))
(cons attrib result)))
CL-ID3> (get-partition ’cielo *examples*)
(CIELO (SOLEADO #:|ej1| #:|ej2| #:|ej8| #:|ej9| #:|
ej11|) (NUBLADO #:|ej3| #:|ej7| #:|ej12| #:|ej13
|) (LLUVIA #:|ej4| #:|ej5| #:|ej6| #:|ej10| #:|
ej14|))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Entropı́a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
(defun entropy (examples attrib)
"It computes the entropy of EXAMPLES with respect to an ATTRIB"
(let ((partition (get-partition attrib examples))
(number-of-examples (length examples)))
(apply #’+
(mapcar #’(lambda(part)
(let* ((size-part (count-if #’atom
(cdr part)))
(proportion
(if (eq size-part 0) 0
(/ size-part
number-of-examples))))
(* -1.0 proportion (log proportion 2))))
(cdr partition)))))
CL-ID3> (entropy *examples* ’jugar-tenis)
0.9402859
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
GUI
Ganancia de Información
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
(defun information-gain (examples attribute)
"It computes information-gain for an ATTRIBUTE in EXAMPLES"
(let ((parts (get-partition attribute examples))
(no-examples (count-if #’atom examples)))
(- (entropy examples *target*)
(apply #’+
(mapcar
#’(lambda(part)
(let* ((size-part (count-if #’atom
(cdr part)))
(proportion (if (eq size-part 0) 0
(/ size-part
no-examples))))
(* proportion (entropy (cdr part) *target*))))
(cdr parts))))))
CL-ID3> (information-gain *examples* ’cielo)
0.2467497
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Mejor partición
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
(defun best-partition (attributes examples)
"It computes one of the best partitions induced by ATTRIBUTES over EXAMPLES"
(let* ((info-gains
(loop for attrib in attributes collect
(let ((ig (information-gain examples attrib))
(p (get-partition attrib examples)))
(when *trace*
(format t "Partición inducida por el atributo ˜s:˜ %˜s˜ %"
attrib p)
(format t "Ganancia de información: ˜s˜ %"
ig))
(list ig p))))
(best (cadar (sort info-gains #’(lambda(x y) (> (car x) (car y)))))))
(when *trace* (format t "Best partition: ˜s˜ %-------------˜ %" best))
best))
CL-ID3> (best-partition (remove *target* *attributes*)
*examples*)
(CIELO (SOLEADO #:|ej1| #:|ej2| #:|ej8| #:|ej9| #:|ej11
|) (NUBLADO #:|ej3| #:|ej7| #:|ej12| #:|ej13|) (
LLUVIA #:|ej4| #:|ej5| #:|ej6| #:|ej10| #:|ej14|))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Induciendo un árbol
1
2
3
4
5
1
2
(defun induce (&optional (examples *examples*))
"It induces the decision tree using learning sertting"
(when (not (member *target* *attributes*))
(error "The target is defined incorrectly: Maybe Weka
modified your ARFF"))
(id3 examples (remove *target* *attributes*)))
CL-ID3> (induce)
(CIELO (SOLEADO (HUMEDAD (NORMAL SI) (ALTA NO))) (
NUBLADO SI) (LLUVIA (VIENTO (FUERTE NO) (DEBIL SI
))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Y con print-tree
1
2
3
4
5
6
7
8
9
10
11
12
CL-ID3> (print-tree (induce))
CIELO
- SOLEADO
HUMEDAD
- NORMAL -> SI
- ALTA -> NO
- NUBLADO -> SI
- LLUVIA
VIENTO
- FUERTE -> NO
- DEBIL -> SI
NIL
Carga de Archivos
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
La interfaz gráfica del sistema
Carga de Archivos
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
capi:contain
I
1
2
Podemos probar codigo de la GUI como sigue:
CL-USER> (capi:contain (capi:display-message
"CL-ID3˜ %˜ %Universidad Veracruzana˜ %Departamento
de Inteligencia Artificial˜ %Sebastián Camacho
No 5˜ %Xalapa, Ver., México 91000˜ %http://www.
uv.mx/aguerra˜ %[email protected]"))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Variables globales (habilitar menus)
1
2
3
4
5
(defvar *examples-on* nil "t enables the examples menu")
(defvar *attributes-on* nil "t enables the attributes menu")
(defvar *induce-on* nil "t enables the induce menu")
(defvar *classify-on* nil "t enables the classify menu")
(defvar *cross-validation-on* nil "t enables the cross-validation
menu")
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Ventana principal: paneles de texto
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(define-interface cl-id3-gui ()
()
(:panes
(source-id-pane text-input-pane
:accessor source-id-pane
:text ""
:enabled nil)
(num-attributes-pane text-input-pane
:accessor num-attributes-pane
:text ""
:enabled nil)
(num-examples-pane text-input-pane
:accessor num-examples-pane
:text ""
:enabled nil)
(class-pane text-input-pane
:accessor class-pane
:text ""
:enabled nil)
(efficiency-pane text-input-pane
:text ""
:enabled nil)
(k-value-pane text-input-pane
:text "0")...
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Ventana principal: Otros paneles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
(tree-pane graph-pane
:title "Decision Tree"
:title-position :frame
:children-function ’node-children
:edge-pane-function
#’(lambda(self from to)
(declare (ignore self from))
(make-instance
’labelled-arrow-pinboard-object
:data (princ-to-string (node-from-label to))))
:visible-min-width 450
:layout-function :top-down)
(state-pane title-pane
:accessor state-pane
:text "Welcome to CL-ID3.")) ...
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
ID3
Ventana principal: Menus 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
(:menus
(file-menu
"File"
(("Open" :selection-callback ’gui-load-file
:accelerator #\o)
("Quit" :selection-callback ’gui-quit
:accelerator #\q)))
(view-menu
"View"
(("Attributes" :selection-callback ’gui-view-attributes
:accelerator #\a
:enabled-function #’(lambda (menu)
(declare (ignore menu)) *attributes-on*))
("Examples" :selection-callback ’gui-view-examples
:accelerator #\e
:enabled-function #’(lambda (menu)
(declare (ignore menu)) *examples-on*))))
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Ventana principal: Menus 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
(id3-menu
"id3"
(("Induce" :selection-callback ’gui-induce
:accelerator #\i
:enabled-function #’(lambda (menu)
(declare (ignore menu)) *induce-on*))
("Classify" :selection-callback ’gui-classify
:accelerator #\k
:enabled-function #’(lambda (menu)
(declare (ignore menu)) *classify-on*))
("Cross-validation" :selection-callback ’gui-cross-validation
:accelerator #\c
:enabled-function #’(lambda (menu)
(declare (ignore menu)) *
cross-validation-on*))))
(help-menu
"Help"
(("About" :selection-callback ’gui-about))))
(:menu-bar file-menu view-menu id3-menu help-menu)
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Ventana principal: Layouts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(:layouts
(main-layout column-layout ’(panes state-pane))
(panes row-layout ’(info-pane tree-pane))
(titles column-layout ’())
(matrix-pane row-layout ’(titles confusion)
:title "Confusion Matrix" :x-gap ’10 :y-gap ’30
:title-position :frame :visible-min-width ’200)
(confusion grid-layout ’())
(info-pane column-layout ’(setting-pane id3-pane matrix-pane))
(setting-pane grid-layout
’("Source File" source-id-pane
"No. Attributes" num-attributes-pane
"No. Examples" num-examples-pane
"Class" class-pane)
:y-adjust :center
:title "Trainning Set"
:title-position :frame :columns ’2)
(id3-pane grid-layout ’("K value" k-value-pane
"Efficiency" efficiency-pane)
:y-adjust :center
:title "Cross Validation"
:title-position :frame :columns ’2))
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Ventana principal: datos iniciales
1
2
3
4
(:default-initargs
:title "CL-ID3"
:visible-min-width 840
:visible-min-height 600))
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Llamadas: gui-load-file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(defun gui-load-file (data interface)
(declare (ignore data))
(let ((file (prompt-for-file
nil
:filter "*.arff"
:filters ’("WEKA files" "*.arff"
"Comme Separated Values" "*.csv"))))
(when file
(let* ((path (princ-to-string file))
(setting (car (last (split-sequence #\/ path)))))
(load-file path)
(setf (text-input-pane-text (source-id-pane interface))
setting)
(setf (text-input-pane-text (num-attributes-pane interface))
(princ-to-string (length *attributes*)))
(setf (text-input-pane-text (num-examples-pane interface))
(princ-to-string (length *examples*)))
(setf (text-input-pane-text (class-pane interface))
(princ-to-string *target*))
(setf (title-pane-text (state-pane interface))
(format nil "The setting ˜s has been loaded"
path))
(setf *examples-on* t *attributes-on* t *induce-on* t)))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Llamadas: gui-quit
1
2
3
(defun gui-quit (data interface)
(declare (ignore data))
(quit-interface interface))
Carga de Archivos
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Llamadas: gui-view-attributes 1
1
2
3
4
5
6
7
8
9
(defun gui-view-attributes (data interface)
(declare (ignore data interface))
(let* ((max-length-attrib (apply #’max
(mapcar #’length
(mapcar #’princ-to-string
*attributes*))))
(pane-total-width (list ’character
(* max-length-attrib
(+ 1 (length *attributes*))))))...
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Llamadas: gui-view-attributes 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(define-interface gui-domains () ()
(:panes
(attributes-pane multi-column-list-panel
:columns ’((:title "Attrib/Class"
:adjust :left
:visible-min-width (character 10))
(:title "Attributes" :adjust :left
:visible-min-width (character 20))
(:title "Domains" :adjust :left
:visible-min-width (character 20)))
:items (loop for a in *attributes* collect
(list (if (eql *target* a) ’c ’a )
a
(get-domain a)))
:visible-min-width pane-total-width
:visible-min-height :text-height
:vertical-scroll t)
(button-pane push-button
:text "Close"
:callback ’gui-quit))
(:default-initargs
:title "CL-ID3:attributes"))
(display (make-instance ’gui-domains))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Dibujando el árbol: listas → nodos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(defstruct node
(inf nil)
(sub-trees nil)
(from-label nil))
(defun make-tree (tree-as-lst)
"It makes a tree of nodes with TREE-AS-LST"
(make-node :inf (root tree-as-lst)
:sub-trees (make-sub-trees (children tree-as-lst))))
(defun make-sub-trees (children-lst)
"It makes de subtrees list of a tree with CHILDREN"
(loop for child in children-lst collect
(let ((sub-tree (second child))
(label (first child)))
(if (leaf-p sub-tree)
(make-node :inf sub-tree
:sub-trees nil
:from-label label)
(make-node :inf (root sub-tree)
:sub-trees (make-sub-trees (children sub-tree))
:from-label label)))))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Dibujando el árbol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
(defmethod print-object ((n node) stream)
(format stream "˜s " (node-inf n)))
(defun display-tree (root interface)
"It displays the tree with ROOT in its pane in INTERFACE"
(with-slots (tree-pane) interface
(setf (graph-pane-roots tree-pane)
(list root))
(map-pane-children tree-pane ;;; redraw panes correcting x/y-adjustments
(lambda (item)
(update-pinboard-object item)))))
(defun node-children (node)
"It gets the children of NODE to be displayed"
(let ((children (node-sub-trees node)))
(when children
(if (leaf-p children) (list children)
children))))
;;; induce
(defun gui-induce (data interface)
"It induces the decisicion tree and displays it in the INTERFACE"
(declare (ignore data))
(setf *current-tree* (induce))
(display-tree (make-tree *current-tree*)
interface))
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Función principal
1
2
3
(defun gui ()
(reset)
(display (make-instance ’cl-id3-gui)))
Mejoras
ID3
GUI
Introducción
Representaciones
Librerı́as ASDF2
Carga de Archivos
Mejoras
Bibliografı́a
T. Mitchell.
Machine Learning.
Computer Science Series. McGraw-Hill International
Editions, Singapore, 1997.
J. Quinlan.
Induction of decision trees.
Machine Learning, 1(1):81–106, 1986.
ID3
GUI
Descargar