Encuentre P (X | Y) óptimo dado que tengo un modelo que tiene un buen rendimiento cuando se entrena en P (Y | X)

11

Datos de entrada:

-> características de la camiseta (color, logotipo, etc.)X

-> margen de beneficioY

He entrenado un bosque aleatorio en los e Y anteriores y he logrado una precisión razonable en los datos de una prueba. Así que tengoXY

.P(Y|X)

Ahora, me gustaría encontrar es decir, la distribución de probabilidad de las características X dado que espero este margen de beneficio.P(X|Y)X

¿Cómo hago eso con un bosque aleatorio (o cualquier otro modelo discriminativo)?

Una sugerencia para mí podría ser comenzar con un modelo generativo en lugar de un modelo discriminatorio. Pero, entiendo que el modelo generativo generalmente requiere una gran cantidad de datos para entrenar, a menos que eso suponga algunas suposiciones muy restrictivas, como la independencia condicional de en el caso de Naive Bayes.X

XYXYP(Y|X)XY

Además, por lo que he escuchado, se ha planteado una pregunta similar para el descubrimiento de fármacos y se han diseñado algoritmos que crean nuevos fármacos candidatos que tienen un alto grado de éxito. ¿Alguien puede señalarme que investigue literatura en este dominio?

Actualizar:

Me he encontrado con esto y esto que habla de que las GAN se usan para el descubrimiento de fármacos. Las redes adversas generativas parecen encajar bien con mi enunciado del problema, así que he estado leyendo sobre ellas. Pero una cosa que entendí es que GAN genera muestras de forma no supervisada. Intentan producir una muestra que es como primero capturar la distribución subyacente de X y luego tomar muestras de esa distribución. Pero estoy interesado en X | Y. X e Y se definen anteriormente. ¿Debería explorar algo más que las GAN? ¿Alguna sugerencia por favor?

Siguiente pregunta:

Imagine que tengo un GAN capacitado que aprendió a hacer camisetas (muestra de salida X). ¿Cómo puedo obtener las 5 mejores camisetas para una Y dada?

claudio
fuente
Esto está estrechamente relacionado con el problema de la mochila o las variantes estocásticas de este. ¿Sería posible reformularlo como tal bajo algunas suposiciones razonables sobre su dominio de entrada?
mjul
@mjul. Sry no te entendió. Por favor elabora. Sin embargo, ¡siempre es bienvenida la propuesta de un enfoque diferente para resolver el problema!
claudio
1
El problema de la mochila es un problema de optimización combinatoria, donde el objetivo es identificar el conjunto de características más rentable (para sus camisetas) suponiendo que conoce el valor y el costo de las características individuales. Se supone que los valores son exactos, no estocásticos. Sin embargo, bajo supuestos de independencia razonables, es posible que pueda volver a expresar su problema como el Problema de la mochila o como una de las variantes estocásticas que también se han estudiado a lo largo de los años. Sin embargo, sin más información no está claro de inmediato que sea posible en su caso.
mjul

Respuestas:

10

Esta respuesta se ha modificado significativamente de su forma original. Los defectos de mi respuesta original se analizarán a continuación, pero si desea ver más o menos cómo se veía esta respuesta antes de realizar la gran edición, eche un vistazo al siguiente cuaderno: https://nbviewer.jupyter.org/github /dmarx/data_generation_demo/blob/54be78fb5b68218971d2568f1680b4f783c0a79a/demo.ipynb

P(X)P(X|Y)P(Y|X)P(X)P(Y|X)X

Estimación de máxima verosimilitud

... y por qué no funciona aquí

En mi respuesta original, la técnica que sugerí era usar MCMC para realizar la estimación de máxima verosimilitud. En general, MLE es un buen enfoque para encontrar las soluciones "óptimas" para las probabilidades condicionales, pero tenemos un problema aquí: porque estamos usando un modelo discriminativo (un bosque aleatorio en este caso) nuestras probabilidades se calculan en relación con los límites de decisión . En realidad, no tiene sentido hablar de una solución "óptima" para un modelo como este porque una vez que nos alejemos lo suficiente del límite de la clase, el modelo solo pronosticará las opciones para todo. Si tenemos suficientes clases, algunas de ellas podrían estar completamente "rodeadas", en cuyo caso esto no será un problema, pero las clases en el límite de nuestros datos serán "maximizadas" por valores que no son necesariamente factibles.

