prediccion - Dibujar línea de regresión, intervalo de confianza e intervalo de predicción en Python
python regresion (1)
Soy nuevo en el juego de regresión y espero trazar una línea de regresión no lineal funcionalmente arbitraria (más confianza e intervalos de predicción) para un subconjunto de datos que satisfaga una determinada condición (es decir, con valor medio de replicación superior a un umbral; ver más abajo).
Los data
se generan para la variable independiente x
en 20 valores diferentes: x=(20-np.arange(20))**2
, con rep_num=10
repeticiones para cada condición. Los datos muestran una fuerte no linealidad en x
y se ve así:
import numpy as np
mu = [.40, .38, .39, .35, .37, .33, .34, .28, .11, .24,
.03, .07, .01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
data = np.zeros((20, rep_num))
for i in range(13):
data[i] = np.clip(np.random.normal(loc=mu[i], scale=0.1, size=rep_num), 0., 1.)
Puedo hacer un diagrama de dispersión de los datos; los medios duplicados se muestran con los puntos rojos:
import matplotlib.pyplot as plt
plt.scatter(np.log10(np.tile(x[:,None], rep_num)), data,
facecolors=''none'', edgecolors=''k'', alpha=0.25)
plt.plot(np.log10(x), data.mean(1), ''ro'', alpha=0.8)
plt.plot(np.log10(x), np.repeat(0., 20), ''k--'')
plt.xlim(-0.02, np.max(np.log10(x)) + 0.02)
plt.ylim(-0.01, 0.7)
Mi objetivo es trazar una línea de regresión solo para aquellos datos que tienen una media de replicación> 0.02. Además, me gustaría agregar un intervalo de confianza del 95% (líneas discontinuas negras) alrededor de la regresión, así como un intervalo de predicción del 95% (líneas punteadas azules); idealmente, el intervalo de predicción también se puede colorear con azul transparente fondo.
La gráfica final (sin el fondo azul dentro del intervalo de predicción) se vería así:
¿Cómo podría hacer esto? Mi búsqueda en línea arrojó enfoques parciales muy diferentes utilizando seaborn, scipy y modelsmodels. Las aplicaciones de algunas de esas funciones de plantilla no parecían funcionar junto con el diagrama de dispersión de matplotlib existente.
OK, aquí hay una oportunidad para esto (sin la banda de predicción, sin embargo). En primer lugar, desea seleccionar los datos aplicables:
threshold = 0.02
reg_x = np.log10(x)[data.mean(1)>threshold]
reg_y = data.mean(1)[data.mean(1)>threshold]
Luego eliges un modelo y realizas un ajuste. Tenga en cuenta que aquí elegí un polinomio de segundo orden, pero en principio podría hacer cualquier cosa. Para los ajustes que uso kapteyn
, este tiene un método de prohibición de confianza incorporado, aunque sería sencillo de implementar (véase, por ejemplo , el método Delta )
from kapteyn import kmpfit
# Set model to fit.
def model(p, x):
a, b, c = p
return a + b*x + c*x**2
# Perform fit.
f = kmpfit.simplefit(model, [.1, .1, .1], reg_x, reg_y)
f
contiene todos los parámetros estimados y demás, puede usarlo para trazar, etc.
x = np.linspace(0, 3, 100)
plt.plot(x, model(f.params, x), linestyle=''-'', color=''black'', marker='''')
Para las bandas de confianza, necesitamos las derivadas parciales del modelo con respecto a los parámetros (sí, algunas matemáticas). Nuevamente, esto es fácil para un modelo polinomial, tampoco debería ser un problema para ningún otro modelo.
# Partial derivatives:
dfdp = [1., reg_x, reg_x**2]
_, ci_upper, ci_lower = f.confidence_band(reg_x, dfdp, 0.95, model)
# Plot.
plt.plot(reg_x, ci_upper, linestyle=''--'', color=''black'', marker='''')
plt.plot(reg_x, ci_lower, linestyle=''--'', color=''black'', marker='''')
Desafortunadamente no hay una rutina prediction_bands()
en el paquete, al menos no que yo sepa. Asuma que encontró algún método para la banda de predicción, el trazado y la preparación se verían igual aunque ..
p_upper, p_lower = prediction_band(*args, **kwargs)
plt.fill_between(reg_x, p_upper, p_lower, facecolor=''blue'', alpha=0.2, linestyle='''')
Espero que esto ayude, L.