Regresión lineal de TensorFlow con faceta y término de interacción

⚡ Resumen inteligente

La regresión lineal aplicada a los datos de vivienda de Boston mejora cuando se encuentran primero los términos de interacción adecuados. Google Facetas expone visualmente esas relaciones, y dos características cruzadas reducen la pérdida de prueba de TensorFlow de 1650 a 1515.

  • 🔘 Primero los datos: Comprender las distribuciones y los valores atípicos precede a cualquier modelo, porque un modelo solo generaliza un patrón que ya se ha localizado.
  • ☑️ Descripción general de las facetas: Las estadísticas por característica muestran valores faltantes, columnas con muchos ceros y desviaciones en la distribución entre entrenamiento y prueba en una sola tabla.
  • ✅ Análisis en profundidad de Facetas: La segmentación por X e Y convierte las relaciones triples en un gráfico bidimensional legible, coloreado según el cuartil de precio.
  • 🧪 Lectura correlativa: El mapa de calor y la cuadrícula de pares señalan a INDUS con NOX, y a DIS con ambos, como posibles interacciones.
  • 🛠️ Estandarización: preprocessing.scale centra las doce columnas continuas antes de que el estimador las vea, dejando CHAS y PRICE sin modificar.
  • 📈 Ganancia medida: Agregar INDUS_NOS e INDUS_NOS_DIS hace que la pérdida promedio pase de 86.89361 a 79.78876 en la división de prueba.

Regresión lineal de TensorFlow con término de faceta e interacción

Regresión lineal de TensorFlow

En este tutorial, aprenderá cómo verificar los datos y prepararlos para crear una tarea de regresión lineal simple.

Este tutorial se divide en dos partes:

  • buscar interacción
  • Prueba el modelo

En la sección tutorial anterior, utilizó el conjunto de datos de Boston para estimar el precio medio de una casa. El conjunto de datos de Boston tiene un tamaño pequeño, con solo 506 observaciones. Este conjunto de datos se considera un punto de referencia para probar nuevos algoritmos de regresión lineal.

El conjunto de datos está compuesto por:

Variable Mareas Ideales para Lecciones
zn La proporción de terreno residencial zonificado para lotes de más de 25,000 pies cuadrados.
indus La proporción de acres de negocios no minoristas por ciudad.
nox concentración de óxidos nítricos
rm número medio de habitaciones por vivienda
edad la proporción de unidades ocupadas por sus propietarios construidas antes de 1940
des distancias ponderadas a cinco centros de empleo de Boston
deuda tasa de impuesto a la propiedad de valor total por dólares 10,000
ptratio la ratio alumnos-maestro por ciudad
médico El valor medio de las viviendas ocupadas por sus propietarios en miles de dólares.
criminal tasa de criminalidad per cápita por ciudad
chas Variable ficticia de Charles River (1 si limita el río; 0 en caso contrario)
B la proporción de negros por ciudad

En este tutorial, estimaremos el precio medio utilizando un regresor lineal, pero la atención se centrará en un proceso particular de aprendizaje automático: "preparación de datos."

Un modelo generaliza el patrón en los datos. Para capturar tal patrón, primero debes encontrarlo. Una buena práctica es realizar un análisis de datos antes de ejecutar cualquier algoritmo de aprendizaje automático.

Elegir las características adecuadas marca la diferencia en el éxito de su modelo. Imagine que intenta estimar el salario de un pueblo, si no incluye el género como covariable, termina con una estimación pobre.

Otra forma de mejorar el modelo es observar la correlación entre la variable independiente. Volviendo al ejemplo, se puede pensar en la educación como un excelente candidato para predecir el salario pero también la ocupación. Es justo decir que la ocupación depende del nivel de educación, es decir, una educación superior a menudo conduce a una mejor ocupación. Si generalizamos esta idea, podemos decir que la correlación entre la variable dependiente y una variable explicativa se puede ampliar con otra variable explicativa más.

Para captar el efecto limitado de la educación sobre la ocupación, podemos utilizar un término de interacción.

Término de interacción entre educación y ocupación ilustrado en una curva salarial.

Si nos fijamos en la ecuación salarial, queda:

Ecuación salarial ampliada con un término de interacción entre educación y ocupación.

If Símbolo del coeficiente beta para el término de interacción es positivo, entonces implica que un nivel adicional de educación produce un mayor aumento en el valor medio de una casa para un nivel de ocupación alto. En otras palabras, existe un efecto de interacción entre educación y ocupación.

La misma familia de estimadores también alimenta el clasificador lineal cuando la etiqueta es una clase en lugar de un precio. En este tutorial, intentaremos ver qué variables pueden ser buenas candidatas para términos de interacción. Comprobaremos si añadir este tipo de información mejora la predicción de precios.

Resumen estadístico

Hay algunos pasos que puedes seguir antes de continuar con el modelo. Como se mencionó anteriormente, el modelo es una generalización de los datos. Lo ideal es comprender primero los datos y luego hacer una predicción. Si no conoces tus datos, tendrás pocas posibilidades de mejorar tu modelo.

Como primer paso, cargue los datos como un marco de datos de pandas y cree un conjunto de entrenamiento y un conjunto de prueba.

Consejos: Para este tutorial, necesitas tener matplotlib y seaborn instalados en Python. Puedes instalar un Python paquete sobre la marcha con Jupyter. Usted No debe hacer esto

!conda install -- yes matplotlib

but

import sys
!{sys.executable} -m pip install matplotlib # Already installed
!{sys.executable} -m pip install seaborn 

Tenga en cuenta que este paso no es necesario si tiene matplotlib y seaborn instalados.

Matplotlib es la biblioteca para crear un gráfico en PythonSeaborn es una biblioteca de visualización estadística construida sobre matplotlib. Proporciona entracParcelas vibrantes y hermosas.

El siguiente código importa las bibliotecas necesarias.

import pandas as pd
from sklearn import datasets
import tensorflow as tf
from sklearn.datasets import load_boston
import numpy as np

La biblioteca sklearn incluye el conjunto de datos de Boston. Puede llamar a su API para importar los datos.

Nota de versión: load_boston fue obsoleto en scikit-learn 1.0 y Eliminado en scikit-learn 1.2 porque el conjunto de datos codifica una característica con carga racial. En una instalación actual, utilice buscar_vivienda_california En su lugar, o bien, cargue usted mismo el archivo sin procesar. El flujo de trabajo que se muestra a continuación no ha cambiado; solo difiere el cargador.

boston = load_boston()
df = pd.DataFrame(boston.data)

Los nombres de las características se almacenan en el objeto feature_names como una matriz.

boston.feature_names

Resultado

array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')

Puede cambiar el nombre de las columnas.

df.columns = boston.feature_names
df['PRICE'] = boston.target
df.head(2)

Las dos primeras filas del DataFrame de Boston después de renombrar las columnas.

Convierte la variable CHAS como una variable de cadena y la etiqueta con sí si CHAS = 1 y no si CHAS = 0

df['CHAS'] = df['CHAS'].map({1:'yes', 0:'no'})
df['CHAS'].head(5)
0    no
1    no
2    no
3    no
4    no
Name: CHAS, dtype: object

Con los pandas, es sencillo dividir el conjunto de datos. Divide aleatoriamente el conjunto de datos con un 80 por ciento de conjunto de entrenamiento y un 20 por ciento de conjunto de prueba. pandas Tiene una función de muestreo incorporada para dividir un marco de datos.

El primer parámetro frac es un valor de 0 a 1. Lo configura en 0.8 para seleccionar aleatoriamente el 80 por ciento del marco de datos.

random_state corrige la mezcla aleatoria, de modo que se devuelven las mismas filas para todos.

### Create train/test set
df_train=df.sample(frac=0.8,random_state=200)
df_test=df.drop(df_train.index)

Puede obtener la forma de los datos. Debería ser:

  • Conjunto de trenes: 506*0.8 = 405
  • Conjunto de prueba: 506*0.2 = 101
print(df_train.shape, df_test.shape)

Resultado

(405, 14) (101, 14)
df_test.head(5)

Resultado

CRIMEN ZN INDUS CHAS NOX RM EDAD DIS RAD TAX PTRACIO B LSTAT PRECIOS
0 0.00632 18.0 2.31 no 0.538 6.575 65.2 4.0900 1.0 296.0 15.3 396.90 4.98 24.0
1 0.02731 0.0 7.07 no 0.469 6.421 78.9 4.9671 2.0 242.0 17.8 396.90 9.14 21.6
3 0.03237 0.0 2.18 no 0.458 6.998 45.8 6.0622 3.0 222.0 18.7 394.63 2.94 33.4
6 0.08829 12.5 7.87 no 0.524 6.012 66.6 5.5605 5.0 311.0 15.2 395.60 12.43 22.9
7 0.14455 12.5 7.87 no 0.524 6.172 96.1 5.9505 5.0 311.0 15.2 396.90 19.15 27.1

Los datos son confusos; a menudo está desequilibrado y salpicado de valores atípicos que desvían el análisis y la capacitación en aprendizaje automático.

El primer paso para limpiar el conjunto de datos es comprender dónde es necesario limpiarlo. Limpiar un conjunto de datos puede ser complicado, especialmente de manera generalizable

El Google El equipo de investigación ha desarrollado una herramienta para este trabajo llamada Facetas Esto te ayuda a visualizar los datos y segmentarlos de diversas maneras. Es un buen punto de partida para comprender cómo está organizado el conjunto de datos.

Facetas te permite encontrar dónde los datos no se parecen exactamente a lo que esperabas.

Excepto por su aplicación web, Google facilita la integración del conjunto de herramientas en un Jupyter cuaderno.

Las Facetas tienen dos partes:

  • Resumen de facetas
  • Análisis profundo de facetas

Resumen de facetas