Para demostrarlo, voy a aprovechar el código de conveniencia que puede encontrar aquí , que proporciona la GenerativeSamplerclase que envuelve el código de mi respuesta original, algún código adicional para esta mejor solución y algunas características adicionales con las que estaba jugando (algunas que funcionan , algunos que no) en lo que probablemente no entraré aquí.

np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y, 
                            target_class=2, 
                            prior=None, 
                            class_err_prob=0.05, # <-- the score we use for candidates that aren't predicted as the target class
                            rw_std=.05,          # <-- controls the step size of the random walk proposal
                            verbose=True, 
                            use_empirical=False)
samples, _ = sampler.run_chain(n=5000)

burn = 1000
thin = 20
X_s = pca.transform(samples[burn::thin,:])

# Plot the iris data
col=['r','b','g']
for i in range(3):
    plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
plt.plot(*X_s.T, 'k')
plt.scatter(*X_s.T, c=np.arange(X_s.shape[0]))
plt.colorbar()
plt.show()

ingrese la descripción de la imagen aquí

En esta visualización, las x son los datos reales, y la clase que nos interesa es verde. Los puntos conectados a la línea son las muestras que dibujamos, y su color corresponde al orden en que fueron muestreados, con su posición de secuencia "adelgazada" dada por la etiqueta de la barra de color a la derecha.

Como puede ver, la muestra divergió de los datos con bastante rapidez y luego, básicamente, se queda bastante lejos de los valores del espacio de características que corresponden a cualquier observación real. Claramente esto es un problema.

Una forma de hacer trampa es cambiar nuestra función de propuesta para permitir que las características tomen valores que realmente observamos en los datos. Probemos eso y veamos cómo eso cambia el comportamiento de nuestro resultado.

np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y, 
                            target_class=2, 
                            prior=None, 
                            class_err_prob=0.05, 
                            verbose=True, 
                            use_empirical=True) # <-- magic happening under the hood
samples, _ = sampler.run_chain(n=5000)

X_s = pca.transform(samples[burn::thin,:])

# Constrain attention to just the target class this time
i=2
plt.scatter(*X_r[y==i,:].T, c='k', marker='x')
plt.scatter(*X_s.T, c='g', alpha=0.3)
#plt.colorbar()
plt.show()


sns.kdeplot(X_s, cmap=sns.dark_palette('green', as_cmap=True))
plt.scatter(*X_r[y==i,:].T, c='k', marker='x')
plt.show()

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

X

P(X)P(Y|X)P(X)P(Y|X)P(X)

Introduzca la regla de Bayes

Después de que me acosabas para ser menos hábil con las matemáticas aquí, jugué con esto bastante (de ahí que construyera la GenerativeSamplercosa), y me encontré con los problemas que expuse anteriormente. Me sentí muy, muy estúpido cuando me di cuenta de esto, pero obviamente lo que estás pidiendo pide una aplicación de la regla de Bayes y me disculpo por ser despectivo antes.

Si no está familiarizado con la regla bayes, se ve así:

P(B|A)=P(A|B)P(B)P(A)

En muchas aplicaciones, el denominador es una constante que actúa como un término de escala para garantizar que el numerador se integre a 1, por lo que la regla a menudo se reformula de la siguiente manera:

P(B|A)P(A|B)P(B)

O en inglés simple: "el posterior es proporcional a los tiempos anteriores la probabilidad".

¿Parecer familiar? Que tal ahora:

P(X|Y)P(Y|X)P(X)

Sí, esto es exactamente lo que trabajamos anteriormente al construir una estimación para el MLE que esté anclada a la distribución observada de los datos. Nunca he pensado en Bayes gobernar de esta manera, pero tiene sentido, así que gracias por darme la oportunidad de descubrir esta nueva perspectiva.

P(Y)

Entonces, después de haber hecho esta idea de que necesitamos incorporar un previo para los datos, hagamos eso ajustando un KDE estándar y veamos cómo eso cambia nuestro resultado.

np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y, 
                            target_class=2, 
                            prior='kde',         # <-- the new hotness
                            class_err_prob=0.05,
                            rw_std=.05,          # <-- back to the random walk proposal
                            verbose=True, 
                            use_empirical=False)
samples, _ = sampler.run_chain(n=5000)

burn = 1000
thin = 20
X_s = pca.transform(samples[burn::thin,:])

# Plot the iris data
col=['r','b','g']
for i in range(3):
    plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
plt.plot(*X_s.T, 'k--')
plt.scatter(*X_s.T, c=np.arange(X_s.shape[0]), alpha=0.2)
plt.colorbar()
plt.show()

ingrese la descripción de la imagen aquí

