C#构建一个简单的前馈神经网络

news2024/11/25 19:03:48
1. 神经网络的基本概念

神经网络是一种模拟人脑神经元结构的计算模型,由多个神经元(节点)组成,这些神经元通过连接(边)相互作用。每个连接都有一个权重,用于表示连接的重要性。神经网络通常分为输入层、隐藏层和输出层。

2. 神经元

神经元是神经网络的基本单元,它接收输入信号,通过激活函数处理这些信号,然后产生输出。常见的激活函数包括Sigmoid、ReLU、Tanh等。

3. 前向传播

前向传播是从输入层到输出层的信号传递过程。每个神经元的输出作为下一层神经元的输入,直到最终产生输出。

4. 反向传播

反向传播是训练神经网络的关键步骤,通过计算损失函数的梯度并调整权重,使得网络的预测误差最小化。

using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Project.NeuralNetwork
{
    /// <summary>
    /// 构建神经网络
    /// 简单的前馈神经网络
    /// </summary>
    public class NeuralNetwork
    {
        /// <summary>
        /// 定义神经网络的层数和每层的神经元数量
        /// </summary>
        private readonly int[] layers;

        /// <summary>
        /// 存储每层的神经元值
        /// </summary>
        private double[][] neurons;

        /// <summary>
        /// 存储每层之间的权重
        /// </summary>
        private double[][][] weights;

        /// <summary>
        /// 存储每层的偏置
        /// </summary>
        private double[][] biases;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="layers"></param>
        public NeuralNetwork(int[] layers)
        {
            this.layers = layers;
            InitializeNeurons();
            InitializeWeightsAndBiases();
        }

        /// <summary>
        /// 初始化神经元数组
        /// </summary>
        private void InitializeNeurons()
        {
            neurons = new double[layers.Length][];
            for (int i = 0; i < layers.Length; i++)
            {
                neurons[i] = new double[layers[i]];
            }
        }

        /// <summary>
        /// 随机初始化权重和偏置
        /// </summary>
        private void InitializeWeightsAndBiases()
        {
            Random random = new Random();
            weights = new double[layers.Length - 1][][];
            biases = new double[layers.Length - 1][];
            for (int i = 0; i < layers.Length - 1; i++)
            {
                weights[i] = new double[layers[i]][];
                for (int j = 0; j < layers[i]; j++)
                {
                    weights[i][j] = new double[layers[i + 1]];
                    for (int k = 0; k < layers[i + 1]; k++)
                    {
                        weights[i][j][k] = random.NextDouble() * 2 - 1;
                    }
                }

                biases[i] = new double[layers[i + 1]];
                for (int j = 0; j < layers[i + 1]; j++)
                {
                    biases[i][j] = random.NextDouble() * 2 - 1;
                }
            }
        }

        /// <summary>
        /// sigmoid激活函数
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        private double Sigmoid(double x)
        {
            return 1.0 / (1.0 + Math.Exp(-x));
        }

        /// <summary>
        /// sigmoid激活函数的导数
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        private double SigmoidDerivative(double x)
        {
            return x * (1 - x);
        }

        /// <summary>
        /// 前向传播
        /// </summary>
        /// <param name="inputs"></param>
        public void Forward(double[] inputs)
        {
            Array.Copy(inputs, neurons[0], inputs.Length);
            for (int i = 1; i < layers.Length; i++)
            {
                for (int j = 0; j < layers[i]; j++)
                {
                    double sum = biases[i - 1][j];
                    for (int k = 0; k < layers[i - 1]; k++)
                    {
                        sum += neurons[i - 1][k] * weights[i - 1][k][j];
                    }
                    neurons[i][j] = Sigmoid(sum);
                }
            }
        }

        /// <summary>
        /// 反向传播
        /// </summary>
        /// <param name="target"></param>
        /// <param name="learningRate"></param>
        public void Backward(double[] target, double learningRate)
        {
            double[][] deltas = new double[layers.Length - 1][];
            // 计算输出层
            deltas[layers.Length - 2] = new double[layers[layers.Length - 1]];
            for (int i = 0; i < layers[layers.Length - 1]; i++)
            {
                double error = target[i] - neurons[layers.Length - 1][i];
                deltas[layers.Length - 2][i] = error * SigmoidDerivative(neurons[layers.Length - 1][i]);
            }
            // 计算隐藏层
            for (int i = layers.Length - 3; i >= 0; i--)
            {
                deltas[i] = new double[layers[i + 1]];
                for (int j = 0; j < layers[i + 1]; j++)
                {
                    double error = 0.0;
                    for (int k = 0; k < layers[i + 2]; k++)
                    {
                        error += deltas[i + 1][k] * weights[i + 1][j][k];
                    }
                    deltas[i][j] = error * SigmoidDerivative(neurons[i + 1][j]);
                }
            }
            // 更新权重和偏差
            for (int i = 0; i < layers.Length - 1; i++)
            {
                for (int j = 0; j < layers[i]; j++)
                {
                    for (int k = 0; k < layers[i + 1]; k++)
                    {
                        weights[i][j][k] += learningRate * neurons[i][j] * deltas[i][k];
                    }
                }
                for (int j = 0; j < layers[i + 1]; j++)
                {
                    biases[i][j] += learningRate * deltas[i][j];
                }
            }
        }

        /// <summary>
        /// 训练神经网络,使用反向传播算法更新权重和偏置
        /// </summary>
        /// <param name="inputs">输入</param>
        /// <param name="targets">目标</param>
        /// <param name="epochs">数据运算次数</param>
        /// <param name="learningRate">学习速率</param>
        public void Train(double[][] inputs, double[][] targets, int epochs, double learningRate)
        {
            for (int epoch = 0; epoch < epochs; epoch++)
            {
                for (int i = 0; i < inputs.Length; i++)
                {
                    Forward(inputs[i]);
                    Backward(targets[i], learningRate);
                }
            }
        }

        /// <summary>
        /// 使用训练好的模型进行预测
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public double[] Predict(double[] input)
        {
            Forward(input);
            return neurons[layers.Length - 1];
        }
    }
}
  • 准备训练数据
  • 训练网络
  • 测试网络并输出结果
           //1. 数据准备
            double[][] inputs = new double[][]
            {
                new double[] { 0, 0 },
                new double[] { 0, 1 },
                new double[] { 1, 0 },
                new double[] { 1, 1 }
            };
            double[][] targets = new double[][]
            {
                new double[] { 0 },
                new double[] { 1 },
                new double[] { 1 },
                new double[] { 0 }
            };
            //2. 构建神经网络
            // 定义神经网络结构:输入层2个神经元,隐藏层3个神经元,输出层1个神经元
            int[] layers = { 2, 3, 1 };
            NeuralNetwork model = new NeuralNetwork(layers);
            //3. 训练和评估
            //使用训练数据训练神经网络,并评估其性能。
            model.Train(inputs, targets, 10000, 0.01);
            //4. 训练神经网络
            model.Train(inputs, targets, epochs: 10000, learningRate: 0.5);
            // 预测数据
            foreach (var input in inputs)
            {
                double[] prediction = model.Predict(input);
                Console.WriteLine($"输入: [{string.Join(", ", input)}] => 输出: [{string.Join(", ", prediction)}]");
            }

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

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

相关文章

C++共享智能指针

C中没有垃圾回收机制&#xff0c;必须自己释放分配的内存&#xff0c;否则就会造成内存泄漏。解决这个问题最有效的方式是使用智能指针。 智能指针是存储指向动态分配(堆)对象指针的类&#xff0c;用于生存期的控制&#xff0c;能够确保在离开指针所在作用域时&#xff0c;自动…

python Flask指定IP和端口

from flask import Flask, request import uuidimport json import osapp Flask(__name__)app.route(/) def hello_world():return Hello, World!if __name__ __main__:app.run(host0.0.0.0, port5000)

虚幻引擎---初识篇

一、学习途径 虚幻引擎官方文档&#xff1a;https://dev.epicgames.com/documentation/zh-cn/unreal-engine/unreal-engine-5-5-documentation虚幻引擎在线学习平台&#xff1a;https://dev.epicgames.com/community/unreal-engine/learning哔哩哔哩&#xff1a;https://www.b…

Java开发经验——SpringRestTemplate常见错误

摘要 本文分析了在使用Spring框架的RestTemplate发送表单请求时遇到的常见错误。主要问题在于将表单参数错误地以JSON格式提交&#xff0c;导致服务器无法正确解析参数。文章提供了错误案例的分析&#xff0c;并提出了修正方法。 1. 表单参数类型是MultiValueMap RestControl…

oracle会话追踪

一 跟踪当前会话 1.1 查看当前会话的SID,SERIAL# #在当前会话里执行 示例&#xff1a; SQL> select distinct userenv(sid) from v$mystat; USERENV(SID) -------------- 1945 SQL> select distinct sid,serial# from v$session where sid1945; SID SERIAL# …

数据可视化复习2-绘制折线图+条形图(叠加条形图,并列条形图,水平条形图)+ 饼状图 + 直方图

目录 目录 一、绘制折线图 1.使用pyplot 2.使用numpy ​编辑 3.使用DataFrame ​编辑 二、绘制条形图&#xff08;柱状图&#xff09; 1.简单条形图 2.绘制叠加条形图 3.绘制并列条形图 4.水平条形图 ​编辑 三、绘制饼状图 四、绘制散点图和直方图 1.散点图 2…

postgresql按照年月日统计历史数据

1.按照日 SELECT a.time,COALESCE(b.counts,0) as counts from ( SELECT to_char ( b, YYYY-MM-DD ) AS time FROM generate_series ( to_timestamp ( 2024-06-01, YYYY-MM-DD hh24:mi:ss ), to_timestamp ( 2024-06-30, YYYY-MM-DD hh24:mi:ss ), 1 days ) AS b GROUP BY tim…

【JavaEE初阶 — 多线程】定时器的应用及模拟实现

目录 1. 标准库中的定时器 1.1 Timer 的定义 1.2 Timer 的原理 1.3 Timer 的使用 1.4 Timer 的弊端 1.5 ScheduledExecutorService 2. 模拟实现定时器 2.1 实现定时器的步骤 2.1.1 定义类描述任务 定义类描述任务 第一种定义方法 …

一文学会Golang里拼接字符串的6种方式(性能对比)

g o l a n g golang golang的 s t r i n g string string类型是不可修改的&#xff0c;对于拼接字符串来说&#xff0c;本质上还是创建一个新的对象将数据放进去。主要有以下几种拼接方式 拼接方式介绍 1.使用 s t r i n g string string自带的运算符 ans ans s2. 使用…

LeetCode 3244.新增道路查询后的最短距离 II:贪心(跃迁合并)-9行py(O(n))

【LetMeFly】3244.新增道路查询后的最短距离 II&#xff1a;贪心&#xff08;跃迁合并&#xff09;-9行py&#xff08;O(n)&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/shortest-distance-after-road-addition-queries-ii/ 给你一个整数 n 和一个二维…

MyBatis中特殊SQL的执行

目录 1.模糊查询 2.批量删除 3.动态设置表名 4.添加功能获取自增的主键 1.模糊查询 List<User> getUserByLike(Param("username") String username); <select id"getUserByLike" resultType"com.atguigu.mybatis.pojo.User">&…

ES 基本使用与二次封装

概述 基本了解 Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;基于 Apache Lucene 构建。它提供了对海量数据的快速全文搜索、结构化搜索和分析功能&#xff0c;是目前流行的大数据处理工具之一。主要特点即高效搜索、分布式存储、拓展性强 核心功能 全文搜索:…

Azkaban部署

首先我们需要现在相关的组件&#xff0c;在这里已经给大家准备好了相关的安装包&#xff0c;有需要的可以自行下载。 只需要启动hadoop集群就可以&#xff0c;如果现在你的hive是打开的&#xff0c;那么请你关闭&#xff01;&#xff01;&#xff01; 如果不关会造成证书冲突…

Jmeter中的定时器

4&#xff09;定时器 1--固定定时器 功能特点 固定延迟&#xff1a;在每个请求之间添加固定的延迟时间。精确控制&#xff1a;可以精确控制请求的发送频率。简单易用&#xff1a;配置简单&#xff0c;易于理解和使用。 配置步骤 添加固定定时器 右键点击需要添加定时器的请求…

JavaEE初学07

JavaEE初学07 MybatisORMMybatis一对一结果映射一对多结果映射 Mybatis动态sqlif标签trim标签where标签set标签foreach标签补充 Mybatis Mybatis是一款优秀的持久层框架&#xff0c;他支持自定义SQL、存储过程以及高级映射。Mybatis几乎免除了所有的JDBC代码以及设置参数和获取…

【layui】table的switch、edit修改

<title>简单表格数据</title><div class"layui-card layadmin-header"><div class"layui-breadcrumb" lay-filter"breadcrumb"><a>系统设置</a><a>简单表格数据</a></div> </div>&…

工具使用_docker容器_crossbuild

1. 工具简介 2. 工具使用 拉取 multiarch/crossbuild 镜像&#xff1a; docker pull multiarch/crossbuild 创建工作目录和示例代码&#xff1a; mkdir -p ~/crossbuild-test cd ~/crossbuild-test 创建 helloworld.c &#xff1a; #include <stdio.h>int main() …

Android 天气APP(三十七)新版AS编译、更新镜像源、仓库源、修复部分BUG

上一篇&#xff1a;Android 天气APP&#xff08;三十六&#xff09;运行到本地AS、更新项目版本依赖、去掉ButterKnife 新版AS编译、更新镜像源、仓库源、修复部分BUG 前言正文一、更新镜像源① 腾讯源③ 阿里源 二、更新仓库源三、修复城市重名BUG四、地图加载问题五、源码 前…

基于Java Springboot海洋馆预约系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

采用python3.12 +django5.1 结合 RabbitMQ 和发送邮件功能,实现一个简单的告警系统 前后端分离 vue-element

一、开发环境搭建和配置 #mac环境 brew install python3.12 python3.12 --version python3.12 -m pip install --upgrade pip python3.12 -m pip install Django5.1 python3.12 -m django --version #用于检索系统信息和进程管理 python3.12 -m pip install psutil #集成 pika…