機器學習練習之正則化

        這個練習是來自http://openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=MachineLearning&doc=exercises/ex5/ex5.html

Regularized linear regression

        之前已經做過線性迴歸, 我們知道線性迴歸就是要找到 一條直線去擬合訓練數據,模型的損失函數爲

        

        但是,這個模型可能會有些權重很大,有些權重很小,導致過擬合,就是過分擬合了訓練數據,使得模型的複雜度提高,泛化能力較差,泛化能力就是對未知數據的預測能力。爲了防止過擬合,通常會加入權重懲罰項,就是模型的正則項。正則項可以取不同的形式,在迴歸問題中取平方損失,就是參數的L2範數,也可以取L1範數。取平方損失時,模型的損失函數變爲:

      

      lambda是正則項係數,如果它的值很大,說明對模型的複雜度懲罰大,對擬合數據的損失懲罰小,這樣它就不會過分擬合數據,在訓練數據上的偏差較大,在未知數據上的variance較小,但是可能出現欠擬合的現象;相反,如果lambda值很小,說明比較注重對訓練數據的擬合,在訓練數據上的bias會小,但是可能會導致過擬合。

      

     要求出theta使得損失J最小,可以將J對theta求導,得到結果如下:

    

    所以直接使用這個方程解就可以求出最佳的theta,不過也可以使得梯度下降算法,但是要折騰一下調步長參數。

  

    程序如下:

%% Exercie: Regularized linear regression
% 正則化的線性迴歸
% 在簡單的線性迴歸上加了正則項,用於懲罰權重,減少模型參數的搜索空間,
% 使得權重不會偏向於某些特徵,模型更加平滑
%%
%% 數據初始化
x = load('ex5Linx.dat'); % x是隻有一個特徵,爲一個列向量
y = load('ex5Liny.dat');
% 畫圖
figure
plot(x, y, 'o', 'MarkerFacecolor', 'r', 'MarkerSize', 8);
m = length(x); % m樣本數量
x = [ones(m,1), x, x.^2, x.^3, x.^4, x.^5];  % 根據x構造特徵向量,這裏是多項式的特徵,每個特徵取(0-5)次方
n = size(x, 2); % 特徵數量
%%
%% 梯度下降算法
% theta = zeros(n, 1); %初始化權重向量,一個列向量
% alpha = 0.01; %學習率,步長
% lambda = 0;
% MAX_ITR = 500;
% for i=1:MAX_ITR
%     grad = (1/m).*(x'*(x*theta-y) + lambda*theta); %計算梯度
%     theta = theta - alpha*grad; %更新權重
% end
% theta
% J = (0.5/m) * (sum((x*theta-y).^2) + lambda*sum(theta.^2)) 
% theta_norm = norm(theta)
%%
%% Normal equations
lambda = [0 1 10];
plotstyle = {'b', 'r', 'g'}
for i = 1:3
    L = lambda(i).*eye(n);
    L(1,1) = 0;
    theta = (x'*x+L)\x'*y;
    theta
    J = (0.5/m) * (sum((x*theta-y).^2) + lambda(i)*sum(theta.^2)) 
    theta_norm = norm(theta)    %計算theta的L2範數
    hold on
    x_vals = (-1:0.05:1)'; %這個範圍要根據x的範圍確定
    features = [ones(size(x_vals)), x_vals, x_vals.^2, x_vals.^3, ...
            x_vals.^4, x_vals.^5];
    plot(x_vals, features*theta, char(plotstyle(i)), 'LineWidth', 2)
    legend(['lambda=', num2str(i)])
end
legend('Training data','\lambda=0', '\lambda=1', '\lambda=10');
title('5th order fit')
hold off
%%
    
    
    


結果:



Regularized Logistic regression

      正則化的邏輯斯蒂迴歸模型也是在之前的logistic regression上增加了正則項。
   
     要使得上面的損失函數最小,同樣這樣使用牛頓方法,它的更新規則爲:
   

      其中一階導和海森矩陣的形式有所變化:
     
   
   程序如下:
function out = map_feature(feat1, feat2)
% MAP_FEATURE    Feature mapping function for Exercise 5
%
%   map_feature(feat1, feat2) maps the two input features
%   to higher-order features as defined in Exercise 5.
%
%   Returns a new feature array with more features
%
%   Inputs feat1, feat2 must be the same size
%
% Note: this function is only valid for Ex 5, since the degree is
% hard-coded in.
    degree = 6;
    out = ones(size(feat1(:,1)));
    for i = 1:degree
        for j = 0:i
            out(:, end+1) = (feat1.^(i-j)).*(feat2.^j);
        end
    end
    
%% Regularized logistic regression
% 加入正則項的邏輯斯蒂迴歸模型
%%
%% 數據初始化
x = load('ex5Logx.dat');  % 這裏x的每一行是一個二維向量,表示有兩個特徵
y = load('ex5Logy.dat');
% Find the indices for the 2 classes
pos = find(y); neg = find(y==0);
x_unfeatured = x; % 保存未構造特徵前的x
x = map_feature(x(:,1), x(:,2)); %由於原始數據下樣本不是線性可分的,所以這裏根據x的2個特徵構造更多的特徵
[m n] = size(x); 
%%
%% 定義sigmoid函數
g = inline('1.0 ./ (1.0+exp(-z))', 'z');
%% 
%% 牛頓算法
lambda = [0 1 10];  %正則項係數
MAX_ITR = 15;
for i = 1:3
    theta = zeros(n, 1); %權重初始化
    J = zeros(MAX_ITR, 1); %保存損失
    for j = 1:MAX_ITR
        h = g(x*theta); %計算sigmoid值
        L = lambda(i) .* eye(n);
        L(1,1) = 0;
        J(j) = -(1.0/m).*sum(y.*log(h) + (1-y).*log(1-h)) + ...
            lambda(i)/(2*m).*norm(theta(2:end))^2;
        grad = (1/m) .* (x'*(h-y) + L*theta); %計算梯度
        H = (1/m) .* x'*diag(h)*diag(1-h)*x + lambda(i)/m.*L;  %計算海森矩陣
        
        theta = theta - H\grad;
    end
    J
    norm_theta = norm(theta)
    figure
    plot(x_unfeatured(pos, 1), x_unfeatured(pos, 2), 'k+', 'LineWidth', 2, 'MarkerSize', 7)
    hold on
    plot(x_unfeatured(neg, 1), x_unfeatured(neg, 2), 'ko', 'MarkerFaceColor', 'y', 'MarkerSize', 7)
    hold on
    %顯示結果
    u = linspace(-1, 1.5, 200);
    v = linspace(-1, 1.5, 200);
    z = zeros(length(u), length(v));
    for ii = 1:length(u)
        for jj = 1:length(v)
            z(ii, jj) = map_feature(u(ii), v(jj))*theta;
        end
    end
    z = z';
    % plot z = 0
    contour(u, v, z, [0,0], 'LineWidth', 2)
    legend('y=1', 'y=0', 'Decision boundary')
    title(sprintf('\\lambda = %g', lambda(i)), 'FontSize', 14)
    hold off
end
    

結果:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章