La descripción general de facetas brinda una descripción general del conjunto de datos. La descripción general de facetas divide las columnas de datos en filas de información destacada que muestra

  1. el porcentaje de observaciones faltantes
  2. valores mínimos y máximos
  3. estadísticas como la media, la mediana y la desviación estándar.
  4. También agrega una columna que muestra el porcentaje de valores que son ceros, lo cual resulta útil cuando la mayoría de los valores son ceros.
  5. Es posible ver estas distribuciones en el conjunto de datos de prueba y en el conjunto de entrenamiento para cada característica. Esto significa que puede verificar que la prueba tenga una distribución similar a los datos de entrenamiento.

Esto es al menos lo mínimo que se debe hacer antes de cualquier tarea de aprendizaje automático. Con esta herramienta, no se pierde este paso crucial y resalta algunas anomalías.

Análisis profundo de facetas

Facets Deep Dive es una herramienta genial. Te permite obtener información clara sobre tu conjunto de datos y acercar la vista al máximo para ver un dato individual. Esto significa que puedes filtrar los datos por filas y columnas en cualquiera de las características del conjunto de datos.

Usaremos estas dos herramientas con el conjunto de datos de Boston.

Nota: : No puede utilizar Facets Overview y Facets Deep Dive al mismo tiempo. Primero debe borrar el cuaderno para cambiar la herramienta.

Antes de poder utilizar cualquiera de las dos herramientas, es necesario instalar Facets en el entorno del portátil.

Instalar faceta

Puede utilizar la aplicación web Facet para la mayor parte del análisis. En este tutorial, verá cómo usarlo dentro de un Jupyter Cuaderno.

En primer lugar, debes instalar nbextensions. Para ello, utiliza este código. Copia y pega el siguiente código en la terminal de tu máquina.

pip install jupyter_contrib_nbextensions

Inmediatamente después de eso, debes clonar los repositorios en tu computadora. Tienes dos opciones:

Opción 1) Copia y pega este código en la terminal. (Recomendado)

Si no tiene Git instalado en su máquina, vaya a esta página. URL Git para Windows Página de descarga y sigue las instrucciones. Una vez que haya terminado, puede usar el comando git en la terminal para usuarios de Mac o el indicador de Anaconda para Windows usuario

git clone https://github.com/PAIR-code/facets

Opción 2) Vaya al el repositorio de códigos/facetas PAIR y descargar los repositorios.

Página del repositorio de facetas de código PAIR en GitHub

La página del repositorio que se muestra arriba contiene el botón de descarga que se utiliza en la opción 2. Si elige la primera opción, el archivo se guardará en su carpeta de descargas. Puede dejar que el archivo se descargue o arrastrarlo a otra ubicación.

Puede comprobar dónde se almacenan Facets con esta línea de comando:

echo `pwd`/`ls facets`

Ahora que ha localizado Facets, debe instalarlo en Jupyter Computadora portátil. Debe configurar el directorio de trabajo en la ruta donde se encuentran las facetas.

Su directorio de trabajo actual y la ubicación del zip de Facets deberían ser los mismos.

Terminal que muestra la carpeta facetas en el directorio de trabajo actual.

El listado de la terminal anterior confirma que facets se encuentra en el directorio de trabajo actual. Debes indicar el directorio de trabajo a Facet:

cd facets

Para instalar Facetas en Jupyter, tienes dos opciones. Si instalaste Jupyter con Conda para todos los usuarios, copia este código:

jupyter nbextension install facets-dist/

De lo contrario, utilice:

jupyter nbextension install facets-dist/ --user

Muy bien, ya está todo listo. Abramos Descripción general de facetas.

Descripción general de las facetas de ejecución en Jupyter

La descripción general utiliza un Python script para calcular las estadísticas. Debe importar el script llamado generic_feature_statistics_generator a Jupyter. No te preocupes; el script se encuentra en los archivos de facetas.

Necesitas localizar su camino. Se hace fácilmente. Abres facetas, abres el archivo facets_overview y luego python. Copia la ruta

Ruta de acceso al archivo de la carpeta facets_overview de Python

Después de eso, vuelve a Jupytery escribe el siguiente código. Cambia la ruta '/Users/Thomas/facets/facets_overview/python' por la tuya.

# Add the facets overview python code to the python path# Add t 
import sys
sys.path.append('/Users/Thomas/facets/facets_overview/python')

Puede importar el script con el siguiente código.

from generic_feature_statistics_generator import 
GenericFeatureStatisticsGenerator

En Windows, el mismo código se convierte en

import sys
sys.path.append(r"C:\Users\Admin\Anaconda3\facets-master\facets_overview\python")

from generic_feature_statistics_generator import GenericFeatureStatisticsGenerator

Para calcular las estadísticas de funciones, debe utilizar la función GenericFeatureStatisticsGenerator(), y utiliza el objeto ProtoFromDataFrames. Puede pasar el marco de datos en un diccionario. Por ejemplo, si queremos crear un resumen estadístico para el conjunto de trenes, podemos almacenar la información en un diccionario y usarla en el objeto "ProtoFromDataFrames".

'name': 'train', 'table': df_train

Nombre es el nombre de la tabla que se muestra y utiliza el nombre de la tabla que desea calcular el resumen. En su ejemplo, la tabla que contiene los datos es df_train

# Calculate the feature statistics proto from the datasets and stringify it for use in facets overview
import base64

gfsg = GenericFeatureStatisticsGenerator()

proto = gfsg.ProtoFromDataFrames([{'name': 'train', 'table': df_train},
                                  {'name': 'test', 'table': df_test}])

#proto = gfsg.ProtoFromDataFrames([{'name': 'train', 'table': df_train}])
protostr = base64.b64encode(proto.SerializeToString()).decode("utf-8")

Por último, simplemente copie y pegue el código a continuación. El código proviene directamente de GitHub. Deberías poder ver esto:

Tabla general de Facetas con estadísticas resumidas por característica

# Display the facets overview visualization for this data# Displ 
from IPython.core.display import display, HTML

HTML_TEMPLATE = """<link rel="import" href="/nbextensions/facets-dist/facets-jupyter.html" >
        <facets-overview id="elem"></facets-overview>
        <script>
          document.querySelector("#elem").protoInput = "{protostr}";
        </script>"""
html = HTML_TEMPLATE.format(protostr=protostr)
display(HTML(html))

Gráfico de correlación y cuadrícula de pares

Tras analizar los datos y su distribución, se puede generar una matriz de correlación. Esta matriz calcula el coeficiente de Pearson, cuyo valor oscila entre -1 y 1, donde un valor positivo indica una correlación positiva y un valor negativo, una correlación negativa.

Le interesa ver qué variables pueden ser buenas candidatas para términos de interacción.

Nota de versión: La máscara de abajo llama np.bool, un alias que quedó obsoleto en NumPy 1.20 y Eliminado en NumPy 1.24En una versión reciente de NumPy, la misma línea genera AttributeError: module 'numpy' has no attribute 'bool'; el incorporado bool es el reemplazo directo.

## Choose important feature and further check with Dive
%matplotlib inline  
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="ticks")
# Compute the correlation matrix
corr = df.corr('pearson')
# Generate a mask for the upper triangle
mask = np.zeros_like(corr, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True
# Set up the matplotlib figure
f, ax = plt.subplots(figsize=(11, 9))

# Generate a custom diverging colormap
cmap = sns.diverging_palette(220, 10, as_cmap=True)

# Draw the heatmap with the mask and correct aspect ratio
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,annot=True,
            square=True, linewidths=.5, cbar_kws={"shrink": .5})

Resultado

<matplotlib.axes._subplots.AxesSubplot at 0x1a184d6518>

Mapa de calor de correlación de Seaborn de las variables de Boston

En el mapa de calor anterior, los cuadrados más oscuros indican correlaciones más fuertes. En la matriz se puede observar:

  • LSTAT
  • RM

Están fuertemente correlacionados con el PRECIO. Otra característica interesante es la fuerte correlación positiva entre NOX e INDUS, lo que significa que estas dos variables se mueven en la misma dirección. Ambas también están correlacionadas con el PRECIO. DIS también está altamente correlacionado con INDUS y NOX.

Ya tienes un primer indicio de que INDUS y NOX pueden ser buenos candidatos para un término de interacción, y que DIS también podría ser interesante para centrarse en él.

Puedes profundizar un poco más trazando una cuadrícula de pares. Ilustrará más detalladamente el mapa de correlación que trazó antes.

La cuadrícula de pares se compone de la siguiente manera:

  • Parte superior: diagrama de dispersión con línea ajustada
  • Diagonal: gráfico de densidad de granos
  • Parte inferior: gráfico de densidad de núcleo multivariado

Te centras en cuatro variables independientes. La elección corresponde a las variables con una fuerte correlación con el PRECIO.

  • INDUS
  • NOX
  • RM
  • LSTAT

además, el PRECIO.

Nota: que el error estándar se agrega de forma predeterminada al diagrama de dispersión.

attributes = ["PRICE", "INDUS", "NOX", "RM", "LSTAT"]

g = sns.PairGrid(df[attributes])
g = g.map_upper(sns.regplot, color="g")
g = g.map_lower(sns.kdeplot,cmap="Reds", shade=True, shade_lowest=False)
g = g.map_diag(sns.kdeplot)

Resultado

Cuadrícula de pares de Seaborn de PRICE, INDUS, NOX, RM y LSTAT

Empecemos por la parte superior:

  • El precio está correlacionado negativamente con INDUS, NOX y LSTAT; correlacionado positivamente con RM.
  • Existe una ligera no linealidad entre LSTAT y PRICE.
  • Hay como una línea recta cuando el precio es igual a 50. Según la descripción del conjunto de datos, PRECIO se ha truncado en el valor de 50.

Diagonal: NOX parece tener dos grupos, uno alrededor de 0.5 y otro alrededor de 0.85.

