Python & Data Science

Por qué falla tu modelo KNN en alta dimensionalidad: Entendiendo la maldición de la dimensionalidad

Imagina encontrar a un vecino en tu calle. Caminas unas cuantas casas y ahí está. Ahora imagina encontrar a ese mismo vecino en un rascacielos con mil millones de habitaciones. Incluso con miles de personas adentro, las probabilidades de que alguien esté en la habitación justo al lado de la tuya caen a casi cero. Para Sam en HomeMatch, esa es exactamente la trampa: cada nueva característica que añade a su modelo de vendibilidad de 30 días hace que el “vecino más cercano” para cada listado sea un poco menos significativo.

La última vez, Sam vio cómo las Máquinas de Vectores de Soporte construyen amplias autopistas para separar los datos. Entonces, ¿qué sucede con un enfoque más sencillo como K-Vecinos más Cercanos (KNN), cuando seguimos amontonando más características?

Podrías pensar que más características —estatura, peso, color de ojos, comida favorita, código postal— facilitarían encontrar una coincidencia. En la ciencia de datos, suele ocurrir lo contrario. Esta es la “Maldición de la Dimensionalidad”.

1. El problema de los ingredientes de pizza

Piensa en encontrar un vecino en una línea 1D. Coloca 10 puntos en una cuerda de 10 pulgadas, y es seguro que alguien estará cerca. Ahora pasa a un cuadrado 2D — como una pizza. Esos mismos 10 puntos empiezan a sentirse más separados. En un cubo 3D, deambulan en un enorme espacio vacío.

A medida que añadimos dimensiones, el espacio para que las cosas se escondan crece exponencialmente. Entonces, ¿qué le pasa a la distancia del vecino más cercano a medida que añadimos dimensiones? Comprobémoslo en Python.

import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdist

def average_nearest_neighbor_distance(dims, n_points=100):
    # Create 100 random points in a unit hypercube of 'dims' dimensions
    points = np.random.rand(n_points, dims)
    # Calculate distances between all points
    distances = cdist(points, points)
    # Set diagonal to infinity so we don't pick ourselves as the neighbor
    np.fill_diagonal(distances, np.inf)
    # Return the average distance to the closest neighbor
    return np.mean(np.min(distances, axis=1))

dimensions = range(1, 101, 5)
avg_distances = [average_nearest_neighbor_distance(d) for d in dimensions]

plt.plot(dimensions, avg_distances, marker='o')
plt.xlabel("Number of Features (Dimensions)")
plt.ylabel("Avg Distance to Nearest Neighbor")
plt.title("The Neighborhood Gets Lonely Fast")
plt.show()

print(f"Distance in 1D: {avg_distances[0]:.4f}")
print(f"Distance in 100D: {avg_distances[-1]:.4f}")
  • np.random.rand(n_points, dims) genera 100 puntos aleatorios distribuidos uniformemente en un hipercubo unitario de dims dimensiones (cada coordenada entre 0 y 1) — a medida que dims aumenta, los puntos se separan más porque el volumen del hipercubo crece exponencialmente con cada nueva dimensión.
  • cdist(points, points) calcula la matriz de distancias por pares completa entre todos los 100 puntos — el resultado es un arreglo de 100×100 donde la entrada [i, j] es la distancia euclidiana desde el punto i hasta el punto j.
  • np.fill_diagonal(distances, np.inf) establece la diagonal (la distancia de cada punto a sí mismo) en infinito — sin esto, el vecino más cercano de cada punto sería él mismo a una distancia de 0, lo que anularía el propósito del experimento.
  • np.min(distances, axis=1) encuentra el valor más pequeño en cada fila — esa es la distancia de cada punto a su vecino más cercano.
  • np.mean(...) promedia esas distancias mínimas entre todos los 100 puntos — este único número es la métrica que rastreamos a medida que las dimensiones aumentan de 1 a 100.
  • dimensions = range(1, 101, 5) produce conteos de dimensiones 1, 6, 11, …, 96 — avanzar de 5 en 5 da una tendencia suave sin ejecutar los 100 valores individuales.
  • plt.plot(dimensions, avg_distances, marker='o') grafica la tendencia con marcadores circulares — la curva asciende abruptamente, confirmando visualmente que incluso tu vecino más cercano se aleja a medida que las dimensiones se acumulan.
  • print(f"Distance in 1D: {avg_distances[0]:.4f}") imprime el promedio en 1D — este debería ser un número pequeño (alrededor de 0.01), confirmando que en 1D los vecinos están genuinamente cerca.
  • print(f"Distance in 100D: {avg_distances[-1]:.4f}") imprime el valor de ~100 dimensiones — este debería acercarse al máximo teórico (cercano a 1.0 en un hipercubo unitario), mostrando que incluso tu vecino ‘más cercano’ está casi tan lejos como lo permite todo el espacio.

Lo que esto significa en la práctica: en 1D, tu vecino estaba justo al lado — a quizás 0.01 unidades de distancia. Al llegar a 100 dimensiones, tu vecino más cercano está a casi 1.0 unidades de distancia. Ese es el ancho completo de nuestro espacio de búsqueda. Todos se han convertido en extraños.

2. ¿Qué hace realmente KNN?

KNN es el algoritmo “social”. Asume que las cosas que están cerca son similares. ¿Quieres saber si una casa es “Roja” o “Azul” (como nuestro ejemplo del capítulo de SVM)? KNN observa las KK casas más cercanas y hace una votación.

El problema: KNN depende completamente de que el vecindario sea representativo. Un vecindario vacío, o un vecino “más cercano” a millas de distancia, y la lógica se rompe. Aquí hay un KNN estándar en un conjunto de datos simple de 2 características.

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import make_blobs

# Create a simple 2D dataset
X, y = make_blobs(n_samples=100, centers=2, random_state=42, cluster_std=1.5)

# Train KNN with 3 neighbors
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X, y)

# Predict for a new point
new_point = [[0, 0]]
prediction = knn.predict(new_point)
print(f"Prediction for point at (0,0): {prediction[0]} (0=Blue, 1=Red)")
  • from sklearn.neighbors import KNeighborsClassifier importa el clasificador KNN de scikit-learn — este es el “lazy learner” que almacena todos los datos de entrenamiento y pospone el cálculo hasta el momento de la predicción.
  • make_blobs(n_samples=100, centers=2, random_state=42, cluster_std=1.5) crea 100 puntos en 2 clusters con desviación estándar 1.5 — random_state=42 garantiza la reproducibilidad; el cluster_std moderado significa que los clusters se superponen ligeramente pero siguen siendo distinguibles, lo cual es el punto ideal donde KNN funciona bien.
  • KNeighborsClassifier(n_neighbors=3) crea un KNN que observa los 3 puntos de entrenamiento más cercanos — la clase predicha es el voto por mayoría entre esos 3 vecinos.
  • knn.fit(X, y) “entrena” el modelo — para KNN, este paso simplemente almacena los datos de entrenamiento; no se aprenden pesos hasta que se llama a predict, por eso KNN se llama un “lazy learner” (no ocurre ningún aprendizaje en el momento del fit).
  • new_point = [[0, 0]] define un único punto de consulta en el origen — el modelo medirá la distancia Euclidiana desde (0, 0) a todos los 100 puntos de entrenamiento, seleccionará los 3 más cercanos y hará una votación por mayoría.
  • knn.predict(new_point) retorna la etiqueta predicha — prediction[0] extrae el valor escalar del arreglo retornado para que pueda imprimirse.

En 2D, esto funciona bien — los puntos están agrupados estrechamente. Pero añade más características, y la “cercanía” se convierte en una mentira.

3. El fenómeno del ‘espacio vacío’

Aquí está la parte complicada: en dimensiones altas, la mayoría de los puntos de datos terminan en las esquinas o en la ‘corteza’ externa del espacio. El centro queda vacío.

Piensa en una naranja. En 3D, la mayor parte de la naranja es fruta, con una cáscara delgada. Pero en 100 dimensiones, esa ‘naranja matemática’ es aproximadamente 99% cáscara y 1% fruta. Si tus datos son la fruta, están todos pegados contra los bordes.

def volume_ratio(dims):
    # Ratio of a slightly smaller inner cube to the full unit cube
    inner_edge = 0.9
    return (inner_edge ** dims)

dimensions = [1, 2, 5, 10, 50, 100]
for d in dimensions:
    ratio = volume_ratio(d)
    print(f"In {d}D, the 'center' holds {ratio*100:.2f}% of the volume.")
  • inner_edge = 0.9 define la longitud del borde del “cubo interior” — imagina recortar 5% de cada lado del cubo unitario, dejando un cubo más pequeño de borde 0.9 en el centro; la región entre el cubo interior y el límite exterior es la “cáscara”.
  • inner_edge ** dims calcula la proporción de volumen — en dims dimensiones, el volumen de un hipercubo es edge^dims, por lo que la proporción del cubo interior respecto al cubo completo es 0.9^dims; esto se reduce exponencialmente porque cada nueva dimensión multiplica la proporción por otro 0.9.
  • dimensions = [1, 2, 5, 10, 50, 100] muestrea un rango de números de dimensiones — desde 1D hasta 100D, mostrando el colapso dramático del 90% hasta prácticamente 0%.
  • print(f"In {d}D, the 'center' holds {ratio*100:.2f}% of the volume.") formatea la proporción como un porcentaje — en 1D el centro contiene 90%, en 2D es 81%, para 10D es menos de 35%, y para 100D se redondea a 0.00%, demostrando visualmente el fenómeno del “centro vacío”.

Para 100 dimensiones, el centro contiene 0.00% del volumen. Tus puntos de datos están muy separados entre sí. Así que cuando KNN busca un vecino, tiene que cruzar mucho espacio vacío.

4. Veamos qué pasa con las matemáticas

La fórmula de la distancia euclidiana —nuestra medida de ‘cercanía’— pierde su contraste en altas dimensiones. En 2D, hay una clara diferencia entre tu mejor amigo a una pulgada de distancia y un extraño a diez millas de distancia.

En 100D, las matemáticas se comportan de manera diferente. Tu amigo ‘más cercano’ podría estar a 10.1 millas de distancia mientras que tu enemigo ‘más lejano’ está a 10.2. Si todos están aproximadamente a la misma distancia, ¿cómo eliges a un vecino ‘más cercano’? La señal se ahoga en el ruido de demasiadas características.

# Comparing distance distributions
def plot_dist_ratio(dims):
    points = np.random.rand(500, dims)
    dists = cdist(points, points).flatten()
    dists = dists[dists > 0] # Ignore distance to self
    plt.hist(dists, bins=50, alpha=0.5, label=f"{dims}D")

plt.figure(figsize=(10, 6))
plot_dist_ratio(2)
plot_dist_ratio(100)
plt.legend()
plt.title("Distance Concentration: Everyone becomes equally far away")
plt.xlabel("Distance")
plt.show()
  • points = np.random.rand(500, dims) genera 500 puntos aleatorios en dims dimensiones — usamos 500 puntos (más que los 100 del experimento anterior) para que los histogramas sean más suaves y el efecto de concentración sea más evidente visualmente.
  • cdist(points, points).flatten() calcula la matriz de distancias por pares completa de 500×500 y la aplana en un arreglo 1D de 250,000 valores — esto incluye todas las distancias por pares, no solo las distancias de los vecinos más cercanos, por lo que podemos ver toda la distribución.
  • dists[dists > 0] filtra las auto-distancias cero — las entradas diagonales (donde la distancia de un punto a sí mismo es exactamente 0) crearían un pico engañoso en 0 en el histograma; esta máscara las elimina.
  • plt.hist(dists, bins=50, alpha=0.5, label=f"{dims}D") dibuja un histograma con 50 bins y 50% de transparencia — alpha=0.5 permite que tanto el histograma 2D como el de 100D sean visibles al superponerse en los mismos ejes.
  • plot_dist_ratio(2) y plot_dist_ratio(100) generan los dos histogramas superpuestos — el histograma 2D será amplio y disperso (las distancias varían mucho, por lo que la “cercanía” es significativa), mientras que el histograma 100D será un pico alto y estrecho (todas las distancias convergen casi al mismo valor, haciendo que la “cercanía” no tenga sentido).
  • plt.legend() añade una leyenda que distingue las curvas 2D y 100D — el contraste visual entre la dispersión amplia de 2D y el pico estrecho de 100D es la conclusión clave de todo el artículo.

La maldición de la dimensionalidad: concentración de distancias y colapso del volumen

La distancia euclidiana entre dos puntos en dd dimensiones:

d(x,y)=i=1d(xiyi)2d(\mathbf{x}, \mathbf{y}) = \sqrt{\sum_{i=1}^{d} (x_i - y_i)^2}

A medida que dd crece, la distancia media por pares crece proporcionalmente a d\sqrt{d}, pero su dispersión relativa se reduce — por lo que todas las distancias convergen hacia el mismo valor:

dmaxdmindmind0(distance concentration)\frac{d_{\max} - d_{\min}}{d_{\min}} \xrightarrow{d \to \infty} 0 \qquad \text{(distance concentration)}

Mientras tanto, la fracción de volumen en el “centro” del hipercubo colapsa exponencialmente:

volume ratio=(inner edgefull edge)d=0.9dd0\text{volume ratio} = \left(\frac{\text{inner edge}}{\text{full edge}}\right)^{d} = 0.9^{d} \xrightarrow{d \to \infty} 0

Inglés sencilloSímbolo estadísticoEquivalente en Python
Distancia euclidiana en dd dimensionesd(x,y)=i=1d(xiyi)2d(\mathbf{x}, \mathbf{y}) = \sqrt{\sum_{i=1}^{d} (x_i - y_i)^2}cdist(points, points)
Número de dimensiones (características)dddims en average_nearest_neighbor_distance(dims)
Proporción de volumen interior respecto al total0.9d0.9^{d}inner_edge ** dims en volume_ratio(dims)
Contraste relativo de distancias (0\to 0 significa que todas las distancias son iguales)dmaxdmindmin\frac{d_{\max} - d_{\min}}{d_{\min}}(implícito — visualizado mediante plt.hist)
Distancia media por pares (crece como d\sqrt{d})E[d]dE[d] \propto \sqrt{d}np.mean(np.min(distances, axis=1))

El histograma 100D es un pico alto y estrecho—casi cada par de puntos se encuentra a exactamente la misma distancia. En ese punto, el modelo básicamente está adivinando.

5. La solución: Selección de características y PCA

Entonces, ¿qué hacemos? Seamos selectivos. Más datos no siempre son mejores datos. La reducción de dimensionalidad vuelve a acercar a esos vecinos.

El objetivo es encontrar el ‘manifold’—el espacio más pequeño y de menor dimensión donde realmente viven los datos. Así es como el Análisis de Componentes Principales (PCA) ayuda a un modelo KNN con problemas.

from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# Create a dataset with 2 useful features and 98 noise features
X_useful, y = make_blobs(n_samples=500, centers=2, n_features=2, random_state=42)
X_noise = np.random.rand(500, 98)
X_high_dim = np.hstack([X_useful, X_noise])

X_train, X_test, y_train, y_test = train_test_split(X_high_dim, y, test_size=0.2)

# KNN on high-dimensional noisy data
knn_noisy = KNeighborsClassifier(n_neighbors=5)
knn_noisy.fit(X_train, y_train)
pred_noisy = knn_noisy.predict(X_test)

# KNN after PCA (reducing 100 dimensions to 2)
pca = PCA(n_components=2)
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)

knn_pca = KNeighborsClassifier(n_neighbors=5)
knn_pca.fit(X_train_pca, y_train)
pred_pca = knn_pca.predict(X_test_pca)

print(f"Accuracy with 100 features: {accuracy_score(y_test, pred_noisy):.2f}")
print(f"Accuracy after PCA (2 features): {accuracy_score(y_test, pred_pca):.2f}")
  • make_blobs(n_samples=500, centers=2, n_features=2, random_state=42) crea 500 puntos con solo 2 características significativas — estas 2 características contienen la señal real que separa las clases; el resto será puro ruido.
  • X_noise = np.random.rand(500, 98) genera 98 columnas de ruido aleatorio puro — estas características no tienen relación con las etiquetas; son las “habitaciones vacías” en el rascacielos que ahogan la señal.
  • X_high_dim = np.hstack([X_useful, X_noise]) apila horizontalmente las 2 características útiles con las 98 columnas de ruido — produciendo un conjunto de datos de 100 características donde solo 2 dimensiones importan, simulando lo que sucede cuando Sam mete todos los atributos de listado disponibles en el modelo.
  • train_test_split(X_high_dim, y, test_size=0.2) divide 80/20 en entrenamiento y prueba — 400 puntos de entrenamiento, 100 puntos de prueba, todos con las mismas 100 características.
  • KNeighborsClassifier(n_neighbors=5) con 100 características tendrá dificultades — en 100D, los 5 vecinos más cercanos son esencialmente aleatorios porque todas las distancias son casi iguales.
  • pca = PCA(n_components=2) crea un objeto PCA que proyectará los datos de 100 dimensiones en las 2 direcciones de máxima varianza — idealmente recuperando las 2 dimensiones útiles y descartando las 98 dimensiones de ruido.
  • pca.fit_transform(X_train) ajusta el PCA en los datos de entrenamiento y los transforma en un solo paso — los componentes del PCA se aprenden solo del conjunto de entrenamiento; llamar a fit_transform en los datos de entrenamiento asegura que la proyección no esté influenciada por los datos de prueba (sin fuga de datos).
  • pca.transform(X_test) aplica la misma proyección al conjunto de prueba — ten en cuenta que usamos transform (no fit_transform) para que los datos de prueba se proyecten sobre los mismos componentes aprendidos del conjunto de entrenamiento.
  • accuracy_score(y_test, pred_noisy) y accuracy_score(y_test, pred_pca) comparan ambos enfoques — la versión con PCA debería recuperar la mayor parte de la señal al colapsar el ruido, mientras que el KNN en 100D sin procesar se degradará porque las características de ruido abruman la métrica de distancia.

El modelo ingenuo probablemente se equivocaba por un margen significativo—a menudo con una precisión 10-20% menor. Usando PCA, eliminamos las 98 dimensiones de ‘espacio vacío’ y ruido. Ahora KNN podía centrarse en las 2 dimensiones donde existían los verdaderos ‘vecindarios’.

Cuando KNN se degrada en altas dimensiones, Sam tiene tres estrategias principales — cada una con diferentes compensaciones:

La reducción de dimensionalidad (PCA) proyecta los datos en menos ejes de máxima varianza, colapsando las dimensiones de ruido en un subespacio compacto donde las distancias recuperan su significado. Es no supervisado (no mira las etiquetas) y rápido, pero asume que las direcciones de máxima varianza también son las direcciones que contienen la señal discriminante de clases — lo cual no siempre es cierto. Si las 98 características de ruido tienen una varianza mayor que las 2 útiles, PCA conservará el ruido y descartará la señal.

La selección de características (conservar solo las más informativas) es más directa — usa pruebas estadísticas, información mutua o importancia basada en modelos para identificar qué características importan realmente, y luego descarta el resto. Es interpretable (sabes exactamente qué características sobrevivieron) y preserva los significados originales de las características, pero requiere más ajuste manual y puede pasar por alto interacciones que solo importan en combinación.

Cambiar a modelos basados en árboles (Random Forest, Gradient Boosting) evita por completo el problema de la distancia. Los árboles se dividen según los valores de características individuales, no en distancias entre puntos, por lo que son inmunes al efecto de concentración de distancias de la maldición de la dimensionalidad. Manejan tipos de características mixtas de forma nativa y escalan mejor a datos tabulares de alta dimensión — pero sacrifican la lógica intuitiva de “listados similares obtienen predicciones similares” que hizo que KNN fuera atractivo en primer lugar.

CriterioPCA + KNNSelección de características + KNNModelo basado en árboles
¿Preserva distancias?Sí (en el espacio reducido)Sí (en las características seleccionadas)No (usa divisiones, no distancias)
¿Maneja ruido correlacionado?Riesgoso (puede conservar ruido de alta varianza)Mejor (puede descartar el ruido por nombre)El mejor (los árboles ignoran características inútiles)
InterpretabilidadModerada (los componentes principales son difíciles de nombrar)Alta (sabes qué características sobreviven)Moderada (importancia de características disponible)
Nivel de esfuerzoBajo (una llamada a PCA)Medio (requiere estrategia de selección)Bajo (simplemente cambia el modelo)
Mejor para Sam cuandoEl ruido es de baja varianza, la señal se distribuye en muchas característicasUnas pocas características claramente importan y el resto es ruidoMuchas características importan, tipos mixtos, las interacciones son complejas

Regla general para el problema HomeMatch de Sam: Comienza con la selección de características si Sam sabe qué características deberían importar para la vendibilidad — es la solución más transparente. Si la señal se distribuye en muchas características correlacionadas y él no puede elegirlas fácilmente a mano, el PCA es el siguiente paso. Si ninguno funciona porque los datos son simplemente demasiado desordenados y de alta dimensión, cambia a un ensamble de árboles — que es hacia donde Sam ya se dirigía en P04 y P06.

6. Resumen: Guía de supervivencia para altas dimensiones

A medida que aumentan las dimensiones, nuestros puntos de datos se vuelven solitarios. El centro del espacio desaparece y la palabra “cercano” deja de tener mucho significado. Aquí tienes una lista de verificación para la próxima vez que construyas un modelo:

  • Revisa tu proporción: ¿100 características pero solo 100 filas? KNN casi con seguridad fallará.
  • Cuidado con la concentración de distancias: Si las puntuaciones de confianza de tu modelo son casi todas idénticas, es probable que la maldición de la dimensionalidad esté actuando.
  • Simplifica primero: Prueba la reducción de dimensionalidad (como PCA) o la selección de características antes de abandonar un modelo basado en distancias.

Lo siguiente en la serie, Sam pasa a una tarea secundaria: clasificar los prospectos spam de las consultas reales de listados en la bandeja de entrada de HomeMatch. Se encuentra con un modelo que no se preocupa en absoluto por la distancia: Naive Bayes. Su supuesto de independencia “ingenuo” suele funcionar mejor de lo que esperarías.

Comprueba tu comprensión

Las siguientes preguntas van desde la simple memorización hasta el diseño abierto, siguiendo aproximadamente la Taxonomía de Bloom.

Recordar ¿Qué es la “Maldición de la Dimensionalidad” y qué le pasa a la distancia promedio entre puntos aleatorios a medida que las dimensiones aumentan?

Comprender Con tus propias palabras, explica la analogía de la “naranja matemática”: ¿por qué el centro de un cubo de alta dimensionalidad casi no contiene nada de su volumen?

Aplicar Usando la fórmula volume_ratio del artículo (inner_edge ** dims con inner_edge = 0.9), calcula qué porcentaje del volumen ocupa el centro en dims = 20, y compáralo con el valor reportado en el artículo en dims = 100.

Analizar El artículo muestra que en 100D, “tu amigo ‘más cercano’ podría estar a 10.1 millas de distancia y tu enemigo ‘más lejano’ podría estar a 10.2 millas de distancia”. Explica paso a paso por qué esta pérdida de “contraste” entre lo cercano y lo lejano rompe específicamente la lógica de votación de KNN, a pesar de que las distancias en sí sigan calculándose técnicamente de manera correcta.

Evaluar La solución PCA del artículo reduce 100 dimensiones (2 útiles + 98 ruido) a 2 componentes. Critica esta configuración específica: PCA no sabe cuáles 2 de las 100 características originales fueron las “útiles”, solo encuentra direcciones de varianza máxima. ¿Qué fallaría en esta solución si las 98 características de “ruido” tuvieran una varianza mucho mayor que las 2 útiles?

Crear Diseña una verificación de diagnóstico que un científico de datos podría ejecutar antes de entrenar un modelo KNN para decidir si la Maldición de la Dimensionalidad probablemente será un problema para su conjunto de datos específico (alguna combinación de recuento de filas, recuento de características y/o una verificación de distribución de distancias como el histograma del artículo). Describe qué resultado les indicaría que deben cambiar de estrategia.


Artículos relacionados

Referencias y lecturas adicionales

  • Cover, T. & Hart, P. (1967). “Nearest Neighbor Pattern Classification.” IEEE Transactions on Information Theory, 13(1), 21–27. — el artículo fundamental que formalizó la regla de los k-vecinos más cercanos y demostró que su tasa de error está acotada por el doble de la tasa óptima de Bayes, estableciendo a KNN como un aprendiz perezoso con fundamento teórico.
  • Bellman, R. (1957). Dynamic Programming. Princeton University Press. — el libro donde se acuñó por primera vez el término “maldición de la dimensionalidad”, originalmente en el contexto de la programación dinámica, pero adoptado universalmente para describir la explosión exponencial del volumen y la concentración de distancias en espacios de alta dimensionalidad.
  • Kaggle: House Prices — Advanced Regression Techniques — una competencia de regresión tabular con 79 características donde la reducción de dimensionalidad y la selección de características son estrategias centrales; un buen entorno de pruebas para evaluar si PCA o la selección de características ayudan a un modelo base KNN a competir con modelos basados en árboles.
  • scikit-learn: Nearest Neighbors documentation — documentación oficial que cubre KNeighborsClassifier, KNeighborsRegressor, métricas de distancia (euclidean, manhattan, minkowski), y orientación sobre cómo elegir n_neighbors.
  • scikit-learn: PCA documentation — documentación oficial para sklearn.decomposition.PCA, que incluye n_components, fit_transform, transform, y el atributo explained_variance_ratio_ para diagnosticar cuántos componentes conservar.

Esta traducción fue generada automáticamente y puede contener errores. Si el idioma inglés es tu preferencia, puedes leer el artículo original en inglés .

«Aplica lo que aprendiste» es para suscriptores Supporter e Insider.

Suscríbete para desbloquear los ejercicios de este artículo.

Ver planes

¿Buscas otra cosa?

Busca en todos los artículos por título, resumen o tema.