C++最易读手撸神经网络两隐藏层(任意Nodes每层)梯度下降230820a

这是史上最简单、清晰,最易读的……
C++语言编写的 带正向传播、反向传播(Forward ……和Back Propagation)……任意Nodes数的人工神经元神经网络……。

大一学生、甚至中学生可以读懂。

适合于,没学过高数的程序员……照猫画虎编写人工智能、深度学习之神经网络,梯度下降……


著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

“我在网上看到过很多神经网络的实现方法,但这一篇是最简单、最清晰的。”

一位来自Umass的华人小哥Along Asong,写了篇神经网络入门教程,在线代码网站Repl.it联合创始人Amjad Masad看完以后,给予如是评价。

// c++神经网络手撸20梯度下降22_230820a.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include<iostream>
#include<vector>
#include<iomanip> //std::setprecision
#include<sstream> //std::getline std::stof()using namespace std;
//
float Loss误差损失之和001 = 0.0;class NN神经网络NN {private: int inputNode输入层之节点数s, hidden01Node隐藏层01结点数s, hidden22Nodes, outputNode输出层结点数s;vector<vector<float>> 输入层到第1隐藏层之权重矩阵, 隐藏层1到第二隐藏层2之权重矩阵1to2, 隐藏22到输出层de权重矩阵; //这些变量为矩阵vector<float> 隐藏层1偏置1, 隐藏层2偏置2, O输出偏置o;vector<float>隐藏层1数据1, 隐藏层2数据2, 输出数据output;void initLayer每一层的WeightsAndBiases(vector<vector<float>>& weights权重, vector<float>& biases偏置){for (size_t i = 0; i < weights权重.size(); ++i) {//for110ifor (size_t j = 0; j < weights权重[0].size(); ++j) { weights权重[i][j] = ((rand() % 2) - 1) / 1.0; }biases偏置[i] = ((rand() % 2) - 1) / 1.0;}//for110i}//void initLayerWeightsAndBiases(void initWeightsAndBiases初始化权重和偏置矩阵() {initLayer每一层的WeightsAndBiases(输入层到第1隐藏层之权重矩阵, 隐藏层1偏置1);initLayer每一层的WeightsAndBiases(隐藏层1到第二隐藏层2之权重矩阵1to2, 隐藏层2偏置2);initLayer每一层的WeightsAndBiases(隐藏22到输出层de权重矩阵 , O输出偏置o);}//激活函数-激活的过程vector<float> activate(const  vector<float>& inputs, const  vector< vector<float>>& weights, const  vector<float>& biases) {vector<float> layer_output(weights.size(), 0.0);for (size_t i = 0; i < weights.size(); i++) {for (size_t j = 0; j < inputs.size(); j++) {layer_output[i] += inputs[j] * weights[i][j];}//for220jlayer_output[i] += biases[i];layer_output[i] = sigmoid(layer_output[i]);}//for110ireturn layer_output;}//vector<float> activate//subtract求差:两个 向量的差std::vector<float> subtract(const std::vector<float>& a, const std::vector<float>& b) {std::vector<float> result(a.size(), 0.0);for (size_t i = 0; i < a.size(); i++) {result[i] = a[i] - b[i];}return result;}//vector<float>subtract//dotT点乘std::vector<float> dotT(const std::vector<float>& a, const std::vector<std::vector<float>>& b) {std::vector<float> result(b[0].size(), 0.0);for (size_t i = 0; i < b[0].size(); i++) {for (size_t j = 0; j < a.size(); j++) {result[i] += a[j] * b[j][i];}}return result;}//更新权重矩阵s(们), 和偏置(向量)S们void updateWeights(const std::vector<float>& inputs, const std::vector<float>& errors, const std::vector<float>& outputs,std::vector<std::vector<float>>& weights, std::vector<float>& biases, float lr) {for (size_t i = 0; i < weights.size(); i++) {for (size_t j = 0; j < weights[0].size(); j++) {weights[i][j] += lr * errors[i] * sigmoid导函数prime(outputs[i]) * inputs[j];}biases[i] += lr * errors[i] * sigmoid导函数prime(outputs[i]);}}//void updateWeights(public:NN神经网络NN(int inputNode输入层之节点数s, int hidden01Node隐藏层01结点数s, int hidden22Nodes, int outputNode输出层结点数s):inputNode输入层之节点数s(inputNode输入层之节点数s), hidden01Node隐藏层01结点数s(hidden01Node隐藏层01结点数s), hidden22Nodes(hidden22Nodes), outputNode输出层结点数s(outputNode输出层结点数s){srand(time(NULL));//初始换权重矩阵输入层到第1隐藏层之权重矩阵.resize(hidden01Node隐藏层01结点数s, vector<float>(inputNode输入层之节点数s));隐藏层1到第二隐藏层2之权重矩阵1to2.resize(hidden22Nodes, vector<float>(hidden01Node隐藏层01结点数s));隐藏22到输出层de权重矩阵.resize(outputNode输出层结点数s, vector<float>(hidden22Nodes));//隐藏层1偏置1.resize(hidden01Node隐藏层01结点数s);隐藏层2偏置2.resize(hidden22Nodes);O输出偏置o.resize(outputNode输出层结点数s);initWeightsAndBiases初始化权重和偏置矩阵();}//NN神经网络NN(i//sigmoid激活函数及导数float sigmoid(float x){ return 1.0 / (1.0 + exp(-x)); }float sigmoid导函数prime(float x) { return x * (1 - x); }//Forward前向传播vector<float> predict(const vector<float>& input输入数据) {//用激活函数sigmoid-激活的过程隐藏层1数据1 = activate(input输入数据, 输入层到第1隐藏层之权重矩阵, 隐藏层1偏置1); //激活函数// 第一隐藏层到第二隐藏层隐藏层2数据2 = activate(隐藏层1数据1, 隐藏层1到第二隐藏层2之权重矩阵1to2, 隐藏层2偏置2);//hidden1, wh1h2, bias_h2);// 第二隐藏层到输出层输出数据output = activate(隐藏层2数据2, 隐藏22到输出层de权重矩阵, O输出偏置o);// , wh2o, bias_o);return 输出数据output;}//vector<float>predict(// 反向传播//Backpropagationvoid train(const  vector<float>& inputs, const  vector<float>& target目标数据s, float lr学习率) {vector<float> output尝试的输出数据s = predict(inputs);// 输出层误差vector<float> output_error输出误差s = subtract(target目标数据s, output尝试的输出数据s);//Loss误差损失之和001 = 0.0;for (int ii = 0; ii < outputNode输出层结点数s; ++ii) { Loss误差损失之和001 += fabs(output_error输出误差s[ii]); }//=========================================================================// 隐藏层2误差vector<float> hidden2_errors = dotT(output_error输出误差s, 隐藏22到输出层de权重矩阵);// 隐藏层1误差vector<float> hidden1_errors = dotT(hidden2_errors, 隐藏层1到第二隐藏层2之权重矩阵1to2);// 更新权重: 隐藏层2到输出层(的权重矩阵updateWeights(隐藏层2数据2,   output_error输出误差s, output尝试的输出数据s, 隐藏22到输出层de权重矩阵, O输出偏置o, lr学习率);// 更新权重: 隐藏层1到隐藏层2updateWeights(隐藏层1数据1,   hidden2_errors, 隐藏层2数据2, 隐藏层1到第二隐藏层2之权重矩阵1to2, 隐藏层2偏置2, lr学习率);// 更新权重: 输入层到隐藏层1的权重矩阵)updateWeights(inputs,   hidden1_errors, 隐藏层1数据1, 输入层到第1隐藏层之权重矩阵, 隐藏层1偏置1, lr学习率);}// void train(// // 反向传播//Backpropagation};//class NN神经网络NN {#define Num训练数据的个数s 5
int main()
{NN神经网络NN nn(9, 11, 4, 2);// 11, 10, 4);// Exampleint 训练数据的个数s = Num训练数据的个数s;std::vector<float> input[Num训练数据的个数s];/*  input[0] = {0,1,0, 0,1,0, 0,1,0};      //1“竖线”或 “1”字{ 1.0, 0.5, 0.25, 0.125 };input[1] = { 0,0,0, 1,1,1,0,0,0 };      //-“横线”或 “-”减号{ 1.0, 0.5, 0.25, 0.125 };input[2] = { 0,1,0, 1,1,1, 0,1,0 };      //+“+”加号{ 1.0, 0.5, 0.25, 0.125 };input[3] = { 0,1,0, 0,1.2, 0,  0,1, 0 };   // '1'或 '|'字型{ 1.0, 0.5, 0.25, 0.125 };input[4] = { 1,1,0, 1,0,1.2,  1,1,1 };      //“口”字型+{ 1.0, 0.5, 0.25, 0.125 };std::vector<float> target[Num训练数据的个数s];target[0] = { 1.0, 0,0,0 };// , 0};//1 , 0}; //0.0, 1.0, 0.5};      //{ 0.0, 1.0 };target[1] = { 0, 1.0 ,0,0 };// , 0};//- 91.0, 0};// , 0, 0}; //target[2] = { 0,0,1.0,0 };// , 0};//+ 1.0, 0.5};target[3] = { 1.0 ,0,0, 0.5 };// , 0}; //1target[4] = { 0,0,0,0 };// , 1.0}; //“口”*/vector<float> target[Num训练数据的个数s];input[0] = { 0,0,0, 1,1,1, 0,0,0 };     target[0] = { 0, 1 };   //"-"input[1] = { 0,1,0, 0,1,0, 0,1,0 };     target[1] = { 1.0, 0 };input[2] = { 1,1,1, 0,0,0, 0,0,0 };     target[2] = { 0, 0.5 };input[3] = { 0,0,1, 0,0,1, 0,0,1 };     target[3] = { 0.9, 0 };for (int i = 0; i < 50000; ++i) {//for110ifor (int jj = 0; jj < Num训练数据的个数s - 1;  ++jj) {//for (auto& val: input ) {nn.train(input[jj], target[jj], 0.001);if (0 ==i % 10000) { cout << "[Lost:" << Loss误差损失之和001 << endl; }}//for220jj}//for110icout << endl;//--------------------------------------input[1] = { 0,0,0, 1,1, 0.98, 0,0,0 };      //1/ std::vector<float> outpu输出数据001t = nn.predict(input[0]);for (auto& val : outpu输出数据001t)std::cout << std::fixed << std::setprecision(9) << val << " ";cout << endl;//-------------------------------------------------------------std::string str0001;do {std::cout << std::endl << "请输入一个字符串(要求字符串是包含9个由逗号分隔的数字的字符串,如 1,2,0,0,5,0,0,8,9等): " << std::endl;std::getline(std::cin, str0001);std::stringstream s01s001(str0001);for (int i = 0; i < 9; ++i) {std::string temp;std::getline(s01s001, temp, ',');input[1][i] = (float)std::stof(temp); // 将字符串转化为整数}std::cout << "数字数组为: ";for (int i = 0; i < 9; ++i) {std::cout << input[1][i] << " ";}outpu输出数据001t = nn.predict(input[1]);std::cout << std::endl;for (auto& val : outpu输出数据001t)std::cout << std::fixed << std::setprecision(9) << val << " ";} while (true);// 1 == 1);//======================================cout << "Hello World!\n";
}//

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

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

相关文章

矿井水处理技术离子交换树脂法

矿井水除氟的要求一般是处理后水中的含氟量≤1.0mg/L。氟化物含量高的原水往往呈偏碱性&#xff0c;pH值常大于7.5。利用阴离子交换树脂上的可交换阴离子&#xff0c;去交换水中的氟离子&#xff0c;达到除氟目的。氟离子的选择交换性较大&#xff0c;树脂上的SO42-、Cl-等阴离…

卷积过程详细讲解

1&#xff1a;单通道卷积 以单通道卷积为例&#xff0c;输入为&#xff08;1,5,5&#xff09;&#xff0c;分别表示1个通道&#xff0c;宽为5&#xff0c;高为5。假设卷积核大小为3x3&#xff0c;padding0&#xff0c;stride1。 卷积过程如下&#xff1a; 相应的卷积核不断…

企微配置回调服务

1、企微配置可信域名 2、企微获取成员userID 3、企微获取用户敏感数据 4、企微配置回调服务 文章目录 一、简介1、概述2、相关文档地址 二、企微配置消息服务器1、配置消息接收参数2、参数解析3、参数拼接规则 三、代码编写—使用已有库1、代码下载2、代码修改3、服务代码编写 …

基于swing的超市信息管理系统java jsp仓库进销存mysql源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 基于swing的超市信息管理系统 系统有1权限&#xff1…

Linux驱动开发(Day5)

思维导图&#xff1a; 不同设备号文件绑定&#xff1a;

回归预测 | MATLAB实现SA-ELM模拟退火算法优化极限学习机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SA-ELM模拟退火算法优化极限学习机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SA-ELM模拟退火算法优化极限学习机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本…

ElasticSearch-集成ik分词器

本文已收录于专栏 《中间件合集》 目录 背景介绍版本选择优势说明集成过程1.下载安装包2.解压安装包3.重启ElasticSearch服务3.1通过ps -ef | grep elastic查看正在启动的es进程号3.2使用kill -9 xxx 杀死进程3.3使用 ./elasticsearch 启动es服务 分词测试细粒度分词方式分词请…

CTFshow 限时活动 红包挑战9 详细题解

CTFshow红包挑战9 题目源码开源了。源码如下&#xff1a; common.php <?phpclass user{public $id;public $username;private $password;public function __toString(){return $this->username;}}class cookie_helper{private $secret "*************"; /…

【Java架构-包管理工具】-Maven私服搭建-Nexus(三)

本文摘要 Maven作为Java后端使用频率非常高的一款依赖管理工具&#xff0c;在此咱们由浅入深&#xff0c;分三篇文章&#xff08;Maven基础、Maven进阶、私服搭建&#xff09;来深入学习Maven&#xff0c;此篇为开篇主要介绍Maven私服搭建-Nexus 文章目录 本文摘要1. Nexus安装…

【multimaster_fkie】多 ros master core 通信库,不配置主从机进行 ros 多机通信

1. 简介 多个 ros 系统之间可以通过配置 ros 主从机实现互相通信&#xff0c;但有的场景每个 ros 系统都需要运行 rosmaster/roscore &#xff0c;这种情况下就需要使用 multimaster_fkie 库来实现 ros 通信。 Github&#xff1a;https://github.com/fkie/multimaster_fkie RO…

本地搭建CFimagehost私人图床【公网远程访问】

文章目录 1.前言2. CFImagehost网站搭建2.1 CFImagehost下载和安装2.2 CFImagehost网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

Redis数据结构之Set

Set 类型是一个无序并唯一的键值集合&#xff0c;它的存储顺序不会按照插入的先后顺序进行存储。Redis 中集合是通过哈希表实现的&#xff0c;所以添加&#xff0c;删除&#xff0c;查找的复杂度都是 O(1)。相对于列表&#xff0c;集合也有两个特点&#xff1a;无序、不可重复 …

js reverse实现数据的倒序

2023.8.25今天我学习了如何在数组顺序进行倒序排列&#xff0c;如&#xff1a; 原数组为&#xff1a; 我们只需要对数组使用reverse()方法 let demo [{id: 1, name: 一号},{id: 2, name: 二号},{id: 3, name: 三号},]demo.reverse()console.log(demo) 扩展&#xff1a; 当我…

jmeter入门:接口压力测试全解析

一.对接口压力测试 1.配置 1.添加线程组&#xff08;参数上文有解释 这里不介绍&#xff09; 2.添加取样器 不用解释一看就知道填什么。。。 3.添加头信息&#xff08;否则请求头对不上&#xff09; 也不用解释。。。 4.配置监听器 可以尝试使用这几个监听器。 2.聚合结果…

Tushare入门小册

Tushare入门小册 一、Tushare平台介绍 Pro版数据更稳定质量更好了&#xff0c;我们提供的不再是直接从互联网抓取&#xff0c;而是通过社区的采集和整理存入数据库经过质量控制后再提供给用户。但Pro依然是个开放的&#xff0c;免费的平台&#xff0c;不带任何商业性质和目的…

什么是服务端渲染?前后端分离的优点和缺点?

一.概念 服务端渲染简单点就是服务端直接返回给客户端一个完整的页面&#xff0c;也就是一个完整的html页面&#xff0c;这个页面上已经有数据了。说到这里你可能会觉得后端怎么写页面啊&#xff0c;而且服务端返回页面不是加载更慢吗&#xff1f;错了&#xff0c;因为我们现在…

4.网络设计与redis、memcached、nginx组件(一)

网络组件系列文章目录 第四章 网络设计与redis、memcached、nginx组件 文章目录 网络组件系列文章目录文章的思维导图前言一、网络相关的问题&#xff0c;网络开发中要处理那些问题&#xff1f;网络操作IO连接建立连接断开消息到达消息发送网络操作IO特性 二、网络中IO检测IO函…

VR、AR、MR 傻傻分不清楚?区别的底层逻辑?

VR是一种能够制作虚拟物体并与人互动的基础技术。它与操作者所处的环境无关。AR可以让在特定位置出现或消失。MR可以让虚拟物体与真实物体进行互动。 AR和MR的大部分应用场景都是随机的&#xff0c;所以硬件基本都采用手机和眼镜。提升了便携性。牺牲了性能。这就导致了AR与MR…

基于Springboot+vue的宠物服务管理系统——LW模板

摘 要 21世纪的今天&#xff0c;随着人类生活从低层次不断向高层次跃进&#xff0c;人类和宠物的关系已经密不可分。人们生活水平的进步进而带来了宠物生活水平的进步&#xff0c;因此对于宠物的管理也愈发的丰富起来&#xff0c;宠物的膳食安排&#xff0c;宠物的医疗安排等都…

罗勇军 →《算法竞赛·快冲300题》每日一题:“乘积” ← 动态规划

【题目来源】http://oj.ecustacm.cn/problem.php?id1781http://oj.ecustacm.cn/viewnews.php?id1023【题目描述】 给你一个长度为 n 的序列&#xff0c;序列中的元素只包括 1 和 -1。 请问有多少个连续的子序列乘积为正数。【输入格式】 输入第一行为正整数 n。&#xff08;n…