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.…...
加入国内正规水漆定制招商,实际收益和体验究竟如何?
家人们,最近不少人都在考虑加入国内正规水漆定制招商,我作为爱瑞德全屋定制的深度体验者,今天就来跟大家好好唠唠实际收益和体验到底咋样。我之前家里装修,就面临着不少痛点。家里收纳那叫一个混乱,各种东西堆得到处都…...
智能硬件监控新范式:LibreHardwareMonitor的架构解析与实战指南
智能硬件监控新范式:LibreHardwareMonitor的架构解析与实战指南 【免费下载链接】LibreHardwareMonitor Libre Hardware Monitor is free software that can monitor the temperature sensors, fan speeds, voltages, load and clock speeds of your computer. 项…...
2025届最火的十大降重复率工具横评
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在学术跟内容创作范围内,AI生成文本的检测越发严格,所谓“降AI率网站…...
蓝桥杯嵌入式备赛:用STM32定时器捕获模式搞定频率测量(附完整代码)
蓝桥杯嵌入式竞赛实战:STM32定时器捕获模式精准测频全攻略 在蓝桥杯嵌入式竞赛的战场上,频率测量是选手们经常需要攻克的关键技术点之一。无论是信号发生器输出、传感器脉冲还是通信模块载波,准确快速地获取频率参数往往是功能实现的第一步。…...
ERNIE-4.5-0.3B-PT实战:vLLM高效部署,Chainlit打造可视化对话界面
ERNIE-4.5-0.3B-PT实战:vLLM高效部署,Chainlit打造可视化对话界面 1. 项目概述与核心价值 在当今AI技术快速发展的背景下,如何在本地环境中高效部署和调用大语言模型成为许多开发者的实际需求。本文将详细介绍如何使用vLLM框架部署ERNIE-4.…...
PyQt5多线程避坑指南:从QThread.wait()阻塞到lambda表达式简化信号连接
PyQt5多线程避坑指南:从QThread.wait()阻塞到lambda表达式简化信号连接 在PyQt5开发中,多线程编程是提升GUI应用响应性的关键技能,但也是新手最容易踩坑的领域之一。本文将聚焦两个典型陷阱:主线程误用QThread.wait()导致的界面冻…...
【仅限信创首批试点单位内部流通】:Java中间件国产化适配checklist V3.2(含国密算法注入、SM4加解密模板代码)
更多请点击: https://intelliparadigm.com 第一章:Java中间件国产化适配的战略背景与政策合规要点 近年来,国家对关键信息基础设施自主可控提出明确要求,《网络安全审查办法》《关键信息基础设施安全保护条例》及信创产业“28N”…...
《作妖计》通天塔副本速通技巧:手把手教你配置如来、多宝幻化增伤流
《作妖计》通天塔&副本极限增伤流实战手册:从幻化配置到怒气微操 在《作妖计》的高阶PVE玩法中,通天塔和灭神殿副本一直是检验玩家阵容深度与策略理解的试金石。当常规的装备强化、武将升星已经无法突破当前瓶颈时,一套精准的增伤体系往往…...
Amulet-Map-Editor完整功能解析:从世界编辑到格式转换
Amulet-Map-Editor完整功能解析:从世界编辑到格式转换 【免费下载链接】Amulet-Map-Editor A Minecraft world editor and converter that supports all versions since Java 1.12 and Bedrock 1.7. 项目地址: https://gitcode.com/gh_mirrors/am/Amulet-Map-Edit…...
面试场景:互联网大厂Java求职者挑战与学习
面试场景:互联网大厂Java求职者挑战与学习 场景设定: 谢飞机是一位程序员,正在挑战一家互联网大厂的Java岗位面试。面试官严肃认真,谢飞机有点紧张不自信。他对简单的问题能够侃侃而谈,但面对复杂问题却有些词不达意。…...
