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

本文为学习吴恩达版本机器学习教程的代码整理,使用的数据集为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]}")

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

多阶段构建:精妙优化Docker镜像大小和性能

在容器化应用的世界中,Docker镜像大小和性能优化是至关重要的。多阶段构建是一项强大的技术,通过精心设计Dockerfile,可以在构建镜像时去除不必要的组件,从而显著减小镜像大小,提高性能。本文章将深入讨论多阶段构建的…

Knowledge Graph知识图谱—9. Data Quality and Linking

9. Data Quality and Linking 9.1 How well are the linked open data in practice? Linked Open Vocabularies(LOV) project – analyze usage of vocabularies 9.2 Quality Linked Data Conformance vs. Quality Conformance: – i.e., following standards and best prac…

语音验证码可以用在哪些方面?

电商行业 由于行业竞争日渐激烈,大多数电商采用补贴用户的营销方式抢占市场,其中,新用户补贴较为常见,随之也衍生出一部分恶意刷单的人群。 而语音验证码在一定程度上保证了一个号码对应一个账号,大大增强了刷单难度…

分页存储管理

页框和页面 将内存空间分为一个个大小相等的分区 (比如:每个分区4KB),每个分区就是一个“页框”(页框页内存块物理块物理页面)。每个页框有一个编号,即“页框号”(页框号页帧号内存块号物理块号物理页号),页框号从0开始。 为了将各个进程的数…

JS基础源码之手写模拟new

JS基础源码之手写模拟new 手写模拟new初步实现最终实现 手写模拟new new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一。 我们先看看new实现了哪些功能: function Person (name,age){this.name name;this.age age;this.habit Games;…

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

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

目标检测锚框

目标检测锚框 最开始呢,我们需要先介绍一下框,先学会一下怎么画框 导入所需要的包 from PIL import Image import d2lzh_pytorch as d2l import numpy as np import math import torch展示一下本次实验我们用到的图像,猫狗 d2l.set_figsiz…

智能优化算法应用:基于帝国主义竞争算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于帝国主义竞争算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于帝国主义竞争算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.帝国主义竞争算法4.实验参数设定…

C语言--动态内存【详细解释】

一.动态内存介绍🍗 在C语言中,动态内存分配是指在程序运行时根据需要动态申请内存空间,以便在程序的不同阶段存储和使用数据。动态内存的分配与释放需要一组函数来实现,包括malloc、calloc、realloc和free。 malloc: 函数用于分配…

原创改进|多策略融合的改进蜣螂优化算法

作者在前段时间的一篇文章中介绍过了蜣螂优化算法(dung beetle optimizer,DBO)的原理及实现,该算法是由东华大学沈波教授团队在2022年提出[1],其灵感来自蜣螂的滚球、跳舞、觅食、偷窃和繁殖行为这5种习性,其不同的子种群执行了不…

Unity 射线检测(Raycast)检测图层(LayerMask)的设置

目录 主要内容 拓展: 主要内容 Raycast函数有很多重载(函数的重载根据函数的参数来决定) 这里只涉及这个重载,其余重载可以很方便得在Visual Studio中看源码获取; public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hit…

java实现局域网内视频投屏播放(三)投屏原理

常见投屏方案 常见的投屏方案主要有以下几种: DLNA DLNA的全称是DIGITAL LIVING NETWORK ALLIANCE(数字生活网络联盟)。DLNA委员会已经于2017年1月5日正式解散,原因是旧的标准已经无法满足新设备的发展趋势,DLNA标准将来也不会再更新。但是…

【Android嵌入式开发及实训课程实验】【项目1】 图形界面——计算器项目

【项目1】 图形界面——计算器项目 需求分析界面设计实施1、创建项目2、 界面实现实现代码1.activity_main.xml2.Java代码 - MainActivity.java 3、运行测试 注意点结束~ 需求分析 开发一个简单的计算器项目,该程序只能进行加减乘除运算。要求界面美观,…

排序算法-快速排序

1.快速排序(递归) 快速排序是 Hoare 于 1962 年提出的一种二叉树结构的交换排序方法,其基本思想为: 任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素…

Armv8/Armv9从入门到精通-课程介绍

通知,Arm二期,咱们也有大合集PDF了,共计1587页,还未完成,后续持续更新和优化中。为了方便大家阅读、探讨、做笔记,特意整了此合集PPT,为了增加标签目录,还特意开了福兮阅读器会员。 …

OkHttp: 拦截器和事件监听器

文章目录 1. 拦截器1. 拦截器链2. 实际案例1. 注册为应用拦截器2. 注册为网络拦截器 3. 如何选择用哪种拦截器1. 应用拦截器2. 网络层拦截器3. 重写请求4. 重写响应 4. 可用性 2. 事件监听器1. 请求的生命周期2. EventListener使用案例3. EventListener.Factory4. 调用失败的请…

【产品经理】产品专业化提升路径

产品专业化就是上山寻路,梳理一套作为产品经理的工作方法。本文作者从设计方法、三基座、专业强化、优秀产品拆解、零代码这五个方面,对产品经理的产品专业化进行了总结归纳,一起来看一下吧。 产品专业化就是上山寻路,梳理一套作为…

8 Buildroot 根文件系统构建

一、根文件系统简介 根文件系统一般也叫做 rootfs,这个是属于 Linux 内核的一部分。 根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于普通的文件系统,它的特殊之处在于,…

十六 动手学深度学习v2计算机视觉 ——样式迁移

文章目录 基于CNN的样式迁移 基于CNN的样式迁移 我们通过前向传播(实线箭头方向)计算风格迁移的损失函数,并通过反向传播(虚线箭头方向)迭代模型参数,即不断更新合成图像。 风格迁移常用的损失函数由3部分组…

源码角度简单介绍LinkedList

LinkedList是一种常见的数据结构,但是大多数开发者并不了解其底层实现原理,以至于存在很多误解,在这篇文章中,将带大家一块深入剖析LinkedList的源码,并为你揭露它们背后的真相。首先想几个问题,例如&#…