one-vs-all案例
阿新 • • 發佈:2018-11-14
使用one-vs-all初始手寫字母識別
資料特點
- 每一個圖片都是20 x 20的畫素矩陣,但是在輸入的樣本中是一個1 x 400的向量,標籤y在{0, 1, 2, ..., 9}之間取值
- 共有5000個訓練樣本
視覺化資料
- 從5000個樣本中隨機的挑選出100個訓練樣本進行視覺化
- 得到的100個樣本中,每一個樣本都是一個向量,要想對其視覺化,需要將其從向量還原為原始的矩陣
- 首先確定矩陣的高和寬(單位是畫素pixel)
- 建立一個displayArray矩陣,用來儲存100個樣本轉換為矩陣的畫素資料,形象地講,就是將100個圖片放到一個大的面板上,這樣才能做到視覺化資料
- 初始完畢displayArray矩陣之後,使用matlib中的imagesc函式將其顯示出來
- 程式碼如下:
- myDisplayData.m
function [h, displayArray] = myDisplayData(X) % 獲取一張圖片的高和寬 exampleHeight = round(sqrt(size(X(1, :), 2))); exampleWidth = round(size(X(1, :), 2) / exampleHeight); % 計算整個面板的高和寬(但是是圖片的個數) [m, n] = size(X); displayRows = round(sqrt(m)); displayCols = round(m / displayRows); % 先創建出displayRows * exampleHeight, displayCols * exampleWidth的面板 displayArray = ones(displayRows * exampleHeight, displayCols * exampleWidth); % 將圖片放到面板對應的位置上 % 下面的式子就和數學有一些關係,如何確定現在填充的矩陣在displayArray中的位置 currExample = 1; for i = 1:displayRows for j = 1:displayCols displayArray(... (i - 1) * exampleWidth + 1:exampleWidth + (i - 1) * exampleWidth, ... (j - 1) * exampleHeight + 1:exampleHeight + (j - 1) * exampleHeight ... ) = ... reshape(X(currExample, :), ... exampleHeight, exampleWidth); currExample = currExample + 1; end end colormap(gray); h = imagesc(display_array); axis image off; end
資料預處理
- 為X新增bias(偏移量): X = [ones(m, 1), X]; % m表示樣本的數量
- m: 訓練樣本的數量
- n: 特徵的數量,不包括bias(偏移)特徵
- y: 標籤,{0, 1, 2, ..., 9}
- numLabel: y可以取的值的個數,這裡為10
確定假設函式
- 由題目可知,這是一個典型的Multi-Class Logistic Regression問題,因此使用邏輯迴歸模型
- 模型函式: \[h(\theta)=g(\theta^{T}x)={{1}\over{1+e^{-\theta^{T}x}}}\]
- 因為這個一個10分類的問題,所以需要擬合出10個假設函式才行,也就是要最小化出10個\(\theta\)
計算損失函式(cost function)和梯度
- 損失函式公式: \[J(\theta)={{1}\over{m}}\sum_{i=1}^m(-y^{(i)}log(h_{\theta}(x^{(i)})) - (1-y^{(i)})log(1-h_{\theta}(x^{(i)})))+{{\lambda}\over{2m}}\sum_{j=1}^m{\theta_{j}^2}\]其中\(\theta\), \(y^{(i)}\), \(x^{(i)}\)為向量或者矩陣,後一項是對非偏差項的正則化
- 梯度公式: j >= 1 \[{{\partial}\over{\partial}\theta_{j}}J(\theta)={{1}\over{m}}\sum_{i=1}^m{(h_{\theta}(x^{(i)})-y^{(i)})x^{(i)}} + {{\lambda}\over{m}}\theta_{j}\] j = 0 \[{{\partial}\over{\partial}\theta_{0}}J(\theta)={{1}\over{m}}\sum_{i=1}^m{(h_{\theta}(x^{(i)})-y^{(i)})x^{(i)}}\]
- 注意,上面的\(h_{\theta}(x^{(i)})\)是sigmoid函式,自己在實現的時候總是將其寫成線性迴歸函式
在oneVsAll.m檔案中實現\(minimize_{\theta}J(\theta)\)
- 每一個類都進行梯度下降,計算出這一類的引數,也就是寫一個迴圈,在每一個迴圈中都有可以得到最終的這個類別對應的引數,迴圈的次數為numLabels
核心程式碼
for index = 1:numLabels initialTheta = zeros(n + 1, 1); options = optimset('GradObj', 'on', 'MaxIter', 50); % fmincg會自動選擇最優的學習率alpha allTheta(index, :) = fmincg(@(t)(lrCostFunction(t, X, (y == index), lambda)), ... initialTheta, options); end
預測
- 輸入的一個樣本,需要為其新增bias值,在將樣本分別輸入到10個假設函式中,計算出最大的值,那個值對應的就是類別。
- 核心程式碼
tmp = zeros(m, num_labels);
for i = 1:num_labels
tmp(:, i) = sigmoid(X * allTheta(i, :)');
end
[val, p] = max(tmp, [], 2);