本案例主要利用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)为训练集中的特征值xlegend('训练数据', '线性回归')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); endend%我们需要在调用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;%变量初始化为013 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);%初始化每次迭代时,代价函数的值初始化为015 theta_s=theta;%初始化theta变量,赋初值16 17 for iter = 1:num_iters18 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 end36 J_history37 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下载。