function [w, loss_history] = gradient_descent(X, y, w, num_iters, mu, regType, lambda);
% Implementacija algoritma gradijentnog spusta.

loss_history = zeros(num_iters, 1);

% Ilustracija treniranja modela.
animation = true;
if (animation)
    plot(X(:, 2:end), y, 'rx', 'MarkerSize', 5);
    hold on;
end

for i = 1:num_iters
    % Racunamo funkciju gubitka kao i gradijent.
    [loss, grad] = loss_function(X, y, w, regType, lambda);
    % Azuriramo koeficijente modela.
    w = w - mu .* grad;
    % Belezimo vrednost funkcije gubitka za kasniju vizuelizaciju minimizacije greske.
    loss_history(i) = loss;


    % Ilustracija treniranja modela.
    if (animation && mod(i, 100) == 0)
        plot(X(:, 2), X*w, '-');
        legend(sprintf('Iteration: %d\n', i));
        pause;
    end
end

end
