作业2-线性回归的Matlab代码实现

一、前言

        相关配置:Matlab 2020a(版本的影响应该不大,.m代码基本都能运行,个人感觉就是Simulink对版本的要求高一些)

二、任务描述

        基于近两节课的理论推导,用代码实现线性回归,并对预测结果进行分析。同时体会学习率、迭代次数对系统的影响(收敛速度、代码运行速度等)。

三、代码实现

        我们将任务假设为房价的预测,研究单变量的线性回归,即输入特征只有一个(房屋面积)。使用一次函数来生成相关样本(这里的一次函数为笔者随意设置,并不与现实的情况相符合)。

% ----------------------原始数据集---------------------- %
x = linspace(0, 1000, 200); % 生成横坐标(房屋面积)数据
y = 1.5 * x + 100; % 生成房价
data = [x; y]; % 组合成二维数据

        这样生成的样本(以50个样本为例)连起来就是一条直线。然而现实情况是,样本数据或多或少会存在“噪声”,房价与房屋面积也不会呈现完美的一次函数关系。所以我们需要对样本增加“噪声”。代码示例如下:

noise_level = 30;  % 定义噪声参数noise = noise_level * randn(size(data)); % 生成与数据相同大小的高斯噪声
noisy_data = data + noise; % 将噪声添加到数据中noisy_x = noisy_data(1,:); % 添加噪声后的特征(房屋面积)
noisy_y = noisy_data(2,:); % 添加噪声后的结果(房价)

        其中randn 函数用于生成符合标准正态分布(均值为 0,标准差为 1)的随机数。增加“噪声”后的样本示例如下图所示。我们可以发现,样本点出现了一定的变化,呈现一种“随机”的状态。

        在进行梯度下降迭代之前,我们还需要将样本数据进行归一化。对自变量和因变量进行归一化或标准化,使其值更为均衡,有利于帮助模型更快收敛。(笔者在之前的测试中发现,若不进行归一化,输出的截距θ0会为0或者其他奇奇怪怪的问题。)

        【特别注意】最终我们预测结果的那条线的相关参数需要进行反归一化才行!!!

std_x = (noisy_x - mean(noisy_x)) / std(noisy_x); % 标准化x
std_y = (noisy_y - mean(noisy_y)) / std(noisy_y); % 标准化y

        接下来就是进行梯度下降的迭代了。代码主要分为以下三步

①、依据输入特征,获得预测值(预测的房价)

②、计算梯度,获得当前的θ0和θ1(实际情况是需要对θ0和θ1求偏导,代码中直接给出了计算结果,详见《机器学习-周志华》P54的式3.5和式3.6)

③、更新参数,获取新的θ0和tθ1(这里需要注意学习率α不宜设置的过大。过大的α可能会导致损失函数J无法收敛)

④、计算损失值

         主循环代码如下所示:

% ------------------------------主循环代码-------------------------------
% GPT的例程是固定一个迭代次数,例如1000次,次数到了就退出循环,输出结果
% 笔者尝试固定一个损失值,当损失小于固定值时才退出循环,但运行效果不佳,
% 故放弃了这种方案
% ----------------------------------------------------------------------
for i = 1 : iteration_numy_pred = theta1 * std_x + theta0; % 预测值% 计算梯度d_theta1 = (1/m) * (theta1 * sum(std_x.^2) - sum((std_y - theta0) .* std_x));d_theta0 = theta0 - (1/m) * sum(std_y - theta1 * std_x);% 更新参数theta1 = theta1 - alpha * d_theta1;theta0 = theta0 - alpha * d_theta0;loss = (1/m) * sum((y_pred - std_y).^2); % 计算损失J_history(i) = loss;
end

        主循环结束运行的方式笔者认为可以有两种方法。第一种是如上图所示的,通过设定迭代次数,当迭代次数到了后,退出循环。第二种是人为设定一个损失值,当计算的损失值小于设定的损失值时,退出循环。在测试中,第二种方法效果并不好,有时代码会长时间运行,无法跳出循环,遂放弃。

        到这一步,我们就完成“模型的训练”啦,在画图之前,别忘了我们还需要进行反归一化。

% 反归一化后,才是真正的theta0和theta1
theta1 = theta1 * (std(noisy_y) / std(noisy_x)); % 恢复原始斜率
theta0 = mean(noisy_y) - theta1 * mean(noisy_x); % 恢复原始截距

四、输出结果与分析

        下图为迭代500次的预测结果,其中绿色的回归线与数据点基本吻合,说明模型预测效果较好。

         此外迭代500次的损失函数的收敛图如下图所示,我们可以发现,损失值随着迭代次数的增加逐渐减小,呈现一种收敛的状态。

        下图是迭代1000次的 损失函数的收敛图,我们可以发现,迭代次数超过500后,损失值几乎不再发生变化(本身“损失”就已经很小了),所以无脑的增加迭代次数并不一定是好的,适可而止,在大模型训练中也能节约计算时间。

         以下Matlab“命令窗口”打印的数据结果,我们可以发现,最终输出的线性回归方程与前文设置的一次方程y=1.5x+100相近似。

迭代次数:500次
loss损失:0.011024
最终线性回归方程:y = 1.49x + 104.89
theta1 = 1.49, theta0 = 104.89
>> 

         通过绘制J(\theta _{0},\theta _{1})的图像,我们也可以发现,最终的损失函数J会有一个全局最小的点。(这只是一个简单的测试样例)

五、程序代码 

clc;
clear;
close all;% ----------------------原始数据集---------------------- %
x = linspace(0, 1000, 200); % 生成横坐标(房屋面积)数据
y = 1.5 * x + 100; % 生成房价
data = [x; y]; % 组合成二维数据% -------------------------变量------------------------ %
iteration_num = 500; % 迭代次数
noise_level = 30;    % 定义噪声参数
theta1 = 0;          % 初始化斜率
theta0 = 0;          % 初始化截距
alpha = 0.01;        % 学习率
m = length(y);       % 样本数量
J_history = zeros(iteration_num, 1); % 记录每次迭代的损失值noise = noise_level * randn(size(data)); % 生成与数据相同大小的高斯噪声
noisy_data = data + noise; % 将噪声添加到数据中noisy_x = noisy_data(1,:); % 添加噪声后的特征(房屋面积)
noisy_y = noisy_data(2,:); % 添加噪声后的结果(房价)std_x = (noisy_x - mean(noisy_x)) / std(noisy_x); % 标准化x
std_y = (noisy_y - mean(noisy_y)) / std(noisy_y); % 标准化y% ------------------------------主循环代码-------------------------------
% GPT的例程是固定一个迭代次数,例如1000次,次数到了就退出循环,输出结果
% 笔者尝试固定一个损失值,当损失小于固定值时才退出循环,但运行效果不佳,
% 故放弃了这种方案
% ----------------------------------------------------------------------
for i = 1 : iteration_numy_pred = theta1 * std_x + theta0; % 预测值% 计算梯度d_theta1 = (1/m) * (theta1 * sum(std_x.^2) - sum((std_y - theta0) .* std_x));d_theta0 = theta0 - (1/m) * sum(std_y - theta1 * std_x);% 更新参数theta1 = theta1 - alpha * d_theta1;theta0 = theta0 - alpha * d_theta0;loss = (1/m) * sum((y_pred - std_y).^2); % 计算损失J_history(i) = loss;
end% ------------------------------绘制图像1------------------------------- %
subplot(2, 1, 1); % 创建两个子图
plot(noisy_data(1,:), noisy_data(2,:), '.b');
grid on; % 添加网格
xlim([0, 1000]); % 设置x轴范围
ylim([0, 1800]); % 设置y轴范围
hold on; % 保持图形,防止被后续图形覆盖% 反归一化后,才是真正的theta0和theta1
theta1 = theta1 * (std(noisy_y) / std(noisy_x)); % 恢复原始斜率
theta0 = mean(noisy_y) - theta1 * mean(noisy_x); % 恢复原始截距y_fit = theta1 * noisy_x + theta0;  % 计算回归线的 y 值
plot(noisy_x, y_fit, '-g', 'LineWidth', 2); % 绘制回归线title('运行结果');          % 标题
xlabel('房屋面积');         % 横坐标标签
ylabel('房屋价格');         % 纵坐标标签
legend('数据点', '回归线');  % 图例hold off;% ------------------------------绘制图像2------------------------------- %
subplot(2, 1, 2); % 创建两个子图
plot(1 : iteration_num, J_history, '-r', 'LineWidth', 2);
grid on; % 添加网格
title('损失函数收敛图'); % 标题
xlabel('迭代次数');      % 横坐标标签
ylabel('损失值');        % 纵坐标标签% ------------------------------输出结果------------------------------- %
fprintf('迭代次数:%d次\n', iteration_num); 
fprintf('loss损失:%.6f\n', loss);
fprintf('最终线性回归方程:y = %.2fx + %.2f\n', theta1, theta0);
fprintf('theta1 = %.2f, theta0 = %.2f\n', theta1, theta0);% -----------------------------END OF FILE---------------------------- %

六、加餐 

        其实是自己忘记了(汗...)

        在更新公式中,有一个学习率参数α,我们尝试修改α来看看对模型的影响。

α = 0.01 

 α = 0.002

  α = 5 

         通过 以上测试我们可以发现,α越小,模型收敛的速度越慢,需要通过增加迭代次数来达到预期的效果。而当α取值不当时,模型可能无法收敛。因此选取合适学习率α以及迭代次数至关重要,这影响到了代码运行的效率以及最终的预测结果。(迭代次数越多,代码循环的次数越多,耗费的时间越长。)

七、闲聊

        这只是一次课堂作业的学习记录。很遗憾的是,笔者未来的工作规划并不考虑机器学习方向,自己还是比较喜欢做硬件,所以大家并不需要因为这篇文章对我进行关注,后续也不一定会更新有关机器学习方向的内容,抱歉。

        此外,有关Matlab的代码笔者参考了GPT的例程,主要的逻辑框架为GPT生成,笔者只是对输入样本、一些运行参数、相关公式、整体代码风格以及输出图像的效果进行了修改,特此声明。(感叹:GPT太强大了,真的节约了很多的时间。)

2024-10-20-18:50,爽

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/56921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot+Vue+uniapp微信小程序的澡堂预订的微信小程序的详细设计和实现

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

目标检测系统【环境详细配置过程】(CPU版本)

(如果你使用的是笔记本电脑,没有比较好的GPU,可以配置CPU运行环境) 链接:上百种【基于YOLOv8/v10/v11的目标检测系统】目录(pythonpyside6界面系统源码可训练的数据集也完成的训练模型) 1.安装…

MySQL中什么情况下类型转换会导致索引失效

文章目录 1. 问题引入2. 准备工作3. 案例分析3.1 正常情况3.2 发生了隐式类型转换的情况 4. MySQL隐式类型转换的规则4.1 案例引入4.2 MySQL 中隐式类型转换的规则4.3 验证 MySQL 隐式类型转换的规则 5. 总结 如果对 MySQL 索引不了解,可以看一下我的另一篇博文&…

CTF(七)

导言: 本文主要讲述在CTF竞赛中,Misc(杂项)题目中的CatchCat。 靶场链接:攻防世界 (xctf.org.cn) 一,分析题目。 下载并解压附件: CatchCat.txt文件内容为: 发现是坐标。 另一个…

表贴式永磁同步电机无感控制-基于滑膜观测器SMO法

导读:在全速域范围内,一般的永磁同步电机无感控制要分为低速区域和高速区域两个部分。原因在于常规的方法是利用模型建立反电动势观测器来求解转子位置信息,但其只适合在中高速区域。本文介绍一种基于滑膜观测器SMO法+PLL的方法。 需要文章中的仿真,关注微信公众号:浅谈电…

python机器人编程——用python调用API控制wifi小车的实例程序

目录 一、前言二、一个客户端的简单实现2.1 首先定义一个类及属性2.2 其次定义连接方法2.3 定义一些回调函数2.4 定义发送小车指令方法2.5 定义一个正常关闭方法 三、python编程控制小车的demo实现四、小结PS.扩展阅读ps1.六自由度机器人相关文章资源ps2.四轴机器相关文章资源p…

【大数据技术基础 | 实验四】HDFS实验:读写HDFS文件

文章目录 一、实验目的二、实验要求三、实验原理(一)Java Classpath(二)Eclipse Hadoop插件 四、实验环境五、实验内容和步骤(一)配置master服务器classpath(二)使用master服务器编写…

JVM学习总结:字节码篇

本文是学习尚硅谷宋红康老师主讲的 尚硅谷JVM精讲与GC调优教程 的总结 ,部分内容也参考了 JavaGuide 网站(文末有链接) JVM 概述 Oracle JDK 与 OpenJDK 是什么关系? 2006 年 SUN 公司将 Java 开源,也就有了 OpenJDK。…

Games202作业5(完结)

单帧降噪 也就是针对图像空间进行降噪 也就是我们需要在像素(i,j)的四周进行采样,然后将采样的权重加到一起,然后所有的权重和像素的乘积也加到一起,然后相除,得到最终滤波后的(i,j)像素期望的结果。 Buf…

P4可编程技术详解:从理论到硬件实现

P4的诞生 为打破传统的固定封装模式,充分解放数据平面的编程能力,Nick McKeown领导的斯坦福大学研究团队于2014年提出可编程处理语言P4。借助P4的数据平面编程能力,用户可在网卡、交换机、路由器等网络设备上实现包括VXLAN、MPLS等在内的各种…

电影评论网站开发:Spring Boot技术指南

3系统分析 3.1可行性分析 通过对本电影评论网站实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本电影评论网站采用SSM框架,JAVA作为开发语言&#…

Linux文件的查找和打包以及压缩

文件的查找 文件查找的用处,在我们需要文件但却又不知道文件在哪里的时候 文件查找存在着三种类型的查找 1、which或whereis:查找命令的程序文件位置 2、locate:也是一种文件查找,但是基于数据库的查找 3、find:针…

基于SpringBoot+Vue+uniapp微信小程序的社区门诊管理系统的详细设计和实现(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

01 设计模式-创造型模式-工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,它提供了一种创建对象的方式,使得创建对象的过程与使用对象的过程分离。 工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。 通过使用工厂模式…

1.2.3 TCP IP模型

TCP/IP模型(接网叔用) 网络接口层 网络层 传输层 应用层 理念:如果某些应用需要“数据格式转换”“会话管理功能”,就交给应用层的特定协议去实现 tip:数据 局部正确不等于全局正确 但是,数据的 全局正…

数码准备记录

1.数据结构 常见的数据结构包括数组、链表、栈、队列、树(如二叉树、B树、B树)、图等 2.队列和栈的区别 队列是一种先入先出的数据结构,即最先加入的元素被最先移除; 栈是一种后进后出的数据结构,即最后加入的元素…

RTMP协议分析

理论 总体介绍 RTMP协议是应⽤层协议,是要靠底层可靠的传输层协议(通常是TCP)来保证信息传输的可靠性的。在基于传输层协议的链接建⽴完成后,RTMP协议也要客户端和服务器通过“握⼿”来建⽴基于传输层链接之上的RTMP Connection链…

Collection 单列集合 List Set

集合概念 集合是一种特殊类 ,这些类可以存储任意类对象,并且长度可变, 这些集合类都位于java.util中,使用的话必须导包 按照存储结构可以分为两大类 单列集合 Collection 双列集合 Map 两种 区别如下 Collection 单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两…

Electron-(二)桌面应用的启动动画创建

一、概述 在很多桌面应用中都会有启动画面的显示。启动画面可以解决在启动时耗时较长,将每一步反馈给用户。另外一方面解决启动过程中的环境检查及检查结果的反馈。 在当今的桌面应用领域,启动动画已成为提升用户体验的重要组成部分。它不仅仅是一个简单…

【Linux】main函数的参数列表从何而来?

Linux系统进程通过exec系列函数启动新程序时,argc整型 、 argv数组 和 环境变量表 environ 会作为 exec 系列函数的参数,显式传递给新程序的 main 函数。 main函数的参数列表 在C语言中,main函数的标准参数列表通常如下所示: in…