問題描述:使用邏輯回歸(logistic regression)和神經網絡(neural networks)識別手寫的阿拉伯數字(0-9)
一、邏輯回歸實現:
數據加載到octave中,如下圖所示:
①樣本數據的可視化
隨機選擇100個樣本數據,使用Octave可視化的結果如下:
②使用邏輯回歸來實現多分類問題(one-vs-all)
所謂多分類問題,是指分類的結果為三類以上。比如,預測明天的天氣結果為三類:晴(用y==1表示)、陰(用y==2表示)、雨(用y==3表示)
分類的思想,其實與邏輯回歸分類(默認是指二分類,binary classification)很相似,對“晴天”進行分類時,將另外兩類(陰天和下雨)視為一類:(非晴天),這樣,就把一個多分類問題轉化成了二分類問題。示意圖如下:(圖中的圓圈 表示:不屬於某一類的 所有其他類)
對於N分類問題(N>=3),就需要N個假設函數(預測模型),也即需要N組模型參數θ(θ一般是一個向量)
然后,對於每個樣本實例,依次使用每個模型預測輸出,選取輸出值最大的那組模型所對應的預測結果作為最終結果。
因為模型的輸出值,在sigmoid函數作用下,其實是一個概率值。,注意:hθ(1)(x),hθ(2)(x),hθ(3)(x)三組 模型參數θ 一般是不同的。比如:
hθ(1)(x),輸出 預測為晴天(y==1)的概率
hθ(2)(x),輸出 預測為陰天(y==2)的概率
hθ(3)(x),輸出 預測為雨天(y==3)的概率
③Octave代碼實現
對於上面的識別阿拉伯數字的問題,一共需要訓練出10個邏輯回歸模型,每個邏輯回歸模型對應着識別其中一個數字。
我們一共有5000個樣本,樣本的預測結果值就是:y=(1,2,3,4,5,6,7,8,9,10),其中 10 代表 數字0
我們使用fmincg庫函數 來求解使得代價函數取最小值的 模型參數θ
function [all_theta] = oneVsAll(X, y, num_labels, lambda) %ONEVSALL trains multiple logistic regression classifiers and returns all %the classifiers in a matrix all_theta, where the i-th row of all_theta %corresponds to the classifier for label i % [all_theta] = ONEVSALL(X, y, num_labels, lambda) trains num_labels % logistic regression classifiers and returns each of these classifiers % in a matrix all_theta, where the i-th row of all_theta corresponds % to the classifier for label i % Some useful variables m = size(X, 1); n = size(X, 2); % You need to return the following variables correctly all_theta = zeros(num_labels, n + 1); % Add ones to the X data matrix X = [ones(m, 1) X]; % ====================== YOUR CODE HERE ====================== % Instructions: You should complete the following code to train num_labels % logistic regression classifiers with regularization % parameter lambda. % % Hint: theta(:) will return a column vector. % % Hint: You can use y == c to obtain a vector of 1's and 0's that tell you % whether the ground truth is true/false for this class. % % Note: For this assignment, we recommend using fmincg to optimize the cost % function. It is okay to use a for-loop (for c = 1:num_labels) to % loop over the different classes. % % fmincg works similarly to fminunc, but is more efficient when we % are dealing with large number of parameters. % % Example Code for fmincg: % % % Set Initial theta % initial_theta = zeros(n + 1, 1); % % % Set options for fminunc % options = optimset('GradObj', 'on', 'MaxIter', 50); % % % Run fmincg to obtain the optimal theta % % This function will return theta and the cost % [theta] = ... % fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), ... % initial_theta, options); % initial_theta = zeros(n + 1, 1); options = optimset('GradObj','on','MaxIter',50); for c = 1:num_labels %num_labels 為邏輯回歸訓練器的個數,num of logistic regression classifiers all_theta(c, :) = fmincg(@(t)(lrCostFunction(t, X, (y == c),lambda)), initial_theta,options ); end % ========================================================================= end
function [J, grad] = lrCostFunction(theta, X, y, lambda) %LRCOSTFUNCTION Compute cost and gradient for logistic regression with %regularization % J = LRCOSTFUNCTION(theta, X, y, lambda) computes the cost of using % theta as the parameter for regularized logistic regression and the % gradient of the cost w.r.t. to the parameters. % Initialize some useful values m = length(y); % number of training examples % You need to return the following variables correctly J = 0; grad = zeros(size(theta)); % ====================== YOUR CODE HERE ====================== % Instructions: Compute the cost of a particular choice of theta. % You should set J to the cost. % Compute the partial derivatives and set grad to the partial % derivatives of the cost w.r.t. each parameter in theta % % Hint: The computation of the cost function and gradients can be % efficiently vectorized. For example, consider the computation % % sigmoid(X * theta) % % Each row of the resulting matrix will contain the value of the % prediction for that example. You can make use of this to vectorize % the cost function and gradient computations. % % Hint: When computing the gradient of the regularized cost function, % there're many possible vectorized solutions, but one solution % looks like: % grad = (unregularized gradient for logistic regression) % temp = theta; % temp(1) = 0; % because we don't add anything for j = 0 % grad = grad + YOUR_CODE_HERE (using the temp variable) % J = ( log( sigmoid(theta'*X') ) * y + log( 1-sigmoid(theta'*X') ) * (1 - y) )/(-m) + (lambda / (2*m)) * ( ( theta( 2:length(theta) ) )' * theta(2:length(theta)) ); grad = ( X' * ( sigmoid(X*theta)-y ) )/m + ( lambda / m ) * ( [0; ones( length(theta) - 1 , 1 )].*theta ); % ============================================================= grad = grad(:); end
下面來解釋一下 for循環:
num_labels 為分類器個數,共10個,每個分類器(模型)用來識別10個數字中的某一個。
我們一共有5000個樣本,每個樣本有400中特征變量,因此:模型參數θ 向量有401個元素。
initial_theta = zeros(n + 1, 1); % 模型參數θ的初始值(n == 400)
all_theta是一個10*401的矩陣,每一行存儲着一個分類器(模型)的模型參數θ 向量,執行上面for循環,就調用fmincg庫函數 求出了 所有模型的參數θ 向量了。
求出了每個模型的參數向量θ,就可以用 訓練好的模型來識別數字了。對於一個給定的數字輸入(400個 feature variables) input instance,每個模型的假設函數hθ(i)(x) 輸出一個值(i = 1,2,...10)。取這10個值中最大值那個值,作為最終的識別結果。比如g(hθ(8)(x))==0.96 比其它所有的 g(hθ(i)(x)) (i = 1,2,...10,但 i 不等於8) 都大,則識別的結果為 數字 8
function p = predictOneVsAll(all_theta, X) %PREDICT Predict the label for a trained one-vs-all classifier. The labels %are in the range 1..K, where K = size(all_theta, 1). % p = PREDICTONEVSALL(all_theta, X) will return a vector of predictions % for each example in the matrix X. Note that X contains the examples in % rows. all_theta is a matrix where the i-th row is a trained logistic % regression theta vector for the i-th class. You should set p to a vector % of values from 1..K (e.g., p = [1; 3; 1; 2] predicts classes 1, 3, 1, 2 % for 4 examples) m = size(X, 1); num_labels = size(all_theta, 1); % You need to return the following variables correctly p = zeros(size(X, 1), 1); % Add ones to the X data matrix X = [ones(m, 1) X]; % ====================== YOUR CODE HERE ====================== % Instructions: Complete the following code to make predictions using % your learned logistic regression parameters (one-vs-all). % You should set p to a vector of predictions (from 1 to % num_labels). % % Hint: This code can be done all vectorized using the max function. % In particular, the max function can also return the index of the % max element, for more information see 'help max'. If your examples % are in rows, then, you can use max(A, [], 2) to obtain the max % for each row. % [~,p] = max( X * all_theta',[],2); % 求矩陣(X*all_theta')每行的最大值,p 記錄矩陣每行的最大值的索引 % ========================================================================= end
二、神經網絡實現
由於邏輯回歸是線性分類(它的假設函數是一個線性函數,就是划一條直線,把數據分成了兩類。
對於一些復雜的類別,邏輯回歸就解決不了了。比如下面這個圖片中的分類。(無法通過 划直線 將 叉叉 和 圓圈 分開)
而神經網絡,則能夠實現很復雜的非線性分類問題。
對於神經網絡而言,同樣有一個訓練樣本矩陣 X,同時還有一個模型參數 Theta 矩陣,通過某種算法將 模型參數矩陣 訓練好之后(求出 Theta 矩陣),再使用前向傳播算法( feedforward propagation algorithm)(感覺就像是矩陣相乘嘛), 就可以對輸入的測試樣本進行預測了。
本作業中, 模型參數 Theta 矩陣是已經訓練好了的,直接 load 即可。如下所示:
function p = predict(Theta1, Theta2, X) %PREDICT Predict the label of an input given a trained neural network % p = PREDICT(Theta1, Theta2, X) outputs the predicted label of X given the % trained weights of a neural network (Theta1, Theta2) % Useful values m = size(X, 1); num_labels = size(Theta2, 1); % You need to return the following variables correctly p = zeros(size(X, 1), 1); % ====================== YOUR CODE HERE ====================== % Instructions: Complete the following code to make predictions using % your learned neural network. You should set p to a % vector containing labels between 1 to num_labels. % % Hint: The max function might come in useful. In particular, the max % function can also return the index of the max element, for more % information see 'help max'. If your examples are in rows, then, you % can use max(A, [], 2) to obtain the max for each row. % % 模擬實現前向傳播算法 X = [ones(m, 1) X]; a_super_2 = sigmoid(Theta1 * X'); a_super_2 = [ones(1,m); a_super_2];% add bias unit a_super_3 = sigmoid(Theta2 * a_super_2); %================================== [~,p] = max( a_super_3' ,[], 2 ); % 對樣本的結果進行預測,與邏輯回歸的預測類似,選取輸出的最大值 作為最終的預測結果 % ========================================================================= end
注意:我們正是通過 max 函數,求得矩陣 a_super3′ 的每一行的最大值。將每一行的中的最大值 的索引 賦值給向量p。其中,a_super3′ 是一個5000行乘10列的矩陣
向量p就是預測的結果向量。而由於 a_super3′ 有10列,故 p 中每個元素的取值范圍為[1,10],即分別代表了數字 0-9(其中10 表示 0)
測試代碼如下:
rp = randperm(m); >> >> for i = 1:m % Display fprintf('\nDisplaying Example Image\n'); displayData(X(rp(i), :)); pred = predict(Theta1, Theta2, X(rp(i),:)); fprintf('\nNeural Network Prediction: %d (digit %d)\n', pred, mod(pred, 10)); % Pause with quit option s = input('Paused - press enter to continue, q to exit:','s'); if s == 'q' break end end
例如下圖所示的數字: