单变量线性回归的机器学习代码

news2024/10/6 18:22:47

本文为学习吴恩达版本机器学习教程的代码整理,使用的数据集为https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/f2757f85b99a2b800f4c2e3e9ea967d9e17dfbd8/code/ex1-linear%20regression/ex1data1.txt

将数据集和py代码放到同一目录中,使用Spyder打开运行,代码中整体演示了数据加载处理过程、线性回归损失函数计算方法、批量梯度下降方法、获得结果后的预估方法、线性回归结果函数绘制、模型导出及加载使用方法,其中最后三部分彼此无依赖关系可单独执行。详细代码为下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib

# 导入数据
path =  'ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])

"""
计算线性回归模型的损失值
"""
def computeCost(X, y, theta):
    """
    此函数计算给定参数 theta 下的均方误差损失。它用于评估线性回归模型预测值与实际值之间的差异。
    损失值越小,表明模型的预测越准确。

    Parameters:
    X : numpy.ndarray 表示特征数据集的矩阵,其中包含了模型用于预测的特征。
    y : numpy.ndarray 表示目标变量的向量,包含了每个数据点的实际值。
    theta : numpy.ndarray 线性回归模型的参数向量,包括截距项和特征的系数。

    Returns:
    float 返回计算得到的均方误差损失值。
    """

    # 计算模型预测值和实际值之间的差异
    inner = np.power(((X * theta.T) - y), 2)

    # 计算并返回均方误差损失的平均值
    return np.sum(inner) / (2 * len(X))

# 在数据集前面加入一列全为1的数据,用于适配截距项
data.insert(0, 'Ones', 1)

# 分离特征(X)和目标变量(y)
cols = data.shape[1]
X = data.iloc[:,0:cols-1]#X是所有行,去掉最后一列
y = data.iloc[:,cols-1:cols]#X是所有行,最后一列

# 将X和y的类型转换为numpy矩阵,方便后续计算
X = np.matrix(X.values)
y = np.matrix(y.values)
theta = np.matrix(np.array([0,0]))# 初始化theta

# 计算初始的损失值,仅为输出和最终损失对比
initial_cost = computeCost(X, y, theta)
print("初始的损失值:", initial_cost)

"""
执行批量梯度下降
"""
def gradientDescent(X, y, theta, alpha, iters):
    """
    这个函数通过迭代地调整参数 theta,以最小化损失函数。

    Parameters:
    X : numpy.ndarray 特征数据集矩阵。
    y : numpy.ndarray 目标变量向量。
    theta : numpy.ndarray 线性回归模型的初始参数向量。
    alpha : float 学习率,控制梯度下降的步长。
    iters : int 梯度下降的迭代次数。

    Returns:
    tuple 返回一个元组,包含优化后的 theta 和每次迭代的损失值数组。
    """

    # 初始化一个临时变量,用于更新 theta
    temp = np.matrix(np.zeros(theta.shape))

    # 获取 theta 中参数的数量
    parameters = int(theta.ravel().shape[1])

    # 初始化一个数组,用于记录每次迭代的损失值
    cost = np.zeros(iters)
    
    # 迭代进行梯度下降
    for i in range(iters):
        # 计算当前参数下的误差
        error = (X * theta.T) - y
        
        # 对每个参数进行更新
        for j in range(parameters):
            # 计算误差与特征值的乘积
            term = np.multiply(error, X[:,j])
            
            # 更新 theta 的第 j 个参数
            temp[0,j] = theta[0,j] - ((alpha / len(X)) * np.sum(term))
            
        # 更新 theta
        theta = temp

        # 记录当前的损失值
        cost[i] = computeCost(X, y, theta)
        
    # 返回优化后的参数和损失值记录
    return theta, cost

# 设置学习率和迭代次数
alpha = 0.01
iters = 2000

# 执行梯度下降算法,优化theta
g, cost = gradientDescent(X, y, theta, alpha, iters)

# 计算优化后的损失值,仅为输出和初始损失对比
final_cost = computeCost(X, y, g)
print("优化后的损失值", final_cost)

"""
使用需要预测的数据X进行预测
"""
# 假设的人口数据
population_values = [3.5, 7.0]  # 代表35,000和70,000人口

# 对每个人口值进行预测
for pop in population_values:
    # 将人口值转换为与训练数据相同的格式(包括截距项)
    predict_data = np.matrix([1, pop])  # 添加截距项

    # 使用模型进行预测
    predict_profit = np.dot(predict_data, g.T)
    print(f"模型预测结果 {pop} : {predict_profit[0,0]}")


"""
使用模型绘制函数
"""
# 创建预测函数
x = np.linspace(data.Population.min(), data.Population.max(), 100)
f = g[0, 0] + (g[0, 1] * x)

# 绘制线性回归结果
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(x, f, 'r', label='Prediction')# 绘制预测线
ax.scatter(data.Population, data.Profit, label='Traning Data')# 绘制训练数据点
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()

"""
使用模型绘制损失值变化曲线
"""
# 绘制损失函数的变化
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(np.arange(iters), cost, 'r') # 损失值随迭代次数的变化
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()

"""
保存模型
"""
# 保存模型
joblib.dump(g, 'linear_regression_model.pkl')

"""
加载模型并执行预测
"""
# 加载模型
loaded_model = joblib.load('linear_regression_model.pkl')

# 假设的人口数据
population_values = [3.5, 7.0]  # 代表35,000和70,000人口

# 使用模型进行预测
for pop in population_values:
    # 更新预测数据矩阵,包括当前的人口值
    predict_data = np.matrix([1, pop])
    
    # 进行预测
    predict_value = np.dot(predict_data, loaded_model.T)
    print(f"加载模型预测结果 {pop} : {predict_value[0,0]}")

运行后结果:
在这里插入图片描述
在这里插入图片描述
输出结果:

初始的损失值: 32.072733877455676
优化后的损失值 4.47802760987997
模型预测结果 3.5 : 0.349676138927709
模型预测结果 7.0 : 4.487420850578528
加载模型预测结果 3.5 : 0.349676138927709
加载模型预测结果 7.0 : 4.487420850578528

上一个版本的线性回归算法是依据批量梯度下降公式过程计算出来的,但实际上直接使用矩阵来计算能够极大提升效率,代码如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib

# 导入数据
path = 'ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])

# 分离特征和目标变量
X = data.iloc[:, 0:1].values  # Population列
y = data.iloc[:, 1].values  # Profit列
m = len(y)  # 样本数量

# 添加一列全为1的截距项
X = np.append(np.ones((m, 1)), X, axis=1)

# 初始化模型参数
theta = np.zeros(2)

# 批量梯度下降参数
alpha = 0.01  # 学习率
iterations = 1500  # 迭代次数

# 批量梯度下降算法
def gradientDescent(X, y, theta, alpha, num_iters):
    m = len(y)  # 获取样本数量

    for i in range(num_iters):  # 对于指定的迭代次数
        # 计算当前theta下的预测值。这是通过矩阵X(特征)和theta(参数)的点积来完成的。
        predictions = X.dot(theta)
        # 计算预测值和实际值之间的误差。
        errors = np.subtract(predictions, y)
        # 计算梯度:首先,计算特征矩阵X的转置和误差的点积;
        # 然后,乘以学习率alpha和样本数量的倒数。
        sum_delta = (alpha / m) * X.transpose().dot(errors)
        # 更新参数theta:从当前theta中减去梯度(乘以学习率)。
        theta = theta - sum_delta  
    return theta  # 在完成所有迭代后,返回最终的参数theta。


# 进行梯度下降以拟合模型
theta = gradientDescent(X, y, theta, alpha, iterations)

"""
使用需要预测的数据X进行预测
"""
# 假设的人口数据
population_values = [3.5, 7.0]  # 代表35,000和70,000人口

# 对每个人口值进行预测
for pop in population_values:
    # 将人口值转换为与训练数据相同的格式(包括截距项)
    predict_data = np.matrix([1, pop])  # 添加截距项

    # 使用模型进行预测
    predict_profit = np.dot(predict_data, theta.T)
    print(f"模型预测结果 {pop} : {predict_profit[0,0]}")
"""
使用模型绘制函数
"""
# 创建预测函数
x_values = np.array(X[:, 1])
f = theta[0] + (theta[1] * x_values)

# 绘制图表
fig, ax = plt.subplots(figsize=(12, 8))
ax.plot(x_values, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profit, label='Training Data')
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()

"""
保存模型
"""
# 保存模型
joblib.dump(theta, 'linear_regression_model.pkl')

"""
加载模型并执行预测
"""
# 加载模型
loaded_model = joblib.load('linear_regression_model.pkl')

# 假设的人口数据
population_values = [3.5, 7.0]  # 代表35,000和70,000人口

# 使用模型进行预测
for pop in population_values:
    # 更新预测数据矩阵,包括当前的人口值
    predict_data = np.matrix([1, pop])
    
    # 进行预测
    predict_value = np.dot(predict_data, loaded_model.T)
    print(f"模型预测结果 {pop} : {predict_value[0,0]}")

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

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

相关文章

HarmonyOS(二)—— 初识ArkTS开发语言(下)之ArkTS声明式语法和组件化基础

前言: 通过前面ArkTS开发语言(上)之TypeScript入门以及ArkTS开发语言(中)之ArkTS的由来和演进俩文我们知道了ArkTS的由来以及演进,知道了ArkTS具备了声明式语法和组件化特性,今天,搭…

计网 - 如何理解 Mac地址 、 IP地址 、端口号

文章目录 概述Mac地址IP 地址IP 地址和 MAC 地址之间的区别端口号为什么端口号有 65535 个?端口号的确定标准既定的端口号时序分配法 观察端口号 小结 概述 Mac地址(Media Access Control Address)和IP地址(Internet Protocol Ad…

蓝桥杯小白赛第一场(1~6)(期望DP)

1、模拟 2、贪心 3、前缀和 4、猜结论 5、双指针 6、期望DP 1. 蘑菇炸弹 思路&#xff1a;一个简单的暴力模拟。 #include <bits/stdc.h> using namespace std; int main() {int n;cin >> n;vector<int>a(n , 0);for(int i 0 ; i < n ; i )cin &…

西南交通大学【数据结构实验8】

实验内容及要求&#xff1a; 编写控制台应用程序&#xff0c;提供以下菜单项&#xff1a; 插入元素 从键盘输入若干两两互不相同的非0整数&#xff0c;直到输入0时停止。将输入的所有非0整数按输入次序插入二叉排序树(初始时是空树)。 插入某个非0整数时&#xff0c;若该整…

Linux——基本指令(二)

​ 个人主页&#xff1a;日刷百题 系列专栏&#xff1a;〖C语言小游戏〗〖Linux〗〖数据结构〗 〖C语言〗 &#x1f30e;欢迎各位→点赞&#x1f44d;收藏⭐️留言&#x1f4dd; ​ ​ 写在前面&#xff1a; 紧接上一章&#xff0c;我们在理解接下来的命令之前&#xff0c…

IEEE Transactions on Industrial Electronics工业电子TIE论文投稿须知

一、背景 IEEE TIE作为控制领域的TOP期刊&#xff0c;接收机器人、控制、自动驾驶、仪器和传感等方面的论文&#xff0c;当然范围不止这些&#xff0c;感兴趣的可以自行登录TIE官网查看。所投稿论文必须经过实验验证&#xff0c;偏工程应用类&#xff0c;当然也必须有方法上的…

Qt之自定义QToolTip,去掉显示动画和隐藏延时

一.效果 先来看看Qt原生QToolTip的缺点: 1.当提示内容无变化时,弹窗无法移动。只能先传个空字符串强制弹窗隐藏,然后在新位置再传个字符串。 If the text is the same as the currently shown tooltip, the tip will not move. You can force moving by first hiding the t…

LTspice 中电容的类型

目录 背景钽电容、铝电容陶瓷电容新电容技术聚合物铝电容 背景 在 LTspice 中仿真电路时&#xff0c;需要选择合适的电容&#xff0c;由于刚接触 LTspice 和模拟电路&#xff0c;所以不清楚如何选择与实际常用电容对应的型号&#xff0c;于是整理了一个类型列表&#xff0c;方…

飞天使-linux操作的一些技巧与知识点3-http的工作原理

文章目录 http工作原理nginx的正向代理和反向代理的区别一个小技巧dig 命令巧用 http工作原理 http1.0 协议 使用的是短连接&#xff0c;建立一次tcp连接&#xff0c;发起一次http的请求&#xff0c;结束&#xff0c;tcp断开 http1.1 协议使用的是长连接&#xff0c;建立一次tc…

Ubuntu20.04降低linux版本到5.4.0-26-generic

前言 试用ubuntu20.04安装昇腾的驱动和cann的时&#xff0c;出现如下问题&#xff1a; (base) rootubuntu:/home/work# ./Ascend-hdk-910-npu-driver_23.0.rc3_linux-aarch64.run --full Verifying archive integrity... 100% SHA256 checksums are OK. All good. Uncompr…

IDEA 出现问题:git提交commit时Perform code analysis卡住解决方案

问题 git提交commit时Perform code analysis卡住很久 解决方案一 1、打开 IntelliJ IDEA&#xff0c;进入 File -> Settings&#xff08;或者使用快捷键 CtrlAltS&#xff09;。 2、在弹出的 Settings 窗口中&#xff0c;找到 Version Control -> Commit Dialog 选项…

Redis - 事务隔离机制

Redis 的事务的本质是 一组命令的批处理 。这组命令在执行过程中会被顺序地、一次性 全部执行完毕&#xff0c;只要没有出现语法错误&#xff0c;这组命令在执行期间是不会被中断。 当事务中的命令出现语法错误时&#xff0c;整个事务在 exec 执行时会被取消。 如果事务中的…

计算机操作系统原理分析期末复习

一、理解与识记 三种基本的OS类型及各自的特点&#xff1a; 批处理系统&#xff08;内存同时存放几个作业。优点&#xff1a;资源利用率高、作业吞吐量大、系统开销小&#xff1b;缺点&#xff1a;用户无交互性、作业平均周转时间长&#xff09;、分时系统&#xff08;时间片技…

排序的简单理解(下)

4.交换排序 基本思想&#xff1a;所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置 交换排序的特点是&#xff1a;将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 4.1 冒泡排序 冒泡排序&#xff08…

初始数据库 - 了解数据库

centos 7 版本当中安装 mysql 安装与卸载中&#xff0c;⽤⼾全部切换成为root&#xff0c;⼀旦 安装&#xff0c;普通⽤⼾是可以使用的。 卸载不需要的环境 首先&#xff0c;在安装之前&#xff0c;要先确定你当前系统当中是否已经有了mysql 的环境&#xff0c;如果你不想卸…

2023全国职业院校技能大赛信息安全管理与评估正式赛(模块三CTF)

全国职业院校技能大赛高等职业教育组信息安全管理与评估 \任务书\ 模块三 网络安全渗透、理论技能与职业素养 极安云科专注技能竞赛&#xff0c;包含网络建设与运维和信息安全管理与评估两大赛项&#xff0c;及各大CTF&#xff0c;基于两大赛项提供全面的系统性培训&#xf…

用户案例:系统保留分区未分配驱动器号

“遇到了Win7保留分区无法改变驱动器号的问题。我尝试使用激活工具激活Win7时收到提示&#xff0c;系统保留分区未分配驱动器号。根据网上的建议&#xff0c;我打算在磁盘管理中给保留分区分配驱动号。然而&#xff0c;在电脑中我发现了两个未分配驱动器号的分区&#xff0c;一…

【PTA刷题+代码+详解】求二叉树度为1的结点个数(递归法)

文章目录 题目C代码详解 题目 在二叉树T中&#xff0c;其度为1的结点是指某结点只有左孩子或只有右孩子。利用递归方法求二叉树T的度为1的结点个数。 1&#xff09;如果TNULL&#xff0c;则是空树&#xff0c;度为1的结点个数为0&#xff0c;返回值为0&#xff1b; 2&#xff0…

GEE:重分类

作者:CSDN @ _养乐多_ 本文记录了在 Google Earth Engine(GEE)平台上对一副类别图像进行重分类的代码。并以 COPERNICUS/Landcover/100m/Proba-V-C3/Global 数据集中的土地利用数据为例。 结果如下图所示, 文章目录 一、核心函数二、示例代码三、代码链接一、核心函数 核…

保姆级:Windows Server 2012上安装.NET Framework 3.5

目录 一.问题所在无法在安装SQL server2008&#xff08;2012&#xff09; 1.无法安装一下功能 .NET Framework 3.5 二.解决措施 1、打开服务器管理器 2、添加角色和功能 3、选择安装功能 4、指定备用源路径 5、配置本地文件路径 一.问题所在无法在安装SQL server2008&…