Градиентный спуск, кажется, терпит неудачу
Я реализовал алгоритм спуска градиента для минимизации функции затрат, чтобы получить гипотезу для определения того, имеет ли изображение хорошее качество. Я сделал это в Октаве. Идея каким-то образом основана на алгоритме из класс машинного обучения от Andrew Ng
Поэтому у меня есть 880 значений "y", которые содержат значения от 0,5 до ~ 12. И у меня есть 880 значений от 50 до 300 в "Х", которые должны предсказать качество изображения.
К сожалению, алгоритм, кажется, терпит неудачу, после некоторых итераций значение для theta настолько мало, что theta0 и theta1 становятся "NaN". И моя линейная регрессионная кривая имеет странные значения...
вот код для алгоритма спуска градиента:
(theta = zeros(2, 1);
, alpha = 0.01, итерации = 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
И вот вычисление для функции затрат:
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
Ответы
Ответ 1
Я думаю, что ваша функция computeCost
неверна.
В прошлом году я посещал класс NG, и у меня есть следующая реализация (векторизация):
m = length(y);
J = 0;
predictions = X * theta;
sqrErrors = (predictions-y).^2;
J = 1/(2*m) * sum(sqrErrors);
Остальная часть реализации кажется мне прекрасной, хотя вы также можете ее векторизовать.
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));
Затем вы устанавливаете временные теты (здесь называемые theta_1 и theta_2) правильно обратно в "настоящую" тету.
Как правило, более целесообразно векторизовать вместо циклов, это менее раздражает чтение и отладка.
Ответ 2
i векторизовал тэта-вещь...
может помочь кому-то
theta = theta - (alpha/m * (X * theta-y)' * X)';
Ответ 3
Если вам интересно, как выглядящий сложный выглядящий цикл for
может быть векторизован и сжат в одно однострочное выражение, тогда, пожалуйста, прочитайте. Вектор вектора:
theta = theta - (alpha/m) * (X' * (X * theta - y))
Ниже приводится подробное объяснение того, как мы получаем это векторизованное выражение, используя алгоритм спуска градиента:
Это алгоритм спуска градиента для точной настройки значения θ:
![введите описание изображения здесь]()
Предположим, что заданы следующие значения X, y и θ:
- m = количество примеров обучения
- n = количество функций + 1
![введите описание изображения здесь]()
Здесь
- m = 5 (примеры обучения)
- n = 4 (функции + 1)
- X = m x n matrix
- y = m x 1 векторная матрица
- θ = n x 1 векторная матрица
- x i - пример обучения я th
- x j - это функция j th в данном учебном примере
Далее
-
h(x) = ([X] * [θ])
(m x 1 матрица прогнозируемых значений для нашего набора тренировок)
-
h(x)-y = ([X] * [θ] - [y])
(m x 1 матрица ошибок в наших прогнозах)
Целевая задача машинного обучения сводится к минимизации ошибок в предсказаниях. Исходя из вышеизложенного, наша матрица ошибок является векторной матрицей m x 1
следующим образом:
![введите описание изображения здесь]()
Чтобы вычислить новое значение θ j, мы должны получить суммирование всех ошибок (m строк), умноженное на j th значение функции обучения set X. То есть, возьмите все значения в E, отдельно умножите их с помощью функции j th примера соответствующего обучения и добавьте их все вместе. Это поможет нам получить новое (и, надеюсь, лучшее) значение θ j. Повторите этот процесс для всех j или количества функций. В матричной форме это можно записать как:
![введите описание изображения здесь]()
Это можно упростить как:
![введите описание изображения здесь]()
-
[E]' x [X]
даст нам матрицу векторов строк, так как E '- матрица 1 x m, а X - матрица m x n. Но нас интересует получение матрицы столбцов, поэтому мы переносим результирующую матрицу.
Более лаконично, его можно записать так:
![введите описание изображения здесь]()
Так как (A * B)' = (B' * A')
и A'' = A
, мы также можем записать выше как
![введите описание изображения здесь]()
Это исходное выражение, с которым мы начали:
theta = theta - (alpha/m) * (X' * (X * theta - y))
Ответ 4
Если у вас все в порядке с использованием функции стоимости наименьших квадратов, вы можете попробовать использовать нормальное уравнение вместо градиентного спуска. Это намного проще - только одна строка - и вычислительно быстрее.
Вот нормальное уравнение:
http://mathworld.wolfram.com/NormalEquation.html
И в октавной форме:
theta = (pinv(X' * X )) * X' * y
Вот учебник, в котором объясняется, как использовать нормальное уравнение: http://www.lauradhamilton.com/tutorial-linear-regression-with-octave
Ответ 5
Не масштабируясь, как векторная версия, вычисление градиентного спуска на основе цикла должно генерировать те же результаты. В приведенном выше примере наиболее вероятным случаем градиентного спуска, неспособным вычислить правильную тету, является значение альфа.
С проверенным набором функций снижения стоимости и градиентного спуска и набором данных, аналогичных описанному в вопросе, theta заканчивается значениями NaN сразу после нескольких итераций, если alpha = 0.01
. Однако, когда установлено как alpha = 0.000001
, спуск градиента работает так, как ожидалось, даже после 100 итераций.
Ответ 6
Использование только векторов здесь - это компактная реализация LR с градиентным спуском в 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}]
Примечание. Конечно, предполагается, что X является матрицей n * 2, причем X [[, 1]] содержит только 1s '
Ответ 7
Это должно работать: -
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) );