machine learning - learning - pendiente de gradiente parece fallar
gradientdescent octave (8)
Implementé un algoritmo de descenso de gradiente para minimizar una función de costo con el fin de obtener una hipótesis para determinar si una imagen tiene una buena calidad. Lo hice en Octave. La idea se basa de alguna manera en el algoritmo de la clase de aprendizaje automático de Andrew Ng
Por lo tanto, tengo 880 valores "y" que contienen valores de 0.5 a ~ 12. Y tengo 880 valores de 50 a 300 en "X" que deberían predecir la calidad de la imagen.
Lamentablemente, el algoritmo parece fallar, después de algunas iteraciones, el valor de theta es tan pequeño que theta0 y theta1 se convierten en "NaN". Y mi curva de regresión lineal tiene valores extraños ...
aquí está el código para el algoritmo de descenso de gradiente: ( theta = zeros(2, 1);
alfa = 0.01, iteraciones = 1500)
function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
m = length(y); % number of training examples
J_history = zeros(num_iters, 1);
for iter = 1:num_iters
tmp_j1=0;
for i=1:m,
tmp_j1 = tmp_j1+ ((theta (1,1) + theta (2,1)*X(i,2)) - y(i));
end
tmp_j2=0;
for i=1:m,
tmp_j2 = tmp_j2+ (((theta (1,1) + theta (2,1)*X(i,2)) - y(i)) *X(i,2));
end
tmp1= theta(1,1) - (alpha * ((1/m) * tmp_j1))
tmp2= theta(2,1) - (alpha * ((1/m) * tmp_j2))
theta(1,1)=tmp1
theta(2,1)=tmp2
% ============================================================
% Save the cost J in every iteration
J_history(iter) = computeCost(X, y, theta);
end
end
Y aquí está el cálculo para la función de costo:
function J = computeCost(X, y, theta) %
m = length(y); % number of training examples
J = 0;
tmp=0;
for i=1:m,
tmp = tmp+ (theta (1,1) + theta (2,1)*X(i,2) - y(i))^2; %differenzberechnung
end
J= (1/(2*m)) * tmp
end
Aunque no es escalable como una versión vectorizada, un cálculo basado en bucles de un descenso de gradiente debería generar los mismos resultados. En el ejemplo anterior, el caso más probable del descenso del gradiente al no poder calcular el theta correcto es el valor de alfa.
Con un conjunto verificado de funciones de descenso de gradiente y coste y un conjunto de datos similar al descrito en la pregunta, theta termina con valores NaN justo después de algunas iteraciones si alpha = 0.01
. Sin embargo, cuando se establece como alpha = 0.000001
, el descenso del gradiente funciona como se esperaba, incluso después de 100 iteraciones.
Creo que su función computeCost
es incorrecta. Asistí a la clase de NG el año pasado y tengo la siguiente implementación (vectorizada):
m = length(y);
J = 0;
predictions = X * theta;
sqrErrors = (predictions-y).^2;
J = 1/(2*m) * sum(sqrErrors);
El resto de la implementación me parece bien, aunque también puedes vectorizarlos.
theta_1 = theta(1) - alpha * (1/m) * sum((X*theta-y).*X(:,1));
theta_2 = theta(2) - alpha * (1/m) * sum((X*theta-y).*X(:,2));
Luego está configurando las thetas temporales (aquí llamadas theta_1 y theta_2) correctamente de regreso al theta "real".
En general, es más útil vectorizar en lugar de bucles, es menos molesto leer y depurar.
Esto debería funcionar:-
theta(1,1) = theta(1,1) - (alpha*(1/m))*((X*theta - y)''* X(:,1) );
theta(2,1) = theta(2,1) - (alpha*(1/m))*((X*theta - y)''* X(:,2) );
Si está bien con el uso de una función de costo por mínimos cuadrados, entonces podría intentar usar la ecuación normal en lugar de la pendiente de gradiente. Es mucho más simple, solo una línea, y computacionalmente más rápido.
Aquí está la ecuación normal: http://mathworld.wolfram.com/NormalEquation.html
Y en forma de octava:
theta = (pinv(X'' * X )) * X'' * y
Aquí hay un tutorial que explica cómo usar la ecuación normal: http://www.lauradhamilton.com/tutorial-linear-regression-with-octave
Si se está preguntando cómo el bucle de búsqueda aparentemente complejo se puede vectorizar y agrupar en una única expresión de una línea, continúe leyendo. La forma vectorizada es:
theta = theta - (alpha/m) * (X'' * (X * theta - y))
A continuación se presenta una explicación detallada de cómo llegamos a esta expresión vectorizada usando un algoritmo de descenso de gradiente:
Este es el algoritmo de descenso de gradiente para ajustar el valor de θ:
Supongamos que se dan los siguientes valores de X, y y::
- m = número de ejemplos de entrenamiento
- n = número de características + 1
aquí
- m = 5 (ejemplos de entrenamiento)
- n = 4 (características + 1)
- X = matriz mxn
- y = mx 1 matriz vectorial
- θ = nx 1 matriz de vectores
- x i es el i ejemplo de entrenamiento
- x j es la j ésima característica en un ejemplo de entrenamiento dado
Promover,
-
h(x) = ([X] * [θ])
(mx 1 matriz de valores predichos para nuestro conjunto de entrenamiento) -
h(x)-y = ([X] * [θ] - [y])
(mx 1 matriz de errores en nuestras predicciones)
el objetivo general del aprendizaje automático es minimizar los errores en las predicciones. En base al corolario anterior, nuestra matriz de errores es la matriz vectorial mx 1
siguiente manera:
Para calcular el nuevo valor de θ j , tenemos que obtener una suma de todos los errores (m filas) multiplicado por el valor de j elemento del conjunto de entrenamiento X. Es decir, tomar todos los valores en E, multiplicarlos individualmente con j característica del ejemplo de entrenamiento correspondiente , y agréguelos todos juntos. Esto nos ayudará a obtener el nuevo (y, con suerte, mejor) valor de θ j . Repita este proceso para todas las j o la cantidad de funciones. En forma de matriz, esto se puede escribir como:
Esto se puede simplificar como:
-
[E]'' x [X]
nos dará una matriz de vectores de filas, ya que E'' es una matriz de 1 xm y X es una matriz de mxn. Pero estamos interesados en obtener una matriz de columna, por lo tanto, transponemos la matriz resultante.
De manera más sucinta, se puede escribir como:
Dado que (A * B)'' = (B'' * A'')
, y A'''' = A
, también podemos escribir lo anterior como
Esta es la expresión original con la que comenzamos:
theta = theta - (alpha/m) * (X'' * (X * theta - y))
Usando solo vectores aquí está la implementación compacta de LR con Gradient Descent en Mathematica:
Theta = {0, 0}
alpha = 0.0001;
iteration = 1500;
Jhist = Table[0, {i, iteration}];
Table[
Theta = Theta -
alpha * Dot[Transpose[X], (Dot[X, Theta] - Y)]/m;
Jhist[[k]] =
Total[ (Dot[X, Theta] - Y[[All]])^2]/(2*m); Theta, {k, iteration}]
Nota: Por supuesto, uno asume que X es una matriz * 2, con X [[, 1]] que contiene solo 1s ''
es más limpio de esta manera, y vectorizado también
predictions = X * theta;
errorsVector = predictions - y;
theta = theta - (alpha/m) * (X'' * errorsVector);
he vectorizado lo theta ... podría ayudar a alguien
theta = theta - (alpha/m * (X * theta-y)'' * X)'';