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.…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
鸿蒙HarmonyOS 5军旗小游戏实现指南
1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发,采用DevEco Studio实现,包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...