本案例主要利用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下载。
请发表评论