XP(X|Y)

# MAP estimation

from sklearn.neighbors import KernelDensity
from sklearn.model_selection import GridSearchCV
from scipy.optimize import minimize

grid = GridSearchCV(KernelDensity(), {'bandwidth': np.linspace(0.1, 1.0, 30)}, cv=10, refit=True)
kde = grid.fit(samples[burn::thin,:]).best_estimator_

def map_objective(x):
    try:
        score = kde.score_samples(x)
    except ValueError:
        score = kde.score_samples(x.reshape(1,-1))
    return -score

x_map = minimize(map_objective, samples[-1,:].reshape(1,-1)).x

print(x_map)

x_map_r = pca.transform(x_map.reshape(1,-1))[0]
col=['r','b','g']
for i in range(3):
    plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
sns.kdeplot(*X_s.T, cmap=sns.dark_palette('green', as_cmap=True))
plt.scatter(x_map_r[0], x_map_r[1], c='k', marker='x', s=150)
plt.show()

ingrese la descripción de la imagen aquí

Y ahí lo tiene: la gran 'X' negra es nuestra estimación MAP (esos contornos son el KDE de la parte posterior).

David Marx
fuente
Gracias por tu respuesta. Tengo una pregunta. alpha = np.min ([f (new) / f (old), 1]) ..... aquí f (new) es P (Y = 0 | X = new) ya que estamos usando model.predict_proba que da distribución de Y dada X ...... pero de en.wikipedia.org/wiki/Metropolis –Hastings_algorithm lo que pude entender es alfa debería ser min (P (X = new | y = 0) / P (X = old | y = 0), 1). ¿Entendí mal algo?
claudio
También mencionó en la nota de TLDR "Use MCMC para generar muestras a partir de p (X | Y) al calificar los valores de candidato X contra la probabilidad condicional de clase proporcionada por su modelo". Pero no es model.predict_proba dando probabilidad de clase dada X. ¿Cómo puedes decir P (X1 | Y = 0)> P (X2 | Y = 0) solo porque model.predict_proba (X1) [0,0]> modelo .predict_proba (X2) [0,0]. Leí la relación de model.predict_proba como P (Y = 0 | X1)> P (Y = 0 | X2). por favor avíseme dónde me equivoco
claudio
También otra pregunta de seguimiento ... ¿Cuál es la función de distribución de propuesta simétrica aquí? ¡Gracias David por ayudarme!
claudio
La propuesta simétrica es una caminata aleatoria gaussiana. Planeo actualizar esto pronto con una demostración de una función de propuesta "empírica" ​​también. Con respecto a las matemáticas de MCMC, no te obsesiones demasiado. Al mantener Y fijo y ejecutar X candidatos contra p (Y | X), el MCMC aproxima el MLE para X en p (Y = 0 | X), es decir, la función que estoy muestreando desde aquí no es p (Y | X ) (de lo contrario, estaría generando una secuencia de etiquetas de clase), es L (X; Y). Esto efectivamente me da una distribución sobre p (X | Y = 0). La función de puntuación en la relación de metrópolis es p (Y | X), pero la forma en que la uso produce muestras de p (X | Y).
David Marx
Hola David ¿Puedes escribir las matemáticas? Me está costando convencerme de las matemáticas. Revisé tu perfil para descubrir que eres un graduado de estadísticas. Explique sus puntos para ayudar a simples mortales como yo: P. Especialmente "Manteniendo Y fijo y ejecutando X candidatos contra p (Y | X), el MCMC aproxima el MLE para X en p (Y = 0 | X), es decir, la función que estoy muestreando desde aquí no es p (Y | X) (de lo contrario estaría generando una secuencia de etiquetas de clase), es L (X; Y). Esto efectivamente me da una distribución sobre p (X | Y = 0). "¡Gracias de antemano!
claudio el
0

Una forma de avanzar podría ser:

Cree una red neuronal de avance que, dado Y (probablemente desee normalizarla) prediga la X. Por lo tanto, la salida del modelo (la última capa) sería un conjunto de neuronas softmax para cada característica. Entonces, si la función 1 (por ejemplo, el color) tiene 4 opciones, aplicará el softmax en cuatro neuronas y hará lo mismo en cada función.

Entonces, su función de pérdida podría ser la suma (o una combinación lineal si lo prefiere) de la entropía cruzada para cada característica.

Escalera mecánica
fuente
gracias por tu respuesta! Pero, estoy buscando una respuesta que sugiera múltiples enfoques y mencione los pros y los contras de cada enfoque.
claudio