1个简单倍频程函数
首先在D:\Machine Learning\ex1目录下建立一个warmUpExercise.m的文件,用写字板打开,向其中加入代码,该函数用来实现显示一个5*5的单位矩阵。
function A = warmUpExercise() %定义了一个函数,返回是一个A矩阵
A=[]; %定义一个矩阵
A=eye(5); %A矩阵被赋值为5*5的单位矩阵
end
打开Octave,将当前路径转换到D:\Machine Learning\ex1,调用warmUpExercise函数显示矩阵。
单变量线性回归
绘制数据
在D:\Machine Learning\ex1目录下建立一个plotData.m文件,在该文件里面完成绘制数据集中数据的功能:
function plotData(x, y) %函数没有返回值,参数为x,y
plot(x,y,'x','MarkerSiz',10); %绘制数据点,以x形状展示,显示标记的大小为10
ylabel('Profit in $10,000s'); %y轴坐标标题
xlabel('Population of City in 10,000s');%x轴坐标标题
ex1data1.txt包含线性回归问题的数据集,将这个文件复制到D:\Machine Learning\ex1目录下。在Ocatve里面记载这个数据集,然后将数据集的第一列赋给X向量,第二列赋给Y变量。顺便获取训练集例子个数。调用plotData函数将其显示出来。
运行结果如图:
坡度下降
首先在D:\Machine Learning\ex1目录下建立一个computeCost.m文件,在这里面用来实现:
function J = computeCost(X, y, theta)
%返回值为代价函数值,第一个参数是x0,x1两列组成的矩阵,
%第二个参数是对应的一列的y值,
%第三个参数是θ0、θ1组成的2*1的矩阵
m=length(y); %保存训练集的数据个数
J=0; %将代价函数的值初始化为0
m=size(y,1); %返回矩阵的行数
m=1.0/2/m;
J=(sum((X*theta-y).^2))*m; %点乘就是两个矩阵相应的元素相乘
end
然后在D:\Machine Learning\ex1目录下建立一个gradientDescent.m文件,在这里面用来实现如下算法:
现在要利用梯度下降更新θ0、θ1。
function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
%函数返回值有两个,第一个就是θ0、θ1的2*1矩阵,另一个矩阵保存每次迭代后代价函数的值。
%第四个参数是学习率
%第五个参数是迭代次数
m=length(y); %训练例子的个数
J_history=zeros(num_iters,1);%初始化代价函数值矩阵
for iter=1:num_iters
%进入迭代过程
temp1=sum(X*theta-y);%因为X矩阵第一类全为1,省略不写
temp2=sum((X*theta-y).*X(:,2));
theta(1,1)=theta(1,1)-alpha*1.0/m*temp1;
theta(2,1)=theta(2,1)-alpha*1.0/m*temp2;
J_history(iter)=computeCost(X,y,theta);%将代价函数值保存到相应的矩阵中
end
end
现在打开Octave,将路径转到当前目录下。
首先初始化X矩阵和theta矩阵,迭代次数和学习率。
计算θ0、θ1均为0时候代价函数的值。如图为32.073
梯度下降求θ0、θ1,此时代价函数最小。
θ0=-3.6303、θ1=1.1664。
然后调用hold on函数将新的图形绘制在旧的图形之上,hold off关闭此操作。同时绘图时放置图例在右上方
然后根据x的值预测y的值,这里注意要将x转变成X:
下面我们试着画出θ0、θ1与J之间的关系,这里用曲面和等高线图来表示
- 打开Octave,首先分别给θ0、θ1坐标轴创建N个元素的向量,分别均匀分布于-10到10,-1到4。然后初始化J值,对应于θ0、θ1共N*N个J值。
- 将实际计算的J值存储到对应矩阵中
- 由于网状网格在surf命令中的工作方式,我们需要在调用surf之前转置J_vals,否则轴将被翻转。同时调用figure函数,使用plot函数前调用此函数,保证n不同,可以开启多个图表窗口而不会被覆盖。调用surf绘制曲面,调用contour函数绘制等高线。logspace函数将创建20个元素的向量,指数分布与10-2到103之间。最后在这个等高线图上面绘制最佳的θ0、θ1的红色标记。
运行图形如图:
多元线性回归
特征缩放
ex1data2.txt复制到D:\Machine Learning\ex1目录下,通过查看这些值,第一列的值大约是第二列值的1000倍,第三列为因变量,前两列的自变量。当两个特征变量相差数量级时,首先执行特征缩放可以使梯度下降更快地收敛。在当前路径下建立featureNormalize.m的文件,在该文件中进行特征缩放:
function [X_norm, mu, sigma] = featureNormalize(X)
%函数返回值有三个,第一个返回特征化后的前两列数据(自变量)组成的矩阵
%第二个参数返回1*2的均值矩阵
%第三个参数返回1*2的标准差矩阵
%参数是前两列数据(自变量)组成的矩阵
X_norm = X;
mu = zeros(1, size(X, 2));%初始化mu为1*2的矩阵
sigma = zeros(1, size(X, 2));
mu = mean(X);%求均值
sigma = std(X);%求标准差
X_norm = (X_norm - mu)./sigma;
end
坡度下降
- 在当前目录下添加computeCostMulti.m文件,实现代码与单变量代价函数代码一致。
- 在当前目录下添加gradientDescentMulti.m文件,实现多变量梯度下降算法,这里利用了矩阵运算。
unction [theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters)
m = length(y);
J_history = zeros(num_iters, 1);
for iter = 1:num_iters
temp = X' * (X*theta - y);
%其他代码与单变量梯度下降算法一致,这里由于是多变量,就采用矩阵一起进行运算,没有分开计算θ
theta = theta - alpha./m * temp;
J_history(iter) = computeCostMulti(X, y, theta);
end
end
运用正规方程方法求解参数
在当前目录下添加normalEqn.m文件。
function [theta] = normalEqn(X, y)
%函数返回值就是θ矩阵
theta = zeros(size(X, 2), 1);
%zeros(3,1),因为两个自变量特征变量加上一个常数项特征变量
theta = pinv(X' * X) * X' * y;%pinv是求逆矩阵
end
Octave操作下的作业解题与图形绘制
打开Octave,先将当前路径设置到指定目录下:
加载数据集,将数据集第一列和第二列赋值给X,第三列的值赋值给y,同时记录数据集数据个数:
由于X中两个特征变量相差数量级,所以先对X进行特征缩放,再给X加上常数项的特征变量,让X成为m*3的矩阵:
设置学习率和迭代次数,同时初始化θ矩阵,进行梯度下降算法处理:
输出梯度下降后的θ矩阵中对应的各个系数的值:
所以拟合的最佳的线性回归方程可以表示为y=334302.06399+100087.11601x1+ 3673.54845x2
绘制迭代次数与代价函数值之间的关系:
绘制的图形如下:
可以看到迭代次数达300次左右,就已经基本迭代出相应的θ矩阵中各个θ值了
下面利用正规方程的方法解决这个问题,再一次读入数据,给X,y进行赋值,正规方程不用进行特征缩放和多次迭代,一次计算出结果。
也计算出相应的θ值了,不过和梯度下降计算出的值有些不同。