作业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.rhkb.cn/news/452460.html

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

相关文章

【vue】vue-router_ vue3路由管理器

代码获取 vue-router_ vue3路由管理器 ⼀、基本介绍 1. 单⻚应⽤程序介绍 1.1 概念 单⻚应⽤程序:SPA(Single Page Application)是指所有的功能都在⼀个HTML⻚⾯上实现 1.2 具体⽰例 单⻚应⽤⽹站: ⽹易云⾳乐 https://music.163.com/ 多⻚应⽤⽹…

linux环境下C程序的编译过程以及makefile的简单使用

在windows下,很多用来进行编程软件对于写好的文件,点击编译即可生成想要文件。如.exe可执行文件,.hex文件或者.bin文件等等。软件为我们省略了很多事。但是对于linux初学者来说,初次接触linux系统,面对命令行黑框框有点…

git-合并连续两次提交(一个功能,备注相同)

前言: 场景是这样,由于我是实现一个功能,先进行了一次commit,然后我发现写的有些小问题,优化了一下功能并且把代码优化了一次,于是又提交了一次。两次的提交都是以相同的备注(当然这个无所谓)&a…

智能时代摩托车一键启动无钥匙进入感受科技前线

向智能化与高性能迈进,技术创新与绿色转型引领摩托车行业智能化出行。 摩托车一键启动无钥匙进入功能是一种先进的车辆控制系统,它允许驾驶员在不使用传统机械钥匙的情况下,通过智能感应技术自动解锁和启动摩托车。这种系统通常包括一个智能钥匙&#x…

【前端】如何制作一个自己的网站(11)

接上文。 除了前面的颜色样式外,字体样式和文本样式也是网页设计中的重要组成部分。 合适的字体和文本排版,不仅可以使页面更加美观,也可以提升用户体验。接下来,我们先来看看CSS如何设置字体样式。 字体样式 同时设置了字体样…

Python SQL 注入攻击及其防护措施:编写安全的数据库查询

Python SQL 注入攻击及其防护措施:编写安全的数据库查询 SQL 注入(SQL Injection)是一种常见且危险的安全漏洞,攻击者通过操纵应用程序的数据库查询输入,执行未经授权的操作,可能会导致数据库数据泄露、篡…

闯关leetcode——136. Single Number

大纲 题目地址内容 解题代码地址 题目 地址 内容 Given a non-empty array of integers nums, every element appears twice except for one. Find that single one. You must implement a solution with a linear runtime complexity and use only constant extra space. …

leetcode30:串联所有单词的字串

给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如,如果 words ["ab","cd","ef"], 那么 "abcdef…

thinkpad E14 GEN5 加内存

1、正面 2、背面 3、角落 松掉所有螺丝后,用塑料撬片沿着角落开始撬。把所有的卡口都撬开就可以了。 4、内存盖子 取下背板,就看到内存区域了。上面覆盖了一个散热金属盖子。 拿掉金属盖子。 5、内存卡口 我的这代笔记本是板载16G DDR4 3200内存&…

Java 类和对象详解(下)

个人主页:鲤鱼王打挺-CSDN博客 目录 💗前言: 💯一.static关键字 1. 为什么要使用static 2. static 修饰成员变量: 3. static 修饰成员方法: ​编辑 4. 静态代码块 5.静态导入包 💯二.…

C++进阶——set和map

目录 前言 一、set 1.set的基本介绍 2.set的使用 2.1构造与迭代器 2.2插入 2.3删除 2.4查找 2.5获取需要的区间 2.6一些使用示例 3.set和multiset的区别 4.set相关oj题目 二、map 1.map的基本介绍 2.map的使用 2.1构造与迭代器 2.2增删查以及获取区间 2.3数据…

【C语言】strtok、strerror函数

1、strtok函数使用 注意:使用strtok时包含头文件:string.h strtok函数原型: char* strtok(char* str, const char* sep); (1)sep参数指向一个字符串,定义了用作分隔符的字符集合。 &#x…

xlsx xlsx-style-vite 实现前端根据element 表格导出excel且定制化样式 背景 列宽等

前言 先看下最终效果图吧,需要的可以参考我的实现方式 这是最终导出的表格文件 类似这种的,特定单元格需要额外标注,表头也有月份然后细分的,表格组件是这样的 注意 别使用xlsx-style 这个库,太多问题了,…

优阅达携手 Theobald 亮相新加坡科技周,助力企业 SAP 数据集成与应用

针对不同用户需求量身定制解决方案,帮助企业轻松应对从数据提取到分析、从开发到流程管理的 SAP 数据挑战。 上周,2024 新加坡科技周在滨海湾金沙会议展览中心圆满落幕。在为期两天的活动中,七大专题展览同时进行,超过 2,000 家…

【Router】路由器中NAT、NAPT、NPT是什么?

参考链接 NAT vs. NAPT: What’s the Difference? IPv6 Network Prefix Translation (NPt) | pfSense Documentation (netgate.com) 趣谈NAT/NAPT的原理,这篇不可不读! - 知乎 (zhihu.com) NAT (Network Address Translation) NAT说明 NAT&#x…

Java | Leetcode Java题解之第486题预测赢家

题目&#xff1a; 题解&#xff1a; class Solution {public boolean PredictTheWinner(int[] nums) {int length nums.length;int[] dp new int[length];for (int i 0; i < length; i) {dp[i] nums[i];}for (int i length - 2; i > 0; i--) {for (int j i 1; j …

SQL Server 2019数据库“正常,已自动关闭”

现象&#xff1a; SQL Server 2019中&#xff0c;某个数据库在SQL Server Management Studio&#xff08;SSMS&#xff09;中的状态显示为“正常&#xff0c;已自动关闭”。 解释&#xff1a; 如此显示&#xff0c;是由于该数据库的AUTO_ CLOSE选项被设为True。 在微软的官…

webAPI中的排他思想、自定义属性操作、节点操作(配大量案例练习)

一、排他操作 1.排他思想 如果有同一组元素&#xff0c;我们想要某一个元素实现某种样式&#xff0c;需要用到循环的排他思想算法&#xff1a; 1.所有的元素全部清除样式 2.给当前的元素设置样式 注意顺序能不能颠倒&#xff0c;首先清除全部样式&#xff0c;再设置自己当前的…

位运算题目-Java实现-LeetCode题解:判断字符是否唯一-丢失的数字-两整数之和-只出现一次的数字 II-消失的两个数字

这里是Themberfue 上一篇文章讲完了常见位运算的技巧以及总结 那么本章则通过五道题来运用这些技巧 判定字符是否唯一 题目解析 本题要求判断给定字符串中的字符是否唯一&#xff0c;也就是每个字符是否只出现一次 算法讲解 本题用哈希表遍历每一个字符也可以解决 如果这题使…

设计模式02-桥接模式(Java)

4.2 桥接模式 **1.定义&#xff1a;**将抽象与实现分离&#xff0c;使它们可以独立变化。它是用组合关系代替继承关系来实现&#xff0c;从而降低了抽象和实现这两个可变维度的耦合度。 2.结构&#xff1a; 抽象化角色 &#xff1a;定义抽象类&#xff0c;并包含一个对实现化…