Sesión 9A#
Factores#
Objetivos:
Entender el concepto de factor.
Apropiar las operaciones que podemos desarrollar con los factores.
Introducción al uso de la librería pgmpy
¿Qué es un factor?#
Un factor es una función o tabla que asigna un número real (no necesariamente una probabilidad) a cada combinación posible de valores de un conjunto de variables aleatorias.
Su entrada son las variables aleatorias \(X_1, X_2, \ldots, X_k\).
Su salida es un número real.
El conjunto de variables que se usa se llama alcance (scope):
Ejemplos de factores#
(a) Distribución conjunta:
Una distribución conjunta es un factor cuyo alcance son todas las variables aleatorias del modelo.
Por ejemplo:
\(P(I,D,G)\)
I |
D |
G |
P(I,D,G) |
|---|---|---|---|
i0 |
d0 |
g0 |
0.03 |
i0 |
d0 |
g1 |
0.25 |
i0 |
d1 |
g0 |
0.1 |
i0 |
d1 |
g1 |
0.35 |
i1 |
d0 |
g0 |
0.05 |
i1 |
d0 |
g1 |
0.15 |
i1 |
d1 |
g0 |
0.04 |
i1 |
d1 |
g1 |
0.03 |
La suma de todas las entradas es 1 — esa es la única diferencia con un factor general. Lo que hace a esto un factor es simplemente que cada entrada es un número real no negativo.
(b) Medida sin normalizar:
Partimos de la distribución conjunta P(I, D, G) del inciso anterior y fijamos G = g¹ — nos quedamos solo con las filas donde G toma ese valor:
Por ejemplo:
\(P(I, D, G=g^{1})\)
I |
D |
\(P(I, D, G=g^{1})\) |
|---|---|---|
i⁰ |
d⁰ |
0.25 |
i⁰ |
d¹ |
0.35 |
i¹ |
d⁰ |
0.15 |
i¹ |
d¹ |
0.03 |
(c) Distribución condicional (CPD):
Por ejemplo:
\(P(G | I, D)\)
I |
D |
g¹ |
g² |
g³ |
|---|---|---|---|---|
i⁰ |
d⁰ |
0.3 |
0.4 |
0.3 |
i⁰ |
d¹ |
0.05 |
0.25 |
0.7 |
i¹ |
d⁰ |
0.9 |
0.08 |
0.02 |
i¹ |
d¹ |
0.5 |
0.3 |
0.2 |
(d) Factores generales:
Por ejemplo:
A |
B |
\(\phi\) |
|---|---|---|
a⁰ |
b⁰ |
30 |
a⁰ |
b¹ |
5 |
a¹ |
b⁰ |
1 |
a¹ |
b¹ |
10 |
Operaciones de factores#
1. Producto de factores
A |
B |
\(\phi_1\) |
|---|---|---|
\(a^0\) |
\(b^0\) |
5 |
\(a^0\) |
\(b^1\) |
8 |
\(a^1\) |
\(b^0\) |
1 |
\(a^1\) |
\(b^1\) |
0 |
\(a^2\) |
\(b^0\) |
3 |
\(a^2\) |
\(b^1\) |
9 |
B |
C |
\(\phi_2\) |
|---|---|---|
\(b^0\) |
\(c^0\) |
5 |
\(b^0\) |
\(c^1\) |
7 |
\(b^1\) |
\(c^0\) |
1 |
\(b^1\) |
\(c^1\) |
2 |
A |
B |
C |
\(\phi_3\) |
|---|---|---|---|
\(a^0\) |
\(b^0\) |
\(c^0\) |
\(5\times 5 = 25\) |
\(a^0\) |
\(b^0\) |
\(c^1\) |
\(5\times 7 = 35\) |
\(a^0\) |
\(b^1\) |
\(c^0\) |
\(8\times 1 = 8\) |
\(a^0\) |
\(b^1\) |
\(c^1\) |
\(8\times 2 = 16\) |
\(a^1\) |
\(b^0\) |
\(c^0\) |
\(1\times 5 = 5\) |
\(a^1\) |
\(b^0\) |
\(c^1\) |
\(1\times 7 = 7\) |
\(a^1\) |
\(b^1\) |
\(c^0\) |
\(0\times 1 = 0\) |
\(a^1\) |
\(b^1\) |
\(c^1\) |
\(0\times 2 = 0\) |
\(a^2\) |
\(b^0\) |
\(c^0\) |
\(3\times 5 = 15\) |
\(a^2\) |
\(b^0\) |
\(c^1\) |
\(3\times 7 = 21\) |
\(a^2\) |
\(b^1\) |
\(c^0\) |
\(9\times 1 = 9\) |
\(a^2\) |
\(b^1\) |
\(c^1\) |
\(9\times 2 = 18\) |
# Importamos pgmpy.factors.discrete.DiscreteFactor
from pgmpy.factors.discrete import DiscreteFactor
DiscreteFactor?
# Factores phi1, phi2
phi1 = DiscreteFactor(
variables=['A', 'B'],
cardinality=[3,2],
values=[5,8,1,0,3,9]
)
phi2 = DiscreteFactor(
variables=['B', 'C'],
cardinality=[2,2],
values=[5,7,1,2]
)
Factor: φ₁(A, B)
Variables y cardinalidades:
A → 3 valores posibles (a⁰, a¹, a²)
B → 2 valores posibles (b⁰, b¹)
Cardinalidad total: 3 × 2 = 6 combinaciones
#print
print(phi1)
+------+------+------------+
| A | B | phi(A,B) |
+======+======+============+
| A(0) | B(0) | 5.0000 |
+------+------+------------+
| A(0) | B(1) | 8.0000 |
+------+------+------------+
| A(1) | B(0) | 1.0000 |
+------+------+------------+
| A(1) | B(1) | 0.0000 |
+------+------+------------+
| A(2) | B(0) | 3.0000 |
+------+------+------------+
| A(2) | B(1) | 9.0000 |
+------+------+------------+
Factor: φ₂(B, C)
Variables y cardinalidades:
B → 2 valores posibles (b⁰, b¹)
C → 2 valores posibles (c⁰, c¹)
Cardinalidad total: 2 × 2 = 4 combinaciones
#print
print(phi2)
+------+------+------------+
| B | C | phi(B,C) |
+======+======+============+
| B(0) | C(0) | 5.0000 |
+------+------+------------+
| B(0) | C(1) | 7.0000 |
+------+------+------------+
| B(1) | C(0) | 1.0000 |
+------+------+------------+
| B(1) | C(1) | 2.0000 |
+------+------+------------+
# Producto de factores(.product)
phi3 = phi1.product(phi2, inplace=False)
print(phi3)
+------+------+------+--------------+
| C | A | B | phi(C,A,B) |
+======+======+======+==============+
| C(0) | A(0) | B(0) | 25.0000 |
+------+------+------+--------------+
| C(0) | A(0) | B(1) | 8.0000 |
+------+------+------+--------------+
| C(0) | A(1) | B(0) | 5.0000 |
+------+------+------+--------------+
| C(0) | A(1) | B(1) | 0.0000 |
+------+------+------+--------------+
| C(0) | A(2) | B(0) | 15.0000 |
+------+------+------+--------------+
| C(0) | A(2) | B(1) | 9.0000 |
+------+------+------+--------------+
| C(1) | A(0) | B(0) | 35.0000 |
+------+------+------+--------------+
| C(1) | A(0) | B(1) | 16.0000 |
+------+------+------+--------------+
| C(1) | A(1) | B(0) | 7.0000 |
+------+------+------+--------------+
| C(1) | A(1) | B(1) | 0.0000 |
+------+------+------+--------------+
| C(1) | A(2) | B(0) | 21.0000 |
+------+------+------+--------------+
| C(1) | A(2) | B(1) | 18.0000 |
+------+------+------+--------------+
#Producto de factores(*)
phi3 = phi1 * phi2
print(phi3)
+------+------+------+--------------+
| C | A | B | phi(C,A,B) |
+======+======+======+==============+
| C(0) | A(0) | B(0) | 25.0000 |
+------+------+------+--------------+
| C(0) | A(0) | B(1) | 8.0000 |
+------+------+------+--------------+
| C(0) | A(1) | B(0) | 5.0000 |
+------+------+------+--------------+
| C(0) | A(1) | B(1) | 0.0000 |
+------+------+------+--------------+
| C(0) | A(2) | B(0) | 15.0000 |
+------+------+------+--------------+
| C(0) | A(2) | B(1) | 9.0000 |
+------+------+------+--------------+
| C(1) | A(0) | B(0) | 35.0000 |
+------+------+------+--------------+
| C(1) | A(0) | B(1) | 16.0000 |
+------+------+------+--------------+
| C(1) | A(1) | B(0) | 7.0000 |
+------+------+------+--------------+
| C(1) | A(1) | B(1) | 0.0000 |
+------+------+------+--------------+
| C(1) | A(2) | B(0) | 21.0000 |
+------+------+------+--------------+
| C(1) | A(2) | B(1) | 18.0000 |
+------+------+------+--------------+
2. Marginalización de factores
Tienes un factor:
X |
Y |
Z |
\(\phi_1\) |
|---|---|---|---|
\(x^0\) |
\(y^0\) |
\(z^0\) |
10 |
\(x^0\) |
\(y^0\) |
\(z^1\) |
5 |
\(x^0\) |
\(y^1\) |
\(z^0\) |
15 |
\(x^0\) |
\(y^1\) |
\(z^1\) |
16 |
\(x^1\) |
\(y^0\) |
\(z^0\) |
14 |
\(x^1\) |
\(y^0\) |
\(z^1\) |
30 |
\(x^1\) |
\(y^1\) |
\(z^0\) |
2 |
\(x^1\) |
\(y^1\) |
\(z^1\) |
8 |
queremos obtener otro más pequeño:
\(\psi(Y,Z) = \sum_{X}\phi_1(X, Y, Z)\)
Y |
Z |
\(\psi\) |
|---|---|---|
\(y^0\) |
\(z^0\) |
10 + 14 = 24 |
\(y^0\) |
\(z^1\) |
5 + 30 = 35 |
\(y^1\) |
\(z^0\) |
15 + 2 = 17 |
\(y^1\) |
\(z^1\) |
16 + 8 = 24 |
Para cada combinación de \(Y\) y \(Z\), sumamos todos los valores posbiles de \(X\).
# Factor phi1
phi1 = DiscreteFactor(
variables=['X', 'Y', 'Z'],
cardinality=[2,2,2],
values=[10,5,15,16,14,30,2,8]
)
# Marginalización resp. X (.marginalize)
phi_marg_x = phi1.marginalize(variables=['X'], inplace=False)
print(phi_marg_x)
+------+------+------------+
| Y | Z | phi(Y,Z) |
+======+======+============+
| Y(0) | Z(0) | 24.0000 |
+------+------+------------+
| Y(0) | Z(1) | 35.0000 |
+------+------+------------+
| Y(1) | Z(0) | 17.0000 |
+------+------+------------+
| Y(1) | Z(1) | 24.0000 |
+------+------+------------+
# Marginalización resp. X, Y (.marginalize)
phi1_marg_xy = phi1.marginalize(variables=['X', 'Y'], inplace=False)
print(phi1_marg_xy)
+------+----------+
| Z | phi(Z) |
+======+==========+
| Z(0) | 41.0000 |
+------+----------+
| Z(1) | 59.0000 |
+------+----------+
3. Reducción de factores
X |
Y |
Z |
\(\phi_1(X,Y,Z)\) |
|---|---|---|---|
\(x^0\) |
\(y^0\) |
\(z^0\) |
10 |
\(x^0\) |
\(y^0\) |
\(z^1\) |
5 |
\(x^0\) |
\(y^1\) |
\(z^0\) |
15 |
\(x^0\) |
\(y^1\) |
\(z^1\) |
16 |
\(x^1\) |
\(y^0\) |
\(z^0\) |
14 |
\(x^1\) |
\(y^0\) |
\(z^1\) |
30 |
\(x^1\) |
\(y^1\) |
\(z^0\) |
2 |
\(x^1\) |
\(y^1\) |
\(z^1\) |
8 |
\(\psi(X,Z) = \phi_1(X, y^1, Z)\)
X |
Y |
Z |
\(\phi_1\) |
|---|---|---|---|
\(x^0\) |
\(y^1\) |
\(z^0\) |
15 |
\(x^0\) |
\(y^1\) |
\(z^1\) |
16 |
\(x^1\) |
\(y^1\) |
\(z^0\) |
2 |
\(x^1\) |
\(y^1\) |
\(z^1\) |
8 |
Como \(Y=y^1\) es constante, el factor resultante no depende de Y:
X |
Z |
\(\phi_1\) |
|---|---|---|
\(x^0\) |
\(z^0\) |
15 |
\(x^0\) |
\(z^1\) |
16 |
\(x^1\) |
\(z^0\) |
2 |
\(x^1\) |
\(z^1\) |
8 |
# Factor phi1
phi1 = DiscreteFactor(
variables=['X', 'Y', 'Z'],
cardinality=[2,2,2],
values=[10,5,15,16,14,30,2,8]
)
# Reducción phi1(X, y1, Z)(.reduce)
phi1_red = phi1.reduce(values=[('Y', 1)], inplace=False)
print(phi1_red)
+------+------+------------+
| X | Z | phi(X,Z) |
+======+======+============+
| X(0) | Z(0) | 15.0000 |
+------+------+------------+
| X(0) | Z(1) | 16.0000 |
+------+------+------------+
| X(1) | Z(0) | 2.0000 |
+------+------+------------+
| X(1) | Z(1) | 8.0000 |
+------+------+------------+
# Reducción phi1(X, y1, z0)(.reduce)
phi1_red2 = phi1.reduce(values=[('Y', 1), ('Z', 0)], inplace=False)
print(phi1_red2)
+------+----------+
| X | phi(X) |
+======+==========+
| X(0) | 15.0000 |
+------+----------+
| X(1) | 2.0000 |
+------+----------+
La gran pregunta#
¿Por qué los factores son tan importantes en redes bayesianas y modelos probabilísticos?
El problema de las distribuciones grandes#
Imaginen que tenemos muchas variables aleatorias, digamos que \(N=20\). Si cada una puede tomar solo 2 valores (por ejemplo, sí o no), una distribución conjunta completa tendría que guardar:
\(2^{20} = 1,048,576\) combinaciones posibles.
y si cada variable dependiera de las demás, la tabla sería enorme e imposible de manejar.
¿Y si las variables dependen entre sí?#
Los factores solo son útiles cuando las dependencias son locales — cuando cada variable depende de pocas otras, no de todas.