7 · Una app de predicción interactiva
Ahora conecta los widgets al modelo: lee valores de características desde los campos, ensámblalos en un vector ordenado, llama a `model.predict`, y muestra el resultado con `st.metric`. Envuelve los campos en `st.form` para que el script se re-ejecute solo al hacer clic en enviar — no en cada tecla.
Construye un predictor al estilo Streamlit: las llamadas de widgets leen cada característica en una variable, las ensamblas en un vector ORDENADO (el mismo orden de entrenamiento que la ruta de Flask), llamas a `model.predict`, y lo muestras con `st.metric`/`st.write`. Envuelve los campos en `st.form` + `st.form_submit_button` para que la re-ejecución-y-predicción ocurra UNA VEZ al enviar — no en cada tecla.
Sin esto:
Sin un formulario, cada tecla re-ejecuta el script y re-predice a mitad de escritura sobre valores a medio ingresar; y sin ensamblar el vector en el orden de entrenamiento, alimentarías características en las posiciones equivocadas — el mismo bug silencioso que la API de Flask.
La lección 6 te dio widgets y el modelo de re-ejecución. Ahora los conectamos al modelo para construir un predictor interactivo real — el equivalente en Streamlit de la ruta /predict de Flask, pero para un humano en vez de una máquina.
Lee cada característica de un widget. Gracias al modelo de re-ejecución, leer la entrada es trivial: asigna cada llamada de widget a una variable. tenure = st.slider("Tenure", 0, 72, 12) te da el tenure actual; charges = st.number_input("Cargos mensuales", value=80.0) da los cargos actuales; un st.selectbox para una categórica, y así. Después de que el script se re-ejecuta, cada variable ya contiene el último valor que el usuario eligió.
Ensambla el vector de características — el orden sigue importando. Esta es la misma disciplina que la API de Flask: el modelo fue entrenado con las características en un orden específico, así que debes construir el vector en ese orden exacto. Toma cada valor por nombre de tus widgets en el orden de entrenamiento: x = np.array([[tenure, charges, calls, is_premium]]) — con las columnas alineadas a FEATURES. Equivócate en el orden y alimentas "cargos" en la posición de "tenure": una predicción segura y sin sentido.
Predice, luego muestra. Llama a model.predict_proba(x) (o model.predict), luego muestra el resultado con un widget de visualización. st.metric("Probabilidad de churn", "83%") renderiza un número grande estilo panel; st.write(...) muestra texto libre o datos; st.success(...) / st.error(...) dan un banner de estado con color. Esta es la recompensa de cara al humano — una predicción legible, no JSON crudo.
El problema del formulario — y st.form. Aquí hay una sutileza que crea el modelo de re-ejecución. Por defecto, cada interacción con un widget re-ejecuta todo el script — así que si tienes cinco campos, el script se re-ejecuta (y re-predice) en el instante en que el usuario toca cualquiera de ellos, a menudo sobre un valor a medio ingresar. Eso es derrochador y nervioso. El arreglo es st.form: agrupas los campos dentro de un bloque with st.form("..."): que termina en st.form_submit_button("Predecir"). Dentro de un formulario, cambiar los widgets NO dispara una re-ejecución — Streamlit retiene los valores hasta que el usuario hace clic en el botón de envío, y solo entonces re-ejecuta el script una vez con todas las entradas juntas. Así el usuario llena todo, hace un clic, y obtiene exactamente una predicción. st.form_submit_button(...) devuelve True en esa corrida de envío, que es tu señal para predecir.
Cuándo usar un formulario vs widgets sueltos. Usa widgets sueltos cuando quieras reactividad instantánea y viva — un slider que actualiza un gráfico mientras lo arrastras se siente genial. Usa un formulario cuando las entradas deban agruparse — una predicción de varios campos donde re-predecir a mitad de ingreso es inútil y quieres una acción deliberada de "Predecir". Una app de predicción es el caso de libro para un formulario.
La celda de solo-lectura muestra el predictor interactivo completo: un st.form de campos → un vector ordenado → model.predict → st.metric.
Una app de predicción de Streamlit: `st.form` agrupa los campos para que el script se re-ejecute solo al enviar, los widgets se ensamblan en un vector de características ordenado, corre `model.predict_proba`, y `st.metric`/`st.success`/`st.error` muestran el resultado.
En un predictor de Streamlit, ¿cómo obtiene el código el valor que el usuario eligió en `tenure = st.slider("Tenure", 0, 72, 12)`?
- Lee las características asignando llamadas de widgets a variables, luego ensámblalas en un vector en el orden de entrenamiento EXACTO — la misma disciplina de orden que la API de Flask.
- Predice con `model.predict`/`predict_proba` y muestra el resultado con widgets amigables como `st.metric`, `st.success`, y `st.error` — no JSON crudo.
- Envuelve las predicciones de varias entradas en `st.form` + `st.form_submit_button` para que el script se re-ejecute una vez al enviar, no en cada tecla — agrupando las entradas en una acción deliberada.
Este patrón widgets→vector→`predict`→`st.metric` es cómo funciona casi todo demo de ML en Streamlit — es el camino más rápido de un modelo entrenado a una herramienta de predicción clicable que un interesado puede usar de verdad.
Si lo quitas: Sin agrupar las entradas en un formulario, la app re-predice en cada tecla sobre valores a medio ingresar; sin ensamblaje ordenado, la predicción es segura pero incorrecta.