Para saber más sobre esto, puedes mirar la parte inferior. La densidad de kernel multivariante es interesante en el sentido de que colorea dónde se encuentran la mayoría de los puntos. La diferencia con el diagrama de dispersión dibuja una densidad de probabilidad, aunque no haya ningún punto en el conjunto de datos para una determinada coordenada. Cuando el color es más intenso, indica una alta concentración de puntos alrededor de esta área.

Si se comprueba la densidad multivariable de INDUS y NOX, se puede ver la correlación positiva y los dos grupos. Cuando la participación de la industria es superior a 18, la concentración de óxidos nítricos es superior a 0.6.

Puedes pensar en agregar una interacción entre INDUS y NOX en la relación lineal.

Finalmente, puedes utilizar la segunda herramienta creada por GoogleAnálisis detallado de facetas. La interfaz se divide en cuatro secciones principales. El área central muestra los datos con zoom. En la parte superior del panel, se encuentra el menú desplegable que permite modificar la disposición de los datos, controlar la faceta, el posicionamiento y el color. A la derecha, se muestra una vista detallada de una fila específica de datos. Al hacer clic en cualquier punto de datos en la visualización central, se puede ver información detallada sobre ese punto en particular.

Durante el paso de visualización de datos, lo que le interesa es buscar la correlación por pares entre la variable independiente y el precio de la vivienda. Sin embargo, implica al menos tres variables y trabajar con gráficos 3D es complicado.

Una forma de abordar este problema es crear una variable categórica. Es decir, podemos crear un gráfico 2D y colorear los puntos. Podemos dividir la variable PRECIO en cuatro categorías, donde cada categoría representa un cuartil (por ejemplo, 0.25, 0.5, 0.75). A esta nueva variable la llamamos Q_PRICE.

## Check non linearity with important features
df['Q_PRICE'] =  pd.qcut(df['PRICE'], 4, labels=["Lowest", "Low", "Upper", "upper_plus"])
## Show non linearity between RM and LSTAT
ax = sns.lmplot(x="DIS", y="INDUS", hue="Q_PRICE", data=df, fit_reg = False,palette="Set3")

Diagrama de dispersión de DIS frente a INDUS coloreado por cuartil de precio

Análisis en profundidad de Facetas

Para abrir Deep Dive, necesitas transformar los datos a formato JSON. Pandas tiene un método para ello: llama al método to_json en el DataFrame.

La primera línea de código establece el tamaño del sprite en función del número de filas que contiene el conjunto de datos.

df['Q_PRICE'] =  pd.qcut(df['PRICE'], 4, labels=["Lowest", "Low", "Upper", "upper_plus"])
sprite_size = 32 if len(df.index)>50000 else 64
jsonstr = df.to_json(orient='records')

El código que aparece a continuación proviene de Google GitHub. Después de ejecutar el código, debería poder ver esto:

Vista de dispersión facetada de Facetas del conjunto de datos de Boston

# Display thde Dive visualization for this data
from IPython.core.display import display, HTML

# Create Facets template  
HTML_TEMPLATE = """<link rel="import" href="/nbextensions/facets-dist/facets-jupyter.html">
        <facets-dive sprite-image-width="{sprite_size}" sprite-image-height="{sprite_size}" id="elem" height="600"></facets-dive>
        <script>
          document.querySelector("#elem").data = {jsonstr};
        </script>"""

# Load the json dataset and the sprite_size into the template
html = HTML_TEMPLATE.format(jsonstr=jsonstr, sprite_size=sprite_size)

# Display the template
display(HTML(html))

Le interesa ver si existe una relación entre el precio de la industria, la concentración de óxido, la distancia al centro de trabajo y el precio de la casa.

Para eso, primero divida los datos por rango de industria y color con el cuartil de precios:

  • Seleccione facetado X y elija INDUS.
  • Seleccione Pantalla y elija DIS. Coloreará los puntos con el cuartil del precio de la vivienda.

Aquí, los colores más oscuros indican una mayor distancia al primer centro de empleo.

Hasta ahora, vuelve a mostrar lo que ya saben: una tasa industrial más baja, un precio más alto. Ahora podéis ver el desglose por INDUX, por NOX.

Seleccione facetado Y y elija NOX.

Ahora puede ver que la casa que está más lejos del primer centro de trabajo tiene la participación industrial más baja y, por lo tanto, la concentración de óxido más baja. Si elige mostrar el tipo con Q_PRICE y amplía la esquina inferior izquierda, puede ver de qué tipo de precio se trata.

Tiene otra pista de que la interacción entre IND, NOX y DIS pueden ser buenos candidatos para mejorar el modelo.

La exploración ha dado como resultado dos interacciones candidatas, por lo que el siguiente paso es probarlas en un modelo real.

Regresión lineal con TensorFlow

En esta sección, estimará el modelo de regresión lineal con el TensorFlow API de estimación. Proceda de la siguiente manera:

  • Prepara los datos
  • Estimar un modelo de referencia: sin interacción
  • Estimar un modelo con interacción.

