Правильно ли моя реализация стохастического градиентного спуска?

Я пытаюсь разработать стохастический градиентный спуск, но я не знаю, правильно ли это на 100%.

  • стоимость, генерируемая моим алгоритмом стохастического градиентного спуска, иногда очень далека от стоимости, генерируемой fminuc или пакетным градиентным спуском.
  • в то время как стоимость пакетного градиентного спуска сходится, когда я устанавливаю Альфа скорости обучения 0,2, я вынужден установить Альфа скорости обучения 0,0001 для моей стохастической реализации, чтобы она не расходилась. Это нормально?

вот некоторые результаты, которые я получил с набором обучения 10,000 элементов и num_iter = 100 или 500

    FMINUC : 
    Iteration  #100 | Cost: 5.147056e-001

    BACTH GRADIENT DESCENT  500 ITER
    Iteration #500 - Cost = 5.535241e-001

    STOCHASTIC GRADIENT DESCENT 100 ITER
    Iteration #100 - Cost = 5.683117e-001  % First time I launched
    Iteration #100 - Cost = 7.047196e-001  % Second time I launched

реализация градиентного спуска для логистической регрессии

J_history = zeros(num_iters, 1); 

for iter = 1:num_iters 

    [J, gradJ] = lrCostFunction(theta, X, y, lambda);
    theta = theta - alpha * gradJ;
    J_history(iter) = J;

    fprintf('Iteration #%d - Cost = %d... rn',iter, J_history(iter));
end

реализация стохастического градиентного спуска для логистической регрессии

% number of training examples
m = length(y);

% STEP1 : we shuffle the data
data = [y, X];
data = data(randperm(size(data,1)),:);
y = data(:,1);
X = data(:,2:end);

for iter = 1:num_iters 

     for i = 1:m
        x = X(i,:); % Select one example
        [J, gradJ] = lrCostFunction(theta, x, y(i,:), lambda);
        theta = theta - alpha * gradJ;
     end

     J_history(iter) = J;
     fprintf('Iteration #%d - Cost = %d... rn',iter, J);

end

для справки, вот функция стоимости логистической регрессии, используемая в моем примере

function [J, grad] = lrCostFunction(theta, X, y, lambda)

m = length(y); % number of training examples

% We calculate J    
hypothesis = sigmoid(X*theta); 
costFun = (-y.*log(hypothesis) - (1-y).*log(1-hypothesis));    
J = (1/m) * sum(costFun) + (lambda/(2*m))*sum(theta(2:length(theta)).^2);

% We calculate grad using the partial derivatives
beta = (hypothesis-y); 
grad = (1/m)*(X'*beta);
temp = theta;  
temp(1) = 0;   % because we don't add anything for j = 0  
grad = grad + (lambda/m)*temp; 
grad = grad(:);

end

3 ответов


это очень хорошо. Если вы беспокоитесь о выборе соответствующей скорости обучения alpha, вы должны подумать о применении поиск строки метод.

Line search-это метод, который выбирает оптимальную скорость обучения для градиентного спуска на каждой итерации, что лучше, чем использование фиксированной скорости обучения на протяжении всего процесса оптимизации. Оптимальное значение для скорости обучения alpha - Это тот, который локально (от current theta в направлении отрицательный градиент) уменьшает функцию цены.

на каждой итерации градиентного спуска начните со скорости обучения alpha = 0 и постепенно увеличивайте alpha фиксированным шагом deltaAlpha = 0.01, например. Пересчитать параметры theta и оцените функцию цены. Поскольку функция стоимости выпуклая, путем увеличения alpha (то есть, двигаясь в направлении отрицательного градиента) функция затрат сначала начнет уменьшаться, а затем (в какой-то момент) увеличиваться. В этот момент остановите поиск строки и возьмите последнюю alpha прежде чем функция цены начали расти. Теперь обновите параметры theta С alpha. Если функция стоимости никогда не начнет увеличиваться, остановитесь на alpha = 1.

Примечание: для больших коэффициентов регуляризации (lambda = 100, lambda = 1000) возможно, что deltaAlpha слишком большой, и этот градиентный спуск расходится. Если это так, уменьшите deltaAlpha 10 раз (deltaAlpha = 0.001, deltaAlpha = 0.0001) пока вы не получите соответствующие deltaAlpha для которого градиентный спуск сходится.

кроме того, вы должны подумать об использовании некоторого завершающего условия, отличного от количества итераций, например, когда разница между функциями затрат в двух последующих итерациях становится достаточно маленькой (меньше, чем некоторые epsilon).


существует причина для небольшого значения скорости обучения. Короче говоря, когда скорость обучения уменьшается с соответствующей скоростью и при относительно мягких предположениях, стохастический градиентный спуск почти наверняка сходится к глобальный минимум когда целевая функция выпуклой или псевдовыпуклый, и в противном случае почти наверняка сходится к локальный минимум. Это на самом деле является следствием Роббинс-Сигмунд теорема.

Robbins, Herbert; Siegmund, David O. (1971). "Теорема сходимости для неотрицательных почти supermartingales и некоторых приложений". В Рустаги, Джагдиш С. методы оптимизации в статистике. Академическая Пресса


скорость обучения всегда от 0 до 1. Если вы установите скорость обучения очень высокой, то она следует желаемому в меньшей степени, из-за пропуска. Поэтому возьмите небольшую скорость обучения, даже если это займет больше времени. Результат будет более убедительным.