分類
分類應是極為常見的問題,我們生活周邊的一切事物,皆是類別分明。機器學習領域,處理分類問題的方法有多種,如邏輯回歸、支持向量機、以及無監督學習的K-mean等等。本文主要介始邏輯回歸。
邏輯回歸
邏輯回歸,主要用於解決分類問題,例如二分類。
對於二分類問題,通過給出的樣本\((x,y)\)(若為二分類,y={0,1}),確定一個可以對數據一分為二的邊界,有了這個邊界,對於一個新的樣本,根據其特征,便能預測其類屬。邊界可以是一根直線,或是一個圓,或是一個多邊形等。
對於多分類問題,可以通過執行多次二分類解決:保留要區分的一類,剩下的歸為另一類。例如,區分A、B、C類,需執行如下三次二分類:
首先,保留A類,將B和C歸為other,執行二分類,區分出A類。
接着,保留B類,將A和C歸為other,執行二分類,區分出B類。
同樣,保留C類,將A和B歸為other,執行二分類,區分出C類。
分類問題的解決方法,與線性回歸類似,一樣從誤差函數入手,一樣使用梯度下降法。
原理
分類問題,其 \(y\) 值一般設置為有限的離散值,例如0、1。所以系統所要做的工作,就是當一個新的樣本輸入時,需要判斷其為可能值的概率分別有多大,以此在確定其y值,即其類屬。
1、模型假設
令邏輯回歸的假設函數為:\(h_\theta(x) = g(\theta^Tx)\)
其中,\(g(z) = \frac{1}{1+e^{-z}}\),為sigmoid函數。
對g(z)函數的理解
g(z)函數是來源於最大熵原理,通過拉格朗日乘數法(尋找變量受一個或多個條件限制的多元函數極值的方法)求偏導得出,故而 \(h_\theta(x)\)的值,其實是系統 "認為" 樣本為 "1" 的概率值P,即:
\( h_\theta(x) = P(y=1|x) \)
使用 sigmoid 函數的優點
以二分類為例,根據輸入樣本的特征,確定其輸出為 0 或 1,顯然階跌函數有這些特性,如下
可以看到,階躍函數在 \(t_0\) 處有兩個問題:
(1) \(t_0\) 時的值應當認為 0 還是 1?
(2) \(t_0\) 發生了躍變,數學上求導麻煩。
而sigmoid函數,其值滿足0~1之間,且為單調遞增的連續曲線,比之階躍函數更有優勢。
2、誤差函數
誤差函數為
\( J = \frac{1}{m} \sum_{i=1}^{m}[-y^{(i)}log(h_\theta(x^{(i)})) - (1-y^{(i)})log(1-h_\theta(x^{(i)}))] \)
誤差函數對 \(\theta\) 的導數為
\( grad = \frac{1}{m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)} \)
一、最簡單的二分類,一階特征,直線邊界
1、誤差函數及偏導數
1.1 誤差函數實現
function [J, grad] = costFunction(theta, X, y)
m = length(y); % number of training examples
J = 0;
grad = zeros(size(theta));
h = sigmoid(X*theta);
J = ((-y' * log(h)) - (1-y)' * log(1-h))/m;
grad = 1/m .* X' * (h-y);
% =============================================================
end
1.2 誤差函數測試
[m, n] = size(X);
% Add intercept term to x and X_test
X = [ones(m, 1) X];
% Initialize fitting parameters
initial_theta = zeros(n + 1, 1);
% Compute and display initial cost and gradient
[cost, grad] = costFunction(initial_theta, X, y);
fprintf('Cost at initial theta (zeros): %f\n', cost);
fprintf('Expected cost (approx): 0.693\n');
fprintf('Gradient at initial theta (zeros): \n');
fprintf(' %f \n', grad);
fprintf('Expected gradients (approx):\n -0.1000\n -12.0092\n -11.2628\n');
% Compute and display cost and gradient with non-zero theta
test_theta = [-24; 0.2; 0.2];
[cost, grad] = costFunction(test_theta, X, y);
fprintf('\nCost at test theta: %f\n', cost);
fprintf('Expected cost (approx): 0.218\n');
fprintf('Gradient at test theta: \n');
fprintf(' %f \n', grad);
fprintf('Expected gradients (approx):\n 0.043\n 2.566\n 2.647\n');
2、梯度下降算法
這里使用優化的函數進行
% Set options for fminunc
options = optimset('GradObj', 'on', 'MaxIter', 400);
% Run fminunc to obtain the optimal theta
% This function will return theta and the cost
[theta, cost] = fminunc(@(t)(costFunction(t, X, y)), initial_theta, options);
% Print theta to screen
fprintf('Cost at theta found by fminunc: %f\n', cost);
fprintf('Expected cost (approx): 0.203\n');
fprintf('theta: \n');
fprintf(' %f \n', theta);
fprintf('Expected theta (approx):\n');
fprintf(' -25.161\n 0.206\n 0.201\n');
3、預測
prob = sigmoid([1 45 85] * theta);
fprintf(['For a student with scores 45 and 85, we predict an admission ' ...
'probability of %f\n'], prob);
fprintf('Expected value: 0.775 +/- 0.002\n\n');
% Compute accuracy on our training set
p = predict(theta, X);
fprintf('Train Accuracy: %f\n', mean(double(p == y)) * 100);
fprintf('Expected accuracy (approx): 89.0\n');
二、多邊形邊界
上面是最簡單的分類問題,而現實中的樣本,往往需要擬合一條曲線來划分數據,即是多項式擬合。
其處理方法,基本與上式相同。不同的是需要將特征轉為多項式轉換,使之能擬合更復雜的邊界,如圓、或者其他的不規則圖形。
1、數據預處理,生成多項式特征
X = mapFeature(X(:,1), X(:,2));
生成多項式的方法如下:
function out = mapFeature(X1, X2)
degree = 6;
out = ones(size(X1(:,1)));
for i = 1:degree
for j = 0:i
out(:, end+1) = (X1.^(i-j)).*(X2.^j);
end
end
end
2、訓練
使用與一階邊界相同的方法
% Initialize fitting parameters
initial_theta = zeros(size(X, 2), 1);
% Set Options
options = optimset('GradObj', 'on', 'MaxIter', 400);
% Optimize
[theta, J, exit_flag] = ...
fminunc(@(t)(costFunction(t, X, y)), initial_theta, options);
3、預測
二分類的預測方法:對於一個新的樣本,分別計算其為0、1概率,取大於0.5的值做為輸出。
p = predict(theta, X);
fprintf('Train Accuracy: %f\n', mean(double(p == y)) * 100);
function p = predict(theta, X)
m = size(X, 1); % Number of training examples
p = zeros(m, 1);
p_medium = sigmoid(X*theta);
pos = find(p_medium >= 0.5);
p(pos,1)=1;
end
三、多分類問題
例如給出如下訓練集,100張大小為20*20圖,內容為0~9的數字
X 為每張圖的像素數值,即特征數 n = 400
y 為圖上的數字,即y = {0,1,2,3,4,5,6,7,8,9}
1、訓練
[all_theta] = oneVsAll(X, y, num_labels);
分別對每個數字進行訓練,得出10個theta矩陣。
function [all_theta] = oneVsAll(X, y, num_labels)
m = size(X, 1);
n = size(X, 2);
all_theta = zeros(num_labels, n + 1);
% Add ones to the X data matrix
X = [ones(m, 1) X];
initial_thata = zeros(n+1,1);
options = optimset('GradObj','on','MaxIter',50);
for c = 1:num_labels
[all_theta(c,:)] = fmincg(@(t)(costFunction(t,X,(y ==c))),initial_thata,options);
end
end
2、預測
輸入一張圖片,計算其為0~9的各個概率,概率最大的值就是其輸出。
pred = predictOneVsAll(all_theta, X);
fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100);
function p = predictOneVsAll(all_theta, X)
m = size(X, 1);
num_labels = size(all_theta, 1);
p = zeros(size(X, 1), 1);
X = [ones(m, 1) X];
% 計算得出X中,可能的所有概率值,取最大
h = sigmoid(X* all_theta');
[~,p] = max(h,[],2);
end