Nota de versión: <font dir="auto" style="vertical-align: inherit;">las </font> tf-estimator El paquete lanzó su versión final con TensorFlow 2.15 y está ausente de TensorFlow 2.16 en adelante, por lo que tf.estimator.LinearRegressor Solo funciona con TensorFlow 1.x, a menos que lo migres a un modelo lineal de Keras.

Recuerda que el objetivo del aprendizaje automático es minimizar el error. En este caso, ganará el modelo con el menor error cuadrático medio. El estimador de TensorFlow calcula automáticamente esta métrica.

Datos de preparación

En la mayoría de los casos, es necesario transformar los datos. Por eso, la función Facetas es tan interesante. En la estadística descriptiva, se observan valores atípicos. Estos valores afectan las estimaciones porque no se corresponden con la población analizada. Los valores atípicos suelen sesgar los resultados. Por ejemplo, un valor atípico positivo tiende a sobreestimar el coeficiente.

Una buena solución para abordar este problema es estandarizar la variable. La estandarización significa una desviación estándar de uno y una media de cero. El proceso de estandarización consta de dos pasos. En primer lugar, se subestima la variable.traces el valor medio de la variable. En segundo lugar, se divide por la desviación estándar para que la distribución tenga una desviación estándar unitaria.

La biblioteca scikit-aprender Es útil para estandarizar variables. Para ello, puede utilizar el módulo de preprocesamiento con el objeto de escala.

Puede utilizar la siguiente función para escalar un conjunto de datos. Tenga en cuenta que no escala la columna de etiqueta ni las variables categóricas.

from sklearn import preprocessing
def standardize_data(df): 
    X_scaled = preprocessing.scale(df[['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',
       'TAX', 'PTRATIO', 'B', 'LSTAT']])
    X_scaled_df = pd.DataFrame(X_scaled, columns = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',
       'TAX', 'PTRATIO', 'B', 'LSTAT'])
    df_scale = pd.concat([X_scaled_df,
                       df['CHAS'],
                       df['PRICE']],axis=1, join='inner')
    return df_scale

Puede utilizar la función para construir el tren/conjunto de prueba a escala.

df_train_scale = standardize_data(df_train)
df_test_scale = standardize_data(df_test)

Regresión básica: punto de referencia

En primer lugar, entrenas y pruebas un modelo sin interacción. El propósito es ver la métrica de desempeño del modelo.

La forma de entrenar el modelo es exactamente la misma que en el tutorial. API de alto nivel. Utilizará el estimador TensorFlow LinearRegressor.

Como recordatorio, debes elegir:

  • las características para poner en el modelo
  • transformar las características
  • construir el regresor lineal
  • construir la función input_fn
  • entrenar al modelo
  • probar el modelo

Se utilizan todas las variables del conjunto de datos para entrenar el modelo. En total, hay doce variables continuas y una variable categórica.

## Add features to the bucket: 
### Define continuous list
CONTI_FEATURES  = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT']
CATE_FEATURES = ['CHAS']

Convierte las características en una columna numérica o columna categórica.

continuous_features = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES]
#categorical_features = tf.feature_column.categorical_column_with_hash_bucket(CATE_FEATURES, hash_bucket_size=1000)
categorical_features = [tf.feature_column.categorical_column_with_vocabulary_list('CHAS', ['yes','no'])]

Creas el modelo con el regresor lineal. Guardas el modelo en la carpeta train_Boston.

model = tf.estimator.LinearRegressor(    
	model_dir="train_Boston",     
    feature_columns=categorical_features + continuous_features)

Resultado

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train_Boston', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1a19e76ac8>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

Cada columna de los datos de entrenamiento o prueba se convierte en un Tensor con la función get_input_fn.

FEATURES = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT', 'CHAS']
LABEL= 'PRICE'
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
    return tf.estimator.inputs.pandas_input_fn(
       x=pd.DataFrame({k: data_set[k].values for k in FEATURES}),
       y = pd.Series(data_set[LABEL].values),
       batch_size=n_batch,   
       num_epochs=num_epochs,
       shuffle=shuffle)

Estima el modelo a partir de los datos del tren.

