Octava: regresión logística: diferencia entre fmincg y fminunc

Yo uso a menudo fminunc para un problema de regresión logística. he leido en la web que Andrew Ng usos fmincg en lugar de fminunc, con los mismos argumentos. Los resultados son diferentes, y a menudo fmincg es más exacto, pero no demasiado. (Estoy comparando los resultados de la función fmincg fminunc con los mismos datos)

Entonces, mi pregunta es: ¿cuál es la diferencia entre estas dos funciones? ¿Qué algoritmo tiene implementado cada función? (Ahora, solo uso estas funciones sin saber exactamente cómo funcionan).

Gracias :)

preguntado el 24 de agosto de 12 a las 19:08

Dónde está fmincg? No está en el núcleo de octava y tampoco está en ninguno de los paquetes de Forge. -

8 Respuestas

Tendrás que mirar dentro del código de fmincg porque no es parte de Octave. Después de buscar un poco, descubrí que es un archivo de función proporcionado por la clase de aprendizaje automático de Coursera como parte de la tarea. Lea los comentarios y las respuestas en esta pregunta para una discusión sobre los algoritmos.

contestado el 23 de mayo de 17 a las 12:05

Vaya. gracias :) No me doy cuenta de que tiene un archivo en fmincg en mi carpeta. muchas gracias - hqt

El comentario de esa pregunta no dijo nada sobre fmincg; solo estaban discutiendo fminsearch que no está relacionado con esta pregunta. La respuesta de @emrea sugiere que fmincg está implementando método de gradiente conjugado. - franklin yu

En contraste con otras respuestas aquí que sugieren que la principal diferencia entre fmincg y fminunc es la precisión o la velocidad, quizás la diferencia más importante para algunas aplicaciones es la eficiencia de la memoria. En el ejercicio de programación 4 (es decir, entrenamiento de redes neuronales) de la clase de aprendizaje automático de Andrew Ng en Coursera, el comentario en ex4.m sobre fmincg es

%% =================== Parte 8: Entrenamiento NN ===================
% Ya ha implementado todo el código necesario para entrenar un sistema neuronal
% la red. Para entrenar su red neuronal, ahora usaremos "fmincg", que
% es una función que funciona de manera similar a "fminunc". Recuerda que estos
% de optimizadores avanzados pueden entrenar nuestras funciones de costos de manera eficiente como
% siempre y cuando les proporcionemos los cálculos de gradiente.

Al igual que el póster original, también tenía curiosidad acerca de cómo los resultados de ex4.m podrían diferir usando fminunc en lugar de fmincg. Así que traté de reemplazar la llamada fmincg

options = optimset('MaxIter', 50);
[nn_params, cost] = fmincg(costFunction, initial_nn_params, options);

con la siguiente llamada a fminunc

options = optimset('GradObj', 'on', 'MaxIter', 50);
[nn_params, cost, exit_flag] = fminunc(costFunction, initial_nn_params, options);

pero recibió el siguiente mensaje de error de una compilación de Octave de 32 bits que se ejecuta en Windows:

error: la memoria se agotó o el tamaño solicitado es demasiado grande para el rango del tipo de índice de Octave; se intenta volver al aviso

Una compilación de 32 bits de MATLAB que se ejecuta en Windows proporciona un mensaje de error más detallado:

Error al usar buscar
Sin memoria. Escriba HELP MEMORY para sus opciones.
Error en esponjas (línea 14)
[i,j] = encontrar(S);
Error en color (línea 26)
J = esponjas(J);
Error en sfminbx (línea 155)
grupo = color(Hstr,p);
Error en fminunc (línea 408)
[x,FVAL,~,BANDERA DE SALIDA,SALIDA,GRADADO,HESSIAN] = sfminbx(funfcn,x,l,u, ...
Error en ex4 (línea 205)
[nn_params, cost, exit_flag] = fminunc(costFunction, initial_nn_params, options);

El comando de memoria MATLAB en mi computadora portátil informa:

Matriz máxima posible: 2046 MB (2.146e+09 bytes) *
Memoria disponible para todos los arreglos: 3402 MB (3.568e+09 bytes) **
Memoria utilizada por MATLAB: 373 MB (3.910e+08 bytes)
Memoria física (RAM): 3561 MB (3.734e+09 bytes)
* Limitado por el espacio de direcciones virtuales contiguas disponible.
** Limitado por espacio de dirección virtual disponible.

Anteriormente estaba pensando que el profesor Ng eligió usar fmincg para entrenar la red neuronal ex4.m (que tiene 400 funciones de entrada, 401 incluida la entrada de sesgo) para aumentar la velocidad de entrenamiento. Sin embargo, ahora creo que su razón para usar fmincg fue aumentar la eficiencia de la memoria lo suficiente como para permitir que el entrenamiento se realizara en compilaciones de 32 bits de Octave/MATLAB. Una breve discusión sobre el trabajo necesario para obtener una compilación de Octave de 64 bits que se ejecuta en el sistema operativo Windows es aquí.

Respondido el 07 de junio de 15 a las 18:06

Según el propio Andrew Ng, fmincg se usa no para obtener un resultado más preciso (recuerde, su función de costo será la misma en cualquier caso, y su hipótesis no será más simple ni más compleja), sino porque es más eficiente para hacer gradientes descendentes para hipótesis especialmente complejas. Él mismo parece utilizar fminunc donde las hipótesis tienen pocas características, pero fmincg donde tiene cientos.

Respondido el 30 de enero de 16 a las 17:01

Cuando dices menos términos, ¿qué quieres decir con eso? número de características y parámetros? - Iancovici

fmincg funciona de manera similar a fminunc, pero es más eficiente cuando se trata de una gran cantidad de parámetros. - Kaushalpranav

¿Por qué funciona fmincg?

Aquí hay una copia del código fuente con comentarios que explican los diversos algoritmos utilizados. Es genial, ya que hace lo mismo que hace el cerebro de un niño cuando aprende a discriminar entre un perro y una silla.

Esta es la fuente de Octave para fmincg.m.

function [X, fX, i] = fmincg(f, X, options, P1, P2, P3, P4, P5)
% Minimize a continuous differentialble multivariate function. Starting point
% is given by "X" (D by 1), and the function named in the string "f", must
% return a function value and a vector of partial derivatives. The Polack-
% Ribiere flavour of conjugate gradients is used to compute search directions,
% and a line search using quadratic and cubic polynomial approximations and the
% Wolfe-Powell stopping criteria is used together with the slope ratio method
% for guessing initial step sizes. Additionally a bunch of checks are made to
% make sure that exploration is taking place and that extrapolation will not
% be unboundedly large. The "length" gives the length of the run: if it is
% positive, it gives the maximum number of line searches, if negative its
% absolute gives the maximum allowed number of function evaluations. You can
% (optionally) give "length" a second component, which will indicate the
% reduction in function value to be expected in the first line-search (defaults
% to 1.0). The function returns when either its length is up, or if no further
% progress can be made (ie, we are at a minimum, or so close that due to
% numerical problems, we cannot get any closer). If the function terminates
% within a few iterations, it could be an indication that the function value
% and derivatives are not consistent (ie, there may be a bug in the
% implementation of your "f" function). The function returns the found
% solution "X", a vector of function values "fX" indicating the progress made
% and "i" the number of iterations (line searches or function evaluations,
% depending on the sign of "length") used.
%
% Usage: [X, fX, i] = fmincg(f, X, options, P1, P2, P3, P4, P5)
%
% See also: checkgrad
%
% Copyright (C) 2001 and 2002 by Carl Edward Rasmussen. Date 2002-02-13
%
%
% (C) Copyright 1999, 2000 & 2001, Carl Edward Rasmussen
%
% Permission is granted for anyone to copy, use, or modify these
% programs and accompanying documents for purposes of research or
% education, provided this copyright notice is retained, and note is
% made of any changes that have been made.
%
% These programs and documents are distributed without any warranty,
% express or implied.  As the programs were written for research
% purposes only, they have not been tested to the degree that would be
% advisable in any important application.  All use of these programs is
% entirely at the user's own risk.
%
% [ml-class] Changes Made:
% 1) Function name and argument specifications
% 2) Output display
%

% Read options
if exist('options', 'var') && ~isempty(options) && isfield(options, 'MaxIter')
    length = options.MaxIter;
else
    length = 100;
end

RHO = 0.01;                            % a bunch of constants for line searches
SIG = 0.5;       % RHO and SIG are the constants in the Wolfe-Powell conditions
INT = 0.1;    % don't reevaluate within 0.1 of the limit of the current bracket
EXT = 3.0;                    % extrapolate maximum 3 times the current bracket
MAX = 20;                         % max 20 function evaluations per line search
RATIO = 100;                                      % maximum allowed slope ratio

argstr = ['feval(f, X'];                      % compose string used to call function
for i = 1:(nargin - 3)
  argstr = [argstr, ',P', int2str(i)];
end
argstr = [argstr, ')'];

if max(size(length)) == 2, red=length(2); length=length(1); else red=1; end
S=['Iteration '];

i = 0;                                            % zero the run length counter
ls_failed = 0;                             % no previous line search has failed
fX = [];
[f1 df1] = eval(argstr);                      % get function value and gradient
i = i + (length<0);                                            % count epochs?!
s = -df1;                                        % search direction is steepest
d1 = -s'*s;                                                 % this is the slope
z1 = red/(1-d1);                                  % initial step is red/(|s|+1)

while i < abs(length)                                      % while not finished
  i = i + (length>0);                                      % count iterations?!

  X0 = X; f0 = f1; df0 = df1;                   % make a copy of current values
  X = X + z1*s;                                             % begin line search
  [f2 df2] = eval(argstr);
  i = i + (length<0);                                          % count epochs?!
  d2 = df2'*s;
  f3 = f1; d3 = d1; z3 = -z1;             % initialize point 3 equal to point 1
  if length>0, M = MAX; else M = min(MAX, -length-i); end
  success = 0; limit = -1;                     % initialize quanteties
  while 1
    while ((f2 > f1+z1*RHO*d1) | (d2 > -SIG*d1)) & (M > 0)
      limit = z1;                                         % tighten the bracket
      if f2 > f1
        z2 = z3 - (0.5*d3*z3*z3)/(d3*z3+f2-f3);                 % quadratic fit
      else
        A = 6*(f2-f3)/z3+3*(d2+d3);                                 % cubic fit
        B = 3*(f3-f2)-z3*(d3+2*d2);
        z2 = (sqrt(B*B-A*d2*z3*z3)-B)/A;       % numerical error possible - ok!
      end
      if isnan(z2) | isinf(z2)
        z2 = z3/2;                  % if we had a numerical problem then bisect
      end
      z2 = max(min(z2, INT*z3),(1-INT)*z3);  % don't accept too close to limits
      z1 = z1 + z2;                                           % update the step
      X = X + z2*s;
      [f2 df2] = eval(argstr);
      M = M - 1; i = i + (length<0);                           % count epochs?!
      d2 = df2'*s;
      z3 = z3-z2;                    % z3 is now relative to the location of z2
    end
    if f2 > f1+z1*RHO*d1 | d2 > -SIG*d1
      break;                                                % this is a failure
    elseif d2 > SIG*d1
      success = 1; break;                                             % success
    elseif M == 0
      break;                                                          % failure
    end
    A = 6*(f2-f3)/z3+3*(d2+d3);                      % make cubic extrapolation
    B = 3*(f3-f2)-z3*(d3+2*d2);
    z2 = -d2*z3*z3/(B+sqrt(B*B-A*d2*z3*z3));        % num. error possible - ok!
    if ~isreal(z2) | isnan(z2) | isinf(z2) | z2 < 0   % num prob or wrong sign?
      if limit < -0.5                               % if we have no upper limit
        z2 = z1 * (EXT-1);                 % the extrapolate the maximum amount
      else
        z2 = (limit-z1)/2;                                   % otherwise bisect
      end
    elseif (limit > -0.5) & (z2+z1 > limit)          % extraplation beyond max?
      z2 = (limit-z1)/2;                                               % bisect
    elseif (limit < -0.5) & (z2+z1 > z1*EXT)       % extrapolation beyond limit
      z2 = z1*(EXT-1.0);                           % set to extrapolation limit
    elseif z2 < -z3*INT
      z2 = -z3*INT;
    elseif (limit > -0.5) & (z2 < (limit-z1)*(1.0-INT))   % too close to limit?
      z2 = (limit-z1)*(1.0-INT);
    end
    f3 = f2; d3 = d2; z3 = -z2;                  % set point 3 equal to point 2
    z1 = z1 + z2; X = X + z2*s;                      % update current estimates
    [f2 df2] = eval(argstr);
    M = M - 1; i = i + (length<0);                             % count epochs?!
    d2 = df2'*s;
  end                                                      % end of line search

  if success                                         % if line search succeeded
    f1 = f2; fX = [fX' f1]';
    fprintf('%s %4i | Cost: %4.6e\r', S, i, f1);
    s = (df2'*df2-df1'*df2)/(df1'*df1)*s - df2;      % Polack-Ribiere direction
    tmp = df1; df1 = df2; df2 = tmp;                         % swap derivatives
    d2 = df1'*s;
    if d2 > 0                                      % new slope must be negative
      s = -df1;                              % otherwise use steepest direction
      d2 = -s'*s;
    end
    z1 = z1 * min(RATIO, d1/(d2-realmin));          % slope ratio but max RATIO
    d1 = d2;
    ls_failed = 0;                              % this line search did not fail
  else
    X = X0; f1 = f0; df1 = df0;  % restore point from before failed line search
    if ls_failed | i > abs(length)          % line search failed twice in a row
      break;                             % or we ran out of time, so we give up
    end
    tmp = df1; df1 = df2; df2 = tmp;                         % swap derivatives
    s = -df1;                                                    % try steepest
    d1 = -s'*s;
    z1 = 1/(1-d1);
    ls_failed = 1;                                    % this line search failed
  end
  if exist('OCTAVE_VERSION')
    fflush(stdout);
  end
end
fprintf('\n');

Respondido 25 Feb 15, 04:02

fmincg usa el método de gradiente conjugado

Si observa la imagen en este enlace, verá que el método CG converge mucho más rápido que fminunc, pero asume una serie de restricciones que creo que no son necesarias en el método fminunc (BFGS) (vectores conjugados frente a vectores no conjugados).

En otras palabras, el método fmincg es más rápido pero más tosco que fminunc, por lo que funciona mejor para matrices grandes (muchas características, como miles) que para matrices más pequeñas con hasta cientos de características. Espero que esto ayude.

respondido 05 mar '18, 04:03

fmincg es más preciso que fminunc. El tiempo que toman ambos es casi el mismo. En la red neuronal o en general, que tiene más peso, fminunc puede dar un error de memoria. Por lo tanto, fmincg es más eficiente en memoria.

Utilizando fminunc, la precisión es 93.10 y el tiempo empleado es 11.3794 segundos.

Testing lrCostFunction() with regularization
Cost: 2.534819
Expected cost: 2.534819
Gradients:
 0.146561
 -0.548558
 0.724722
 1.398003
Expected gradients:
 0.146561
 -0.548558
 0.724722
 1.398003
Program paused. Press enter to continue.

Training One-vs-All Logistic Regression...
id = 1512324857357
Elapsed time is 11.3794 seconds.
Program paused. Press enter to continue.

Training Set Accuracy: 93.100000

Utilizando fmincg, la precisión es de 95.12 y el tiempo empleado es de 11.7978 segundos.

Testing lrCostFunction() with regularization
Cost: 2.534819
Expected cost: 2.534819
Gradients:
 0.146561
 -0.548558
 0.724722
 1.398003
Expected gradients:
 0.146561
 -0.548558
 0.724722
 1.398003
Program paused. Press enter to continue.

Training One-vs-All Logistic Regression...
id = 1512325280047
Elapsed time is 11.7978 seconds.

Training Set Accuracy: 95.120000

Respondido el 03 de diciembre de 17 a las 18:12

Usar fmincg para optimizar la función de costo. fmincg funciona de manera similar a fminunc, pero es más eficiente cuando se trata de una gran cantidad de parámetros. Su función de costo será la misma en cualquier caso, y su hipótesis no será más simple ni más compleja, sino porque es más eficiente en el descenso de gradiente para hipótesis especialmente complejas.

Se utiliza para la utilización eficiente de la memoria.

respondido 10 nov., 18:17

¡Felicitaciones por tu primera respuesta SO! Para mejorar un poco más su respuesta, puede vincular alguna evidencia o documentación que respalde lo que ha descrito. - Tim Ogilvy

fmincg es una función interna desarrollada por supuesto en Coursera, a diferencia de fminunc, que es una función de octava incorporada. Dado que ambos se utilizan para la regresión logística, solo difieren en un aspecto. Cuando el número de parámetros a considerar es considerablemente grande (si se compara o no con el tamaño del conjunto de entrenamiento), fmincg funciona más rápido y procesa con mayor precisión que fminunc. Y se prefiere fminunc cuando no hay restricciones (sin restricciones) sobre los parámetros que se le pasan.

Respondido 10 ago 19, 11:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.