小言_互联网的博客

Prometheus计划之吴恩达机器学习笔记(1)线性回归

342人阅读  评论(0)

这一部分是对吴恩达机器学习线性回归部分内容的总结,主要分为以下几个部分

1.数据绘制

2.单变量线性回归

3.重要变量的可视化

4.多变量线性回归

5.标准化方程的直接解

1.数据绘制

已知一个数据集(X,Y),现要将其可视化,在Matlab中代码如下

data = load('ex1data1.txt'); 
%读取数据表中的数据,数据表有两列所以是一个两列的矩阵
%load指令用于读取事先准备好的数据
X = data(:, 1); y = data(:, 2); 
%其中X矩阵为输入,是数据表中的第一列,Y矩阵为输出,是第二列
m = length(y); 
% length函数返回数组维数的最大长度,在这里就是样本容量
%有了上述的准备,就可以调用plot函数进行散点图的绘制
figure; %figure指令用于打开一个新的图片窗口
plot(X,y,'rx','MarkerSize',10);
%这里的plot函数使用方法:
%plot(x轴数据,y轴数据,“rx”意思是散点形状为红色的叉,散点尺寸为10)
ylabel('Profit in $10,000s'); % 设置Y轴的名称
xlabel('Population of City in 10,000s'); % 设置X轴的名称

结果如下:

2.单变量线性回归

有了上述的数据准备,那么现在将X,y的关系假设为一直线
h θ ( x ) = θ T x = θ 0 + θ 1 x 1 h_θ​(x)=θ^Tx=θ_0+θ_1​x_1​
现在就是要运用梯度下降方法求出 θ 0 θ 1 θ_0和θ_1的值
为了是误差最小,首先要定义代价函数 J ( θ ) J(θ) ,具体定义见笔记本,现给出其代码实现

function J = computeCost(X, y, theta)
%function...end是函数的定义形式,这里的函数只返回一个值给J
%该函数要输入三个值,输入X和label y以及theta值
m = length(y); % 样本容量 
J=(1/(2*m)).*sum(((X*theta)-y).^2); 
%sum函数是对括号内的矩阵的每一列的函数求和
%括号内是假设值对label的差的平方
end

由于程序本身的逻辑,在计算 J ( θ ) J(θ) 之前要对 θ θ 进行初始化并且把X矩阵里面添加上 x 0 x_0 ,此外,还要加上学习系数和迭代次数,初始化代码如下

X = [ones(m, 1), data(:,1)];
 % 在原来的基础上添加x_0
theta = zeros(2, 1); 
 % 先将theta初始化为零向量
 % 实际上后面会学到随机初始化方法
iterations = 1500;%迭代次数
alpha = 0.01;%学习系数

现在计算代价函数

J = computeCost(X, y, theta);

算出了第一个代价函数,然后,运用梯度下降法,自动更新代价函数,梯度函数的算法见笔记本,这里仅描述其代码实现
梯度下降算法定义如下

function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
%这种函数返回两个值分别给theta和J_history
%该函数要输入5个值,
%输入X和label y,theta值以及学习系数alpha,还有迭代次数num_iters
m = length(y); % 样本容量
J_history = zeros(num_iters, 1);
%这个东西观察代价函数的变化情况

for iter = 1:num_iters
	theta_s=theta;
	%这里有一个细节要注意,不能直接用theta进行更新
	%因为theta1更新之后,theta2用更新后的矩阵进行更新就会不准确
    theta(1) = theta(1) - alpha / m * sum(X * theta_s - y);
    %对theta0的更新
    theta(2) = theta(2) - alpha / m * sum((X * theta_s - y) .* X(:,2)); 
    %对theta1的更新
    J_history(iter) = computeCost(X, y, theta);
    %记录代价函数的变化情况
end
end

有了上述定义,就可以进行迭代

theta = gradientDescent(X, y, theta, alpha, iterations);

经过指定次数的迭代之后我们找到了 θ θ 的最优解,现将其可视化

% 画线性拟合图
hold on; %由于之前画过散点图,所以这里用hold on指令直接在散点图上画拟合线
plot(X(:,2), X*theta, '-')
%X(:,2)指的就是单变量输入,因为之前添加了x0,所以取第二列
%Y轴“X*theta”是估计值,和label值进行对比
%-’是图线样式
legend('Training data', 'Linear regression')
%legend指令是插入顺序建立图例,所以之前的训练集就是Training data
%后面拟合的就是Linear regression
hold off 
% 这个指令就是取消hold on,下次画图就会在新的画布上进行

现在有了直观的数据,还可以做几个测试

predict1 = [1, 3.5] *theta;
%数据必须是[1,x]1代表x0
fprintf('For population = 35,000, we predict a profit of %f\n',...
    predict1*10000);
predict2 = [1, 7] * theta;
fprintf('For population = 70,000, we predict a profit of %f\n',...
    predict2*10000);

致此,单变量线性回归内容结束

3.重要变量的可视化

因为本例中theta0是-3.63,theta1是1.663,所以我们可以计算一下theta在-10到10,theta1在-1到4范围内的代价函数的情况
步骤如下:
1.建立坐标系(x值取值)

theta0_vals = linspace(-10, 10, 100);
%theta0取-1010,分一百份
theta1_vals = linspace(-1, 4, 100);
%theta1取-14,分一百份

2.逐个计算代价函数的值
但是在这之前,要先将J(θ)初始化

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)];
	  %t就是theta向量,到时候直接输入进代价函数计算公式中
	  J_vals(i,j) = computeCost(X, y, t);
	  %三个输入分别为X,lebal y以及theta
    end
end

但是由于上面那个循环的次序,所以绘图的时候要将J_vals转置一下

J_vals = J_vals';

接下来调用函数进行图形绘制

% 绘制曲面图
figure;%新建一个画布
surf(theta0_vals, theta1_vals, J_vals)
%surf(x,y,z)中的输入x,y,z就对应相应的坐标轴
%本例中x轴就是theta0,y轴就是theta1,z轴就是对应的J(theta)
xlabel('\theta_0'); ylabel('\theta_1');
%简单的标注

% 绘制等高线
figure;%绘制一个新的画布
contour(theta0_vals, theta1_vals, J_vals, logspace(-2, 3, 20))
%contour函数,前两个参数分别对应坐标轴,第三个是值域,第三个值是水平
%所谓水平,就是要画几条线,在值为何值的地方画线
xlabel('\theta_0'); ylabel('\theta_1');
hold on;
%下一幅图在等高线的基础上画
plot(theta(1), theta(2), 'rx', 'MarkerSize', 10, 'LineWidth', 2);
%把我们拟合出来的那个点画在等高线上,发现在最低点附近

4.多变量线性回归

这里我们仍假设在多变量状况下,回归曲线仍然是一条直线
在进行拟合之前首先还是要对数据进行预处理,由于多元变量的特殊性,为了保证运算速度,要对数据进行归一化,具体步骤如下
1.数据读取

data = load('ex1data2.txt');%读取变量
X = data(:, 1:2);%前两列为两个输入元素
y = data(:, 3);%最后一列为label y
m = length(y);%样本空间

2.数据归一化
公式见笔记本,这里仅讨论实现
定义这样一个函数
但是要注意,使用标准方程方法时不需要归一化

function [X_norm, mu, sigma] = featureNormalize(X)
mu = mean(X);%首先计算均值
sigma = std(X);%std函数用于计算标准差,计算X每一列的标准差
X_norm  = (X - repmat(mu,size(X,1),1)) ./ sigma;;
%repmat函数是复制矩阵的函数,repmat(a,1,2)就是竖着复制两个a矩阵,这里的目的就是搞出一个长度为样本空间的平均值(注意这里的平均值是矩阵),然后让每个x都减
%然后统一除以sigma
end

3.梯度下降
对数据预处理完毕之后,就可以进行梯度下降了
首先计算代价函数,其定义公式见笔记,这里仅讨论其实现
代价函数定义如下

function J = computeCostMulti(X, y, theta)
m = length(y); 
J = sum((X * theta - y).^2) / (2*m);
%形式上和单变量是一致的
end

在迭代之前,首先要对一些变量进行初始化

alpha = 0.01;%初始化学习系数
num_iters = 400;%迭代次数
theta = zeros(3, 1);%初始化theta

这里用一个循环实现 θ θ 的迭代,并且返回 J ( θ ) J(θ)的迭代

function [theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters)
m = length(y); %样本容量
J_history = zeros(num_iters, 1); %初始化J(theta)
for iter = 1:num_iters
theta = theta - alpha / m * X' * (X * theta - y); %迭代
J_history(iter) = computeCostMulti(X, y, theta);
end
end

算出θ之后要对一些东西进行可视化

figure;
plot(1:numel(J_history), J_history, '-b', 'LineWidth', 2);
%numl函数返回的是括号内的元素数目,也就是定义了x轴
%plot的用法前面讲过
%LineWidth是线宽
xlabel('Number of iterations');
ylabel('Cost J');
%定义x轴,y轴
fprintf(' %f \n', theta);
%输出最终的theta值

可视化完成之后,要进行测试

注意,用归一化算出来的 θ θ 进行估计的时候,数据也要先归一化再带入拟合方程

price = [1 (([1650 3]-mu) ./ sigma)] * theta;
%测试

5.标准化方程的直接解

首先还是数据的预处理,不多赘述

data = csvread('ex1data2.txt');
%csvread和load函数在这边用法一样
%csvread函数一般处理用逗号分隔的文件
X = data(:, 1:2);
y = data(:, 3);
m = length(y);

添加x0

X = [ones(m, 1) X];

进行完数据预处理之后,就能进行计算了,公式部分见笔记,这里只介绍代码实现

function [theta] = normalEqn(X, y)
theta = pinv( X' * X ) * X' * y;
end

可视化

fprintf('Theta computed from the normal equations: \n');
fprintf(' %f \n', theta);
fprintf('\n');

测试

price = [1 (([1650 3]-mu) ./ sigma)] * theta;


转载:https://blog.csdn.net/qq_35798782/article/details/101752100
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场