El método de descenso de gradiente y ecuación normal para resolver la regresión lineal da diferentes soluciones
Estoy trabajando en un problema de aprendizaje automático y quiero usar la regresión lineal como algoritmo de aprendizaje. He implementado 2 métodos diferentes para encontrar parámetros.theta
del modelo de regresión lineal: descenso de gradiente (más pronunciado) y ecuación normal. En los mismos datos ambos deben dar aproximadamente igualtheta
vector. Sin embargo no lo hacen.
Ambostheta
Los vectores son muy similares en todos los elementos, pero el primero. Ese es el usado para multiplicar el vector de todos los 1 agregados a los datos.
Aquí es cómo eltheta
s parece que (la primera columna es la salida de Pendiente descendente, la segunda salida de la ecuación Normal):
Grad desc Norm eq
-237.7752 -4.6736
-5.8471 -5.8467
9.9174 9.9178
2.1135 2.1134
-1.5001 -1.5003
-37.8558 -37.8505
-1.1024 -1.1116
-19.2969 -19.2956
66.6423 66.6447
297.3666 296.7604
-741.9281 -744.1541
296.4649 296.3494
146.0304 144.4158
-2.9978 -2.9976
-0.8190 -0.8189
¿Qué puede causar la diferencia entheta(1, 1)
regresado por pendiente de gradiente en comparación contheta(1, 1)
devuelto por la ecuación normal? ¿Tengo error en mi código?
Aquí está mi implementación de la ecuación normal en Matlab:
function theta = normalEque(X, y)
[m, n] = size(X);
X = [ones(m, 1), X];
theta = pinv(X'*X)*X'*y;
end
Aquí está el código para el descenso del gradiente:
function theta = gradientDesc(X, y)
options = optimset('GradObj', 'on', 'MaxIter', 9999);
[theta, ~, ~] = fminunc(@(t)(cost(t, X, y)),...
zeros(size(X, 2), 1), options);
end
function [J, grad] = cost(theta, X, y)
m = size(X, 1);
X = [ones(m, 1), X];
J = sum((X * theta - y) .^ 2) ./ (2*m);
for i = 1:size(theta, 1)
grad(i, 1) = sum((X * theta - y) .* X(:, i)) ./ m;
end
end
Yo paso exactamente los mismos datosX
yy
a ambas funciones (no normalizoX
).
Basándome en las respuestas y los comentarios, revisé algunos códigos y realicé algunas pruebas.
Primero quiero comprobar si el problema puede deberse a que X esté cerca del singular como lo sugiereLa respuesta de @ user1489497. Así que reemplacé a pinv por inv, y cuando lo ejecuté realmente obtuve una advertenciaMatrix is close to singular or badly scaled.
. Para asegurarme de que ese no es el problema, obtuve un conjunto de datos mucho más grande y ejecuté pruebas con este nuevo conjunto de datos. Esta vezinv(X)
no mostró la advertencia y el usopinv
yinv
Dio los mismos resultados. Así que espero queX
Ya no está cerca de singular.
EntoncesCambiénormalEque
código como se sugiere porastillas de madera así que ahora se ve como:
function theta = normalEque(X, y)
X = [ones(size(X, 1), 1), X];
theta = pinv(X)*y;
end
Sin embargo el problema sigue ahí.. NuevonormalEque
Funcionar sobre nuevos datos que no están cerca de singular da diferentestheta
comogradientDesc
.
Para averiguar qué algoritmo tiene errores, he ejecutado el algoritmo de regresión lineal del software de minería de datos Weka en los mismos datos. Weka computa theta muy similar a la salida denormalEque
pero diferente a la salida degradientDesc
. Así que supongo quenormalEque
es correcto yhay un error engradientDesc
.
Aquí está la comparación detheta
s calculado por Weka,normalEque
yGradientDesc
:
Weka(correct) normalEque gradientDesc
779.8229 779.8163 302.7994
1.6571 1.6571 1.7064
1.8430 1.8431 2.3809
-1.5945 -1.5945 -1.5964
3.8190 3.8195 5.7486
-4.8265 -4.8284 -11.1071
-6.9000 -6.9006 -11.8924
-15.6956 -15.6958 -13.5411
43.5561 43.5571 31.5036
-44.5380 -44.5386 -26.5137
0.9935 0.9926 1.2153
-3.1556 -3.1576 -1.8517
-0.1927 -0.1919 -0.6583
2.9207 2.9227 1.5632
1.1713 1.1710 1.1622
0.1091 0.1093 0.0084
1.5768 1.5762 1.6318
-1.3968 -1.3958 -2.1131
0.6966 0.6963 0.5630
0.1990 0.1990 -0.2521
0.4624 0.4624 0.2921
-12.6013 -12.6014 -12.2014
-0.1328 -0.1328 -0.1359
También calculé errores según lo sugerido porLa respuesta de justin peel. Salida denormalEque
da un error al cuadrado ligeramente menor pero la diferencia es marginal. Qué es máscuando calculo gradiente de costo detheta
usando la funcióncost
(igual a la utilizada porgradientDesc
) Tengo gradiente cerca de cero. Lo mismo se hace en la salida degradientDesc
No da gradiente cerca de cero. Esto es lo que quiero decir:
>> [J_gd, grad_gd] = cost(theta_gd, X, y, size(X, 1));
>> [J_ne, grad_ne] = cost(theta_ne, X, y, size(X, 1));
>> disp([J_gd, J_ne])
120.9932 119.1469
>> disp([grad_gd, grad_ne])
-0.005172856743846 -0.000000000908598
-0.026126463200876 -0.000000135414602
-0.008365136595272 -0.000000140327001
-0.094516503056041 -0.000000169627717
-0.028805977931093 -0.000000045136985
-0.004761477661464 -0.000000005065103
-0.007389474786628 -0.000000005010731
0.065544198835505 -0.000000046847073
0.044205371015018 -0.000000046169012
0.089237705611538 -0.000000046081288
-0.042549228192766 -0.000000051458654
0.016339232547159 -0.000000037654965
-0.043200042729041 -0.000000051748545
0.013669010209370 -0.000000037399261
-0.036586854750176 -0.000000027931617
-0.004761447097231 -0.000000027168798
0.017311225027280 -0.000000039099380
0.005650124339593 -0.000000037005759
0.016225097484138 -0.000000039060168
-0.009176443862037 -0.000000012831350
0.055653840638386 -0.000000020855391
-0.002834810081935 -0.000000006540702
0.002794661393905 -0.000000032878097
Esto sugeriría que el descenso del gradiente simplemente no converge al mínimo global ... Pero ese no es el caso, ya que lo ejecuto durante miles de iteraciones.Entonces, ¿dónde está el error?