4 votos

¿Se trata de un error en la estandarización de características de la regresión de crestas en el libro Machine Learning in Action?

Soy nuevo en la ML. Actualmente estoy leyendo el libro clásico Aprendizaje automático en acción por Peter Harrington. En su implementación de la regresión de cresta en el listado P165 8.3, el libro estandariza la matriz de características $X$ restando los medios de los atributos y dividiéndolos por varianzas de los atributos no por desviaciones estándar de los atributos ¡! Como sigue:

def ridgeRegres(xMat,yMat,lam=0.2):
    xTx = xMat.T*xMat
    denom = xTx + eye(shape(xMat)[1])*lam
    if linalg.det(denom) == 0.0:
        print "This matrix is singular, cannot do inverse"
        return
    ws = denom.I * (xMat.T*yMat)
    return ws

def ridgeTest(xArr,yArr):
    xMat = mat(xArr); yMat=mat(yArr).T
    yMean = mean(yMat,0)
    yMat = yMat - yMean     #to eliminate X0 take mean off of Y
    #regularize X's
    xMeans = mean(xMat,0)   #calc mean then subtract it off
    xVar = var(xMat,0)      #calc variance of Xi then divide by it
    xMat = (xMat - xMeans)/xVar
    numTestPts = 30
    wMat = zeros((numTestPts,shape(xMat)[1]))
    for i in range(numTestPts):
        ws = ridgeRegres(xMat,yMat,exp(i-10))
        wMat[i,:]=ws.T
    return wMat

Luego llama a ridgeTest por

>>> abX,abY=regression.loadDataSet('abalone.txt')
>>> ridgeWeights=regression.ridgeTest(abX,abY)

No creo que esto tenga ningún sentido. Según normalización Para crear una varianza unitaria, debemos dividir $X-\mu$ por desviación estándar $\sigma$ Porque..: $$ D(\frac{X-\mu}{\sigma})=\frac{1}{\sigma^2}D(X)=\frac{1}{\sigma^2}\sigma^2=1, $$ donde $D(X)=\sigma^2$ es la varianza de $X$ .

Si según el libro, dividir $X-\mu$ por varianza $\sigma^2$ Sólo conseguimos..: $$ D(\frac{X-\mu}{\sigma^2})=\frac{1}{\sigma^4}D(X)=\frac{1}{\sigma^4}\sigma^2=\frac{1}{\sigma^2}, $$ que no es una varianza unitaria.

La razón por la que no estoy tan seguro de que se trate de un error es que, en primer lugar, el libro maneja $Y$ cuidadosamente restando su media y no incluir una columna todo 1 en $X$ aprobado, ambos me parecen adecuados (véase La normalización L2 no castiga la intercepción ). Por lo tanto, no creo que el libro cometa un error tan evidente como éste. En segundo lugar, ni la fe de erratas (véase errata ) o en el foro del libro ya se ha hablado de él. No es un libro nuevo.

Aunque he publicado dividir por std no por varianza en el foro del libro, aún no se ha recibido respuesta. Así que recurro al intercambio de pilas. ¿La estandarización de las características del libro divide erróneamente $X-\mu$ por la varianza o es una acción significativa?

Muchas gracias de antemano. Cualquier pista me ayudará.

0 votos

Hay diferentes maneras de escalar sus datos . La que describes (restar la media, dividir por el std dev) es posiblemente la más común, llamada z-scaling. Si se divide por la varianza, como señalas, no se consigue una varianza unitaria en todas las características, por lo que se acaban teniendo datos escalados centrados en la media en los que cada característica tiene una varianza diferente.

3voto

Even Mien Puntos 10122

Respuesta corta

Sí, parece ser un error y puede tener un impacto importante en la forma de penalizar algunas variables.

Si tienes dos variables con diferente magnitud, este reescalado con básicamente dar una desviación estándar baja al valor con la desviación estándar (inicial) más grande. Por lo tanto, esta variable sufrirá una penalización menor de la que debería. Y esto hará que su regresión dependa de la unidad en la que se expresan los valores (lo cual no es una característica deseable).

Nota al margen

El algoritmo escala la entrada, pero devuelve las salidas evaluadas en las entradas escaladas. Esto hace que sea bastante difícil implementar una función de "predicción"...

Experimento numérico

He solucionado el problema (en el caso de que no haya intercepción) para que el algoritmo devuelva wMat[i,:]=ws.T / xVar .

import numpy as np
import matplotlib.pyplot as plt

def ridgeRegres(xMat,yMat,lam=0.2):
    xTx = xMat.T*xMat
    denom = xTx + np.eye(np.shape(xMat)[1])*lam
    if np.linalg.det(denom) == 0.0:
        print "This matrix is singular, cannot do inverse"
        return
    ws = denom.I * (xMat.T*yMat)
    return ws

# Assuming there is not intercept : y = x_0 + 2 * x_1

def ridgeTest(xArr,yArr):
    xMat = np.mat(xArr); yMat=np.mat(yArr).T
    yMean = np.mean(yMat,0)
    yMat = yMat - yMean     #to eliminate X0 take mean off of Y
    #regularize X's
    xMeans = np.mean(xMat,0)   #calc mean then subtract it off
    xVar = np.var(xMat,0)      #calc variance of Xi then divide by it
    xMat = (xMat - xMeans)/xVar
    numTestPts = 30
    wMat = np.zeros((numTestPts,np.shape(xMat)[1]))
    for i in range(numTestPts):
        ws = ridgeRegres(xMat,yMat,np.exp(i-10))
        wMat[i,:]=ws.T / xVar
    return wMat 

X = np.mat(np.random.rand(50,2))
y = np.mat([1,2]) * X.T 

res_orig = ridgeTest(X,y)

plt.plot(res_orig)
plt.title('Original Scaling')
plt.ylabel('Values of the (estimated) coefficient.')
plt.xlabel('Value of the penalization.')
plt.show()

X[:,1] *= 10
y = np.mat([1,2]) * X.T 
res = ridgeTest(X,y)

plt.plot(res)
plt.title('x_1 has been multiplied by 10')
plt.ylabel('Values of the (estimated) coefficient.')
plt.xlabel('Value of the penalization.')
plt.show()

Resultado

El resultado con la escala original proporciona los valores reales ( $y=x_0+2x_1$ ) mientras que el segundo caso presenta un comportamiento extraño.

enter image description here

enter image description here

Editar

Como dice @Berkmeister en los comentarios, este escalamiento puede ser defendido : en muchos modelos, se puede decidir, arbitrariamente, cambiar los pesos de sus características.

Pero, el hecho de que los coeficientes devueltos por el modelo no se reescalen, y que esta elección de escala (poco común) se proponga sin explicaciones previas, me hace pensar que este código puede ser mejorado.

1 votos

Muchas gracias. No sólo me dices que es un error, sino que lo demuestras experimentalmente. Aprendo mucho sobre cómo probar un modelo a partir de esta respuesta.

0 votos

Machine Learning in Action no debería tener errores como este. Ya que tiene muchos lectores y la mayoría de ellos (como yo) son nuevos en ML y no pueden distinguir lo correcto de lo incorrecto. La influencia puede ser muy mala. Acabo de actualizar mi post sobre este problema en el foro del libro, esperando que el autor se dé cuenta y lo añada a la fe de erratas.

0 votos

@Naomi gracias, he arreglado el problema del índice. En caso de duda, también puedes compararlo con otras implementaciones muy extendidas (sk-learn tiene una implementación de regresión ridge y R tiene el famoso paquete glmnet, por ejemplo), pero la otra advertencia es que tienes que asegurarte de que los parámetros se expresan de forma similar...

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