
% Ottaa 5 parametria
% X_train, syötedata treenaukseen
% Y_train, oikeat vastaukset treenaukseen
% X_test,  syötedata testaukseen
% Y_test,  oikeat vastaukset testaukseen
% k,       kuinka moneen osaan data ristiinvalidoidessa jaetaan

function [expectedError, trainError, testError] = teht3(X_train, Y_train, X_test, Y_test, k)

% Lisätään dataan vakiotermit.
X_train = [X_train ones(length(X_train) , 1)];
X_test  = [X_test  ones(length(X_test)  , 1)];

% Poimitaan datan kokotiedot.
[numSamples, numFeatures] = size(X_train);

% regularisointiparametri
delta = linspace(0, 5, 100);

% varataan w vektoreille tilaa
w = zeros(length(delta), numFeatures);

% Ristiinvalidoinnin osat.
S = ceil(k .* rand(numSamples, 1));

% For each delta
for i = 1:length(delta)
	expectedError(i) = 0;
	
    % For each S
	for j = 1:k
		
        % {S \cut S_k} treenaukseen
		S_X_train = X_train(S ~= j, :);
		S_Y_train = Y_train(S ~= j);
		
        % {S_k} testaukseen
		S_X_test  = X_train(S == j, :);
		S_Y_test  = Y_train(S == j);
        
		% hae w joka minimoi L2 virheen.
		S_w = (S_X_train' * S_X_train + delta(i) * eye(numFeatures)) \ (S_X_train' * S_Y_train);
		
        % Summataan virheiden keskiarvot
		expectedError(i) = expectedError(i) + mean( abs(S_Y_test - S_X_test * S_w) ) / k;
    end
    
	% hae koko datalle w joka minimoi L2 virheen.
    w(i, :) = ((X_train' * X_train + delta(i) * eye(numFeatures)) \ (X_train' * Y_train))';
end

% Valitse virheen minimoiva delta.
[min_error, index] = min(expectedError);

disp('Pienin ennustettu virhe: ')
disp(min_error)

disp('saavutettiin deltalla: ')
disp(delta(index))

disp('jolloin w sai arvon: ')
disp(w(index, :))
