seleccion regresion probabilidad momentos lineal intervalo graficos estadisticos distribuciones confianza caracteristicas bondad ajuste matlab machine-learning classification logistic-regression gradient-descent

regresion - seleccion de caracteristicas matlab



La función de costo en la regresión logística da NaN como resultado (2)

Estoy implementando la regresión logística usando el descenso del gradiente de lotes. Hay dos clases en las que se deben clasificar las muestras de entrada. Las clases son 1 y 0. Mientras entreno los datos, estoy usando la siguiente función sigmoide:

t = 1 ./ (1 + exp(-z));

dónde

z = x*theta

Y estoy usando la siguiente función de costo para calcular el costo, para determinar cuándo dejar de entrenar.

htheta = sigmoid(x*theta); cost = sum(-y .* log(htheta) - (1-y) .* log(1-htheta));

Estoy recibiendo el costo en cada paso para ser NaN ya que los valores de htheta son 1 o cero en la mayoría de los casos. ¿Qué debo hacer para determinar el valor del costo en cada iteración?

Este es el código de descenso de gradiente para la regresión logística:

function [theta,cost_history] = batchGD(x,y,theta,alpha) cost_history = zeros(1000,1); for iter=1:1000 htheta = sigmoid(x*theta); new_theta = zeros(size(theta,1),1); for feature=1:size(theta,1) new_theta(feature) = theta(feature) - alpha * sum((htheta - y) .*x(:,feature)) end theta = new_theta; cost_history(iter) = computeCost(x,y,theta); end end


Hay dos posibles razones por las cuales esto puede estar sucediendo.

Los datos no están normalizados

Esto se debe a que cuando aplica la función sigmoide / logit a su hipótesis, las probabilidades de salida son casi todas aproximadamente 0 o todas 1 y con su función de costo, log(1 - 1) o log(0) producirá -Inf . La acumulación de todos estos términos individuales en su función de costo eventualmente llevará a NaN .

Específicamente, si y = 0 para un ejemplo de entrenamiento y si el resultado de su hipótesis es log(x) donde x es un número muy pequeño que está cerca de 0, examinar la primera parte de la función de costo nos daría 0*log(x) y de hecho producirá NaN . De manera similar, si y = 1 para un ejemplo de entrenamiento y si el resultado de su hipótesis es también log(x) donde x es un número muy pequeño, esto nuevamente nos daría 0*log(x) y producirá NaN . En pocas palabras, el resultado de su hipótesis es muy cercano a 0 o muy cercano a 1.

Esto probablemente se deba al hecho de que el rango dinámico de cada característica es muy diferente y, por lo tanto, una parte de su hipótesis, específicamente la suma ponderada de x*theta para cada ejemplo de capacitación, le dará valores negativos o positivos muy grandes. , y si aplicas la función sigmoidea a estos valores, te acercarás a 0 o 1.

Una forma de combatir esto es normalizar los datos en su matriz antes de realizar el entrenamiento utilizando el descenso de gradiente. Un enfoque típico es normalizar con media cero y varianza unitaria. Dada una característica de entrada x_k donde k = 1, 2, ... n donde tiene n características, la nueva característica normalizada x_k^{new} se puede encontrar por:

m_k es la media de la característica k s_k es la desviación estándar de la característica k . Esto también se conoce como estandarización de datos. Puede leer más detalles sobre esto en otra respuesta que di aquí: ¿Cómo funciona este código para estandarizar los datos?

Debido a que está utilizando el enfoque de álgebra lineal para el descenso de gradiente, supongo que ha antepuesto su matriz de datos con una columna de todos. Sabiendo esto, podemos normalizar sus datos de esta manera:

mX = mean(x,1); mX(1) = 0; sX = std(x,[],1); sX(1) = 1; xnew = bsxfun(@rdivide, bsxfun(@minus, x, mX), sX);

La media y las desviaciones estándar de cada característica se almacenan en mX y sX respectivamente. Puedes aprender cómo funciona este código leyendo la publicación que te he vinculado más arriba. No voy a repetir esas cosas aquí porque ese no es el alcance de esta publicación. Para asegurar la normalización adecuada, he hecho que la desviación media y estándar de la primera columna sea 0 y 1 respectivamente. xnew contiene la nueva matriz de datos normalizada. Use xnew con su algoritmo de descenso de gradiente en su lugar. Ahora, una vez que encuentre los parámetros, para realizar cualquier predicción, debe normalizar cualquier nueva instancia de prueba con la media y la desviación estándar del conjunto de entrenamiento . Debido a que los parámetros aprendidos son con respecto a las estadísticas del conjunto de entrenamiento, también debe aplicar las mismas transformaciones a cualquier dato de prueba que desee enviar al modelo de predicción.

Suponiendo que tiene nuevos puntos de datos almacenados en una matriz llamada xx , debería normalizar y luego realizar las predicciones:

xxnew = bsxfun(@rdivide, bsxfun(@minus, xx, mX), sX);

Ahora que tienes esto, puedes realizar tus predicciones:

pred = sigmoid(xxnew*theta) >= 0.5;

Puedes cambiar el umbral de 0.5 para que sea lo que creas que es lo mejor que determina si los ejemplos pertenecen a la clase positiva o negativa.

La tasa de aprendizaje es demasiado grande

Como mencionaste en los comentarios, una vez que normalizas los datos, los costos parecen ser finitos, pero de repente pasan a NaN después de algunas iteraciones. La normalización solo puede llevarte tan lejos. Si su tasa de aprendizaje o alpha es demasiado grande, cada iteración se rebasará en la dirección hacia el mínimo y, por lo tanto, hará que el costo en cada iteración oscile o incluso diverja, que es lo que parece estar sucediendo. En su caso, el costo es divergente o aumenta en cada iteración hasta el punto en que es tan grande que no se puede representar utilizando la precisión de coma flotante.

Como tal, otra opción es disminuir su tasa de aprendizaje alpha hasta que vea que la función de costo está disminuyendo en cada iteración. Un método popular para determinar cuál es la mejor tasa de aprendizaje es realizar un descenso de gradiente en un rango de valores de alpha logarítmicamente espaciados y ver cuál es el valor de la función de costo final y elegir la tasa de aprendizaje que resultó en el menor costo.

Usar los dos hechos anteriores juntos debería permitir que el descenso del gradiente converja bastante bien, suponiendo que la función del costo sea convexa. En este caso para la regresión logística, sin duda lo es.


Supongamos que tienes una observación donde:

  • el verdadero valor es y_i = 1
  • su modelo es bastante extremo y dice que P (y_i = 1) = 1

Entonces su función de costo obtendrá un valor de NaN porque está agregando 0 * log(0) , que no está definido. Por lo tanto:

Su fórmula para la función de costo tiene un problema (¡hay un sutil 0, problema de infinito)!

Como señaló @rayryeng, 0 * log(0) produce un NaN porque 0 * Inf no es kosher. Esto es realmente un gran problema: si su algoritmo cree que puede predecir un valor perfectamente, asigna incorrectamente un costo de NaN .

En lugar de:

cost = sum(-y .* log(htheta) - (1-y) .* log(1-htheta));

Puede evitar multiplicar 0 por infinito escribiendo su función de costo en Matlab como:

y_logical = y == 1; cost = sum(-log(htheta(y_logical))) + sum( - log(1 - htheta(~y_logical)));

La idea es si y_i es 1, agregamos -log(htheta_i) al costo, pero si y_i es 0, agregamos -log(1 - htheta_i) al costo. Esto es matemáticamente equivalente a -y_i * log(htheta_i) - (1 - y_i) * log(1- htheta_i) pero sin -y_i * log(htheta_i) - (1 - y_i) * log(1- htheta_i) problemas numéricos que esencialmente provienen de que htheta_i es igual a 0 o 1 dentro de los límites de la doble precisión del punto flotante .