本案例主要利用matlab代碼解決“采用實現線性回歸(單一變量)來預測一輛食品卡車的利潤的問題”,代碼中涉及到機器學習中的線性回歸理論知識,本文不着重介紹(詳細可參考吳恩達的《機器學習》),主要介紹其代碼實現過程(源代碼參考吳恩達的《機器學習》的課后作業)。
一、ex1.m實現代碼如下:代碼主要包括三部分:Part 1: 將該線性回歸問題的數據集在圖中表示、 Part 2: 梯度下降算法實現線性回歸、Part 3: 圖像化函數J(theta_0, theta_1)。
%%機器學習練習-線性回歸函數
% 說明
% ------------
% 這個文件包含的代碼將幫助你開始線性回歸問題的練習。
%並且該文件代碼將用到以下子函數:
%
% warmUpExercise.m 簡單的函數例子,產生5*5的特征矩陣函數
% plotData.m 顯示數據,畫圖
% gradientDescent.m 單一變量批量梯度下降函數
% computeCost.m 計算線線回歸的單一變量損失函數算法
%
% x指的是10萬人口的人口規模
% y指的是10萬美元的利潤
%
%% 初始化
clear ; close all; clc
%% ======================= Part 1: 將該線性回歸問題的數據集,在圖中表示 =======================
fprintf('畫出訓練集的數據 ...\n')
data = load('ex1data1.txt');
%文件ex1data1.txt包含了我們的線性回歸問題的數據集。
%第一列是城市的人口,第二列是城市里的一輛食品卡車的利潤。
%利潤的負值表示損失。
X = data(:, 1); y = data(:, 2);
m = length(y); % 訓練集的數量
% 畫出數據,調用畫圖函數
plotData(X, y);
fprintf('運行暫停.按enter鍵繼續..\n');
pause;
%% =================== Part 2: 梯度下降算法 ===================
fprintf('運行梯度下降算法 ...\n')
X = [ones(m, 1), data(:,1)]; % 在X中添加一列數(m個1)
theta = zeros(2, 1); % 初始化擬合參數(0,0)
% 一些梯度下降函數設置
iterations = 1600;%迭代次數設置為1500次
alpha = 0.01;%學習率設置為0.01.
% 計算和顯示初始的成本值
%調用損失函數,計算初值,此時theta值為(0,0)
computeCost(X, y, theta)
%運行批量梯度下降函數
theta = gradientDescent(X, y, theta, alpha, iterations);
% 將theta值打印在屏幕上
fprintf('通過批量梯度下降法找到的Theta值: ');
fprintf('%f %f \n', theta(1), theta(2));
% 畫出線性擬合圖
hold on; % 保持先前的圖可見
plot(X(:,2), X*theta, '-')
%實際擬合的函數為h=theta1*X(1)+theta2*X(2),X(1)=1,X(2)為訓練集中的特征值x
legend('訓練數據', '線性回歸')
hold off % 不要在這個圖上疊加其他的圖形
% 預測人口規模為3.5萬和7萬的利潤值
predict1 = [1, 3.5] *theta;
fprintf('當人口為35,000時,我們預測利潤為 %f\n',...
predict1*10000);
predict2 = [1, 7] * theta;
fprintf('當人口為35,000時,我們預測利潤為 %f\n',...
predict2*10000);
fprintf('運行暫停.按enter鍵繼.\n');
pause;
%% ============= Part 3: 圖像化函數J(theta_0, theta_1) =============
fprintf('Visualizing J(theta_0, theta_1) ...\n')
% 將計算出的覆蓋在網格圖中
theta0_vals = linspace(-10, 10, 100);
theta1_vals = linspace(-1, 4, 100);
%初始化J_vals為一個0矩陣,長度為1000
J_vals = zeros(length(theta0_vals), length(theta1_vals));
% 填入 J_vals矩陣
for i = 1:length(theta0_vals)
for j = 1:length(theta1_vals)
t = [theta0_vals(i); theta1_vals(j)];
J_vals(i,j) = computeCost(X, y, t);
end
end
%我們需要在調用surf函數前將J_vals矩陣轉置,否則這些軸就會被翻轉
J_vals = J_vals';
% 曲面圖
figure;
surf(theta0_vals, theta1_vals, J_vals)
xlabel('\theta_0'); ylabel('\theta_1');
% 等值線
figure;
% 將矩陣J_vals畫作15個等高線間隔在0.01到100之間
contour(theta0_vals, theta1_vals, J_vals, logspace(-2, 3, 20))
xlabel('\theta_0'); ylabel('\theta_1');
hold on;
plot(theta(1), theta(2), 'rx', 'MarkerSize', 10, 'LineWidth', 2);
二、運行結果顯示:
圖一:訓練集數據顯示圖 圖二:梯度下降法實現的線性回歸圖

圖一 圖二
圖三:梯度下降法三維曲線圖 圖四:梯度下降法等高線圖

圖三 圖四
預測結果:
通過批量梯度下降法找到的Theta值: -3.674119 1.170765
當人口為35,000時,我們預測利潤為 4235.595167
當人口為70,000時,我們預測利潤為 45212.381074
三、實現代碼分析
1)第一部分:“ 將該線性回歸問題的數據集,在圖中表示 ”代碼實現比較簡單,主要讀取訓練數據集ex1data1.txt中的數據,然后將數據用圖畫出。
2)第二部分:“梯度下降算法實現線性回歸”,主要包括損失函數function J = computeCost(X, y, theta)和批量梯度下降算法function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)。
其損失函數實現代碼computeCost.m如下所示:
1 function J = computeCost(X, y, theta) 2 %損失函數: 3 % J = COMPUTECOST(X, y, theta) 4 % 計算使用theta的成本作為線性回歸的參數以適應X和y中的數據點, 5 %選擇的參數theta(theta1,theta2)決定了我們得到的直線相對於我們的訓練集的准確程度, 6 %即模型所預測的值與訓練集中實際值之間的差距 7 8 % 初始化一些有用值 9 m = length(y); % 訓練樣本數 10 11 % 需要正確地返回下列變量 12 J = 0;%變量初始化為0 13 14 % ======================代價函數代碼 ====================== 15 % 介紹:計算特定的theta(theta0,theta1)的函數值 16 17 J = sum((X * theta - y).^2) / (2*m); % 如X(79,2) theta(2,1) 18 19 % ========================================================================= 20 21 end
其批量梯度下降算法實現代碼gradientDescent.m如下所示:
1 function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters) 2 %GRADIENTDESCENT Performs gradient descent to learn theta 3 %該函數執行批量梯度下降法來學習theta值 4 % theta = GRADIENTDESENT(X, y, theta, alpha, num_iters) 5 % 該函數通過執行梯度下降算法次數來更新theta值,每次迭代次數跟學習率有關 6 % 函數參數說明: 7 % X :代表特征/輸入變量 8 % y:代表目標變量/輸出變量 9 % theta:線性回歸模型的兩個系數值(h(x)=theta(1)+theta(2)*x) 10 % alpha:學習率 11 % num_iters:迭代次數 12 % 初始化一些有用的值 13 m = length(y); %訓練樣本數 14 J_history = zeros(num_iters, 1);%初始化每次迭代時,代價函數的值初始化為0 15 theta_s=theta;%初始化theta變量,賦初值 16 17 for iter = 1:num_iters 18 19 % ====================== 批量梯度下降法代碼實現====================== 20 % 介紹: 在參數向量theta上執行一個梯度步驟。 21 % 22 % 23 % 提示: 當測試時,它能夠打印有用的代價函數值和梯度算法 24 % 25 theta(1) = theta(1) - alpha / m * sum(X * theta_s - y); 26 theta(2) = theta(2) - alpha / m * sum((X * theta_s - y) .* X(:,2)); % 必須同時更新theta(1)和theta(2),所以不能用X * theta,而要用theta_s存儲上次結果。 27 theta_s=theta; 28 29 30 % ============================================================ 31 32 % 將每次迭代次數計算的成本函數J值保存 33 J_history(iter) = computeCost(X, y, theta); 34 35 end 36 J_history 37 end
3)第三部分:“圖像化函數J(theta_0, theta_1)”,將最佳的theta值,用三維曲線圖和等高線圖表示,但是此方法只能得到大概的最佳的theta值。
四、總結
1)ex1.m中,出現的這兩句代碼:
X = [ones(m, 1), data(:,1)]; % 在X中添加一列數(m個1)
theta = zeros(2, 1); % 初始化擬合參數(0,0)
第一句代碼:生成了一個2*m的矩陣,第一列是系數‘1’,第二列輸入變量x(訓練集中的城市人口數)可以用“X(:,2)”表示。
第二句代碼:初始化theta向量,包含兩個值theta(1)和theta(2)。
這樣編寫的好處是,在后續代碼中X*theat就相當於單變量模型的h=theta(1)*1+theta(2)*x
2)ex1.m中,出現的這兩句代碼:
iterations = 1500;%迭代次數設置為1500次
alpha = 0.01;%學習率設置為0.01
其作用是設置批量梯度下降算法所需要的相關變量,該變量參數可根據實際情況修改。
3)其余代碼實現過程,根據其算法理論知識也很好理解。
全部代碼可以在https://github.com/xtuwang/my_machine-learning_test/blob/master/my-ex1-1.zip下載。
