神经网络/BP(反向传播)代码示例

news/2025/2/11 17:35:33/文章来源:https://www.cnblogs.com/wyl123ly/p/18710199
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <vector>
using namespace std;const int NX = 784, NB = 500, NY = 10;//输入层X,隐藏层B,输出层Y节点数
const double eta = 0.06;//学习率struct Node {double val{};double bias{};vector<double> weight;
} x[NX], b[NB], y[NY];//输入层X,隐藏层B,输出层Y
double g[NY], e[NB];//用于反向传播
double trainx[NX], trainy[NY];//训练数据double sigmoid(double x) { return 1.0 / (1.0 + exp(-x)); }double get_rand_weight() { return rand() % 10 / 5.0 - 1; } //生成(-1,1)随机数
double get_rand_bias() { return rand() % 10 / 500.0 - 0.01; } //生成(-0.01,0.01)随机数//网络初始化
void init() {for (int i = 0; i < NX; i++) {//x[i].bias = get_rand_bias();for (int j = 0; j < NB; j++) {x[i].weight.push_back(get_rand_weight());}}for (int i = 0; i < NB; i++) {b[i].bias = get_rand_bias();for (int j = 0; j < NY; j++) {b[i].weight.push_back(get_rand_weight());}}for (int i = 0; i < NY; i++) {y[i].bias = get_rand_bias();}
};//前向传播
void forward() {//首先需要清空隐藏层和输出层原有的非参数数据!!!for (int i = 0; i < NB; i++) b[i].val = 0;for (int i = 0; i < NY; i++) y[i].val = 0;//输入层读取数据for (int i = 0; i < NX; i++) x[i].val = trainx[i];//输入层->隐藏层for (int i = 0; i < NX; i++) {for (int j = 0; j < NB; j++) {b[j].val += x[i].val * x[i].weight[j];}}//隐藏层求值for (int i = 0; i < NB; i++) {b[i].val = sigmoid(b[i].val - b[i].bias);}//隐藏层->输出层for (int i = 0; i < NB; i++) {for (int j = 0; j < NY; j++) {y[j].val += b[i].val * b[i].weight[j];}}//输出层求值for (int i = 0; i < NY; i++) {y[i].val = sigmoid(y[i].val - y[i].bias);}
}//反向传播
void back() {//计算g和efor (int i = 0; i < NY; i++) {g[i] = y[i].val * (1 - y[i].val) * (trainy[i] - y[i].val);}for (int i = 0; i < NB; i++) {double res = 0;for (int j = 0; j < NY; j++) {res += b[i].weight[j] * g[j];}e[i] = b[i].val * (1 - b[i].val) * res;}//更新w, theta, v, gammafor (int i = 0; i < NB; i++)for (int j = 0; j < NY; j++)b[i].weight[j] += eta * b[i].val * g[j];for (int i = 0; i < NY; i++)y[i].bias -= eta * g[i];for (int i = 0; i < NX; i++)for (int j = 0; j < NB; j++)x[i].weight[j] += eta * x[i].val * e[j];for (int i = 0; i < NB; i++)b[i].bias -= eta * e[i];
}FILE *fImg, *fAns;
int result[1000000] = {0}; //每次训练的结果,正确为1,错误为0
void train(int Case) {//读入一张新的图片//除了前16字节,接下来的信息都是一张一张的图片//每张图片大小为28*28 = 784 = NX,每个char表示该像素对应的灰度,范围为0至255unsigned char img[NX], ans;fread(img, 1, NX, fImg);for (int i = 0; i < NX; i++) trainx[i] = (double)img[i] / 255.0;//读入该图片对应的答案//除了前8字节,第k个字节对应第k张图片的正确答案fread(&ans,1,1,fAns);for(int i = 0; i < NY; i++) trainy[i] = (i == ans) ? 1 : 0;//前向传播,计算答案是否正确forward();int res = 0;for (int i = 0; i <= 9; i++)if (y[i].val > y[res].val)res = i;result[Case] = (res == ans) ? 1 : 0;for (int i = 0; i < 28; i++) {for (int j = 0; j < 28; j++) {if (trainx[i * 28 + j] != 0) cout << 'X';else cout << ' ';}cout << endl;}cout << "Test Case #" << Case <<", result is " << res << ", answer is " << (int)ans << endl;//反向传播back();//输出最近100局的正确率int P = 100, cnt = 0;if(Case % P == 0) {for(int i = 0; i < P; i++)cnt += result[Case - i];cout << Case << " " << cnt << endl;}
}int main() {fImg=fopen("train-images.idx3-ubyte","rb");fseek(fImg, 16, SEEK_SET);fAns=fopen("train-labels.idx1-ubyte","rb");fseek(fAns, 8, SEEK_SET);freopen("result.txt", "w", stdout);init();for (int Case = 1; Case <= 60000; Case++) {train(Case);}return 0;
}

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

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

相关文章

对极几何(Epipolar Geometry)总结

为什么stereo很有用? 当我们需要从单一视角恢复结构时,我们的信息来源有以下几种: \(\bullet\) 从标定架可以获取标定架的位置 / 姿态以及相机内参 K。 \(\bullet\) 从无穷远点和线,加上正交的线和平面等信息,可以获取场景的结构和相机内参 K 。 但是由于内在歧义性,从单…

P10451 做题随笔

Solution 题意 原题链接 对每组数据,给定两颗用 01 序列描述的树,描述规则如下:按照 \(\text{DFS}\) 序进行遍历; 若序列中某位为 0,表示除根节点外的节点进栈;为 1 则表示出栈。要求判断一树是否可以通过交换子树的方式变换成另一子树(对于本题,即两树同构)。 分析 1…

堆排序--代码实现

本文主要说明代码编写思路和具体代码,下面的博文讲的比较全面 参考文章:https://www.cnblogs.com/jingmoxukong/p/4303826.html代码思路(以大根堆为例) 堆排一共分2个阶段:1. 创建一个大根堆 2.交换堆顶和堆尾元素,获取到堆顶元素,并重新维护大根堆 第一个阶段的思路: 从…

贪心tricks总结

贪心题一般没有什么技巧,多做题积累经验。 对于结论或策略,大胆猜想,小心求证,注意使用数据结构优化/结合其他算法。 一般类贪心 主要是证明贪心的正确性。 H. Fight Against Monsters 先用二分求出每个怪需要打的次数。 问题转化为一个排列的答案是 \[\sum_{i=1}^{n} \sum…

dp优化之斜率优化小结

这或许是这几天的济南云斗集训之旅最大的收获吧,若是最后一天的模拟赛文件不会交错也许结局会更好,但在这残酷的现实中却从不会有“如果”一词,母亲以不想让我学了,或许考完今年的 CSP 就可能不学了吧。 本文将效仿《李煜东算法进阶指南》的思路,按照例题层层深入。 P2365…

P3406 海底高铁(差分)

这道题要用到差分,因为反复经过一条路时只需要买一张对应的卡就行了,不用买多张,所以我们可以用差分,算出经过每条路的次数,要注意假设从1到3城市,只经过了道路1和道路2,应该让cha【1】++,cha【3】--; 还有算结果时应该从1到n-1列举每一条路,我最开始就搞错了,还要注…

JPlag:开源的代码抄袭检测工具

一、基本信息•项目地址: https://gitcode.com/gh_mirrors/jp/JPlaghttps://github.com/jplag/JPlag•编程语言:基于Java开发•主要特性:跨平台运行、支持多种文件格式、提供图形用户界面(GUI)和命令行接口、可扩展性强 二、技术特点 •多语言支持:JPlag支持包括Java、C、…

重构谷粒商城01:为何重构谷粒商城

前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶到中高阶程序员。 本项目将基于谷粒商城项目,并且对谷粒商城项目进行二次重构,使其满足最新的主流技术栈…

div设置四个角边框

示例实现 .top-header {background-image:url(../../assets/slider/topHeaderTopLeft.svg), /* 左上角图像 */url(../../assets/slider/topHeaderTopRight.svg), /* 右上角图像 */url(../../assets/slider/topHeaderBottomLeft.svg), /* 左下角图像 */url(../../assets/slider/…

JavaScript根据访问链接不同的后缀参数,展示不同的页面

要求:根据访问者访问不同的后缀链接,展示不同的页面;$(document).ready(function () {// 获取 URL 参数const urlParams = new URLSearchParams(window.location.search);const page = urlParams.get(page) || model; // 默认显示第一个导航项(比分)的内容和图标$(.tab-co…

内外网文件传输方案

文件传输问题:企业内网和外网分开了,如何进行文件快速有效稳定的传输呢?如何 进行文件交换、在线审批、在线审计呢?如何保证安全可控的文件传输、性能及扩展性强、审批审计便捷呢?常见痛点有哪些?纸质申请、线下审批、传递效率很慢,传递成本高, 纸质单据与电子文件脱节…

H3C--堆叠(IRF)

拓扑图 配置流程 配置SW1与SW2堆叠 一、SW1:shutdown 物理端口 配置堆叠优先级,优先级高的成为主设备 创建堆叠逻辑接口,将物理接口加入到堆叠逻辑接口中二、SW1: sysname SW1#irf member 1 priority 6#irf-port 1/1 port group interface FortyGigE1/0/53 port group int…