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

Я на самом деле боролся с этим уже около 2 месяцев. Что отличает их?

hypotheses= X * theta
temp=(hypotheses-y)'
temp=X(:,1) * temp
temp=temp * (1 / m)
temp=temp * alpha
theta(1)=theta(1)-temp

hypotheses= X * theta
temp=(hypotheses-y)'
temp=temp * (1 / m)
temp=temp * alpha
theta(2)=theta(2)-temp



theta(1) = theta(1) - alpha * (1/m) * ((X * theta) - y)' * X(:, 1);
theta(2) = theta(2) - alpha * (1/m) * ((X * theta) - y)' * X(:, 2);

Последний работает. Я просто не уверен, почему ... Я изо всех сил пытаюсь понять необходимость обратной матрицы.


person narthur157    schedule 14.05.2012    source источник
comment
Я не думаю, что это правильная реализация градиентного спуска. Вам нужно обновить. Обе ваши теты одновременно, чтобы быть точным. tmpTheta1= theta(1) - alpha * (1/m) * ((X * theta) - y)' * X(:, 1); tmpTheta2= theta(2) - alpha * (1/m) * ((X * theta) - y)' * X(:, 2); theta(1)=tmpTheta1; theta(2)=tmpTheta2;   -  person Einar Sundgren    schedule 29.04.2013


Ответы (7)


То, что вы делаете в первом примере, во втором блоке вы пропустили шаг, не так ли? Я предполагаю, что вы объединили X с вектором из единиц.

   temp=X(:,2) * temp

Последний пример будет работать, но его можно еще больше векторизовать, чтобы сделать его более простым и эффективным.

Я предположил, что у вас есть только 1 функция. он будет работать одинаково с несколькими функциями, поскольку все, что происходит, это добавление дополнительного столбца в матрицу X для каждой функции. В основном вы добавляете вектор из единиц к x, чтобы векторизовать перехват.

Вы можете обновить матрицу тета 2x1 в одной строке кода. С помощью x соедините вектор из единиц, сделав его матрицей nx2, тогда вы можете вычислить h(x) путем умножения на тета-вектор (2x1), это (X * тета) бит.

Вторая часть векторизации заключается в транспонировании (X * тета) - y), что дает вам матрицу 1 * n, которая при умножении на X (матрица n * 2) будет в основном объединять оба (h (x) -y) x0 и (h(x)-y)x1. По определению оба тета выполняются одновременно. Это приводит к матрице 1 * 2 моих новых тета, которые я просто снова транспонирую, чтобы перевернуть вектор, чтобы он был тех же размеров, что и тета-вектор. Затем я могу выполнить простое скалярное умножение на альфа и векторное вычитание с тета.

X = data(:, 1); y = data(:, 2);
m = length(y);
X = [ones(m, 1), data(:,1)]; 
theta = zeros(2, 1);        

iterations = 2000;
alpha = 0.001;

for iter = 1:iterations
     theta = theta -((1/m) * ((X * theta) - y)' * X)' * alpha;
end
person Shaun Ryan    schedule 19.03.2014
comment
зачем вам нужно транспонировать (1/m) * ((X * theta) - y)' * X в цикле for? - person Graham Slick; 27.03.2016
comment
Тот же вопрос, что и у Грэма, почему транспонировано все это подвыражение? - person qbert65536; 29.04.2016
comment
Результат ((1/m) * ((X * theta) - y)' * X) равен 1x2. theta это 2x1. Таким образом, бит в скобках нужно транспонировать, чтобы он имел те же размеры, и вычесть его из theta. - person AronVanAmmers; 11.05.2016
comment
Тот же вопрос, что и выше. Должно быть тета = тета - (альфа/м) * Х' * (Х * тета - у) - person Weihui Guo; 27.11.2016
comment
Я думаю, что это связано с правилами расчета матрицы... A*B = произведение строк A на строки B... Я имею в виду, концептуально можно использовать общие формулы для градиентного потомка, но тогда, когда вы играя в матричных полях, приходится приспосабливаться к их собственным правилам (умножение строк на строки, коммутативные ограничения и т.д.)... Это всего лишь мое предположение, возможно, я ошибаюсь... - person Telmo; 17.05.2017
comment
Как уже говорилось -> Это приводит к матрице 1 * 2 моих новых тета, которую я просто снова транспонирую, чтобы перевернуть вектор, чтобы он имел те же размеры, что и тета-вектор. Затем я могу выполнить простое скалярное умножение на альфа-канал и вычитание вектора с тета. Для расчета с использованием векторов размерность должна быть правильной. Если я соглашусь с размерами, то это значительно упростит окончательный расчет. Собирая это (и любой код), я упростил его до самой минимальной формы - учитывая время. - person Shaun Ryan; 23.06.2020

В первом случае, если бы X была матрицей 3x2, а тета была матрицей 2x1, то «гипотезы» были бы матрицей 3x1.

Предполагая, что y представляет собой матрицу 3x1, вы можете выполнить (гипотезы - y) и получить матрицу 3x1, тогда транспонирование этого 3x1 представляет собой матрицу 1x3, назначенную temp.

Затем матрице 1x3 присваивается значение тета (2), но это не должна быть матрица.

Последние две строки вашего кода работают, потому что, используя мои примеры mxn выше,

(X * theta)

будет матрица 3x1.

Затем эта матрица 3x1 вычитается из y (матрица 3x1), и в результате получается матрица 3x1.

(X * theta) - y

Таким образом, транспонированная матрица 3x1 представляет собой матрицу 1x3.

((X * theta) - y)'

Наконец, матрица 1x3, умноженная на матрицу 3x1, будет равна скалярной матрице или матрице 1x1, что вам и нужно. Я уверен, что вы уже знаете, но для большей ясности скажу, что X(:,2) — это второй столбец матрицы 3x2, что делает ее матрицей 3x1.

person Justin Nafe    schedule 16.05.2012

Когда вы обновляете, вам нужно сделать как

Start Loop {

temp0 = theta0 - (equation_here);

temp1 = theta1 - (equation_here);


theta0 =  temp0;

theta1 =  temp1;

} End loop
person hbr    schedule 22.10.2013

Это может быть более просто векторизовано с помощью

h = X * theta   % m-dimensional matrix (prediction our hypothesis gives per training example)
std_err = h - y  % an m-dimensional matrix of errors (one per training example)
theta = theta - (alpha/m) * X' * std_err

Помните, что X — это матрица проектирования, и поэтому каждая строка X представляет обучающий пример, а каждый столбец X представляет заданный компонент (скажем, нулевой или первый компоненты) во всех обучающих примерах. Таким образом, каждый столбец X — это именно то, что мы хотим поэлементно умножить на std_err перед суммированием, чтобы получить соответствующий компонент тета-вектора.

person fpghost    schedule 01.11.2018
comment
Вроде все и хорошо. Но почему нам разрешено транспонировать X? Не изменит ли это значение? Многие здесь просто объясняют это тем, что мы должны сделать это, чтобы матрицы были правильными. Но почему? Является ли X' производной? - person Tuxedo Joe; 11.02.2020
comment
``` X * theta ``` Это скалярное произведение или просто поэлементная операция? - person Garde Des Ombres; 27.08.2020

person    schedule
comment
Как мы можем напечатать «J_history» в командной строке? - person Cenk; 27.11.2020
comment
Хорошо, я решил это: [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters); - person Cenk; 27.11.2020

person    schedule
comment
пожалуйста, объясните, как это ответить на вопрос - person Shivani Katukota; 19.03.2019

person    schedule
comment
идея состоит в том, чтобы помочь пользователям продвигаться вперед, а не публиковать полные примеры реальных домашних упражнений. - person EdvardM; 26.06.2015
comment
Пожалуйста, добавьте совет и идею, чтобы ответить на вопрос ОП. Чистый код никому не поможет. - person Saif Ul Islam; 12.05.2020