Cómo utilizar el raspado web para el aprendizaje automático

Aprende a recopilar, preparar y usar datos raspados de la web para proyectos de aprendizaje automático, con consejos sobre la configuración ETL y el entrenamiento de modelos.
24 min read
How to Use Web Scraping for Machine Learning blog image

En esta guía, aprenderás:

  • ¿Qué es el aprendizaje automático?
  • Por qué el raspado web es útil para el aprendizaje automático
  • Cómo realizar el raspado web para el aprendizaje automático
  • Cómo usar el aprendizaje automático en datos raspados
  • Datos sobre el proceso de entrenamiento de modelos de aprendizaje automático con datos raspados
  • Cómo configurar los ETL al extraer datos para el aprendizaje automático

¡Vamos allá!

¿Qué es el aprendizaje automático?

El aprendizaje automático, también conocido como ML, es una subsección de la inteligencia artificial (IA) que se centra en crear sistemas capaces de aprender de los datos. En concreto, la gran revolución que supone aplicar el aprendizaje automático a los programas informáticos y a los sistemas computarizados es que no es necesario programar explícitamente los ordenadores para resolver un problema de ML. Esto se debe a que los sistemas de aprendizaje automático aprenden a partir de los datos.

¿Cómo pueden aprender las máquinas de los datos? Bien, se puede pensar que el aprendizaje automático no es más que matemáticas aplicadas. En efecto, los modelos de aprendizaje automático pueden identificar los patrones de los datos subyacentes a los que se exponen, lo que les permite hacer predicciones sobre los resultados cuando se exponen a nuevos datos de entrada.

Por qué el raspado web ayuda al aprendizaje automático

Los sistemas de aprendizaje automático (aunque, más en general, cualquier sistema de IA)necesitan datos para entrenar los modelos. Aquí es donde el raspado web se presenta como una oportunidad para los profesionales de datos.

He aquí algunas de las razones por las que el raspado web es importante para el aprendizaje automático:

  • Recopilación de datos a escala: los modelos de aprendizaje automático, especialmente los modelos de aprendizaje profundo, requieren grandes cantidades de datos para entrenarse de manera eficaz. El raspado web permite la recopilación de conjuntos de datos a gran escala que podrían no estar disponibles en otros lugares.
  • Fuentes de datos abudantes y diversas: si ya tienes datos para entrenar tus modelos de aprendizaje automático, explorar la web es una oportunidad para ampliar tus conjuntos de datos, ya que esta aloja una gran cantidad de datos.
  • Información actualizada: a veces, los datos de los que dispones no están actualizados con las últimas tendencias; aquí es donde el raspado web puede ayudarte. En efecto, en el caso de los modelos que se basan en la información más reciente (por ejemplo, la predicción del precio de las acciones, el análisis de opiniones de las noticias, etc.), el raspado web puede proporcionar fuentes de datos actualizadas.
  • Mejorar el rendimiento de los modelos: es posible que los datos que tienes nunca sean suficientes, según los modelos o el proyecto en que estés trabajando. Por ello, recuperar datos de la web mediante el raspado web es una forma de obtener más datos con el fin de mejorar el rendimiento del modelo y validarlo.
  • Análisis de mercado: la recopilación de reseñas, comentarios y valoraciones ayuda a entender la opinión de los consumidores, lo cual es muy valioso para las empresas. También puede ayudar a recopilar datos sobre temas emergentes y a pronosticar las tendencias del mercado o la opinión pública.

Requisitos previos

En este tutorial, aprenderás a realizar el raspado web para el aprendizaje automático en Python.

Para reproducir el siguiente proyecto de Python, el sistema debe cumplir los siguientes requisitos previos:

  • Python 3.6 o superior: cualquier versión de Python superior a 3.6 es válida. En concreto, instalaremos las dependencias mediante pip, que ya viene instalado con cualquier versión de Python superior a la 3.4.
  • Jupyter Notebook 6.x: usaremos un Jupyter Notebook para analizar los datos y hacer predicciones con aprendizaje automático. Cualquier versión superior a 6.x es válida.
  • Un IDEVS CODE o cualquier otro IDE de Python que elijas será válido.

Cómo realizar el raspado para el aprendizaje automático

En esta sección paso a paso, aprenderás a crear un proyecto de raspado web que recupere datos para analizarlos más a fondo con el aprendizaje automático.

En detalle, verás cómo rastrear Yahoo Finance para obtener los precios de las acciones de NVIDIA. Luego usaremos esos datos para el aprendizaje automático.

Paso 1: configura el entorno

En primer lugar, crea un repositorio (llamado, por ejemplo, scraping_project) que tenga subcarpetas denominadas datanotebooksscripts del siguiente modo:

scraping_project/
├── data/
│   └── ...
├── notebooks/
│   └── analysis.ipynb
├── scripts/
│   └── data_retrieval.py
└── venv/

Dónde:

  • data_retrieval.py contendrá tu lógica de raspado.
  • analysis.ipynb contendrá la lógica de aprendizaje automático.
  • data/ contendrá los datos raspados para analizarlos mediante el aprendizaje automático.

La carpeta venv/ contiene el entorno virtual. Puedes crearla así:

python3 -m venv venv 

Para activarlo, en Windows, ejecuta:

venv\Scripts\activate

En macOS/Linux, ejecuta:

source venv/bin/activate

Ahora puedes instalar todas las bibliotecas necesarias:

pip install selenium requests pandas matplotlib scikit-learn tensorflow notebook

Paso 2: define la página de destino

Para obtener los datos históricos de NVIDIA, tienes que ir a la siguiente URL:

https://finance.yahoo.com/quote/NVDA/history/

Sin embargo, la página presenta filtros que te permiten definir cómo quieres que se muestren los datos:

filtros que te permiten definir cómo quieres que se muestren los datos

Para recuperar datos suficientes para el aprendizaje automático, puedes filtrarlos por 5 años. Para tu comodidad, puedes usar la siguiente URL que ya filtra los datos por 5 años:

https://finance.yahoo.com/quote/NVDA/history/?frequency=1d&period1=1574082848&period2=1731931014

En esta página, debes dirigirte a la siguiente tabla y recuperar sus datos:

Tabla con datos financieros diarios como precios de apertura y cierre, mínimos, máximos y mucho más

El selector CSS que define la tabla es .table, por lo que puedes escribir el siguiente código en el archivo data_retrieval.py

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common import NoSuchElementException
import pandas as pd
import os

# Configure Selenium
driver = webdriver.Chrome(service=Service())

# Target URL
url = "https://finance.yahoo.com/quote/NVDA/history/?frequency=1d&period1=1574082848&period2=1731931014"
driver.get(url)

# Wait for the table to load
try:
    WebDriverWait(driver, 20).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, ".table"))
    )
except NoSuchElementException:
    print("The table was not found, verify the HTML structure.")
    driver.quit()
    exit()

# Locate the table and extract its rows
table = driver.find_element(By.CSS_SELECTOR, ".table")
rows = table.find_elements(By.TAG_NAME, "tr")

Hasta aquí, este código hace lo siguiente:

  • Configura una instancia del controlador Selenium Chrome
  • Define la URL de destino e indica a Selenium que la visite
  • Espera a que se cargue la tabla: en este caso, Javascript carga la tabla de destino, por lo que el controlador web espera 20 segundos para asegurarse de que la tabla está cargada
  • Intercepta toda la tabla utilizando el selector CSS específico

Paso 3: recupera los datos y guardarlos en un archivo CSV

En este punto, puedes hacer lo siguiente:

  1. Extraer los encabezados de la tabla (se adjuntarán tal cual en el archivo CSV)
  2. Recuperar todos los datos de la tabla
  3. Convertir los datos en un marco de datos Numpy

Puedes hacerlo con el siguiente código:

# Extract headers from the first row of the table
headers = [header.text for header in rows[0].find_elements(By.TAG_NAME, "th")]

# Extract data from the subsequent rows
data = []
for row in rows[1:]:
    cols = [col.text for col in row.find_elements(By.TAG_NAME, "td")]
    if cols:
        data.append(cols)

# Convert data into a pandas DataFrame
df = pd.DataFrame(data, columns=headers)

Paso 4: guarda el archivo CSV en la carpeta data/ 

Si observas la estructura de carpetas creada, recuerda que el archivo data_retrieval.py se encuentra en la carpeta scripts/.  El archivo CVS, en cambio, tiene que guardarse en la carpeta data/, por lo que debes tenerlo en cuenta en tu código:

# Determine the path to save the CSV file
current_dir = os.path.dirname(os.path.abspath(__file__))  

# Navigate to the "data/" directory
data_dir = os.path.join(current_dir, "../data") 

# Ensure the directory exists 
os.makedirs(data_dir, exist_ok=True)  

# Full path to the CSV file
csv_path = os.path.join(data_dir, "nvda_stock_data.csv")  

# Save the DataFrame to the CSV file
df.to_csv(csv_path, index=False)
print(f"Historical stock data saved to {csv_path}")

# Close the WebDriver
driver.quit()

Este código determina la ruta actual (absoluta) con el método os.path.dirname(), navega a la carpeta data/ con el método os.path.join(), se asegura de que existe con el método os.makedirs (data_dir, exist_ok=True), guarda los datos en un archivo CSV con el método df.to_csv() de la biblioteca de Pandas y, por último, cierra el controlador.

Paso 5: reúnelo todo

Este es el código completo del archivo data_retrieval.py

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common import NoSuchElementException
import pandas as pd
import os

# Configure Selenium
driver = webdriver.Chrome(service=Service())

# Target URL
url = "https://finance.yahoo.com/quote/NVDA/history/?frequency=1d&period1=1574082848&period2=1731931014"
driver.get(url)

# Wait for the table to load
try:
    WebDriverWait(driver, 5).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "table.table.yf-j5d1ld.noDl"))
    )
except NoSuchElementException:
    print("The table was not found, verify the HTML structure.")
    driver.quit()
    exit()

# Locate the table and extract its rows
table = driver.find_element(By.CSS_SELECTOR, ".table")
rows = table.find_elements(By.TAG_NAME, "tr")

# Extract headers from the first row of the table
headers = [header.text for header in rows[0].find_elements(By.TAG_NAME, "th")]

# Extract data from the subsequent rows
data = []
for row in rows[1:]:
    cols = [col.text for col in row.find_elements(By.TAG_NAME, "td")]
    if cols:
        data.append(cols)

# Convert data into a pandas DataFrame
df = pd.DataFrame(data, columns=headers)

# Determine the path to save the CSV file
current_dir = os.path.dirname(os.path.abspath(__file__))  

# Navigate to the "data/" directory
data_dir = os.path.join(current_dir, "../data") 

# Ensure the directory exists 
os.makedirs(data_dir, exist_ok=True)

# Full path to the CSV file  
csv_path = os.path.join(data_dir, "nvda_stock_data.csv")

# Save the DataFrame to the CSV file
df.to_csv(csv_path, index=False)
print(f"Historical stock data saved to {csv_path}")

# Close the WebDriver
driver.quit()

Así que, con unas pocas líneas de código, has recuperado 5 años de datos históricos sobre las acciones de NVIDIA y los guardaste en un archivo CSV.

En Windows, inicia el script anterior con:

python data_retrieval.py

O, de forma equivalente, en Linux/macOS:

python3 data_retrieval.py

A continuación se muestra cómo aparecen los datos raspados de salida:

El resultado de la tabla raspada

Uso del aprendizaje automático en datos raspados

Ahora que los datos están guardados en un archivo CSV, puedes usar el aprendizaje automático para hacer predicciones.

Veamos cómo hacerlo en los siguientes pasos.

Paso 1: crea un nuevo archivo Jupyter Notebook

Para crear un nuevo archivo Jupyter Notebook, dirígete a la carpeta notebooks/ desde la carpeta principal:

cd notebooks 

Luego, abre un Jupyter Notebook de la siguiente manera:

jupyter notebook

Cuando el navegador esté abierto, haz clic en Nuevo > Python3 (ipykernel) para crear un nuevo archivo Jupyter Notebook:

Creación de un nuevo archivo Jupyter Notebook

Cambia el nombre del archivo, por ejemplo, a analysis.ipynb.

Paso 2: abre el archivo CSV y muestra el encabezado

Ahora puedes abrir el archivo CSV que contiene los datos y mostrar el encabezado del marco de datos:

import pandas as pd

# Path to the CSV file
csv_path = "../data/nvda_stock_data.csv"

# Open the CVS file
df = pd.read_csv(csv_path)

# Show head
df.head()

Este código va a la carpeta data/ con csv_path = "../data/nvda_stock_data.csv". Luego, abre el CSV con el método pd.read_csv() como marco de datos y muestra su encabezado (las 5 primeras filas) con el método df.head().

He aquí el resultado previsto:

El resultado previsto

Paso 3: visualiza la tendencia a lo largo del tiempo del valor** Adj Close 

Ahora que el marco de datos está cargado correctamente, puedes visualizar la tendencia del valor Adj Close,  que representa el valor de cierre ajustado:

import matplotlib.pyplot as plt

# Ensure the "Date" column is in datetime forma
df["Date"] = pd.to_datetime(df["Date"])

# Sort the data by date (if not already sorted)
df = df.sort_values(by="Date")

# Plot the "Adj Close" values over time
plt.figure(figsize=(10, 6))
plt.plot(df["Date"], df["Adj Close"], label="Adj Close", linewidth=2)

# Customize the plot
plt.title("NVDA Stock Adjusted Close Prices Over Time", fontsize=16) # Sets title
plt.xlabel("Date", fontsize=12) # Sets x-axis label
plt.ylabel("Adjusted Close Price (USD)", fontsize=12) # Sets y-axis label
plt.grid(True, linestyle="--", alpha=0.6) # Defines styles of the line
plt.legend(fontsize=12) # Shows legend
plt.tight_layout()

# Show the plot
plt.show()

Este fragmento hace lo siguiente:

  • df["Date"] accede a la columna Date del marco de datos y, con el método pd.to_datetime(), se asegura de que las fechas estén en el formato de fecha
  • df.sort_values() ordena las fechas de la columna Date.  Esto garantiza que los datos se muestren en orden cronológico.
  • plt.figure() establece las dimensiones del gráfico y plt.plot() lo muestra
  • Las líneas de código del comentario # Personalizar el gráfico ayudan a personalizar el gráfico al proporcionar el título, las etiquetas de los ejes y mostrar la leyenda
  • El método plt.show() es el que permite mostrar el gráfico

El resultado previsto es algo así:

Ejemplo de precios de cierre ajustados de las acciones de NVDA a lo largo del tiempo

Este gráfico muestra la tendencia real de los valores cerrados ajustados a lo largo del tiempo de los valores de las acciones de NVIDIA. El modelo de aprendizaje automático que vas a entrenar tendrá que predecirlos de la mejor manera posible.

Paso 3: prepara los datos para el aprendizaje automático

¡Es hora de preparar los datos para el aprendizaje automático!

Primero, puedes limpiar y preparar los datos:

from sklearn.preprocessing import MinMaxScaler

# Convert data types
df["Volume"] = pd.to_numeric(df["Volume"].str.replace(",", ""), errors="coerce")
df["Open"] = pd.to_numeric(df["Open"].str.replace(",", ""), errors="coerce")

# Handle missing values 
df = df.infer_objects().interpolate() 

# Select the target variable ("Adj Close") and scale the data
scaler = MinMaxScaler(feature_range=(0, 1))  # Scale data between 0 and 1
data = scaler.fit_transform(df[["Adj Close"]])

Este código hace lo siguiente:

  • Convierte los valores Volume y Open con el método en _numeric()
  • Maneja los valores que faltan mediante la interpolación para rellenarlos con el método interpolate()
  • Escala los datos con minMaxScaler()
  • Selecciona y transforma (la escala) la variable de destino Adj Close con el método fit_transform()

Paso 4: crea los conjuntos de tren y prueba

El modelo utilizado para este tutorial es una LSTM (memoria a largo y corto plazo), que es una RNN (red neuronal recurrente), así que se crea una secuencia de pasos que le permita aprender los datos:

import numpy as np

# Create sequences of 60 time steps for prediction
sequence_length = 60
X, y = [], []

for i in range(sequence_length, len(data)):
    X.append(data[i - sequence_length:i, 0])  # Last 60 days
    y.append(data[i, 0])  # Target value

X, y = np.array(X), np.array(y)

# Split into training and test sets
split_index = int(len(X) * 0.8)  # 80% training, 20% testing
X_train, X_test = X[:split_index], X[split_index:]
y_train, y_test = y[:split_index], y[split_index:]

Este código:

  • Crea una secuencia de 60 pasos de tiempo. X es la matriz de las características, mientras que y es la matriz del valor de destino
  • Divide el marco de datos inicial de la siguiente manera: el 80 % se convierte en el conjunto de entrenamiento y el 20 % en el conjunto de pruebas

Paso 5: entrena al modelo

Ya puedes entrenar a la RNN en el conjunto de entrenamiento:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM

# Reshape X for LSTM [samples, time steps, features]
X_train = X_train.reshape((X_train.shape[0], X_train.shape[1], 1))
X_test = X_test.reshape((X_test.shape[0], X_test.shape[1], 1))

# Build the Sequential Neural Network
model = Sequential()
model.add(LSTM(32, activation="relu", return_sequences=False))
model.add(Dense(1))
model.compile(loss="mean_squared_error", optimizer="adam")

# Train the Model
history = model.fit(X_train, y_train, epochs=20, batch_size=32, validation_data=(X_test, y_test), verbose=1)

Este código hace lo siguiente:

  • Vuelve a dibujar la matriz de características para que estén listas para la red neuronal LSTM mediante el método reshape(), tanto para el conjunto de entrenamiento como para el de pruebas
  • Construye la red neuronal LSTM mediante el establecimiento de sus parámetros
  • Ajusta la LSTM al conjunto de entrenamiento mediante el método fit()

Por tanto, el modelo ya se ha ajustado al conjunto de entrenamiento y está listo para hacer predicciones.

Paso 6: haz predicciones y evalúa el rendimiento del modelo

El modelo ya está listo para predecir los valores de Adj Close y puedes evaluar su rendimiento de la siguiente manera:

from sklearn.metrics import mean_squared_error, r2_score

# Make Predictions
y_pred = model.predict(X_test)

# Inverse scale predictions and actual values for comparison
y_test = scaler.inverse_transform(y_test.reshape(-1, 1))
y_pred = scaler.inverse_transform(y_pred)

# Evaluate the Model
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

# print results
print("\nLSTM Neural Network Results:")
print(f"Mean Squared Error: {mse:.2f}")
print(f"R-squared Score: {r2:.2f}")

Este código hace lo siguiente:

  • Invierte los valores del eje horizontal para que los datos puedan presentarse últimamente en orden cronológico. Esto se hace con el método inverse_transform().
  • Evalúa el modelo utilizando el error cuadrático medio  y la puntuación R^2.

Teniendo en cuenta los errores estadísticos que pueden producirse debido a la naturaleza estocástica de los modelos de aprendizaje automático, el resultado previsto es algo así:

Resultado previsto teniendo en cuenta los errores estadísticos

Estos valores son bastante buenos, lo que indica que el modelo elegido es bueno para predecir el Adj Closedadas sus características.

Paso 7: compara los valores reales con los pronosticados con un gráfico

En lo que respecta al aprendizaje automático, a veces no basta con comparar los resultados analíticamente, como hicimos en el paso anterior. Para aumentar las probabilidades de que el modelo elegido sea bueno, una solución típica es crear también un gráfico.

Por ejemplo, una solución común es crear un gráfico que compare los valores reales de Adj Close con los pronosticados por el modelo LSTM:

# Visualize the Results
test_results = pd.DataFrame({
    "Date": df["Date"].iloc[len(df) - len(y_test):],  # Test set dates
    "Actual": y_test.flatten(),
    "Predicted": y_pred.flatten()
})

# Setting plot
plt.figure(figsize=(12, 6))
plt.plot(test_results["Date"], test_results["Actual"], label="Actual Adjusted Close", color="blue", linewidth=2)
plt.plot(test_results["Date"], test_results["Predicted"], label="Predicted Adjusted Close", color="orange", linestyle="--", linewidth=2)
plt.title("Actual vs Predicted Adjusted Close Prices (LSTM)", fontsize=16)
plt.xlabel("Date", fontsize=12)
plt.ylabel("Adjusted Close Price (USD)", fontsize=12)
plt.legend()
plt.grid(alpha=0.6)
plt.tight_layout()
plt.show()

Este código:

  • Establece la comparación de los valores reales y pronosticados en el nivel del conjunto de pruebas, por lo que los valores reales deben recortarse a la forma que tiene el conjunto de pruebas. Esto se hace con los métodos iloc() y flatten().
  • Crea el gráfico, añade etiquetas a los ejes y el título y gestiona otros ajustes para mejorar la visualización.

El resultado previsto es algo parecido a esto:

Precios de cierre ajustados reales frente a precios ajustados previstos

Como muestra el gráfico, los valores pronosticados por la red neuronal LSTM (línea punteada amarilla) predicen bastante bien los valores reales (línea azul continua). Esto era respetable, ya que los resultados analíticos fueron buenos, pero el gráfico sin duda ayuda a visualizar que el resultado es realmente bueno.

Paso 8: reúnelo todo

Este es el código completo del notebook analysis.ipynb

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error, r2_score
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM

# Path to the CSV file
csv_path = "../data/nvda_stock_data.csv"  
# Open CSV as data frame
df = pd.read_csv(csv_path)

# Convert "Date" to datetime format
df["Date"] = pd.to_datetime(df["Date"])

# Sort by date
df = df.sort_values(by="Date")

# Convert data types
df["Volume"] = pd.to_numeric(df["Volume"].str.replace(",", ""), errors="coerce")
df["Open"] = pd.to_numeric(df["Open"].str.replace(",", ""), errors="coerce")

# Handle missing values 
df = df.infer_objects().interpolate()

# Select the target variable ("Adj Close") and scale the data
scaler = MinMaxScaler(feature_range=(0, 1))  # Scale data between 0 and 1
data = scaler.fit_transform(df[["Adj Close"]])

# Prepare the Data for LSTM
# Create sequences of 60 time steps for prediction
sequence_length = 60
X, y = [], []

for i in range(sequence_length, len(data)):
    X.append(data[i - sequence_length:i, 0])  # Last 60 days
    y.append(data[i, 0])  # Target value

X, y = np.array(X), np.array(y)

# Split into training and test sets
split_index = int(len(X) * 0.8)  # 80% training, 20% testing
X_train, X_test = X[:split_index], X[split_index:]
y_train, y_test = y[:split_index], y[split_index:]

# Reshape X for LSTM [samples, time steps, features]
X_train = X_train.reshape((X_train.shape[0], X_train.shape[1], 1))
X_test = X_test.reshape((X_test.shape[0], X_test.shape[1], 1))

# Build the Sequential Neural Network
model = Sequential()
model.add(LSTM(32, activation="relu", return_sequences=False))
model.add(Dense(1))
model.compile(loss="mean_squared_error", optimizer="adam")

# Train the Model
history = model.fit(X_train, y_train, epochs=20, batch_size=32, validation_data=(X_test, y_test), verbose=1)

# Make Predictions
y_pred = model.predict(X_test)

# Inverse scale predictions and actual values for comparison
y_test = scaler.inverse_transform(y_test.reshape(-1, 1))
y_pred = scaler.inverse_transform(y_pred)

# Evaluate the Model
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

# Print results
print("\nLSTM Neural Network Results:")
print(f"Mean Squared Error: {mse:.2f}")
print(f"R-squared Score: {r2:.2f}")

# Visualize the Results
test_results = pd.DataFrame({
    "Date": df["Date"].iloc[len(df) - len(y_test):],  # Test set dates
    "Actual": y_test.flatten(),
    "Predicted": y_pred.flatten()
})

# Setting plot
plt.figure(figsize=(12, 6))
plt.plot(test_results["Date"], test_results["Actual"], label="Actual Adjusted Close", color="blue", linewidth=2)
plt.plot(test_results["Date"], test_results["Predicted"], label="Predicted Adjusted Close", color="orange", linestyle="--", linewidth=2)
plt.title("Actual vs Predicted Adjusted Close Prices (LSTM)", fontsize=16)
plt.xlabel("Date", fontsize=12)
plt.ylabel("Adjusted Close Price (USD)", fontsize=12)
plt.legend()
plt.grid(alpha=0.6)
plt.tight_layout()
plt.show()

Todo este código va directamente a la meta, omitiendo las partes que muestran el encabezado del marco de datos al abrirlo y trazando solo los valores reales de Adj Close. 

Estos pasos se detallaron al principio de este párrafo como parte del análisis preliminar de los datos y ayudan a entender lo que se está haciendo con los datos antes de empezar a entrenar un modelo de aprendizaje automático.

NOTA: el código se ha presentado pieza por pieza, pero, teniendo en cuenta la naturaleza estocástica del ML, se aconseja ejecutar el código completo para entrenar y validar adecuadamente el modelo LSTM. De lo contrario, el gráfico final resultante puede ser muy diferente.

Notas sobre el proceso de entrenamiento de modelos de aprendizaje automático con datos raspados

En aras de la simplicidad, la guía paso a paso que se proporciona en este artículo trata directamente sobre la adaptación de una red neuronal LSTM.

En realidad, no es lo que ocurre con los modelos de aprendizaje automático. Por tanto, cuando se intenta resolver un problema que necesita un modelo de aprendizaje automático, el proceso es el siguiente:

  • Análisis preliminar de datos: es la parte más importante del proceso porque es donde se comprenden los datos que se tienen, se limpian los datos eliminando los valores de NaN, se gestionan los posibles duplicados y se resuelven otros problemas matemáticos relacionados con los datos que se tienen.
  • Entrenamiento de modelos de aprendizaje automático: nunca se sabe si el primer modelo que tienes en mente será el mejor para resolver el problema al que te enfrentas con el aprendizaje automático. Una solución típica es realizar la denominada comprobación puntual, lo que implica:
    • Entrenar de 3 a 4 modelos de aprendizaje automático en el conjunto de entrenamiento y evalúar su rendimiento en dicho conjunto.
    • Conseguir los 2 o 3 modelos de aprendizaje automático que mejor funcionen en el conjunto de entrenamiento y ajustar sus hiperparámetros.
    • Comparar el rendimiento de los mejores modelos con hiperparámetros ajustados en el conjunto de prueba.
    • Elegir el que mejor funcione en el conjunto de pruebas.
  • Despliegue: el modelo que mejor funciona es, por tanto, el que se implementará en producción.

Configuración de ETL al extraer datos para el aprendizaje automático

Al principio de este artículo, definimos por qué el raspado web ayuda en el aprendizaje automático. Sin embargo, es posible que hayas advertido una incoherencia en el proyecto desarrollado que se basa en que los datos recuperados mediante el raspado web se han guardado en un archivo CSV.

Es una práctica habitual en el aprendizaje automático, pero ten en cuenta que es mejor hacerlo al principio de un proyecto de aprendizaje automático, cuando el propósito es encontrar el mejor modelo que pueda predecir los valores futuros de los valores de destino.

Cuando se encuentra el mejor modelo, la práctica subsiguiente consiste en establecer un canal de ETL (extracción, transformación y carga) para recuperar nuevos datos de la web, limpiarlos y cargarlos en una base de datos.

El proceso puede ser algo así:

  • Extracción: esta fase recupera los datos de varias fuentes, incluida la web, mediante el raspado
  • Transformación: los datos recopilados se someten al proceso de limpieza y preparación
  • Carga: los datos recuperados y transformados se procesan y guardan en una base de datos o un almacén de datos

Una vez almacenados los datos, la fase siguiente proporciona la integración con los flujos de trabajo de aprendizaje automático que, entre otras cosas, vuelven a entrenar el modelo con datos nuevos y lo vuelven a validar.

Conclusión

En este artículo, hemos visto cómo recuperar datos de la web mediante el raspado y cómo utilizarlos para fines de aprendizaje automático. También hemos presentado la importancia del raspado web para el aprendizaje automático y hemos analizado el proceso de formación y estructuración de los ETL.

Aunque el proyecto propuesto es sencillo, es comprensible que los procesos subyacentes, especialmente, los relacionados con la estructuración de ETL para recuperar datos de la web de forma continua con el fin de mejorar el modelo de aprendizaje automático, introduzcan complejidades que deberían analizarse con mayor detenimiento.

Raspar Yahoo Finance en escenarios del mundo real puede resultar mucho más complejo de lo que se ha mostrado aquí. El sitio emplea tecnologías antiraspado que requieren atención especial. Si buscas una solución profesional, completa y todo en uno, ¡echa un vistazo a Yahoo Finance Scraper de Bright Data!

Si el raspado no es tu punto fuerte, pero necesitas datos para proyectos de aprendizaje automático, explora nuestras soluciones para lograr una recuperación de datos eficiente y adaptadas a las necesidades de inteligencia artificial y aprendizaje automático.

Crea una cuenta gratuita de Bright Data hoy mismo para probar nuestras API de rastreo o explorar nuestros conjuntos de datos.

No se requiere tarjeta de crédito