现代C++中的从头开始深度学习:【6/8】成本函数

news2025/1/10 1:53:44

现代C++中的从头开始深度学习:成本函数

一、说明

        在机器学习中,我们通常将问题建模为函数。因此,我们的大部分工作都包括寻找使用已知模型近似函数的方法。在这种情况下,成本函数起着核心作用。

        这个故事是我们之前关于卷积的讨论的续集。今天,我们将介绍成本函数的概念,展示常见示例并学习如何编码和绘制它们。与往常一样,从头开始纯C++和本征。

二、关于本系列

        在本系列中,我们将学习如何仅使用普通和现代C++对必须知道的深度学习算法进行编码,例如卷积、反向传播、激活函数、优化器、深度神经网络等。

这个故事是:C++中的成本函数

现代C++中的从头开始深度学习【3/8】:激活函数 

现代C++中的从头开始深度学习:【4/8】梯度下降 

现代C++中的从头开始深度学习:【5/8】卷积 

...更多内容即将推出。

三、机器学习中的建模

        作为人工智能工程师,我们通常将每个任务或问题定义为一个功能。

        例如,如果我们正在开发一个人脸识别系统,我们的第一步是将问题定义为将输入图像映射到标识符的函数:

        对于医疗诊断系统,我们可以定义一个函数来将症状映射到诊断:

        我们可以编写一个模型来提供给定单词序列的图像:

        这是一个无穷无尽的清单。使用函数来表示任务或问题是实现机器学习系统的简化方法。

问题往往是:如何知道 F() 公式?

四、近似函数

        事实上,使用公式或规则序列定义F(X)是不可行的(有一天我将解释原因)。

        一般来说,我们不是找到或定义正确的函数 F(X),而是尝试找到 F(X) 的近似值。 让我们通过假设函数来称这种近似,或者简单地称为H(X)。

        乍一看,这没有意义:如果我们需要找到近似函数 H(X),为什么我们不尝试直接找到 F(X)

        答案是:我们知道H(X)。虽然我们对F(X)知之甚少,但我们几乎知道H(X)的一切:它的公式,参数等。关于 H(X),我们唯一不知道的是它的参数值。

        事实上,机器学习的主要关注点是找到为给定问题和数据确定合适参数值的方法。让我们看看我们如何执行它。

在机器学习术语中,H(X)被称为“F(X)的近似值”。H(X)的存在被通用近似定理所涵盖。

五、成本函数和通用逼近定理

        考虑这样一种情况:我们知道输入的值和相应的输出,但我们不知道 的公式。例如,我们知道如果输入是,那么结果就是。XY = F(X)F(X)X = 1.0F(1.0)Y = 2.0

        4 X 和 F(X) 的映射

        现在,考虑我们有一个已知的函数,我们想知道是否是 的良好近似。因此,我们计算并找到.H(X)H(X)F(X)T = H(1.0)T = 1.9

        这个值有多糟糕,因为我们知道真正的值是什么时候?T = 1.9Y = 2.0X = 1.0

        用于量化 和 之间的差额的成本的指标由成本函数调用。YT

请注意,Y 是期望值,T 是我们猜测获得的实际值H(X)

成本函数的概念是机器学习的核心。让我们以最常见的成本函数为例。

六、均方误差

        最著名的成本函数是均方误差:

        其中 Ti 由核 k 对 Xi 的卷积给出:

我们在上一个故事中讨论了卷积

        请注意,我们有 n 对 (Yn, T n),每都是期望值 Yi 和实际值 Tn 的组合。例如:

        因此,MSE 的评估如下:

我们可以编写MSE的第一个版本,如下所示:

auto MSE = [](const std::vector<double> &Y_true, const std::vector<double> &Y_pred) {

    if (Y_true.empty()) throw std::invalid_argument("Y_true cannot be empty.");

    if (Y_true.size() != Y_pred.size()) throw std::invalid_argument("Y_true and Y_pred sizes do not match.");

    auto quadratic = [](const double a, const double b) {
        double result = a - b;
        return result * result;
    };
    const int N = Y_true.size();
    double acc = std::inner_product(Y_true.begin(), Y_true.end(), Y_pred.begin(), 0.0, std::plus<>(), quadratic);

    double result = acc / N;

    return result;
};

        现在我们知道了如何计算MSE,让我们看看如何使用它来近似函数。

七、使用MSE找到最佳参数的直觉

        假设我们有一个映射 F(X) 合成生成:

F(X) = 2*X + N(0, 0.1)

        其中 N(0, 0.1) 表示从正态分布中抽取的随机值,平均值 = 0,标准差 = 0.1。我们可以通过以下方式生成示例数据:

#include <random>

std::default_random_engine dre(time(0));

