Saltar al contenido principal
LibreTexts Español

7.2: Clasificación sin aprendizaje

  • Page ID
    149995
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Vemos que el trazado de datos multivariados siempre tiene dos problemas: o hay demasiados elementos (por ejemplo, en coordenadas paralelas) que son difíciles de entender, o hay necesidad de alguna operación de agrupación (por ejemplo, mediana o rango) que resultará en la pérdida de información. Lo que será realmente útil es procesar primero los datos de manera segura, por ejemplo, para reducir las dimensiones —de muchas a 2 o 3. Estas técnicas se describen en esta sección.

    Aparte de (a) reducción de dimensionalidad (búsqueda de proyección), los siguientes métodos ayudan a (b) encontrar grupos (clusters) en los datos, (c) descubrir factores ocultos (variables latentes) y comprender la importancia de las variables (selección de características\(^{[1]}\)), (d) reconocer objetos (por ejemplo, formas complicadas) dentro de los datos, típicamente usando densidades e hiato (huecos) en el espacio multidimensional, y (e) señales de desmezcla.

    Screen Shot 2019-01-23 a las 9.45.11 PM.png
    Figura Gráfica\(\PageIndex{1}\) estática de nubes 3D de datos de iris con varias rotaciones.

    Clasificación con datos primarios

    Primario es lo que viene directamente de la observación, y aún no procesa de ninguna manera (para hacer datos secundarios).

    Sombras de hiper nubes: PCA

    RGL (ver arriba) permite encontrar la mejor proyección manualmente, con un ratón. Sin embargo, es posible hacer programáticamente, con análisis de componentes principales, PCA. Pertenece a la familia de métodos no supervisados, métodos de clasificación sin aprendizaje, u ordenación.

    PCA trata los datos como puntos en el espacio virtual multidimensional donde cada dimensión es el carácter único. Estos puntos conforman en conjunto la nube multidimensional. El objetivo del análisis es encontrar una línea que cruce esta nube a lo largo de su parte más alargada, como pera en el palo (Figura\(\PageIndex{2}\)). Este es el primer componente principal. La segunda línea es perpendicular a la primera y nuevamente abarca la segunda parte más alargada de la nube. Estas dos líneas conforman el plano sobre el que se proyecta cada punto.

    Screen Shot 2019-01-23 a las 9.46.47 PM.png
    Figura\(\PageIndex{2}\) El análisis del componente principal es como la pera en la barra.

    Demostrémoslo prácticamente. Cargaremos la imagen de pera bidimensional (de ahí solo dos componentes principales) en blanco y negro y veremos qué hace PCA con ella:

    Código\(\PageIndex{1}\) (R):

    library(png) # package to read PNG images
    aa <- readPNG("data/pear2d_bw.png")
    bb <- which(aa == 0, arr.ind=TRUE) # pixels to coordinates
    ## plot together original (green) and PCA-rotated:
    bbs <- scale(bb)
    pps <- scale(prcomp(bb)$x[, 1:2]) # only two PCs anyway
    xx <- range(c(bbs[, 1], pps[, 1]))
    yy <- range(c(bbs[, 2], pps[, 2]))
    plot(pps, pch=".", col=adjustcolor("black", alpha=0.5), xlim=xx, ylim=yy)
    points(bbs, pch=".", col=adjustcolor("green", alpha=0.5))
    legend("bottomright", fill=adjustcolor(c("green", "black"), alpha=0.5), legend=c("Original", "PCA-rotated"), bty="n", border=0)

    PCA se relaciona con una tarea de encontrar a la “persona más promedio”. La simple combinación de promedios no funcionará, lo cual está bien explicado en el libro “El fin del promedio” de Todd Rose. Sin embargo, generalmente es posible encontrar en el hiperespacio la configuración de parámetros que se adaptarán a la mayoría de las personas, y para esto es para lo que sirve PCA.

    Screen Shot 2019-01-23 a las 9.48.23 PM.png
    Figura\(\PageIndex{3}\) Sombra de la pera: cómo PCA proyecta la imagen.

    Después del procedimiento PCA, todas las columnas (caracteres) se transforman en componentes, y el componente más informativo es el primero, el siguiente es el segundo, luego el tercero etc. El número de componentes es el mismo que el número de caracteres iniciales pero los primeros dos o tres suelen incluir toda la información necesaria. Es por ello que es posible utilizarlos para la visualización 2D de datos multidimensionales. Hay muchas similitudes entre el ACP y el análisis factorial (que está fuera del alcance de este libro).

    Al principio, usaremos un ejemplo del repositorio abierto presentando mediciones de cuatro poblaciones diferentes de juncias:

    Código\(\PageIndex{2}\) (R):

    ca <- read.table("http://ashipunov.info/shipunov/open/carex.txt", h=TRUE)
    str(ca)
    ca.pca <- princomp(scale(ca[,-1]))

    (Escala de función () estandariza todas las variables.)

    La siguiente gráfica (Figura\(\PageIndex{4}\)) es una gráfica de pantalla técnica que muestra la importancia relativa de cada componente:

    Código\(\PageIndex{3}\) (R):

    ca <- read.table("http://ashipunov.info/shipunov/open/carex.txt", h=TRUE)
    ca.pca <- princomp(scale(ca[,-1]))
    plot(ca.pca, main="")
    Screen Shot 2019-01-23 a las 9.50.15 PM.png
    Figura\(\PageIndex{4}\) Gráfica mostrando la importancia de cada componente.

    Aquí es fácil ver que entre cuatro componentes (mismo número que los caracteres iniciales), dos primeros tienen las mayores importancias. Hay una manera de tener lo mismo sin trazar:

    Código\(\PageIndex{4}\) (R):

    ca <- read.table("http://ashipunov.info/shipunov/open/carex.txt", h=TRUE)
    ca.pca <- princomp(scale(ca[,-1]))
    summary(ca.pca)

    Los dos primeros componentes juntos explican alrededor del 84% por ciento de la varianza total.

    La visualización de PCA generalmente se realiza utilizando puntuaciones del modelo PCA (Figura\(\PageIndex{5}\)):

    Código\(\PageIndex{5}\) (R):

    ca <- read.table("http://ashipunov.info/shipunov/open/carex.txt", h=TRUE)
    ca.pca <- princomp(scale(ca[,-1]))
    ca.p <- ca.pca$scores[, 1:2]
    plot(ca.p, type="n", xlab="PC1", ylab="PC2")
    text(ca.p, labels=ca[, 1], col=ca[, 1])
    Hulls(ca.p, ca[, 1]) # asmisc.r
    Screen Shot 2019-01-23 a las 9.52.18 PM.png
    Figura\(\PageIndex{5}\) Diversidad de juncias en la parcela de dos primeros componentes principales.

    (El último comando dibuja cascos que ayudan a concluir que las primeras juncias de la tercera población son intermedias entre la primera y la segunda, podrían ser incluso híbridos. Si hay tres, no dos, componentes que son los más importantes, entonces cualquiera de las gráficas 3D como scatterplot3d () explicadas anteriormente, ayudará a visualizarlos.)

    Es tentador medir la intersección entre cascos. Esto es posible con la función Overlap (), que a su vez carga el paquete PBSMapping:

    Código\(\PageIndex{6}\) (R):

    ca <- read.table("http://ashipunov.info/shipunov/open/carex.txt", h=TRUE)
    ca.pca <- princomp(scale(ca[,-1]))
    ca.p <- ca.pca$scores[, 1:2]
    ca.h <- Hulls(ca.p, ca[, 1], plot=FALSE) # asmisc.r
    ca.o <- Overlap(ca.h) # asmisc.r
    summary(ca.o)

    En ocasiones, los resultados de PCA son útiles para presentar como biplot (Figura\(\PageIndex{6}\)):

    Código\(\PageIndex{7}\) (R):

    ca <- read.table("http://ashipunov.info/shipunov/open/carex.txt", h=TRUE)
    ca.pca <- princomp(scale(ca[,-1]))
    biplot(ca.pca, xlabs=ca[, 1])
    Screen Shot 2019-01-23 a las 9.54.03 PM.png
    La Figura\(\PageIndex{6}\) Biplot muestra la carga de cada carácter en dos primeros componentes.

    Biplot ayuda a comprender visualmente qué tan grande es la carga de cada carácter inicial en los dos primeros componentes. Por ejemplo, los caracteres de altura y longitud de espiga (pero ancho de espiga) tienen una mayor carga en el primer componente que distingue más a las poblaciones. Cargas de funciones () permite ver esta información en forma numérica:

    Código\(\PageIndex{8}\) (R):

    ca <- read.table("http://ashipunov.info/shipunov/open/carex.txt", h=TRUE)
    ca.pca <- princomp(scale(ca[,-1]))
    loadings(ca.pca)

    R tiene dos variantes de cálculo de PCA, primero (ya discutido) con princomp () y segundo con prcomp (). La diferencia radica en la forma en que exactamente se calculan los componentes. La primera forma es tradicional, pero se recomienda la segunda:

    Código\(\PageIndex{9}\) (R):

    iris.pca <- prcomp(iris[, 1:4], scale=TRUE)
    iris.pca$rotation
    iris.p <- iris.pca$x[, 1:2]
    plot(iris.p, type="n", xlab="PC1", ylab="PC2")
    text(iris.p, labels=abbreviate(iris[, 5], 1, method="both.sides"), col=as.numeric(iris[, 5]))
    Ellipses(iris.p[, 1:2], as.numeric(iris[, 5])) # asmisc.r

    El ejemplo anterior muestra algunas diferencias entre dos métodos de PCA. Primero, prcomp () acepta convenientemente la opción de báscula. Segundo, las cargas se toman del elemento de rotación. Tercero, las puntuaciones están en el elemento con x nombre. Por favor, ejecute el código usted mismo para ver cómo agregar elipses de confianza del 95% a la gráfica de ordenación 2D. Se puede ver que Iris setosa (letra “s” en la parcela) es seriamente divergente de otras dos especies, Iris versicolor (“v”) e Iris virginica (“a”).

    Los paquetes ade4 y veganos ofrecen muchas variantes de PCA (Figura\(\PageIndex{7}\)):

    Código\(\PageIndex{10}\) (R):

    library(ade4)
    iris.dudi <- dudi.pca(iris[, 1:4], scannf=FALSE)
    s.class(iris.dudi$li, iris[, 5])
    Screen Shot 2019-01-23 a las 9.55.51 PM.png
    Figura\(\PageIndex{7}\) Diversidad de iris en la gráfica de dos primeros componentes principales (paquete ade4)

    (La gráfica es similar a la mostrada en la Figura\(\PageIndex{5}\); sin embargo, las diferencias entre grupos son aquí más claras.)

    Además, esto es posible utilizar el enfoque inferencial para el PCA:

    Código\(\PageIndex{11}\) (R):

    iris.between <- bca(iris.dudi, iris[, 5], scannf=FALSE)
    randtest(iris.between)

    La aleatorización de Montecarlo permite comprender numéricamente qué tan bien se separan las especies de Iris con este PCA. El alto valor de Observación (72.2% que es mayor al 50%) es el signo de diferencias confiables.

    Existen otras variantes de pruebas de permutación para PCA, por ejemplo, con anosim () del paquete vegano.

    Tenga en cuenta que el análisis de componentes principales es en general una técnica lineal similar al análisis de correlaciones, y puede fallar en algunos casos complicados.

    Solitario de datos: SOM

    Existen varias otras técnicas que permiten la clasificación no supervisada de los datos primarios. Los mapas autoorganizados (SOM) son una técnica algo similar a romper la baraja de cartas en varios montones:

    Código\(\PageIndex{12}\) (R):

    library(kohonen)
    iris.som <- som(scale(iris[, 1:4]), grid = somgrid(3, 3, "hexagonal")) # 9 "piles"
    predict(iris.som)$unit.classif # content of each "pile"
    iris.som$distances # distance to the "center of pile"
    set.seed(1)
    plot(iris.som, main="")
    oldpar <- par(new=TRUE, oma=c(2, rep(0, 3)))
    plot(iris.som, type="mapping", col=iris$Species, main="", border=0)
    par(oldpar)
    legend("top", col=1:3, pch=1, legend=levels(iris$Species))

    La gráfica resultante (Figura\(\PageIndex{8}\)) contiene representación gráfica de valores de caracteres, junto con la colocación de puntos de datos reales.

    Screen Shot 2019-01-23 a las 9.58.24 PM.png
    Figura Mapa\(\PageIndex{8}\) autoorganizativo para datos de iris. Se muestran tanto los valores de caracteres (códigos) como la ubicación de los datos.

    De hecho, SOM es la red neuronal que no aprende. El algoritmo más avanzado de Gas Neural en Crecimiento (GNG) utiliza ideas similares a SOM.

    Densidad de datos: T-SNE

    Con el gran número de muestras, el algoritmo T-SNE (nombre significa “Embedding Estocástico Vecino Distribuido en T”) funciona mejor que el PCA clásico. t-SNE se usa con frecuencia para el reconocimiento de formas. Es bastante fácil emplearlo en R (Figura\(\PageIndex{9}\)):

    Código\(\PageIndex{13}\) (R):

    library(Rtsne)
    iris.unique <- unique(iris)
    set.seed(42)
    tsne.out <- Rtsne(as.matrix(iris.unique[, 1:4]))
    SP <- iris.unique$Species
    plot(tsne.out$Y, col=SP, pch=14+as.numeric(SP), xlab="", ylab="")
    legend("topleft", pch=14+1:nlevels(SP), col=1:nlevels(SP), legend=levels(SP))
    Screen Shot 2019-01-23 a las 9.59.32 PM.png
    Figura\(\PageIndex{9}\) T-SNE algoritmo divide los datos del iris.

    Clasificación con correspondencia

    El análisis de correspondencia es la familia de técnicas similares al PCA, pero aplicables a datos categóricos (primarios o en tablas de contingencia). La variante simple del análisis de correspondencia se implementa en corresp () a partir del paquete MASS (Figura\(\PageIndex{10}\)) que trabaja con tablas de contingencia:

    Código\(\PageIndex{14}\) (R):

    HE <- margin.table(HairEyeColor, 1:2)
    HE.df <- Table2df(HE) # asmisc.r
    biplot(corresp(HE.df, nf = 2), xpd=TRUE)
    legend("topleft", fill=1:2, legend=c("hair","eyes"))

    (Convertimos aquí objeto “tabla” HE en el marco de datos. XPD=true se utilizó para permitir que el texto saliera del cuadro de trazado.)

    Screen Shot 2019-01-23 a las 10.01.00 PM.png
    Figura Gráfica de\(\PageIndex{10}\) correspondencia de la tabla de contingencia.

    En este ejemplo se utilizan datos de HaireyeColor del capítulo anterior. Trazar visualiza ambos parámetros por lo que si la combinación particular de colores es más frecuente, entonces las posiciones de las palabras correspondientes están más cerca. Por ejemplo, los pelos negros y los ojos marrones suelen aparecer juntos. La posición de estas palabras es más distante del centro (designada con cruz) porque los valores numéricos de estos caracteres son remotos.

    Esta posibilidad de visualizar varios conjuntos de caracteres simultáneamente en una gráfica es la característica impresionante del análisis de correspondencia (Figura\(\PageIndex{11}\)):

    Código\(\PageIndex{15}\) (R):

    library(vegan)
    alla <- read.table("data/lakesea_abio.txt", sep="	", h=TRUE)
    allc <- read.table("data/lakesea_bio.txt", sep="	", h=TRUE)
    all.cca <- cca(allc, alla[,-14])
    plot.all.cca <- plot(all.cca, display=c("sp","cn"), xlab="", ylab="")
    points(all.cca, display="sites", pch=ifelse(alla[, 14], 15, 0))
    legend("topleft", pch=c(15, 0), legend=c("lake","sea"))
    text(-1.6, -4.2, "Carex.lasiocarpa", pos=4)

    Esto es mucho más avanzado que biplot. Los datos utilizados aquí contenían factores tanto abióticos (ecotopos) como bióticos (especies vegetales), además de la geografía de algunas islas árticas: fueron estas islas lacustres o islas marinas. La parcela fue capaz de organizar todos estos datos: para factores abióticos, utilizó flechas, para biotic—pluses, y para sitios (islas mismas caracterizadas por la suma de todos los factores disponibles, bióticos y abióticos) —cuadrados de diferente color, dependiendo del origen geográfico. Todas las ventajas podrían identificarse con el comando interactivo identify (plot.all.cca, “species”). Lo hicimos solo para una de las especies más destacadas, Carex lasiocarpa (juncia lanosa) que está claramente asociada con islas lacustres, y también con pantanos.

    Clasificación con distancias

    Una forma importante de clasificación no supervisada es trabajar con distancias en lugar de datos originales. Los métodos basados en la distancia necesitan que primero se calculen las diferencias entre cada par de objetos. La ventaja de estos métodos es que las diferencias podrían calcularse a partir de datos de cualquier tipo: medición, clasificado o nominal.

    Distancias

    Hay miríadas de formas de calcular la disimilitud (o similitud que es esencialmente la disimilitud inversa)\(^{[2]}\). Una de estas formas ya explicadas anteriormente es una correlación (absoluta inversa). Otras formas populares son la distancia euclidiana (cuadrada) y la distancia de Manhattan (cuadra). Ambos (Figura\(\PageIndex{12}\)) son útiles para variables de medición.

    Screen Shot 2019-01-23 a las 10.03.47 PM.png
    Figura Gráfica de análisis de correlación\(\PageIndex{11}\) canónica que muestra islas árticas (cuadrados), especies (cruces) y factores de hábitat (flechas)

    Las distancias de Manhattan son similares a las distancias de conducción, especialmente cuando no hay muchas carreteras disponibles. El siguiente ejemplo son las distancias de conducción entre las ciudades más grandes de Dakota del Norte:

    Código\(\PageIndex{16}\) (R):

    nd <- read.table("data/nd.txt", h=TRUE, sep="	", row.names=1)
    nd.d <- as.dist(nd)
    str(nd.d)
    Screen Shot 2019-01-23 a las 10.07.34 PM.png
    Figura\(\PageIndex{12}\) Euclidiana (1) y Manhattan (2) distancias entre A y B

    En la mayoría de los casos, necesitamos convertir variables sin procesar en matriz de distancia. La forma básica es usar dist (). Tenga en cuenta que las variables clasificadas y binarias generalmente requieren diferentes enfoques que se implementan en los paquetes vegan (function vegdist ()) y cluster (function daisy ()). La última función reconoce el tipo de variable y aplica la métrica más adecuada (incluida la distancia universal de Gower); también acepta la métrica especificada por el usuario:

    Código\(\PageIndex{17}\) (R):

    library(cluster)
    iris.dist <- daisy(iris[, 1:4], metric="manhattan")
    str(iris.dist)

    En biología, se pueden utilizar las distancias taxonómicas de Smirnov, disponibles en el paquete smirnov. En el siguiente ejemplo, utilizamos datos de distribución de especies de plantas en islas pequeñas.

    La siguiente trama pretende ayudar al lector a entenderlos mejor. Es solo una especie de mapa que muestra ubicaciones geográficas y tamaños de islas:

    Código\(\PageIndex{18}\) (R):

    mp <- read.table( "http://ashipunov.info/shipunov/open/moldino_l.txt", h=TRUE, sep="	", row.names=1)
    library(MASS)
    eqscplot(mp$LON, mp$LAT, cex=round(log(mp$SQUARE))-5.5, axes=FALSE, xlab="", ylab="", xpd=T)
    text(mp$LON, mp$LAT, labels=row.names(mp), pos=4, offset=1, cex=.9)

    (Por favor, complótelo usted mismo.)

    Ahora calcularemos y visualizaremos las distancias de Smirnov:

    Código\(\PageIndex{19}\) (R):

    mo <- read.table("http://ashipunov.info/shipunov/open/moldino.txt", h=TRUE, sep="	", row.names=1)
    m1 <- t((mo > 0) * 1) # convert to occurrence 0/1 data and transpose
    library(smirnov)
    m1.Txy <- smirnov(m1)
    m1.s <- (1 - m1.Txy) # similarity to dissimilarity
    dimnames(m1.s) <- list(row.names(m1))
    symnum(m1.s)

    Las distancias de Smirnov tienen una característica interesante: en lugar de 0 o 1, la diagonal de la matriz de similitud se rellena con los valores del coeficiente de singularidad (Txx):

    Código\(\PageIndex{20}\) (R):

    mo <- read.table("http://ashipunov.info/shipunov/open/moldino.txt", h=TRUE, sep="	", row.names=1)
    m1 <- t((mo > 0) * 1) # convert to occurrence 0/1 data and transpose
    library(smirnov)
    m1.Txy <- smirnov(m1)
    m1.Txx <- diag(m1.Txy)
    names(m1.Txx) <- row.names(m1)
    rev(sort(round(m1.Txx, 3)))

    Esto significa que la isla Verik es la más singular en lo que respecta a la ocurrencia de especies de plantas.

    Hacer mapas: escalado multidimensional

    Hay muchas cosas que hacer con la matriz de distancia. Uno de los más directos es el escalado multidimensional, MDS (el otro nombre es “análisis de coordenadas principales”, PCoA):

    Código\(\PageIndex{21}\) (R):

    nd <- read.table("data/nd.txt", h=TRUE, sep="	", row.names=1)
    nd.d <- as.dist(nd)
    nd.c <- cmdscale(nd.d)
    new.names <- sub("y C", "y
    C", row.names(nd))
    library(MASS)
    eqscplot(nd.c, type="n", axes=FALSE, xlab="", ylab="")
    points(nd.c, pch=19)
    text(nd.c, labels=new.names, xpd=TRUE, pos=3, cex=0.8)
    Screen Shot 2019-01-23 a las 10.09.34 PM.png
    Figura No se\(\PageIndex{13}\) trata de un mapa de pueblos de Dakota del Norte sino de la gráfica de salida de cmdscale () a partir de los datos de distancia de conducción.

    Compara la parcela (Figura\(\PageIndex{13}\)) con cualquier mapa geográfico. Si no tienes un mapa de Dakota del Norte pero tienes estas distancias de manejo, ¡cmdscale () permite recrear el mapa!

    Entonces, en esencia, MDS es una tarea inversa a la navegación (encontrar direcciones de manejo desde el mapa): usa “indicaciones de manejo” y hace un mapa a partir de ellas.

    Otro ejemplo menos impresionante pero más útil (Figura\(\PageIndex{14}\)) es de los datos brutos de los iris de Fisher:

    Código\(\PageIndex{22}\) (R):

    library(KernSmooth)
    library(cluster)
    iris.dist <- daisy(iris[, 1:4], metric="manhattan")
    iris.c <- cmdscale(iris.dist)
    est <- bkde2D(iris.c, bandwidth=c(.7, 1.5))
    plot(iris.c, type="n", xlab="Dim. 1", ylab="Dim. 2")
    text(iris.c, labels=abbreviate(iris[, 5], 1, method="both.sides"))
    contour(est$x1, est$x2, est$fhat, add=TRUE, drawlabels=FALSE, lty=3)
    Screen Shot 2019-01-23 a las 10.12.01 PM.png
    Figura\(\PageIndex{14}\) El resultado de la escala multidimensional del iris. datos. La visualización utiliza la estimación de densidad.

    (No hay diferencia real con el PCA porque el escalado multidimensional métrico está relacionado con el análisis de componentes principales; además, la estructura interna de los datos es la misma).

    Para hacer la gráfica “más bonita”, agregamos aquí líneas de densidad de cercanía de punto estimadas con la función BKDE2d () a partir del paquete KernSmooth. Otra forma de mostrar la densidad es trazar una superficie 3D como (Figura\(\PageIndex{15}\)):

    Código\(\PageIndex{23}\) (R):

    library(cluster)
    iris.dist <- daisy(iris[, 1:4], metric="manhattan")
    iris.c <- cmdscale(iris.dist)
    est <- bkde2D(iris.c, bandwidth=c(.7, 1.5))
    persp(est$x1, est$x2, est$fhat, theta=135, phi=45, col="purple3", shade=0.75, border=NA, xlab="Dim. 1", ylab="Dim. 2", zlab="Density")
    Screen Shot 2019-01-23 a las 10.13.58 PM.png
    Figura Superficie de densidad\(\PageIndex{15}\) 3D de datos de iris multidimensionalmente escalados.

    Además de cmdscale (), el paquete MASS (funciones isMDS () y sammon ()) implementa el escalado multidimensional no métrico, y package vegan tiene los metaMDs no métricos avanzados (). El escalado multidimensional no métrico no tiene análogos a las cargas de PCA (importaciones de variables) y proporción de varianza explicada por componente, pero es posible calcular métricas sustitutas:

    Código\(\PageIndex{24}\) (R):

    iris.dist2 <- dist(iris[, 1:4], method="manhattan") ## to remove zero distances:
    iris.dist2[iris.dist2 == 0] <- abs(jitter(0))
    library(MASS)
    iris.m <- isoMDS(iris.dist2)
    cor(iris[, 1:4], iris.m$points) # MDS loadings surrogate
    MDSv(iris.m$points) # asmisc.r

    En consecuencia (y de manera similar a PCA), el carácter de ancho sépalo influye en la segunda dimensión mucho más que otros tres caracteres. También podemos adivinar que dentro de esta solución no métrica, la primera dimensión toma casi 98% de varianza.

    Hacer árboles: agrupación jerárquica

    La otra forma de procesar la matriz de distancia es realizar clústeres jerárquicos que producen dendrogramas, o árboles, que son parcelas de “una y media dimensión” (Figura\(\PageIndex{16}\)):

    Código\(\PageIndex{25}\) (R):

    aa <- read.table("data/atmospheres.txt", h=TRUE, sep="	", row.names=1)
    aa.dist <- dist(t(aa)) # because planets are columns
    aa.hclust <- hclust(aa.dist, method="ward.D")
    plot(aa.hclust, xlab="", ylab="", sub="")

    El método de agrupación de Ward es bien conocido por producir conglomerados nítidos y bien separados (esto, sin embargo, podría llevar a conclusiones falsas si los datos no tienen una estructura aparente). Los planetas distantes son los más similares (en la altura\(\approx25\)), la similitud entre Venus y Marte también es alta (la disimilitud es\(\approx0\)). La Tierra es más sobresaliente, la similitud con Mercurio es menor, en la altura\(\approx100\); pero como Mercurio no tiene verdadera atmósfera, podría ser ignorada.

    A partir de esta parcela se podría producir la siguiente clasificación:

    • Grupo Tierra: Venus, Marte, Tierra, [Mercurio]
    • Grupo Júpiter: Júpiter, Saturno, Urano, Neptuno

    En lugar de este enfoque “especulativo”, se puede usar la función cutree () para producir la clasificación explícitamente; esto requiere el objeto hclust () y el número de clústeres deseados:

    Código\(\PageIndex{26}\) (R):

    library(cluster)
    iris.dist <- daisy(iris[, 1:4], metric="manhattan")
    iris.hclust <- hclust(iris.dist)
    iris.3 <- cutree(iris.hclust, 3)
    head(iris.3) # show cluster numbers
    Misclass(iris.3, iris[, 5]) # asmisc.r
    Screen Shot 2019-01-23 a las 10.19.02 PM.png
    Figura\(\PageIndex{16}\) Dendrograma que refleja similitudes entre atmósferas de planetas del Sistema Solar.

    Para comprobar qué tan bien realiza la clasificación el método seleccionado, escribimos la función personalizada Misclass (). Esta función calcula la matriz de confusión. Tenga en cuenta que Misclass () asume grupos predichos y observados en el mismo orden, vea también a continuación los resultados de la función fanny ().

    La matriz de confusión es una forma sencilla de evaluar el poder predictivo del modelo. Técnica más avanzada del mismo tipo se llama validación cruzada. Como ejemplo, el usuario podría esparcir datos en 10 partes iguales (por ejemplo, con cut ()) y luego, a su vez, hacer que cada parte sea “desconocida” mientras que el resto se convertirá en subconjunto de entrenamiento.

    Como puede ver en la tabla, 32% de Iris virginica fueron clasificados erróneamente. El último es posible mejorar, si cambiamos ya sea métrica de distancia, o método de clustering. Por ejemplo, el método de agrupación de Ward da más clústeres separados y tasas de clasificación errónea ligeramente mejores. Por favor pruébalo tú mismo.

    La agrupación jerárquica no devuelve por defecto ninguna importancia de variable. Sin embargo, todavía es posible ayudar a la selección de entidades con el mapa de calor de agrupación (Figura\(\PageIndex{17}\)):

    Código\(\PageIndex{27}\) (R):

    aa <- read.table("data/atmospheres.txt", h=TRUE, sep="	", row.names=1)
    library(cetcolor)
    heatmap(t(aa), col=cet_pal(12, "coolwarm"), margins=c(9, 6))

    (Aquí también utilizamos el paquete cetcolor que permite crear paletas de colores perceptualmente uniformes.)

    Mapa de calor agrupa por separado filas y columnas y coloca el resultado de la función image () en el centro. Entonces se hace visible qué personajes influyen en qué grupos de objetos y viceversa. En este mapa de calor, por ejemplo, Marte y Venus se agrupan en su mayoría debido a niveles similares de dióxido de carbono.

    Hay demasiados iris para trazar el dendrograma resultante de la manera común. Una solución alternativa es seleccionar solo algunos iris (ver más abajo). Otro método es usar la función Ploth () (Figura\(\PageIndex{18}\)):

    Código\(\PageIndex{28}\) (R):

    Ploth(iris.hclust, col=as.numeric(iris[, 5]), pch=16, col.edges=TRUE, horiz=TRUE, leaflab="none") # asmisc.r
    legend("topleft", fill=1:nlevels(iris[, 5]), legend=levels(iris[, 5]))
    
    Screen Shot 2019-01-23 a las 10.21.22 PM.png
    Figura Mapa de calor de\(\PageIndex{17}\) agrupación para datos de atmósfera.

    Ploth () es útil también si uno necesita simplemente rotar el dendrograma. Por favor, compruebe usted mismo lo siguiente:

    Código\(\PageIndex{29}\) (R):

    tox <- read.table("data/poisoning.txt", h=TRUE)
    oldpar <- par(mar=c(2, 0, 0, 4))
    tox.dist <- as.dist(1 - abs(tox.cor))
    Ploth(hclust(tox.dist, method="ward.D"), horiz=TRUE) # asmisc.r
    par(oldpar)

    (Esto también es una demostración de cómo utilizar la correlación para la distancia. Como verás, la misma conexión entre la ensalada César, el tomate y la enfermedad podría visualizarse con dendrograma. Allí visibles también algunas otras relaciones interesantes.)

    Screen Shot 2019-01-23 a las 10.24.37 PM.png
    Figura Agrupación\(\PageIndex{18}\) jerárquica de datos de iris.

    archivo.

    Planet Aqua está completamente cubierto por aguas poco profundas. Este océano está habitado con diversos organismos planos (Figura\(\PageIndex{19}\)). Estas criaturas (las llamamos “kubricks”) pueden fotosintetizar y/o comer otros organismos o sus partes (que coinciden con la forma de sus bocas), y moverse (solo si no tienen tallos). Proporcionar el dendrograma para especies de kubrick basado en el resultado del agrupamiento jerárquico.

    Screen Shot 2019-01-23 a las 10.26.56 PM.png
    Figura\(\PageIndex{19}\) Ocho especies de kubricks.

    Cómo conocer el mejor método de clustering

    El análisis jerárquico de conglomerados y los parientes (por ejemplo, árboles de filogenia) son visualmente atractivos, pero hay tres preguntas importantes que deben resolverse: (1) qué distancia es la mejor (esto también es relevante para otros métodos basados en la distancia); (2) qué método de agrupación jerárquica es el mejor; y (3) cómo evaluar la estabilidad de los racimos.

    La segunda pregunta es relativamente fácil de responder. La función Co.test (dist, tree) de asmisc.r revela consistencia entre objeto de distancia y clusterización jerárquica. Es esencialmente una prueba de correlación entre las distancias iniciales y las distancias reveladas a partir de la estructura cofenética del dendrograma.

    Las distancias cofenéticas son útiles de muchas maneras. Por ejemplo, para elegir el mejor método de clusterización y, por lo tanto, responder a la segunda pregunta, se podría usar

    Código\(\PageIndex{30}\) (R):

    mo <- read.table("http://ashipunov.info/shipunov/open/moldino.txt", h=TRUE, sep="	", row.names=1)
    m1 <- t((mo > 0) * 1) # convert to occurrence 0/1 data and transpose
    library(smirnov)
    m1.Txy <- smirnov(m1)
    m1.s <- (1 - m1.Txy) # similarity to dissimilarity
    PlotBest.hclust(as.dist(m1.s)) # asmisc.r

    (Haz y revisa esta parcela tú mismo. ¿Qué clustering es mejor?)

    Tenga en cuenta, sin embargo, estas “mejores” puntuaciones no siempre son las mejores para usted. Por ejemplo, todavía se podría decidir usar Ward.d porque hace que los racimos sean nítidos y separados visualmente.

    Para elegir el mejor método de distancia, uno podría usar el enfoque visualmente similar:

    Código\(\PageIndex{31}\) (R):

    mo <- read.table("http://ashipunov.info/shipunov/open/moldino.txt", h=TRUE, sep="	", row.names=1)
    m1 <- t((mo > 0) * 1) # convert to occurrence 0/1 data and transpose
    PlotBest.dist(m1) # asmisc.r

    (Nuevamente, por favor revise la parcela usted mismo.)

    De hecho, solo visualiza la correlación entre el escalado multidimensional de distancias y el análisis de componentes principales de datos brutos. Sin embargo, sigue siendo útil.

    Cómo comparar clústeres

    La agrupación jerárquica son dendrogramas y no es fácil compararlos “fuera de la caja”. Varios métodos diferentes permiten comparar dos árboles.

    Podemos emplear métodos asociados a filogenias biológicas (estos árboles son esencialmente dendrogramas).

    Supongamos que hay dos agrupamientos:

    Código\(\PageIndex{32}\) (R):

    aa <- read.table("data/atmospheres.txt", h=TRUE, sep="	", row.names=1)
    aa.d1 <- hclust(dist(t(aa)))
    aa.d2 <- hclust(as.dist(1 - abs(cor(aa, method="s"))), method="ward.D")

    Library ape tiene la función dist.topo () que calcula la distancia topológica entre árboles, y la biblioteca phangorn calcula varios de esos índices:

    Código\(\PageIndex{33}\) (R):

    aa <- read.table("data/atmospheres.txt", h=TRUE, sep="	", row.names=1)
    library(ape)
    aa.d1 <- hclust(dist(t(aa)))
    aa.d2 <- hclust(as.dist(1 - abs(cor(aa, method="s"))), method="ward.D")
    aa.ph1 <- unroot(as.phylo(aa.d1)) # convert
    aa.ph2 <- unroot(as.phylo(aa.d2))
    dist.topo(aa.ph1, aa.ph2)
    phangorn::treedist(aa.ph1, aa.ph2)

    La siguiente posibilidad es trazar dos árboles uno al lado del otro y mostrar diferencias con líneas que conectan las mismas puntas (Figura\(\PageIndex{20}\)):

    Código\(\PageIndex{34}\) (R):

    aa <- read.table("data/atmospheres.txt", h=TRUE, sep="	", row.names=1)
    library(ape)
    aa.d1 <- hclust(dist(t(aa)))
    aa.d2 <- hclust(as.dist(1 - abs(cor(aa, method="s"))), method="ward.D")
    aa.ph1 <- unroot(as.phylo(aa.d1)) # convert
    aa.ph2 <- unroot(as.phylo(aa.d2))
    ass <- cbind(aa.ph1$tip.label, aa.ph1$tip.label)
    aa.ph2r <- rotate(aa.ph2, c("Earth", "Neptune"))
    cophyloplot(aa.ph1, aa.ph2r, assoc=ass, space=30, lty=2)

    (Tenga en cuenta que a veces es posible que necesite rotar la rama con la función rotate (). La rotación no cambia el dendrograma).

    Screen Shot 2019-01-23 a las 10.28.12 PM.png
    Figura Gráfica de dendrograma\(\PageIndex{20}\) lado a lado para datos de la atmósfera.

    También es posible trazar un árbol de consenso que muestra solo aquellos clústeres que aparecen en ambos agrupamientos:

    Código\(\PageIndex{35}\) (R):

    aa <- read.table("data/atmospheres.txt", h=TRUE, sep="	", row.names=1)
    library(ape)
    aa.d1 <- hclust(dist(t(aa)))
    aa.d2 <- hclust(as.dist(1 - abs(cor(aa, method="s"))), method="ward.D")
    aa.ph1 <- unroot(as.phylo(aa.d1)) # convert
    aa.ph2 <- unroot(as.phylo(aa.d2))
    aa.ph2r <- rotate(aa.ph2, c("Earth", "Neptune"))
    plot(consensus(aa.ph1, aa.ph2r))

    (Por favor, haga esta parcela usted mismo.)

    El mapa de calor también podría usarse para visualizar similitudes entre dos dendrogramas:

    Código\(\PageIndex{36}\) (R):

    aa <- read.table("data/atmospheres.txt", h=TRUE, sep="	", row.names=1)
    library(ape)
    aa.d1 <- hclust(dist(t(aa)))
    aa.d2 <- hclust(as.dist(1 - abs(cor(aa, method="s"))), method="ward.D")
    aa12.match <- Hclust.match(aa.d1, aa.d2) # asmisc.r
    library(cetcolor)
    cols <- cet_pal(max(aa12.match), "blues")
    kheatmap(aa12.match, scale="none", col=cols)

    (hclust.match () cuenta coincidencias entre dos dendrogramas (que se basan en los mismos datos) y luego heatmap () traza estos recuentos como colores, y también suministra la configuración de consenso como dos dendrogramas idénticos en la parte superior y en la izquierda. Por favor, haz esta parcela tú mismo.)

    Tanto el escalado multidimensional como el agrupamiento jerárquico son métodos basados en la distancia. Por favor, haga y revise la siguiente parcela (del paquete vegan3d) para entender cómo compararlos:

    Código\(\PageIndex{37}\) (R):

    mo <- read.table("http://ashipunov.info/shipunov/open/moldino.txt", h=TRUE, sep="	", row.names=1)
    m1 <- t((mo > 0) * 1) # convert to occurrence 0/1 data and transpose
    library(smirnov)
    m1.Txy <- smirnov(m1)
    m1.s <- (1 - m1.Txy) # similarity to dissimilarity
    m1.dist <- as.dist(m1.s)
    m1.hclust <- hclust(m1.dist)
    m1.c <- cmdscale(m1.dist)
    library(vegan3d)
    orditree3d(m1.c, m1.hclust, text=attr(m1.dist, "Labels"), type="t")

    Qué tan buenos son los clústeres resultantes

    Hay varias formas de verificar qué tan buenos son los clústeres resultantes, y muchas se basan en la replicación de arranque (ver Apéndice).

    La función Jclust () presenta un método para arrancar biparticiones y trazar árbol de consenso con valores de soporte (Figura\(\PageIndex{21}\):

    Código\(\PageIndex{38}\) (R):

    mo <- read.table("http://ashipunov.info/shipunov/open/moldino.txt", h=TRUE, sep="	", row.names=1)
    m1 <- t((mo > 0) * 1) # convert to occurrence 0/1 data and transpose
    (m1.j <- Jclust(m1, 3, iter=1000))
    plot(m1.j, rect.lty=2, sub="")
    Screen Shot 2019-01-23 a las 10.30.27 PM.png
    Figura Estabilidad de\(\PageIndex{21}\) Bootstrap de la solución de 3 clústeres para datos de islas de lagos (1000 iteraciones)

    (Tenga en cuenta que Jclust () usa cutree () y por lo tanto funciona solo si “conoce” el número de clústeres deseados. Dado que el resultado del consenso se relaciona con el número de conglomerados, las parcelas con diferentes números de conglomerados serán diferentes).

    Otra forma es usar el paquete pvclust que tiene la capacidad de calcular el soporte para clústeres a través de bootstrap (Figura\(\PageIndex{22}\)):

    Código\(\PageIndex{39}\) (R):

    mo <- read.table("http://ashipunov.info/shipunov/open/moldino.txt", h=TRUE, sep="	", row.names=1)
    m1 <- t((mo > 0) * 1) # convert to occurrence 0/1 data and transpose
    library(pvclust)
    m1.pvclust <- pvclust(t(m1), method.dist="manhattan", nboot=100, parallel=TRUE)
    plot(m1.pvclust, col.pv=c("darkgreen", 0, 0), main="")
    Screen Shot 2019-01-23 a las 10.32.45 PM.png
    Figura\(\PageIndex{22}\) Dendrograma con valores de soporte (paquete pvclust)

    (La función pvclust () agrupa columnas, no filas, así que tenemos que transponer datos de nuevo. En la parcela, los valores numéricos de estabilidad de conglomerados (au) se ubican por encima de cada nodo. Cuanto más cerca estén estos valores a 100, mejor.)

    También hay la función booTA () en el conjunto asmisc.r que permite bootstrap clustering con métodos del paquete filogenético ape:

    Código\(\PageIndex{40}\) (R):

    mo <- read.table("http://ashipunov.info/shipunov/open/moldino.txt", h=TRUE, sep="	", row.names=1)
    m1 <- t((mo > 0) * 1) # convert to occurrence 0/1 data and transpose
    m1.ba <- BootA(m1, FUN=function(.x) # asmisc.r
    as.phylo(hclust(dist(.x, method="minkowski"), method="average")), iter=100, mc.cores=4)
    plot(m1.ba$boot.tree, show.node.label=TRUE)
    plot(m1.ba$cons.tree) # majority-rule consensus

    (Este método requiere hacer una función anónima que utilice los métodos que desee. También traza tanto el árbol de consenso (sin valores de soporte) como el árbol original con valores de soporte. Por favor, haz estos árboles. Tenga en cuenta que por defecto, solo se muestran valores de soporte mayores a 50%.)

    Hacer grupos: k-means y amigos

    Aparte de jerárquico, hay muchas otras formas de agrupación. Por lo general, no devuelven ninguna ordenación (“mapa”) y proporcionan solo membresía al clúster. Por ejemplo, k-means clustering intenta obtener el número de clústeres especificado a priori a partir de los datos brutos (no necesita que se suministre la matriz de distancia):

    Código\(\PageIndex{41}\) (R):

    eq <- read.table("data/eq.txt", h=TRUE)
    eq.k <- kmeans(eq[,-1], 2)

    La agrupación de K-medias no traza árboles; en su lugar, para cada objeto devuelve el número de su clúster:

    Código\(\PageIndex{42}\) (R):

    eq <- read.table("data/eq.txt", h=TRUE)
    eq.k <- kmeans(eq[,-1], 2)
    str(eq.k$cluster)
    Misclass(eq.k$cluster, eq$SPECIES) # asmisc.r

    (Como ve, los errores de clasificación errónea son bajos).

    En lugar de un número de clúster a priori, la función kmeans () también acepta números de fila de centros de clúster.

    La agrupación espectral del paquete kernlab es un método superficialmente similar capaz de separar elementos realmente enredados:

    Código\(\PageIndex{43}\) (R):

    library(kernlab)
    data(spirals)
    set.seed(1)
    sc <- specc(spirals, centers=2)
    plot(spirals, col=sc, xlab="", ylab="")
    Screen Shot 2019-01-23 a las 10.34.23 PM.png
    Figura El agrupamiento espectral\(\PageIndex{23}\) basado en núcleos es capaz de separar dos espirales.

    Los métodos del kernel (como la agrupación espectral) recalculan los datos primarios para que sean más adecuados para el análisis. Soporte de máquinas vectoriales (SVM, ver abajo) es otro ejemplo. También hay kernel PCA (función kpca () en el paquete kernlab).

    El siguiente grupo de métodos de agrupamiento se basa en la lógica difusa y toma en cuenta la borrosidad de las relaciones. Siempre existe la posibilidad de que un objeto particular clasificado en el clúster A pertenezca al clúster B diferente, y la agrupación difusa intenta medir esta posibilidad:

    Código\(\PageIndex{44}\) (R):

    library(cluster)
    iris.f <- fanny(iris[, 1:4], 3)
    head(data.frame(sp=iris[, 5], iris.f$membership))

    La parte textual de la salida de fanny () es lo más interesante. Cada fila contiene múltiples valores de pertenencia que representan la probabilidad de que este objeto esté en el clúster en particular. Por ejemplo, la sexta planta probablemente pertenece al primer racimo pero también hay atracción visible hacia el tercer racimo. Además, fanny () puede redondear membresías y producir clústeres duros como otros métodos de clúster:

    Código\(\PageIndex{45}\) (R):

    Misclass(iris.f$clustering, factor(iris[, 5], levels=c("setosa", "virginica", "versicolor"))) # asmisc.r

    (Tuvimos que volver a nivelar la variable Especie porque fanny () da el número 2 al racimo de Iris virginica).

    Cómo conocer los números de clúster

    Todos los métodos “k-means and friends” quieren saber el número de clústeres antes de que comiencen. Entonces, ¿cómo saber a priori cuántos clusters presentan en los datos? Esta pregunta es una de las más importantes en la agrupación, tanto práctica como teóricamente.

    El análisis visual de la trama de pancartas (inventado por Kaufman & Rousseeuw, 1990) podría predecir este número (Figura\(\PageIndex{24}\)):

    Código\(\PageIndex{46}\) (R):

    eq <- read.table("data/eq.txt", h=TRUE)
    library(cluster)
    eq.a <- agnes(eq[,-1])
    plot(eq.a, which=1, col=c(0, "maroon"))
    Screen Shot 2019-01-23 a las 10.41.12 PM.png
    Figura\(\PageIndex{25}\) Banner plot. Las barras blancas sugieren posibles particiones de clúster.

    Las barras blancas a la izquierda representan datos no agrupados, las líneas granate a la derecha muestran la altura de posibles cúmulos. Por lo tanto, dos clusters es la solución más natural, cuatro clusters deberían ser la siguiente opción posible.

    La agrupación basada en modelos permite determinar cuántos clústeres están presentes en los datos y también la pertenencia a clústeres. El método asume que los clústeres tienen la naturaleza particular y las formas multidimensionales:

    Código\(\PageIndex{47}\) (R):

    library(mclust)
    iris.mclust <- Mclust(iris[, -5])
    summary(iris.mclust) # 2 clusters
    iris.mclust$classification

    (Como veis, revela sólo dos cúmulos. Esto es explicable porque en los datos del iris dos especies son mucho más similares que la tercera.)

    DBSCAN es el potente algoritmo para el big data (como imágenes ráster que constan de miles de millones de píxeles) y existe el paquete R con el mismo nombre (en minúsculas). DBSCAN revela cuántos clústeres hay en los datos a una resolución particular:

    Código\(\PageIndex{48}\) (R):

    library(dbscan)
    kNNdistplot(iris[, -5], k = 5)
    abline(h=.5, col = "red", lty=2)
    (iris.dbscan <- dbscan(iris[, -5], eps = .5, minPts = 5))
    plot(iris.p, type="n", xlab="", ylab="")
    text(iris.p, labels=abbreviate(iris[, 5], 1, method="both.sides"), col=iris.dbscan$cluster+1)

    (No se muestran las parcelas, por favor hágalo usted mismo. Primera parcela ayuda a encontrar el tamaño de barrio (mirada en la rodilla). El segundo ilustra los resultados. De manera similar a la agrupación basada en modelos, DBSCAN revela por defecto solo dos clústeres en los datos del iris).

    Tenga en cuenta que si bien DBSCAN no pudo recuperar las tres especies, recuperó nubes, y también coloca puntos marginales en el grupo de “ruido”. DBSCAN, como ves, es útil para suavizar, parte importante del reconocimiento de imágenes. El parámetro eps permite cambiar la “resolución” de la agrupación y encontrar más, o menos, clústeres. DBSCAN se relaciona con T-SNE (ver arriba) y con métodos supervisados basados en proximidad (como KnN, ver abajo). También puede supervisarse a sí mismo y predecir clústeres para nuevos puntos. Tenga en cuenta que k-medias y DBSCAN se basan en proximidades calculadas específicamente, no directamente en distancias.

    Las estrellas de datos contienen información sobre las 50 estrellas más brillantes en el cielo nocturno, su ubicación y constelaciones. Por favor, use DBSCAN para hacer constelaciones artificiales en la base de la proximidad de estrellas. ¿Cómo se relacionan con las constelaciones reales?

    Obsérvese que la ubicación (ascensión derecha y declinación) se da en grados u horas (sistema sexagesimal), deben convertirse en decimales.

    El método de “cambio de media” busca modos dentro de los datos, que en esencia, es similar a encontrar proximidades. El algoritmo de desplazamiento medio del núcleo es lento, por lo que la versión aproximada de “desenfoque” es típicamente preferible:

    Código\(\PageIndex{49}\) (R):

    library(MeanShift)
    bandwidth <- quantile(dist(iris[, -5]), 0.25)
    (bmsClustering(t(iris[, -5]), h=bandwidth))

    Otro enfoque para encontrar el número de clúster es similar a la trama de pantalla de PCA:

    Código\(\PageIndex{50}\) (R):

    eq <- read.table("data/eq.txt", h=TRUE)
    library(cluster)
    eq.a <- agnes(eq[,-1])
    wss <- (nrow(eq[,-1]) - 1) * sum(apply(eq[,-1], 2, var))
    for (i in 2:15) wss[i] <- sum(kmeans(eq[,-1], centers=i)$withinss)
    barplot(wss, names.arg=1:15, xlab="Number of clusters", main="Sums of squares within groups", yaxt="n", ylab="")

    (Por favor revise esta parcela usted mismo. Al igual que en la parcela de estandarte, es visible que los “acantilados” relativos más altos están después de los números de racimo 1 y 4

    Colección asmisc.r contiene la función Peaks () que ayuda a encontrar máximos locales en una secuencia de datos simple. El número de estos picos en el histograma (con el número sensible de descansos) debe apuntar al número de clústeres:

    Código\(\PageIndex{51}\) (R):

    histdata <- hist(apply(scale(iris[, -5]), 1, function(.x) sum(abs(.x))), breaks=10, plot=FALSE)
    sum(Peaks(histdata$counts))
    > 
    [1] 3

    (“Tres” es el primer número de picos después de “uno” y no cambia cuando 8 < se rompe < 22.)

    Finalmente, el paquete integrador NBCLust permite utilizar diversos métodos para evaluar el número putativo de clústeres:

    Código\(\PageIndex{52}\) (R):

    library(NbClust)
    iris.nb <- NbClust(iris[, -5], method="ward.D") # wait!

    Cómo comparar diferentes ordenaciones

    La mayoría de los métodos de clasificación dan como resultado alguna ordenación, gráfica 2D que incluye todos los puntos de datos. Esto permite compararlos con el análisis de Procrustes (ver Apéndice para más detalles) que rota y escala una matriz de datos para hacer en máxima similar con la segunda (objetivo). Comparemos los resultados de los clásicos PCA y T-SNE:

    Código\(\PageIndex{53}\) (R):

    irisu.pca <- prcomp(iris.unique[, 1:4], scale=TRUE)
    irisu.p <- irisu.pca$x[, 1:2]
    library(vegan)
    irisu.pr <- procrustes(irisu.p, tsne.out$Y)
    plot(irisu.pr, ar.col=iris.unique$Species, xlab="", ylab="", main="") # arrows point to target (PCA)
    with(iris.unique, legend("topright", pch="↑", col=1:nlevels(Species), legend=levels(Species), bty="n"))
    legend("bottomright", lty=2:1, legend=c("PCA", "t-SNE"), bty="n")

    La gráfica resultante (Figura 7.3.1) muestra qué tan densos son los puntos en t-SNE y cómo los propaga PCA. ¿Cuál de los métodos hace mejor agrupación? Encuéntralo tú mismo.

    Referencias

    1. Paquete Boruta es especialmente dios para toda la selección de características relevantes.


    This page titled 7.2: Clasificación sin aprendizaje is shared under a Public Domain license and was authored, remixed, and/or curated by Alexey Shipunov via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.