9 votos

Replicar Shalizi del New York Times PCA ejemplo

Estoy tratando de replicar Shalizi del NY Times PCA ejemplo se encuentra en su Análisis Avanzado de Datos con un Elemental Punto de Vista del libro. He encontrado ejemplos de código y datos aquí

http://www.stat.cmu.edu/~cshalizi/490/pca/

Me cargan los R área de trabajo pca-ejemplos.Rdata, y fue capaz de extraer de un archivo CSV que he puesto en

https://github.com/burakbayramli/classnotes/blob/master/app-math-tr/pca/nytimes.csv

En orden para PCA utilizando SVD, yo lo hice

from pandas import *
import numpy.linalg as lin
nyt = read_csv ("nytimes.csv")
labels = nyt['class.labels']
nyt = nyt.drop(["class.labels"],axis=1)
nyt_demeaned = nyt - nyt.mean(0)
u,s,v = lin.svd(nyt_demeaned.T,full_matrices=False)

Entonces traté de proyectar en el espacio definido por los vectores propios

nyt2 = np.dot(nyt_demeaned, u[:,0:2])

Luego de la parcela

plot(nyt2[:,0],nyt2[:,1],'.')

y

arts = nyt2[labels == 'art']
music = nyt2[labels == 'music']
plot(arts[:,0],arts[:,1],'r.')
plot(music[:,0],music[:,1],'b.')

Puedo conseguir

enter image description here

enter image description here

Esta imagen es diferente de Shalizi la imagen de su libro (utilizando el siguiente código R)

load("pca-examples.Rdata")
nyt.pca = prcomp(nyt.frame[,-1])
nyt.latent.sem = nyt.pca$rotation
    plot(nyt.pca$x[,1:2],type="n")
points(nyt.pca$x[nyt.frame[,"class.labels"]=="art",1:2],
           pch="A",col="red")
    points(nyt.pca$x[nyt.frame[,"class.labels"]=="music",1:2],
       pch="M",col="blue")

enter image description here

Tal vez había un 90 grados de error, se da la vuelta de una manera o de otra, etc. a continuación, usted quizás podría tener las dos imágenes para ser un poco estrecha, pero incluso entonces la distribución no es exactamente correcto, y los puntos de datos para las artes no son tan claramente separado de la música de puntos de datos como lo son en Shalizi de la imagen.

Alguna idea?

11voto

Max Z. Puntos 196

Resulta Shalizi hace algo más de la normalización, se llama inversa de documento ponderación de frecuencia, con este código

scale.cols <- function(x,s) {
  return(t(apply(x,1,function(x){x*s})))
}

div.by.euc.length <- function(x) {
  scale.rows(x,1/sqrt(rowSums(x^2)+1e-16))
}

idf.weight <- function(x) {
  # IDF weighting
  doc.freq <- colSums(x>0)
  doc.freq[doc.freq == 0] <- 1
  w <- log(nrow(x)/doc.freq)
  return(scale.cols(x,w))
}

load("pca-examples.Rdata")
nyt.frame.raw$class.labels <- NULL
nyt.frame <- idf.weight(nyt.frame.raw)
nyt.frame <- div.by.euc.length(nyt.frame)

Cuando me encontré con enfermedad vesicular porcina nyt.marco, en lugar de nyt.marco.raw (después de la carga, el código anterior no es necesario para eso, es sólo para demostración), las dos clases eran claramente seperable. La distribución de los puntos que todavía no se parecía a Shalizi de la imagen, pero creo que puedo trabajar con esto.

Nota: la simple lectura de nytimes4.csv, el archivo normalizado, no es suficiente, los datos todavía debe estar centrada en torno a 0 (de-meaned).

Nota: Después de saltar la caída de una falsa columna en nytimes4.csv y degradante, el resultado es exactamente el mismo que Shalizi.

La misma cosa en Python / Pandas

from pandas import *
nyt = read_csv ("nytimes.csv")
nyt = nyt.drop(['class.labels'],axis=1)
freq = nyt.astype(bool).sum(axis=0)
freq = freq.replace(0,1)
w = np.log(float(nyt.shape[0])/freq)
nyt = nyt.apply(lambda x: x*w,axis=1)
nyt = nyt.apply(lambda x: x / np.sqrt(np.sum(np.square(x))+1e-16), axis=1)

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X