std::normal_distribution<double> gaussian_dist(0., 0.1);
std::uniform_real_distribution<double> uniform_dist(0., 1.);

std::vector<std::pair<double, double>> sample(90);

std::generate(sample.begin(), sample.end(), [&gaussian_dist, &uniform_dist]() {
    double x = uniform_dist(dre);
    double noise = gaussian_dist(dre);
    double y = 2. * x + noise;
    return std::make_pair(x, y);
});

        如果我们使用任何电子表格软件绘制此示例,我们会得到如下所示的内容:

        请注意,我们知道 G(X) 和 F(X) 的公式。然而,在现实生活中,这些生成器功能是潜在现象的未公开秘密。在这里,在我们的示例中,我们只知道它们,因为我们正在生成合成数据来帮助我们更好地理解。

        在现实生活中,我们所知道的一切都是一个假设,即由H(X)= kX定义的假设函数H(X)可能是F(X)的良好近似值。 当然,我们还不知道k的值是多少。

        让我们看看如何使用 MSE 找出合适的 k 值。事实上,它就像为一系列不同的 k 绘制 MSE 一样简单:

std::vector<std::pair<double, double>> measures;

double smallest_mse = 1'000'000'000.;
double best_k = -1;
double step = 0.1;

for (double k = 0.; k < 4.1; k += step) {
    std::vector<double> ts(sample.size());
    std::transform(sample.begin(), sample.end(), ts.begin(), [k](const auto &pair) {
        return pair.first * k;
    });

    double mse = MSE(ys, ts);
    if (mse < smallest_mse) {
        smallest_mse = mse;
        best_k = k;
    }

    measures.push_back(std::make_pair(k, mse));
}

std::cout << "best k was " << best_k << " for a MSE of " << smallest_mse << "\n";

        很多时候,这个程序输出的东西是这样的:

        best k was 2.1 for a MSE of 0.00828671

        如果我们用k绘制MSE(k),我们可以看到一个非常有趣的事实:

        k 从 0 到 4,步长为 0.1

        请注意,MSE(k) 的值在 k = 2 附近最小。实际上,2 是泛型函数 G(X) = 2X 的参数。

        给定数据并使用 0.1 的步长,当 k = 2.1 时,可以找到较小的 MSE(k) 值。这表明 H(X) = 2.1 X 是 F(X) 的良好近似值。 事实上,如果我们绘制F(X)、G(X)和H(X),我们有:

        通过上面的图表,我们可以意识到H(X实际上近似于F(X)。不过,我们可以尝试使用较小的步长(如 0.01 或 0.001)来找到更好的近似值。

代码可以在此存储库中找到

八、成本表面

        MSE(k) 乘以 k 的曲线是成本曲面的一维示例。

MSE 曲线是一维曲面

        前面的示例显示的是,我们可以使用成本表面的最小值来找到参数 k 的最佳拟合值。

该示例描述了机器学习中最重要的范式:通过成本函数最小化的函数近似

        上图显示了一个一维成本曲面,即给定一维k的成本曲线。在二维空间中,即当我们有两个k,即k1k2时,成本面看起来更像一个实际曲面:

2D 成本表面

        无论 k 是 1D、2D 还是更高维,找到最佳第 k 个值的过程都是相同的:找到成本曲线的最小值。

最小成本值也称为全局最小值

        在 1D 空间中,查找全局最小值的过程相对容易。然而,在高维度上,扫描所有空间以找到最小值可能会产生计算成本。在下一个故事中,我们将介绍大规模执行此搜索的算法。

        不仅k可以是高维的。在实际问题中,输出通常也是高维的。让我们学习如何在这种情况下计算 MSE。

九、高维输出上的MSE

        在现实世界的问题中,Y 和 T 是向量或矩阵。让我们看看如何处理这样的数据。

        如果输出是一维的,则MSE的先前公式将起作用。但是如果输出是多维的,我们需要稍微改变一下公式。例如:

        在这种情况下,Yn 和 Tn 不是标量值,而是大小矩阵。在将 MSE 应用于此数据之前,我们需要更改公式,如下所示:(2,3)

        在此公式中,N 是对数,R 是行数,C 是每对中的列数。像往常一样,我们可以使用 lambda 实现此版本的 MSE:

#include <numeric>
#include <iostream>

#include <Eigen/Core>

using Eigen::MatrixXd;

int main() 
{

    auto MSE = [](const std::vector<MatrixXd> &Y_true, const std::vector<MatrixXd> &Y_pred) 
    {

        if (Y_true.empty()) throw std::invalid_argument("Y_true cannot be empty.");

        if (Y_true.size() != Y_pred.size()) throw std::invalid_argument("Y_true and Y_pred sizes do not match.");

        const int N = Y_true.size();
        const int R = Y_true[0].rows();
        const int C = Y_true[0].cols();

        auto quadratic = [](const MatrixXd a, const MatrixXd b) 
        {
            MatrixXd result = a - b;
            return result.cwiseProduct(result).sum();
        };

        double acc = std::inner_product(Y_true.begin(), Y_true.end(), Y_pred.begin(), 0.0, std::plus<>(), quadratic);

        double result = acc / (N * R * C);

        return result;
    };

    std::vector<MatrixXd> A(4, MatrixXd::Zero(2, 3)); 
    A[0] << 1., 2., 1., -3., 0, 2.;
    A[1] << 5., -1., 3., 1., 0.5, -1.5; 
    A[2] << -2., -2., 1., 1., -1., 1.; 
    A[3] << -2., 0., 1., -1., -1., 3.;

    std::vector<MatrixXd> B(4, MatrixXd::Zero(2, 3)); 
    B[0] << 0.5, 2., 1., 1., 1., 2.; 
    B[1] << 4., -2., 2.5, 0.5, 1.5, -2.; 
    B[2] << -2.5, -2.8, 0., 1.5, -1.2, 1.8; 
    B[3] << -3., 1., -1., -1., -1., 3.5;

    std::cout << "MSE: " << MSE(A, B) << "\n";

    return 0;
}

        值得注意的是,无论 k 或 Y 是多维的还是不是多维的,MSE 始终是一个标量值。

十、其他成本函数

        除了MSE,深度学习模型中也经常出现其他成本函数。最常见的是分类交叉熵、对数 cosh 和余弦相似性。

我们将在接下来的故事中介绍这些功能,特别是当我们介绍分类非线性推理时。

十一、结论和下一步

        成本函数是机器学习中最重要的主题之一。在这个故事中,我们学习了如何编写最常用的成本函数MSE代码,以及如何使用它来适应一维问题。我们还了解了为什么成本函数对于查找函数近似如此重要。

        在下一个故事中,我们将学习如何使用成本函数从数据中训练卷积核。我们将介绍拟合内核的基本算法,并讨论训练机制的实现,例如 epoch、停止条件和超参数

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

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

相关文章

【python爬虫】7.爬到的数据存到哪里?

文章目录 前言存储数据的方式存储数据的基础知识基础知识&#xff1a;Excel写入与读取基础知识&#xff1a;csv写入与读取项目&#xff1a;存储周杰伦的歌曲信息 复习 前言 上一关我们以QQ音乐为例&#xff0c;主要学习了如何带参数地请求数据&#xff08;get请求&#xff09;…

软件测试/测试开发丨Pytest和Allure报告 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/26755 Pytest 命名规则 类型规则文件test_开头 或者 _test 结尾类Test 开头方法/函数test_开头注意&#xff1a;测试类中不可以添加__init__构造函数 注…

IP基本原理(上)

文章目录 一、IP的定义二、IP的作用1.标识节点和链路2.寻址和转发3.适应各种数据链路 三、IP头部封装格式四、MTU五、IP地址1.定义2.格式2.1 点分十进制和二进制关系与转换2.2 由网络位主机位组成2.3 网络位长度决定网段 3.分类3.1 A类3.2 B类3.3 C类3.4 D类3.5 E类 4.特殊地址…

Linux虚拟机磁盘扩容

Linux虚拟机磁盘扩容 问题起源 在使用linux系统开发时遇到文件无法创建的问题&#xff0c;根据提示发现是磁盘空间不足。 使用df -h查看具体磁盘使用情况。 针对这个问题&#xff0c;有两种解决方案&#xff1a; 使用du -sh ./*可以查看当前工作目录下各文件的占用空间大小…

【USRP】Ettus USRP X440 (USRP软件无线电设备)

Ettus USRP X440 30 MHz至4 GHz&#xff0c;1.6 GHz 带宽&#xff0c;基于GPS的OCXO&#xff0c;USRP软件无线电设备 - Ettus USRP X440是一款USRP软件无线电(SDR)设备&#xff0c;可帮助您集成硬件和软件&#xff0c;对高性能、多通道、宽带信号生成和分析系统进行原型验证。…

InnoDB的Buffer

一、Buffer内存结构 MySQL 服务器启动的时候就向操作系统申请了一片连续的内存&#xff0c;默认128M&#xff0c;可通过从参数修改。 [server] innodb_buffer_pool_size 268435456 1.1 控制块 控制块包括该页所属的 表空间编号、页号、缓存页在 Buffer Pool 中的地址、链表…

14:00面试,14:06就出来了,问的问题有点变态

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%,…

vue three.js基本案例解析

1.安装依赖 // 比如安装148版本 npm install three0.148.0 --save2.使用页面引用 import * as THREE from three; // 引入扩展库OrbitControls.js import { OrbitControls } from three/addons/controls/OrbitControls.js; // 引入扩展库GLTFLoader.js import { GLTFLoader }…

盘点那些国际知名黑客(上篇)

电影中的黑客仅靠一部电脑就可以窃取别人的信息&#xff0c;利用自己高超的技术让公司甚至国家都胆战心惊。“黑客”原指热心于计算机技术、水平高超的电脑高手&#xff0c;但逐渐区分为黑帽、白帽、灰帽。这些术语源自美国流行文化的老式西部电影&#xff0c;其中主角戴白色或…

企业怎么优化固定资产管理

在优化固定资产管理的过程中&#xff0c;不仅要关注硬件设备和设施的维护&#xff0c;还要重视软件系统和数据管理。一些可能的方法&#xff1a;  需要建立一套完整的资产管理系统。这个系统应该包括资产的采购、登记、使用、维修、报废等各个环节的管理流程。通过这个系统&a…

带你吃透Reactor并发模型

目录 1.概述2.项目介绍2.1 有那些并发模型2.2 能锻炼那些技能2.3目录结构 3.编码实践3.1 前期准备3.1.1 Echo协议3.1.2公共代码抽象3.1.3基准性能压测工具 3.2 并发示例3.2.1 EpollReactorSingleProcess3.2.2 EpollReactorProcessPool3.2.3 EpollReactorThreadPool3.2.4 EpollR…

MongoDb-01——Mac上安装MongoDb以及相关的简单命令

MongoDb-01——Mac上安装MongoDb以及相关的简单命令 1. 下载、安装1.1 官网下载1.2 关于安装MongoDB1.2.1 官方安装文档1.2.2 Mac安装详细步骤&#xff08;使用brew&#xff09; 2. 启动MongoDB2.1 官方说明2.2 作为macOS服务运行的相关命令2.3 访问 3. 链接并使用mongodb3.1 链…

人工智能与软件开发的未来

人工智能正在从各个方面改变软件开发。尽管许多公司竞相推出人工智能功能&#xff0c;但人工智能的潜力已超出了功能层面&#xff0c;成为大多数SaaS解决方案的基础。当机器学习和人工智能模型应用在SaaS技术后&#xff0c;便能提高各种业务流程的效率。人工智能应被视为新的开…

解决报错“No module named ‘pandas.core.indexes‘”

解决办法&#xff1a; 首先使用看一下你的pandas是不是版本太新了&#xff0c;如果使用2.0.0以上的版本&#xff0c;则会出现这个报错。 可以安装1.x.x的版本。 pip install pandas1.5.3

在Bigemap中怎么添加高清地图呢?

会使用到的工具 bigemap gis office&#xff0c;下载链接&#xff1a;BIGEMAP GIS Office-全能版 打开软件&#xff0c;要提示需要授权和添加地图&#xff0c;然后去点击选择地图这个按钮&#xff0c;列表中有个添加按钮点进去选择添加地图的方式。 第一种方式&#xff1a;通…

多轮面试中的策略和技巧:如何稳步晋级

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

如何用数字化系统延长用户运营周期?如何建立数字化用户体系?

如果说运营是进行用户引流、留存及转化的各个细分环节搭建&#xff0c;精细化运营便是针对各个细分环节&#xff0c;结合用户画像、人群定位、场景拆解及数据分析等细节&#xff0c;对用户展开有针对性的运营策略。要知道&#xff0c;运营需要以用户为中心&#xff0c;没有用户…

优思学院|企业推行精益生产要具备哪些前提条件?

企业界早已充斥着各种方法和策略&#xff0c;试图模仿精益生产和六西格玛管理等成功之路&#xff0c;目标在于通过质量工具的运用来改善业务。然而&#xff0c;许多公司在推行这些方法的过程中都犯了一个大错&#xff1a;他们忽视了背后的企业文化和制度&#xff0c;以及精益生…

电脑批量记账,提高效率和管理质量

在快节奏的商业环境中&#xff0c;记账是一项繁琐但必要的任务。为了提高效率和准确性&#xff0c;越来越多的人和企业寻求电脑批量记账的解决方案。 第一步&#xff1a;首先我们要进入晨曦记账本主页面&#xff0c;并点击“收支类别”在弹出来的文件框里输入好类别&#xff0…

Linux查日志的六种实用方法

工具&#xff08;比Xshell好用&#xff0c;国产且免费&#xff09; 先给大家安利一个软件&#xff1a;FinalShell官网 你打印出了日志&#xff0c;可以直接在这个上面搜索高亮 查日志 # 持续打印最新的日志&#xff0c;300行 tail -300f xxx.log# 查某个值 grep "内容&q…