softmax 函数的多种实现方式 包括纯C语言、C++版本、Eigen版本等
softmax 函数的多种实现方式 包括纯C语言、C++版本、Eigen版本等
flyfish
先看这里Softmax函数介绍
版本1 规矩的写法
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cmath>// 计算 softmax 的函数
std::vector<double> softmax(const std::vector<double>& input) {// 找到最大元素以防止 exp 计算时溢出double maxProb = *std::max_element(input.begin(), input.end());// 计算指数并求和std::vector<double> expVals;expVals.reserve(input.size());for (double val : input) {expVals.push_back(std::exp(val - maxProb)); // 计算每个元素的指数}double sumExp = std::accumulate(expVals.begin(), expVals.end(), 0.0); // 求所有指数的和// 归一化指数值以得到 softmax 概率std::vector<double> softmaxProb;softmaxProb.reserve(input.size());for (double val : expVals) {softmaxProb.push_back(val / sumExp); // 每个指数值除以总和得到 softmax 概率}return softmaxProb;
}// 示例用法
int main() {std::vector<double> input = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; // 示例输入std::vector<double> probabilities = softmax(input);// 输出 softmax 概率std::cout << "Softmax 概率:" << std::endl;for (double prob : probabilities) {std::cout << prob << " ";}std::cout << std::endl;// 找到具有最高概率的类别auto maxElementIter = std::max_element(probabilities.begin(), probabilities.end());int classId = std::distance(probabilities.begin(), maxElementIter);double confidence = *maxElementIter;std::cout << "预测类别: " << classId << " 置信度: " << confidence << std::endl;return 0;
}
版本2 合并循环,只使用一个 softmaxProb 向量来存储指数值和最终的 softmax 概率
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cmath>// 计算 softmax 的函数
std::vector<double> softmax(const std::vector<double>& input) {// 找到最大元素以防止 exp 计算时溢出double maxProb = *std::max_element(input.begin(), input.end());// 计算指数和求和std::vector<double> softmaxProb(input.size());double sumExp = 0.0;for (size_t i = 0; i < input.size(); ++i) {softmaxProb[i] = std::exp(input[i] - maxProb);sumExp += softmaxProb[i];}// 归一化指数值以得到 softmax 概率for (double& val : softmaxProb) {val /= sumExp;}return softmaxProb;
}// 示例用法
int main() {std::vector<double> input = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; // 示例输入std::vector<double> probabilities = softmax(input);// 输出 softmax 概率std::cout << "Softmax 概率:" << std::endl;for (double prob : probabilities) {std::cout << prob << " ";}std::cout << std::endl;// 找到具有最高概率的类别auto maxElementIter = std::max_element(probabilities.begin(), probabilities.end());int classId = std::distance(probabilities.begin(), maxElementIter);double confidence = *maxElementIter;std::cout << "预测类别: " << classId << " 置信度: " << confidence << std::endl;return 0;
}
版本3 C++17 使用并行执行策略
std::transform:用于计算每个元素的指数值,并存储在 expVals 中。使用并行执行策略可以提升计算效率。
std::reduce:用于并行求和,替代 std::accumulate。
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <execution>// 计算 softmax 的函数
std::vector<double> softmax(const std::vector<double>& input) {// 找到最大元素以防止 exp 计算时溢出double maxProb = *std::max_element(input.begin(), input.end());// 计算指数和求和,同时避免重复遍历std::vector<double> expVals(input.size());std::transform(std::execution::par, input.begin(), input.end(), expVals.begin(), [maxProb](double val) {return std::exp(val - maxProb);});// 使用 std::reduce 并行求和double sumExp = std::reduce(std::execution::par, expVals.begin(), expVals.end(), 0.0);// 归一化指数值以得到 softmax 概率std::vector<double> softmaxProb(input.size());std::transform(std::execution::par, expVals.begin(), expVals.end(), softmaxProb.begin(), [sumExp](double val) {return val / sumExp;});return softmaxProb;
}// 示例用法
int main() {std::vector<double> input = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; // 示例输入std::vector<double> probabilities = softmax(input);// 输出 softmax 概率std::cout << "Softmax 概率:" << std::endl;for (double prob : probabilities) {std::cout << prob << " ";}std::cout << std::endl;// 找到具有最高概率的类别auto maxElementIter = std::max_element(probabilities.begin(), probabilities.end());int classId = std::distance(probabilities.begin(), maxElementIter);double confidence = *maxElementIter;std::cout << "预测类别: " << classId << " 置信度: " << confidence << std::endl;return 0;
}
版本4 Eigen 库实现
利用 Eigen 库可以高效地进行矩阵和向量运算。Eigen 库通过优化内存布局和利用 SIMD 指令集来提升性能。
Eigen::Map 可以将标准库中的容器(如 std::vector)映射为 Eigen 向量,从而直接进行高效的向量运算。
配置 CMakeLists.txt
# 添加 Eigen 目录
set(EIGEN3_INCLUDE_DIR "path/to/eigen") # 将此路径替换为你解压缩 Eigen 的目录
include_directories(${EIGEN3_INCLUDE_DIR})
#include <iostream>
#include <vector>
#include <algorithm>
#include <Eigen/Dense>// 计算 softmax 的函数
std::vector<double> softmax(const std::vector<double>& input) {// 将输入向量转换为 Eigen 向量Eigen::VectorXd vec = Eigen::Map<const Eigen::VectorXd>(input.data(), input.size());// 找到最大元素以防止 exp 计算时溢出double maxProb = vec.maxCoeff();// 计算指数和求和Eigen::VectorXd expVals = (vec.array() - maxProb).exp();double sumExp = expVals.sum();// 归一化指数值以得到 softmax 概率std::vector<double> softmaxProb(input.size());Eigen::VectorXd result = expVals / sumExp;Eigen::VectorXd::Map(&softmaxProb[0], result.size()) = result;return softmaxProb;
}// 示例用法
int main() {std::vector<double> input = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; // 示例输入std::vector<double> probabilities = softmax(input);// 输出 softmax 概率std::cout << "Softmax 概率:" << std::endl;for (double prob : probabilities) {std::cout << prob << " ";}std::cout << std::endl;// 找到具有最高概率的类别auto maxElementIter = std::max_element(probabilities.begin(), probabilities.end());int classId = std::distance(probabilities.begin(), maxElementIter);double confidence = *maxElementIter;std::cout << "预测类别: " << classId << " 置信度: " << confidence << std::endl;return 0;
}
版本5 纯C语言方式
#include <stdio.h>
#include <stdlib.h>
#include <math.h>// 计算 softmax 的函数
void softmax(const double* input, double* softmaxProb, int size) {// 找到最大元素以防止 exp 计算时溢出double maxProb = input[0];for (int i = 1; i < size; ++i) {if (input[i] > maxProb) {maxProb = input[i];}}// 计算指数和求和double sumExp = 0.0;for (int i = 0; i < size; ++i) {softmaxProb[i] = exp(input[i] - maxProb);sumExp += softmaxProb[i];}// 归一化指数值以得到 softmax 概率for (int i = 0; i < size; ++i) {softmaxProb[i] /= sumExp;}
}// 示例用法
int main() {double input[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; // 示例输入int size = sizeof(input) / sizeof(input[0]);double* probabilities = (double*)malloc(size * sizeof(double));if (probabilities == NULL) {fprintf(stderr, "内存分配失败\n");return 1;}softmax(input, probabilities, size);// 输出 softmax 概率printf("Softmax 概率:\n");for (int i = 0; i < size; ++i) {printf("%f ", probabilities[i]);}printf("\n");// 找到具有最高概率的类别double maxProb = probabilities[0];int classId = 0;for (int i = 1; i < size; ++i) {if (probabilities[i] > maxProb) {maxProb = probabilities[i];classId = i;}}double confidence = maxProb;printf("预测类别: %d 置信度: %f\n", classId, confidence);free(probabilities);return 0;
}
相关文章:
softmax 函数的多种实现方式 包括纯C语言、C++版本、Eigen版本等
softmax 函数的多种实现方式 包括纯C语言、C版本、Eigen版本等 flyfish 先看这里Softmax函数介绍 版本1 规矩的写法 #include <iostream> #include <vector> #include <algorithm> #include <numeric> #include <cmath>// 计算 softmax 的函…...
R语言学习笔记11-读取csv-xlsx-txt-json-pdf-lua格式文件
R语言学习笔记11-读取csv-xlsx-txt-json-pdf-lua格式文件 读取csv使用base的 read.csv 函数使用 readr 包的 read_csv 函数 读取xlsx使用 xlsx 包的 read.xlsx 函数使用 readxl 包的 read_excel 函数 读取txt使用base的文件读取函数 readLines使用 readr 包的 read_lines 函数 …...
Vue的计算属性和方法有什么区别
Vue中的计算属性(computed)和方法(methods)都是用于处理数据和逻辑的重要特性,但它们之间存在一些关键的区别。以下是两者的主要区别: 1. 缓存性 计算属性:计算属性是基于它们的依赖进行缓存的…...
学生成绩管理系统(C语言)
系统分析 1. 主菜单的实现 2. 增加人员功能的实现 3. 删除数据功能的实现 4. 编辑人员功能的实现 5. 排序功能的实现 6. 输出功能 7. 查找信息功能 具体代码 #include <stdio.h> #include <string.h> #include <stdlib.h> #define SIZE 100000typedef struc…...
C语言 通讯录管理 完整代码
这份代码,是我从网上找的。目前是能运行。我正在读。有些不懂的地方,等下再记录下来。 有些地方的命名,还需要重新写一下。 比如: PersonInfo* info &address_book->all_address[address_book->size]; 应该改为: Perso…...
2024北京国际智能工厂及自动化展览会亮点前瞻
随着“工业创新,智造未来”的浪潮席卷而来,2024年度北京国际智能工厂及自动化与工业装配展览会定于8月1日至3日在中国国际展览中心(顺义新馆)盛大开幕。本次展会汇聚了智能制造与自动化技术的最新成果,通过三展联动的创…...
《网络安全等级保护制度详解》
网络安全等级保护制度是我国网络安全领域的一项重要制度,旨在保障网络安全,维护国家安全、社会秩序和公共利益。 网络安全等级保护制度主要包含以下几个关键方面: 等级划分 根据信息系统在国家安全、经济建设、社会生活中的重要程度ÿ…...
使用Wanderboat AI 来规划到巴黎的旅行计划
Wanderboat AI 平台是一个由 GPT-4 驱动的智能旅行规划工具,旨在通过自然对话和多模式互动,为用户提供个性化的旅行行程。以下是该平台的架构和使用方法: 平台架构 GPT-4 驱动:平台利用 GPT-4 的强大自然语言处理能力&#x…...
基于YOLO8的目标检测系统:开启智能视觉识别之旅
文章目录 在线体验快速开始一、项目介绍篇1.1 YOLO81.2 ultralytics1.3 模块介绍1.3.1 scan_task1.3.2 scan_taskflow.py1.3.3 target_dec_app.py 二、核心代码介绍篇2.1 target_dec_app.py2.2 scan_taskflow.py 三、结语 在线体验 基于YOLO8的目标检测系统 基于opencv的摄像头…...
实验07 接口测试postman
目录 知识点 1 接口测试概念 1.1为什么要做接口测试 1.2接口测试的优点 1.3接口测试概念 1.4接口测试原理和目的 2 接口测试内容 2.1测什么 2.1.1单一接口 2.1.2组合接口 2.1.3结构检查 2.1.4调用方式 2.1.5参数格式校验 2.1.6返回结果 2.2四大块 2.2.1功能逻辑…...
C++常用但难记的语法
模板函数的声明和定义必须在同一个文件中。 C中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的大小的。只有模板被真正使用的时…...
Qt 快速保存配置的方法
Qt 快速保存配置的方法 一、概述二、代码1. QFileHelper.cpp2. QSettingHelper.cpp 三、使用 一、概述 这里分享一下,Qt界面开发时,快速保存界面上一些参数配置的方法。 因为我在做实验的时候,界面上可能涉及到很多参数的配置,我…...
RKE部署k8s
移除docker(非必要) rm -rf /etc/docker rm -rf /run/docker rm -rf /var/lib/dockershim rm -rf /var/lib/docker yum list installed | grep docker yum remove ***rke部署k8s集群 cat > /etc/sysctl.conf << EFO net.ipv4.ip_forward 1 n…...
从0开始的STM32HAL库学习8
PWM控制舵机 配置环境 1. 选择TIM2时钟 2.选择内部时钟模式,打开通道二 3.分频系数PSC:72-1 自动重装寄存器ARR:20000-1 输出比较寄存器 CCR:500~2500( 后面可调整 ) 脉冲选择500后期可以改 编辑代码 调用启动函数 HAL_TIM_PWM_Start(&htim2,TIM_CHANN…...
微信小程序数组绑定使用案例(一)
微信小程序数组绑定案例,修改数组中的值 1.Wxml 代码 <view class"list"><view class"item {{item.ischeck?active:}}" wx:for"{{list}}"><view class"title">{{item.name}} <text>({{item.id}…...
Kudu节点数规划
作者:南墨 一、概述 由于Kudu是Hadoop生态的一部分(虽然它不依赖于Hadoop生态系统),因此大多数实际应用场景需要的不仅仅是Kudu;为了输入数据,可能需要Kafka、StreamSets或Spark Streaming;对…...
flutter 充电气泡
前言: 之前一直看到 有手机充电的时候 有气泡从Type-C 的位置冒泡上来 慢慢上移, 然后和上面的圆圈 会和,感觉还是挺好看的。今天试了下用 Flutter 实现了一版本。大致效果如下,而且气泡 和 气泡直接还可以粘黏 实现原理ÿ…...
【C++】deque以及优先级队列
容器适配器 deque的介绍deque的原理介绍 priority_queue的介绍与使用priority_queue的介绍priority_queue的使用constructor(构造函数)emptypushpoptopsize priority_queue的模拟实现 仿函数何为适配器容器适配器deque的缺陷选择deque作为适配器的理由ST…...
手机如何播放电脑的声音?
准备工具: 有线耳机,手机,电脑,远控软件 1.有线耳机插电脑上 2.电脑安装pc版远控软件,手机安装手机端控制版远控软件 3.手机控制电脑开启声音控制 用手机控制电脑后,打开声音控制,电脑播放视频…...
系统架构设计师教程 第3章 信息系统基础知识-3.6 办公自动化系统(OAS)-解读
系统架构设计师教程 第3章 信息系统基础知识-3.6 办公自动化系统(OAS) 3.6.1 办公自动化系统的概念3.6.1.1 办公活动3.6.1.1 办公自动化的概念 3.6.2 办公自动化系统的功能3.6.2.1 事务处理3.6.2.1.1 单机系统3.6.2.1.2 多机系统 3.6.2.2 信息管理3.6.2.…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