model.train(input_fn=get_input_fn(df_train_scale, 
                                      num_epochs=None,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 1 into train_Boston/model.ckpt.
INFO:tensorflow:loss = 56417.703, step = 1
INFO:tensorflow:global_step/sec: 144.457
INFO:tensorflow:loss = 76982.734, step = 101 (0.697 sec)
INFO:tensorflow:global_step/sec: 258.392
INFO:tensorflow:loss = 21246.334, step = 201 (0.383 sec)
INFO:tensorflow:global_step/sec: 227.998
INFO:tensorflow:loss = 30534.78, step = 301 (0.439 sec)
INFO:tensorflow:global_step/sec: 210.739
INFO:tensorflow:loss = 36794.5, step = 401 (0.477 sec)
INFO:tensorflow:global_step/sec: 234.237
INFO:tensorflow:loss = 8562.981, step = 501 (0.425 sec)
INFO:tensorflow:global_step/sec: 238.1
INFO:tensorflow:loss = 34465.08, step = 601 (0.420 sec)
INFO:tensorflow:global_step/sec: 237.934
INFO:tensorflow:loss = 12241.709, step = 701 (0.420 sec)
INFO:tensorflow:global_step/sec: 220.687
INFO:tensorflow:loss = 11019.228, step = 801 (0.453 sec)
INFO:tensorflow:global_step/sec: 232.702
INFO:tensorflow:loss = 24049.678, step = 901 (0.432 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train_Boston/model.ckpt.
INFO:tensorflow:Loss for final step: 23228.568.


<tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a19e76320>

Por fin, estima el rendimiento del modelo en el conjunto de prueba.

model.evaluate(input_fn=get_input_fn(df_test_scale, 
                                      num_epochs=1,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-29-02:40:43
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train_Boston/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-29-02:40:43
INFO:tensorflow:Saving dict for global step 1000: average_loss = 86.89361, global_step = 1000, loss = 1650.9785


{'average_loss': 86.89361, 'global_step': 1000, 'loss': 1650.9785}

La pérdida del modelo es 1650.9785. Esta es la métrica a superar en la siguiente sección.

Mejorar el modelo: término de interacción

Durante la primera parte del tutorial, observaste una relación interesante entre las variables. Las diferentes técnicas de visualización revelaron que INDUS y NOX están vinculadas y potencian mutuamente su efecto sobre el precio. La interacción entre INDUS y NOX no solo afecta el precio, sino que este efecto se intensifica cuando interactúa con DIS.

Es hora de generalizar esta idea y ver si se puede mejorar la predicción del modelo.

Debes añadir dos nuevas columnas a cada conjunto de datos: entrenamiento y prueba. Para ello, crea una función para calcular el término de interacción y otra para calcular el término de interacción triple. Cada función genera una columna. Una vez creadas las nuevas variables, puedes concatenarlas a los conjuntos de datos de entrenamiento y prueba.

En primer lugar, es necesario crear una nueva variable para la interacción entre INDUS y NOX.

La siguiente función devuelve dos marcos de datos, tren y prueba, con la interacción entre var_1 y var_2, en su caso INDUS y NOX.

def interaction_term(var_1, var_2, name):
    t_train = df_train_scale[var_1]*df_train_scale[var_2]
    train = t_train.rename(name)
    t_test = df_test_scale[var_1]*df_test_scale[var_2]
    test = t_test.rename(name)
    return train, test

Almacenas las dos nuevas columnas.

interation_ind_ns_train, interation_ind_ns_test= interaction_term('INDUS', 'NOX', 'INDUS_NOS')
interation_ind_ns_train.shape
(325,)

En segundo lugar, crea una segunda función para calcular el término de interacción triple.

def triple_interaction_term(var_1, var_2,var_3, name):
    t_train = df_train_scale[var_1]*df_train_scale[var_2]*df_train_scale[var_3]
    train = t_train.rename(name)
    t_test = df_test_scale[var_1]*df_test_scale[var_2]*df_test_scale[var_3]
    test = t_test.rename(name)
    return train, test
interation_ind_ns_dis_train, interation_ind_ns_dis_test= triple_interaction_term('INDUS', 'NOX', 'DIS','INDUS_NOS_DIS')

Ahora que tiene todas las columnas necesarias, puede agregarlas al conjunto de datos de entrenamiento y prueba. Nombra estos dos nuevos marcos de datos:

  • df_train_new
  • df_test_new
df_train_new = pd.concat([df_train_scale,
                          interation_ind_ns_train,
                          interation_ind_ns_dis_train],
                         axis=1, join='inner')
df_test_new = pd.concat([df_test_scale,
                         interation_ind_ns_test,
                         interation_ind_ns_dis_test],
                         axis=1, join='inner')
df_train_new.head(5)

Resultado

DataFrame de entrenamiento con las columnas INDUS_NOS e INDUS_NOS_DIS añadidas.

Eso es todo: puedes estimar el nuevo modelo con los términos de interacción y ver cómo es la métrica de rendimiento.

CONTI_FEATURES_NEW  = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT',
                       'INDUS_NOS', 'INDUS_NOS_DIS']
### Define categorical list
continuous_features_new = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES_NEW]
model = tf.estimator.LinearRegressor(
    model_dir="train_Boston_1", 
    feature_columns= categorical_features + continuous_features_new)

Resultado

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train_Boston_1', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0x1a1a5d5860>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

Code

FEATURES = ['CRIM', 'ZN', 'INDUS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT','INDUS_NOS', 'INDUS_NOS_DIS','CHAS']
LABEL= 'PRICE'
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
    return tf.estimator.inputs.pandas_input_fn(
       x=pd.DataFrame({k: data_set[k].values for k in FEATURES}),
       y = pd.Series(data_set[LABEL].values),
       batch_size=n_batch,   
       num_epochs=num_epochs,
       shuffle=shuffle)
model.train(input_fn=get_input_fn(df_train_new, 
                                      num_epochs=None,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 1 into train_Boston_1/model.ckpt.
INFO:tensorflow:loss = 56417.703, step = 1
INFO:tensorflow:global_step/sec: 124.844
INFO:tensorflow:loss = 65522.3, step = 101 (0.803 sec)
INFO:tensorflow:global_step/sec: 182.704
INFO:tensorflow:loss = 15384.148, step = 201 (0.549 sec)
INFO:tensorflow:global_step/sec: 208.189
INFO:tensorflow:loss = 22020.305, step = 301 (0.482 sec)
INFO:tensorflow:global_step/sec: 213.855
INFO:tensorflow:loss = 28208.812, step = 401 (0.468 sec)
INFO:tensorflow:global_step/sec: 209.758
INFO:tensorflow:loss = 7606.877, step = 501 (0.473 sec)
INFO:tensorflow:global_step/sec: 196.618
INFO:tensorflow:loss = 26679.76, step = 601 (0.514 sec)
INFO:tensorflow:global_step/sec: 196.472
INFO:tensorflow:loss = 11377.163, step = 701 (0.504 sec)
INFO:tensorflow:global_step/sec: 172.82
INFO:tensorflow:loss = 8592.07, step = 801 (0.578 sec)
INFO:tensorflow:global_step/sec: 168.916
INFO:tensorflow:loss = 19878.56, step = 901 (0.592 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train_Boston_1/model.ckpt.
INFO:tensorflow:Loss for final step: 19598.387.


<tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a1a5d5e10>
model.evaluate(input_fn=get_input_fn(df_test_new, 
                                      num_epochs=1,
                                      n_batch = 128,
                                      shuffle=False),
                                      steps=1000)

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-29-02:41:14
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train_Boston_1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-29-02:41:14
INFO:tensorflow:Saving dict for global step 1000: average_loss = 79.78876, global_step = 1000, loss = 1515.9863


{'average_loss': 79.78876, 'global_step': 1000, 'loss': 1515.9863}

La nueva pérdida es 1515.9863. Con solo agregar dos nuevas variables, pudo disminuir la pérdida. Significa que puede hacer una mejor predicción que con el modelo de referencia.

Modelo Conjunto de características Directorio de modelos pérdida promedio de
12 columnas continuas estandarizadas más CHAS tren_Boston 86.89361 1650.9785
Con interacción Benchmark más INDUS_NOS e INDUS_NOS_DIS tren_Boston_1 79.78876 1515.9863

Ambas cifras provienen de la misma división de prueba de 101 filas, por lo que la caída de aproximadamente un 8 por ciento en la pérdida promedio se atribuye únicamente a las dos columnas de interacción.

Preguntas Frecuentes

Se dejó de usar en scikit-learn 1.0 y se eliminó en la versión 1.2. El conjunto de datos contiene una característica basada en una suposición sobre la autosegregación racial y los precios de las viviendas, y el estudio original nunca validó su premisa sobre la calidad del aire. Las viviendas de California o Ames son los sustitutos habituales.

Un término polinómico eleva al cuadrado o al cubo una variable para modificar su propia curva. Una interacción multiplica dos variables diferentes, de modo que la pendiente de una depende del valor de la otra. Este tutorial explica el segundo tipo: INDUS por NOX.

Busque pares que se correlacionen entre sí y con el objetivo. El mapa de calor de Pearson y la cuadrícula de pares hacen esto visualmente; aquí INDUS y NOX se agrupan juntos y ambos track PRICE, que es la señal que justifica cruzarlos.

Las bibliotecas de ingeniería de características automatizadas generan transformaciones y cruces candidatos, los evalúan comparándolos con un conjunto de datos de prueba y conservan solo aquellos que reducen el error. Esto reemplaza la lectura manual del mapa de calor que se muestra aquí, aunque un humano aún debe verificar el significado de las columnas generadas.

Copilot maneja bien las tareas repetitivas de trazado de datos: cuadrículas de pares, mapas de calor enmascarados, plantillas HTML para facetas. Revisa los argumentos que sugiere, ya que seaborn renombró varios de ellos y Copilot combina sin problemas firmas antiguas y actuales.

No. La pérdida debe compararse en la misma división de datos reservada, como se hace aquí. Una pérdida que solo se aplica a los datos de entrenamiento indica sobreajuste, y añadir columnas casi siempre mejora el ajuste del entrenamiento, independientemente de si contienen información real o no.

La máscara utiliza np.bool, un alias obsoleto en NumPy 1.20 y eliminado en la versión 1.24. Las instalaciones recientes generan un AttributeError. Sustituirlo por el bool integrado mantiene el mismo comportamiento; np.bool_ también funciona si se necesita el tipo escalar de NumPy.

CHAS es una variable categórica de tipo sí o no, y PRICE es la etiqueta. Centrar y escalar una variable ficticia dificulta la lectura de su coeficiente sin alterar el ajuste, y escalar la etiqueta simplemente reescalaría la pérdida reportada. Solo los doce predictores continuos están estandarizados.

Resumir este post con: