Tutorial de regresión lineal con TensorFlow [Ejemplos]

⚔ Resumen inteligente

La regresión lineal en TensorFlow modela la relación entre características numéricas y un valor objetivo continuo. Este tutorial entrena un predictor de precios de viviendas en Boston de tres maneras distintas, utilizando Pandas, NumPy y las canalizaciones de entrada nativas de TensorFlow con el estimador LinearRegressor.

  • šŸ”˜ formulario modelo: Una regresión lineal ajusta y = sesgo + peso Ɨ x, extendida con mĆ”s covariables para problemas multivariados.
  • ā˜‘ļø Bucle de entrenamiento: El descenso de gradiente ajusta los pesos en cada iteración hasta que el error cuadrĆ”tico medio deja de disminuir.
  • āœ… API del estimador: LinearRegressor solo necesita columnas de caracterĆ­sticas, un directorio de modelo y una función de entrada.
  • 🧪 Tres oleoductos: Los conjuntos de datos de Pandas, NumPy y TensorFlow nativo alimentan el mismo modelo y devuelven predicciones idĆ©nticas.
  • šŸ› ļø Ejemplo trabajado: Nueve caracterĆ­sticas de Boston predicen el valor medio de las viviendas y alcanzan una pĆ©rdida de prueba de 3215.
  • āš ļø Versión realidad: Los estimadores quedaron obsoletos en TensorFlow 2.12 y se eliminaron en la versión 2.16, por lo que conviene adaptar el trabajo nuevo a Keras.

Regresión lineal con TensorFlow

¿Qué es la regresión lineal?

Regresión lineal La regresión lineal simple es un método estadístico para modelar relaciones entre dos variables. Este modelado se realiza entre una variable de respuesta escalar y una o mÔs variables explicativas. La relación con una sola variable explicativa se denomina regresión lineal simple, y con mÔs de una variable explicativa, regresión lineal múltiple.

TensorFlow proporciona herramientas para tener control total de los cƔlculos. Esto se hace con la API de bajo nivel. AdemƔs de eso, TensorFlow estƔ equipado con una amplia gama de API para realizar muchas aprendizaje automƔtico algoritmos. Esta es la API de alto nivel, y TensorFlow los llama estimadores.

  • API de bajo nivel: Construir la arquitectura y la optimización del modelo desde cero. Es complicado para un principiante.
  • API de alto nivel: Defina el algoritmo. Es fĆ”cil de usar. TensorFlow proporciona una caja de herramientas llamada estimador construir, entrenar, evaluar y hacer una predicción.

En este tutorial, utilizarÔ el solo estimadoresLos cÔlculos son mÔs rÔpidos y fÔciles de implementar. La primera parte explica cómo usar el optimizador de descenso de gradiente para entrenar una regresión lineal en TensorFlow. En la segunda parte, usarÔs el conjunto de datos de Boston para predecir el precio de una casa con un estimador de TensorFlow.

Descargar el conjunto de datos de Boston

Cómo entrenar un modelo de regresión lineal

Antes de comenzar a entrenar el modelo, veamos qué es realmente una regresión lineal.

Imagina que tienes dos variables, x e y, y tu tarea es predecir el valor de y conociendo el valor de x. Si representas los datos grÔficamente, podrÔs observar una relación positiva entre tu variable independiente, x, y tu variable dependiente, y, como se muestra en el diagrama de dispersión a continuación.

Diagrama de dispersión de x frente a y que muestra una relación lineal positiva.

PodrƔs observar que si x=1, y serƔ aproximadamente igual a 6, y si x=2, y serƔ alrededor de 8.5.

Este mƩtodo no es muy preciso y es propenso a errores, especialmente con un conjunto de datos que contiene cientos de miles de puntos.

Una regresión lineal se evalúa con una ecuación. La variable y se explica por una o varias covariables. En su ejemplo, solo hay una variable dependiente. Si tienes que escribir esta ecuación, serÔ:

Ecuación de regresión lineal simple con un sesgo, un peso y un término de error.

Con:

  • SĆ­mbolo del coeficiente de sesgo es el sesgo. Es decir, si x=0, y=Valor del coeficiente de sesgo cuando x es igual a cero
  • SĆ­mbolo de coeficiente de ponderación asociado con x es el peso asociado con x
  • SĆ­mbolo del tĆ©rmino de error residual es el residuo, o el error del modelo. Incluye lo que el modelo no puede aprender de los datos.

Imagina que ajustas el modelo y encuentras la siguiente solución para:

  • Coeficiente de sesgo ajustado igual a 3.8. = 3.8
  • Coeficiente de ponderación ajustado igual a 2.78 = 2.78

Puedes sustituir esos números en la ecuación y se convierte en:

y= 3.8 + 2.78x

Ahora tienes una mejor manera de encontrar los valores de y. Es decir, puedes reemplazar x con cualquier valor que desees para predecir y. En la imagen a continuación, hemos reemplazado x en la ecuación con todos los valores del conjunto de datos y hemos graficado el resultado.

Línea de regresión ajustada dibujada en rojo a través de los puntos de datos graficados.

La lƭnea roja representa el valor ajustado, es decir, los valores de y para cada valor de x. No es necesario conocer el valor de x para predecir y; para cada x existe un valor que corresponde a la lƭnea roja. TambiƩn se pueden realizar predicciones para valores de x mayores que 2.

Si desea ampliar la regresión lineal a mÔs covariables, puede hacerlo agregando mÔs variables al modelo. La diferencia entre el anÔlisis tradicional y la regresión lineal radica en que esta última examina cómo reacciona la variable y ante cada variable x tomada de forma independiente.

Veamos un ejemplo. Imagina que quieres predecir las ventas de una heladería. El conjunto de datos contiene información diversa, como el clima (lluvioso, soleado, nublado) e información del cliente (salario, género, estado civil).

El anƔlisis tradicional intentarƔ predecir las ventas, por ejemplo, calculando el promedio de cada variable y tratando de estimar las ventas para diferentes escenarios. Esto darƔ lugar a predicciones deficientes y limitarƔ el anƔlisis al escenario elegido.

Si usas regresión lineal, puedes escribir esta ecuación:

Ecuación de regresión lineal múltiple que combina varias covariables ponderadas.

El algoritmo encontrarÔ la mejor solución para los pesos; es decir, intentarÔ minimizar el coste, que es la diferencia entre la línea ajustada y los puntos de datos.

Como funciona el algoritmo

El siguiente diagrama resume el ciclo que repite el algoritmo: seleccionar los pesos, predecir y, medir el error y corregir los pesos.

Diagrama de flujo del bucle de entrenamiento de regresión lineal desde pesos aleatorios hasta error minimizado

El algoritmo elegirÔ un número aleatorio para cada Coeficiente de sesgo inicializado aleatoriamente y Coeficiente de ponderación inicializado aleatoriamente y reemplace el valor de x para obtener el valor previsto de y. Si el conjunto de datos tiene 100 observaciones, el algoritmo calcula 100 valores predichos.

Podemos calcular el error, observado Término de error del modelo utilizado en el cÔlculo de pérdidas, del modelo, que es la diferencia entre el valor predicho y el valor real. Un error positivo significa que el modelo subestima la predicción de y, y un error negativo significa que el modelo sobreestima la predicción de y.

Objetivo de minimización del error cuadrÔtico expresado en notación matemÔtica.

Tu objetivo es minimizar el cuadrado del error. El algoritmo calcula la media del error cuadrÔtico. Este paso se llama minimización del error. Para la regresión lineal, esto es el Error cuadrÔtico medio, también llamado MSE. MatemÔticamente es:

Fórmula del error cuadrÔtico medio escrita en notación matricial.

Lugar:

  • SĆ­mbolo del vector de peso utilizado en la fórmula del MSE son los pesos, asĆ­ que Notación de valor predicho utilizada en la fórmula MSE se refiere al valor predicho
  • y son los valores reales
  • m es el nĆŗmero de observaciones

Tenga en cuenta que Notación de matriz de pesos transpuesta significa que utiliza la transpuesta de las matrices. El Notación de sumatoria y media utilizada en la fórmula del MSE es la notación matemÔtica de la media.

El objetivo es encontrar lo mejor. Símbolo de peso óptimo que minimiza el MSE que minimiza el MSE.

Si el error promedio es grande, significa que el modelo funciona mal y los pesos no se eligen correctamente. Para corregir los pesos, es necesario utilizar un optimizador. El optimizador tradicional se llama Descenso de gradiente.

El descenso de gradiente toma la derivada y disminuye o aumenta el peso. Si la derivada es positiva, el peso disminuye. Si la derivada es negativa, el peso aumenta. El modelo actualizarÔ los pesos y recalcularÔ el error. Este proceso se repite hasta que el error ya no cambie. Cada pasada se llama iteraciónAdemÔs, los gradientes se multiplican por una tasa de aprendizaje, que indica la velocidad del aprendizaje.

Si la tasa de aprendizaje es demasiado baja, el algoritmo tardarÔ mucho tiempo en converger, ya que requiere muchas mÔs iteraciones. Si la tasa de aprendizaje es demasiado alta, es posible que el algoritmo nunca converja. La curva de pérdida que se muestra a continuación representa el error en función del número de iteraciones para este conjunto de datos.

Curva de pérdida que muestra cómo el error disminuye y se estabiliza después de aproximadamente veinte iteraciones.

Como se puede observar en la imagen superior, el modelo repite el proceso unas 20 veces antes de encontrar un valor estable para los pesos, alcanzando asĆ­ el menor error.

Tenga en cuenta que el error no es cero, sino que se estabiliza en torno a 5. Esto significa que el modelo presenta un error típico de 5. Si desea reducir el error, deberÔ añadir mÔs información al modelo, como mÔs variables, o utilizar estimadores diferentes.

Recuerdas la primera ecuación:

Ecuación de regresión lineal final ajustada con los pesos calculados.

Los pesos finales son 3.8 y 2.78. El siguiente video muestra cómo el descenso de gradiente optimiza la función de pérdida para encontrar estos pesos.

Cómo entrenar una regresión lineal con TensorFlow

Ahora que comprende mejor lo que sucede detrÔs del capó, estÔ listo para usar la API del estimador proporcionada por TensorFlow para entrenar su primera regresión lineal usando TensorFlow.

Nota de versión: El flujo de trabajo del estimador que se muestra a continuación se escribió para TensorFlow 1.x y las primeras versiones de 2.x. TensorFlow marcó el tf.estimator y tf.feature_column Las API quedaron totalmente obsoletas en la versión 2.12 y se eliminaron los Estimadores en la versión 2.16. En una instalación actual, ejecute este código dentro de un TensorFlow 1.15 o 2.x-with-tf.compat.v1 entorno, o portarlo a Keras, donde tf.keras.layers.Dense(1) AdemĆ”s, las capas de preprocesamiento reemplazan al LinearRegressor y las columnas de caracterĆ­sticas. Los conceptos —caracterĆ­sticas, etiquetas, lotes, Ć©pocas, MSE y descenso de gradiente— se mantienen sin cambios.

UtilizarƔs el conjunto de datos de Boston, que incluye las siguientes variables.

Variable Mareas Ideales para Lecciones
criminal tasa de criminalidad per cƔpita por ciudad
zn proporción de terreno residencial zonificado para lotes de mÔs de 25,000 pies cuadrados.
indus 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 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 ratio alumnos-maestro por localidad
médico Valor medio de las viviendas ocupadas por sus propietarios en miles de dólares

CrearĆ” tres conjuntos de datos diferentes:

datos objetivo dar forma a
Capacitación Especializada Entrena el modelo y obtén los pesos. de 400
Evaluación Evaluar el rendimiento del modelo con datos invisibles. de 100
Predicción Utilice el modelo para predecir el valor de la vivienda a partir de nuevos datos de 6

El objetivo es utilizar las caracterĆ­sticas del conjunto de datos para predecir el valor de la vivienda.

Durante la segunda parte del tutorial, aprenderĆ” a utilizar TensorFlow con tres formas diferentes de importar los datos:

  • Con pandas
  • Con NumPy
  • Solo TensorFlow

Tenga en cuenta que las tres opciones proporcionan los mismos resultados.

AprenderÔs a usar la API de alto nivel para construir, entrenar y evaluar un modelo de regresión lineal de TensorFlow. Si usaras la API de bajo nivel, tendrías que definir manualmente lo siguiente:

  • Función de pĆ©rdida
  • Optimizador: descenso de gradiente
  • Multiplicación de matrices
  • Grafico y tensor

Esto resulta tedioso y mƔs complicado para un principiante.

Solución Pandas

Debe importar las bibliotecas necesarias para entrenar el modelo.

import pandas as pd
from sklearn import datasets
import tensorflow as tf
import itertools

Paso 1) Importar los datos con pandas.

Usted define los nombres de las columnas y los almacena en COLUMNS. Puede usar pd.read_csv() para importar los datos.

COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age",
           "dis", "tax", "ptratio", "medv"]

Dirige cada llamada a los archivos CSV que descargaste anteriormente.

training_set = pd.read_csv("E:/boston_train.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)
test_set = pd.read_csv("E:/boston_test.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)
prediction_set = pd.read_csv("E:/boston_predict.csv", skipinitialspace=True,skiprows=1, names=COLUMNS)

Puede imprimir la forma de los datos.

print(training_set.shape, test_set.shape, prediction_set.shape)

Resultado

(400, 10) (100, 10) (6, 10)

Tenga en cuenta que la etiqueta, es decir, su variable dependiente (y), estƔ incluida en el conjunto de datos. Por lo tanto, debe definir otras dos listas: una que contenga solo las caracterƭsticas y otra con el nombre de la etiqueta. Estas dos listas le indicarƔn a su estimador cuƔles son las caracterƭsticas del conjunto de datos y quƩ nombre de columna corresponde a la etiqueta.

Se hace con el siguiente código.

FEATURES = ["crim", "zn", "indus", "nox", "rm",
                 "age", "dis", "tax", "ptratio"]
LABEL = "medv"

Paso 2) Convertir los datos

Necesitas convertir las variables numƩricas al formato adecuado. TensorFlow proporciona un mƩtodo para convertir una variable continua: tf.feature_column.numeric_column().

En el paso anterior, definiste una lista de caracterƭsticas que deseas incluir en el modelo. Ahora puedes usar esta lista para convertirlas en datos numƩricos. Si deseas excluir caracterƭsticas de tu modelo, puedes eliminar una o mƔs variables de la lista FEATURES antes de construir feature_cols.

Tenga en cuenta que utilizarÔ un Python Utiliza una comprensión de listas con la lista FEATURES para crear una nueva lista llamada feature_cols. Esto te ayuda a evitar escribir tf.feature_column.numeric_column() nueve veces. Una comprensión de listas es una forma mÔs rÔpida y limpia de crear nuevas listas.

feature_cols = [tf.feature_column.numeric_column(k) for k in FEATURES]

Paso 3) Definir el estimador

En este paso, debe definir el estimador. TensorFlow proporciona seis estimadores predefinidos, tres para tareas de clasificación y tres para tareas de regresión de TensorFlow:

  • Regresor
    • DNNRegresor
    • Regresor lineal
    • DNNLinearCombinedRegressor
  • clasificar
    • Clasificador DNN
    • Clasificador lineal
    • Clasificador combinado lineal DNN

En este tutorial, utilizarÔ el regresor lineal. Para acceder a esta función, necesita utilizar tf.estimator.

La función necesita dos argumentos:

  • feature_columns: contiene las variables que se incluirĆ”n en el modelo.
  • model_dir: ruta para almacenar el grĆ”fico, guardar los parĆ”metros del modelo, etc.

TensorFlow crearÔ automÔticamente una carpeta llamada train en su directorio de trabajo. Debe usar esta ruta para acceder a ella. TensorTablero, como se muestra en el ejemplo de regresión de TensorFlow a continuación.

estimator = tf.estimator.LinearRegressor(
        feature_columns=feature_cols,
        model_dir="train")

Resultado

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train', '_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 0x1a215dc550>, '_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}

La parte complicada de TensorFlow es cómo alimentar el modelo. TensorFlow estÔ diseñado para trabajar con computación paralela y conjuntos de datos muy grandes. Debido a las limitaciones de los recursos de la mÔquina, es imposible alimentar el modelo con todos los datos a la vez. Para ello, es necesario alimentarlo por lotes cada vez. Tenga en cuenta que hablamos de conjuntos de datos enormes con millones o mÔs registros. Si no se añaden lotes, se producirÔ un error de memoria.

Por ejemplo, si sus datos contienen 100 observaciones y define un tamaño de lote de 10, significa que el modelo verÔ 10 observaciones para cada iteración (10*10).

Cuando el modelo ha procesado todos los datos, finaliza una época. Una época define cuÔntas veces se procesarÔn los datos. Es recomendable desactivar este paso y permitir que el modelo realice un número determinado de iteraciones.

Un segundo aspecto a considerar es si se desea barajar los datos antes de cada iteración. Durante el entrenamiento, es importante barajar los datos para que el modelo no aprenda un patrón específico del conjunto de datos. Si el modelo aprende los detalles del patrón subyacente, tendrÔ dificultades para generalizar la predicción a datos desconocidos. Esto se conoce como sobreajuste. El modelo funciona bien con los datos de entrenamiento, pero no puede predecir correctamente para datos desconocidos.

TensorFlow facilita estos dos pasos. Cuando los datos llegan al pipeline, sabe cuƔntas observaciones necesita (lote) y si tiene que mezclar los datos.

Para indicarle a TensorFlow cómo alimentar el modelo, puede usar pandas_input_fn. Este objeto necesita cinco parÔmetros:

  • x: datos de caracterĆ­sticas
  • y: datos de la etiqueta
  • tamaƱo_lote: lote. Por defecto 128
  • num_epoch: nĆŗmero de Ć©pocas, por defecto 1
  • Mezclar: mezclar los datos o no. Por defecto, Ninguno.

Necesitas alimentar el modelo varias veces, así que defines una función para repetir este proceso. Llama a esta función get_input_fn.

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)

El mƩtodo habitual para evaluar el desempeƱo de un modelo es:

  • Entrenar a la modelo
  • EvalĆŗe el modelo en un conjunto de datos diferente.
  • Haz una predicción

El estimador de TensorFlow proporciona tres funciones diferentes para llevar a cabo estos tres pasos fƔcilmente.

Paso 4) Entrenar a la modelo

Puedes usar el método de entrenamiento del estimador para ajustar el modelo. El estimador de entrenamiento requiere una función de entrada (input_fn) y un número de pasos. Puedes usar la función que creaste anteriormente para alimentar el modelo. Luego, le indicas al modelo que itere 1000 veces. Ten en cuenta que no especificas el número de épocas; dejas que el modelo itere 1000 veces. Si estableces el número de épocas en 1, el modelo iterarÔ cuatro veces, ya que hay 400 registros en el conjunto de entrenamiento y el tamaño del lote es 128.

  1. Filas 128
  2. Filas 128
  3. Filas 128
  4. Filas 16

Por lo tanto, es mÔs sencillo establecer el número de épocas en ninguno y definir el número de iteraciones, como se muestra en el ejemplo de clasificación de TensorFlow a continuación.

estimator.train(input_fn=get_input_fn(training_set,
                                           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/model.ckpt.
INFO:tensorflow:loss = 83729.64, step = 1
INFO:tensorflow:global_step/sec: 238.616
INFO:tensorflow:loss = 13909.657, step = 101 (0.420 sec)
INFO:tensorflow:global_step/sec: 314.293
INFO:tensorflow:loss = 12881.449, step = 201 (0.320 sec)
INFO:tensorflow:global_step/sec: 303.863
INFO:tensorflow:loss = 12391.541, step = 301 (0.327 sec)
INFO:tensorflow:global_step/sec: 308.782
INFO:tensorflow:loss = 12050.5625, step = 401 (0.326 sec)
INFO:tensorflow:global_step/sec: 244.969
INFO:tensorflow:loss = 11766.134, step = 501 (0.407 sec)
INFO:tensorflow:global_step/sec: 155.966
INFO:tensorflow:loss = 11509.922, step = 601 (0.641 sec)
INFO:tensorflow:global_step/sec: 263.256
INFO:tensorflow:loss = 11272.889, step = 701 (0.379 sec)
INFO:tensorflow:global_step/sec: 254.112
INFO:tensorflow:loss = 11051.9795, step = 801 (0.396 sec)
INFO:tensorflow:global_step/sec: 292.405
INFO:tensorflow:loss = 10845.855, step = 901 (0.341 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train/model.ckpt.
INFO:tensorflow:Loss for final step: 5925.9873.

Puedes comprobar TensorBoard con el siguiente comando:

activate hello-tf
# For MacOS
tensorboard --logdir=./train
# For Windows
tensorboard --logdir=train

Paso 5) EvalĆŗa tu modelo

Puede evaluar el ajuste de su modelo en el conjunto de prueba con el siguiente código:

ev = estimator.evaluate(
          input_fn=get_input_fn(test_set,
          num_epochs=1,
          n_batch = 128,
          shuffle=False))

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-13-01:43:13
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-13-01:43:13
INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.15896, global_step = 1000, loss = 3215.896

Puede imprimir la pérdida con el siguiente código:

loss_score = ev["loss"]
print("Loss: {0:f}".format(loss_score))

Resultado

Loss: 3215.895996

El modelo tiene una pƩrdida de 3215. Puedes consultar las estadƭsticas descriptivas para hacerte una idea de la magnitud del error.

training_set['medv'].describe()

Resultado

count    400.000000
mean      22.625500
std        9.572593
min        5.000000
25%       16.600000
50%       21.400000
75%       25.025000
max       50.000000
Name: medv, dtype: float64

Según la estadística resumida anterior, el precio promedio de una vivienda es de 22 mil, con un precio mínimo de 5 mil y un mÔximo de 50 mil. Dado que la pérdida reportada es el error cuadrÔtico medio, el error típico en las unidades originales es aproximadamente la raíz cuadrada de 32.16, lo que equivale a unos 5.7 mil dólares.

Paso 6) hacer la predicción

Finalmente, puedes utilizar el mƩtodo predict del estimador TensorFlow para estimar el valor de seis casas en Boston.

y = estimator.predict(
         input_fn=get_input_fn(prediction_set,
         num_epochs=1,
         n_batch = 128,
         shuffle=False))

Para imprimir los valores estimados, puede utilizar este código:

predictions = list(p["predictions"] for p in itertools.islice(y, 6))
print("Predictions: {}".format(str(predictions)))

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Predictions: [array([32.297546], dtype=float32), array([18.96125], dtype=float32), array([27.270979], dtype=float32), array([29.299236], dtype=float32), array([16.436684], dtype=float32), array([21.460876], dtype=float32)]

El modelo pronostica los siguientes valores:

Casa Predicción
1 32.29
2 18.96
3 27.27
4 29.29
5 16.43
6 21.46

Tenga en cuenta que desconocemos el valor real de estas seis casas. En el tutorial de aprendizaje profundo, intentarĆ” superar el modelo lineal.

Solución NumPy

Esta sección explica cómo entrenar el modelo utilizando un estimador NumPy para alimentar los datos. El método es el mismo, con la única diferencia de que se utilizarÔ el estimador numpy_input_fn.

Lee los mismos tres archivos CSV, pero conserva solo las matrices NumPy sin procesar con .values.

training_set_n = pd.read_csv("E:/boston_train.csv").values
test_set_n = pd.read_csv("E:/boston_test.csv").values
prediction_set_n = pd.read_csv("E:/boston_predict.csv").values

Paso 1) Importar los datos

En primer lugar, debes diferenciar las variables de características de las etiquetas. Esto se aplica tanto a los datos de entrenamiento como a los de evaluación. Es mÔs rÔpido definir una función para dividir los datos.

def prepare_data(df):
        X_train = df[:, :-3]
        y_train = df[:,-3]
        return X_train, y_train

Puedes usar esta función para separar la etiqueta de las características de los conjuntos de datos de entrenamiento y evaluación.

X_train, y_train = prepare_data(training_set_n)
X_test, y_test = prepare_data(test_set_n)

Debes excluir la última columna del conjunto de datos de predicción porque solo contiene valores NaN.

x_predict = prediction_set_n[:, :-2]

Confirma la forma de la matriz. Ten en cuenta que la etiqueta no debe tener una segunda dimensión, lo que significa (400,).

print(X_train.shape, y_train.shape, x_predict.shape)

Resultado

(400, 9) (400,) (6, 9)

Puede construir las columnas de caracterĆ­sticas de la siguiente manera:

feature_columns = [      tf.feature_column.numeric_column('x', shape=X_train.shape[1:])]

El estimador se define como antes: se especifican las columnas de características y dónde guardar el grÔfico.

estimator = tf.estimator.LinearRegressor(
         feature_columns=feature_columns,
         model_dir="train1")

Resultado

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'train1', '_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 0x1a218d8f28>, '_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}

Puedes usar el estimador NumPy para alimentar el modelo con los datos y luego entrenarlo. Ten en cuenta que definimos la función input_fn de antemano para facilitar la lectura.

# Train the estimator
train_input = tf.estimator.inputs.numpy_input_fn(
           x={"x": X_train},
           y=y_train,
           batch_size=128,
           shuffle=False,
           num_epochs=None)
estimator.train(input_fn = train_input,steps=5000)

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 train1/model.ckpt.
INFO:tensorflow:loss = 83729.64, step = 1
INFO:tensorflow:global_step/sec: 490.057
INFO:tensorflow:loss = 13909.656, step = 101 (0.206 sec)
INFO:tensorflow:global_step/sec: 788.986
INFO:tensorflow:loss = 12881.45, step = 201 (0.126 sec)
INFO:tensorflow:global_step/sec: 736.339
INFO:tensorflow:loss = 12391.541, step = 301 (0.136 sec)
INFO:tensorflow:global_step/sec: 383.305
INFO:tensorflow:loss = 12050.561, step = 401 (0.260 sec)
INFO:tensorflow:global_step/sec: 859.832
INFO:tensorflow:loss = 11766.133, step = 501 (0.117 sec)
INFO:tensorflow:global_step/sec: 804.394
INFO:tensorflow:loss = 11509.918, step = 601 (0.125 sec)
INFO:tensorflow:global_step/sec: 753.059
INFO:tensorflow:loss = 11272.891, step = 701 (0.134 sec)
INFO:tensorflow:global_step/sec: 402.165
INFO:tensorflow:loss = 11051.979, step = 801 (0.248 sec)
INFO:tensorflow:global_step/sec: 344.022
INFO:tensorflow:loss = 10845.854, step = 901 (0.288 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train1/model.ckpt.
INFO:tensorflow:Loss for final step: 5925.985.
Out[23]:
<tensorflow.python.estimator.canned.linear.LinearRegressor at 0x1a1b6ea860>

Para evaluar tu modelo, repites el mismo paso con una función de entrada diferente.

eval_input = tf.estimator.inputs.numpy_input_fn(
       x={"x": X_test},
       y=y_test,
       shuffle=False,
       batch_size=128,
       num_epochs=1)
   estimator.evaluate(eval_input,steps=None)

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-13-01:44:00
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-13-01:44:00
INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.158947, global_step = 1000, loss = 3215.8945
Out[24]:
{'average_loss': 32.158947, 'global_step': 1000, 'loss': 3215.8945}

Finalmente, puedes calcular la predicción. Debería ser similar al resultado de Pandas.

test_input = tf.estimator.inputs.numpy_input_fn(
        x={"x": x_predict},
        batch_size=128,
        num_epochs=1,
        shuffle=False)
        y = estimator.predict(test_input)

predictions = list(p["predictions"] for p in itertools.islice(y, 6))
print("Predictions: {}".format(str(predictions)))

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Predictions: [array([32.297546], dtype=float32), array([18.961248], dtype=float32), array([27.270979], dtype=float32), array([29.299242], dtype=float32), array([16.43668], dtype=float32), array([21.460878], dtype=float32)]

Solución de TensorFlow

La última sección estÔ dedicada a un puro TensorFlow Solución. Este método es un poco mÔs complicado que los otros dos.

Tenga en cuenta que si utiliza un Jupyter cuaderno, necesitas reiniciar y borrar el kernel para ejecutar esta sesión.

TensorFlow ha creado una excelente herramienta para pasar los datos a la canalización. En esta sección, usted mismo crearÔ la función input_fn.

Paso 1) Definir la ruta y el formato de los datos.

En primer lugar, debes declarar dos variables con la ruta de los archivos CSV. Ten en cuenta que tienes dos archivos: uno para el conjunto de entrenamiento y otro para el conjunto de prueba.

import tensorflow as tf
df_train = "E:/boston_train.csv"
df_eval = "E:/boston_test.csv"

A continuación, debes definir las columnas que deseas utilizar del archivo CSV. Usaremos todas. Después, debes declarar el tipo de cada variable.

Las variables de punto flotante se definen mediante [0.]

COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age",
                "dis", "tax", "ptratio", "medv"]
RECORDS_ALL = [[0.0], [0.0], [0.0], [0.0],[0.0],[0.0],[0.0],[0.0],[0.0],[0.0]]

Paso 2) Definir la función input_fn

La función se puede dividir en tres partes:

  1. Importar los datos
  2. Crear el iterador
  3. Consumir los datos

A continuación se muestra el código completo para definir la función. El código se explicarÔ mÔs adelante.

def input_fn(data_file, batch_size, num_epoch = None):
       # Step 1
          def parse_csv(value):
          columns = tf.decode_csv(value, record_defaults= RECORDS_ALL)
          features = dict(zip(COLUMNS, columns))
          #labels = features.pop('median_house_value')
          labels =  features.pop('medv')
          return features, labels

          # Extract lines from input files using the Dataset API.
          dataset = (tf.data.TextLineDataset(data_file) # Read text file
          .skip(1) # Skip header row
          .map(parse_csv))

          dataset = dataset.repeat(num_epoch)
          dataset = dataset.batch(batch_size)
          # Step 3
          iterator = dataset.make_one_shot_iterator()
          features, labels = iterator.get_next()
          return features, labels

Importar los datos

Para un archivo CSV, el método dataset lee una línea a la vez. Para construir el conjunto de datos, debe usar el objeto TextLineConjunto de datos. Tu conjunto de datos tiene un encabezado, así que debes usar skip(1) para omitir la primera línea. En este punto, solo lees los datos y excluyes el encabezado en la canalización. Para alimentar el modelo, debes separar las características de la etiqueta. El método utilizado para aplicar cualquier transformación a los datos es map.

Este método llama a una función que usted crearÔ para indicar cómo transformar los datos. En resumen, necesita pasar los datos a la TextLineObjeto de conjunto de datos, excluyendo el encabezado, y aplicando una transformación indicada por una función.

Code explicación

  • tf.datos.TextLineDataset(data_file): esta lĆ­nea lee el archivo CSV.
  • .skip(1): omite el encabezado
  • .map(parse_csv)): analiza los registros y los convierte en tensores.

Necesitas definir una función para dar instrucciones al objeto mapa. Puedes llamar a esta función parse_csv.

Esta función analiza el archivo CSV con el método tf.decode_csv y declara las características y la etiqueta. Las características se pueden declarar como un diccionario o una tupla. Se utiliza el método del diccionario por su mayor comodidad.

Code explicación

  • tf.decode_csv(value, record_defaults= RECORDS_ALL): el mĆ©todo decode_csv utiliza la salida del TextLineConjunto de datos para leer el archivo CSV. record_defaults le indica a TensorFlow los tipos de columna. En TensorFlow 2.x, este sĆ­mbolo se encuentra en tf.io.decode_csv.
  • dict(zip(COLUMNS, columns)): rellena el diccionario con todas las columnas, por ejemplotracted durante este procesamiento de datos
  • features.pop('medv'): excluye la variable objetivo de las variables de caracterĆ­sticas y crea una variable de etiqueta.

El conjunto de datos necesita mÔs elementos para alimentar iterativamente los tensores. De hecho, es necesario agregar el método `repeat` para que el conjunto de datos continúe alimentando el modelo indefinidamente. Si no se agrega este método, el modelo iterarÔ solo una vez y luego generarÔ un error porque no se ingresarÔn mÔs datos al proceso.

Después, puedes controlar el tamaño del lote con el método `batch`. Esto significa que le indicas al conjunto de datos cuÔntos datos quieres pasar a la canalización en cada iteración. Si estableces un tamaño de lote grande, el modelo serÔ lento.

Paso 3) Crear el iterador

Ahora estĆ” listo para el segundo paso: cree un iterador para devolver los elementos del conjunto de datos.

La forma mƔs sencilla de crear un operador es con el mƩtodo make_one_shot_iterator.

DespuƩs de eso, puede crear las funciones y etiquetas desde el iterador.

Paso 4) Consumir los datos

Puedes comprobar qué ocurre con la función input_fn. Necesitas llamar a la función en una sesión para consumir los datos. Prueba con un tamaño de lote igual a 1.

Tenga en cuenta que imprime las caracterĆ­sticas en un diccionario y la etiqueta como una matriz.

MostrarÔ la primera línea del archivo CSV. Puedes intentar ejecutar este código varias veces con diferentes tamaños de lote.

next_batch = input_fn(df_train, batch_size = 1, num_epoch = None)
with tf.Session() as sess:
     first_batch  = sess.run(next_batch)
     print(first_batch)

Resultado

({'crim': array([2.3004], dtype=float32), 'zn': array([0.], dtype=float32), 'indus': array([19.58], dtype=float32), 'nox': array([0.605], dtype=float32), 'rm': array([6.319], dtype=float32), 'age': array([96.1], dtype=float32), 'dis': array([2.1], dtype=float32), 'tax': array([403.], dtype=float32), 'ptratio': array([14.7], dtype=float32)}, array([23.8], dtype=float32))

Paso 5) Definir la columna de caracterĆ­sticas

Debes definir las columnas numƩricas de la siguiente manera:

X1= tf.feature_column.numeric_column('crim')
X2= tf.feature_column.numeric_column('zn')
X3= tf.feature_column.numeric_column('indus')
X4= tf.feature_column.numeric_column('nox')
X5= tf.feature_column.numeric_column('rm')
X6= tf.feature_column.numeric_column('age')
X7= tf.feature_column.numeric_column('dis')
X8= tf.feature_column.numeric_column('tax')
X9= tf.feature_column.numeric_column('ptratio')

Tenga en cuenta que debe combinar todas las variables en un mismo contenedor.

base_columns = [X1, X2, X3,X4, X5, X6,X7, X8, X9]

Paso 6) Construye el modelo

Puedes entrenar el modelo con el estimador LinearRegressor.

model = tf.estimator.LinearRegressor(feature_columns=base_columns, model_dir='train3')

Resultado

INFO:tensorflow:Using default config. INFO:tensorflow:Using config: {'_model_dir': 'train3', '_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 0x1820a010f0>, '_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}

Necesitas usar un función lambda para permitirte escribir los argumentos para la función input_fn. Si no utilizas una función lambda, no podrÔs entrenar el modelo.

# Train the estimator
model.train(steps =1000,
          input_fn= lambda : input_fn(df_train,batch_size=128, num_epoch = None))

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 train3/model.ckpt.
INFO:tensorflow:loss = 83729.64, step = 1
INFO:tensorflow:global_step/sec: 72.5646
INFO:tensorflow:loss = 13909.657, step = 101 (1.380 sec)
INFO:tensorflow:global_step/sec: 101.355
INFO:tensorflow:loss = 12881.449, step = 201 (0.986 sec)
INFO:tensorflow:global_step/sec: 109.293
INFO:tensorflow:loss = 12391.541, step = 301 (0.915 sec)
INFO:tensorflow:global_step/sec: 102.235
INFO:tensorflow:loss = 12050.5625, step = 401 (0.978 sec)
INFO:tensorflow:global_step/sec: 104.656
INFO:tensorflow:loss = 11766.134, step = 501 (0.956 sec)
INFO:tensorflow:global_step/sec: 106.697
INFO:tensorflow:loss = 11509.922, step = 601 (0.938 sec)
INFO:tensorflow:global_step/sec: 118.454
INFO:tensorflow:loss = 11272.889, step = 701 (0.844 sec)
INFO:tensorflow:global_step/sec: 114.947
INFO:tensorflow:loss = 11051.9795, step = 801 (0.870 sec)
INFO:tensorflow:global_step/sec: 111.484
INFO:tensorflow:loss = 10845.855, step = 901 (0.897 sec)
INFO:tensorflow:Saving checkpoints for 1000 into train3/model.ckpt.
INFO:tensorflow:Loss for final step: 5925.9873.
Out[8]:
<tensorflow.python.estimator.canned.linear.LinearRegressor at 0x18225eb8d0>

Puede evaluar el ajuste de su modelo en el conjunto de prueba con el siguiente código:

results = model.evaluate(steps =None,input_fn=lambda: input_fn(df_eval, batch_size =128, num_epoch = 1))
for key in results:
print("   {}, was: {}".format(key, results[key]))

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-05-13-02:06:02
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train3/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-05-13-02:06:02
INFO:tensorflow:Saving dict for global step 1000: average_loss = 32.15896, global_step = 1000, loss = 3215.896
   average_loss, was: 32.158958435058594
   loss, was: 3215.89599609375
   global_step, was: 1000

El último paso consiste en predecir el valor del objetivo a partir del valor de la matriz de características. Puedes crear un diccionario con los valores que deseas predecir. Tu modelo tiene nueve características, así que debes proporcionar un valor para cada una. El modelo generarÔ una predicción para cada una de ellas.

En el código siguiente, se escriben los valores de cada característica que se encuentra en el archivo CSV df_predict.

Necesitas escribir una nueva función input_fn porque no hay etiquetas en el conjunto de datos. Puedes usar la API from_tensors del objeto Dataset.

prediction_input = {
          'crim': [0.03359,5.09017,0.12650,0.05515,8.15174,0.24522],
          'zn': [75.0,0.0,25.0,33.0,0.0,0.0],
          'indus': [2.95,18.10,5.13,2.18,18.10,9.90],
          'nox': [0.428,0.713,0.453,0.472,0.700,0.544],
          'rm': [7.024,6.297,6.762,7.236,5.390,5.782],
          'age': [15.8,91.8,43.4,41.1,98.9,71.7],
          'dis': [5.4011,2.3682,7.9809,4.0220,1.7281,4.0317],
          'tax': [252,666,284,222,666,304],
          'ptratio': [18.3,20.2,19.7,18.4,20.2,18.4]
     }
     def test_input_fn():
     dataset = tf.data.Dataset.from_tensors(prediction_input)
     return dataset

     # Predict all our prediction_input
     pred_results = model.predict(input_fn=test_input_fn)

Finalmente, imprimes las predicciones.

for pred in enumerate(pred_results):
print(pred)

Resultado

INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from train3/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
(0, {'predictions': array([32.297546], dtype=float32)})
(1, {'predictions': array([18.96125], dtype=float32)})
(2, {'predictions': array([27.270979], dtype=float32)})
(3, {'predictions': array([29.299236], dtype=float32)})
(4, {'predictions': array([16.436684], dtype=float32)})
(5, {'predictions': array([21.460876], dtype=float32)})

INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train3/model.ckpt-5000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. (0, {'predictions': array([35.60663], dtype=float32)}) (1, {'predictions': array([22.298521], dtype=float32)}) (2, {'predictions': array([25.74533], dtype=float32)}) (3, {'predictions': array([35.126694], dtype=float32)}) (4, {'predictions': array([17.94416], dtype=float32)}) (5, {'predictions': array([22.606628], dtype=float32)})

Los tres métodos arrojan las mismas seis predicciones, lo que confirma que la elección entre Pandas, NumPy y un conjunto de datos nativo de TensorFlow es una cuestión de conveniencia, no de precisión.

Preguntas Frecuentes

No. TensorFlow marcó los estimadores y las columnas de características como totalmente obsoletos en la versión 2.12 y los eliminó en la versión 2.16. Instale TensorFlow 1.15 o 2.15 para ejecutar este código sin modificaciones, o bien, reescriba el modelo con capas de Keras, que es lo que ahora recomienda el equipo de TensorFlow.

Cargue los archivos CSV con pandasEscala las nueve características con una capa de normalización y luego apila una única unidad Dense(1). Compila con un optimizador y una función de pérdida de error cuadrÔtico medio, y luego llama a fit. Una unidad Dense sin activación es una regresión lineal.

Comience con un valor aproximado de 0.01 y ajústelo por múltiplos de diez. Un valor demasiado pequeño requiere muchas mÔs iteraciones para converger, mientras que un valor demasiado grande provoca oscilaciones en la pérdida. Grafique la curva de pérdida y conserve el valor mÔximo que aún permita una disminución gradual.

scikit-learn eliminó load_boston en la versión 1.2 por motivos éticos relacionados con una variable racial artificial. Este tutorial lee archivos CSV simples, por lo que el enlace de descarga sigue funcionando, pero los nuevos proyectos deberían usar los conjuntos de datos de vivienda de California o Ames.

El error cuadrÔtico medio (RMSE) restaura las unidades originales, el error absoluto medio (EAM) minimiza los valores atípicos y el coeficiente de determinación (R²) indica la proporción de la varianza explicada. Se recomienda incluir una métrica de error absoluto junto con el R², ya que un R² elevado puede ocultar errores de predicción individuales importantes.

La regresión lineal predice un número continuo, como el precio de una casa. clasificador lineal predice una etiqueta de clase discreta. Ambos ajustan una suma ponderada de las características, pero el clasificador pasa esa suma a través de un umbral de decisión.

Los pipelines automatizados evalúan las características mediante regularización Lasso, información mutua o importancia de permutación, y luego descartan las mÔs débiles. Las herramientas de AutoML buscan opciones de preprocesamiento y del modelo de forma conjunta, lo que reduce el tiempo que se dedica a seleccionar manualmente las columnas que deben incluirse en feature_cols.

Copilot genera rÔpidamente código repetitivo, incluyendo funciones de entrada, listas de columnas de características y bucles de evaluación. Considera cada sugerencia como un borrador, ya que con frecuencia incluye llamadas obsoletas a Estimator. Antes de ejecutar cada símbolo generado, compruébalo con la API actual de TensorFlow.

Resumir este post con: