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

1. 神经网络的基本概念

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

2. 神经元

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

3. 前向传播

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

4. 反向传播

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

cs 复制代码
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];
        }
    }
}
  • 准备训练数据
  • 训练网络
  • 测试网络并输出结果
cs 复制代码
           //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)}]");
            }
相关推荐
秀儿还能再秀7 分钟前
神经网络(系统性学习四):深度学习——卷积神经网络(CNN)
人工智能·深度学习·机器学习·cnn·学习笔记
小乖兽技术1 小时前
C#13新特性介绍:LINQ 的优化设计
开发语言·c#·linq
hccee2 小时前
DevExpress控件 基本使用
c#
归-途2 小时前
C#构建一个简单的循环神经网络,模拟对话
神经网络·机器学习·c#
慕卿扬4 小时前
基于python的机器学习(四)—— 聚类(一)
笔记·python·学习·机器学习·聚类
shepherd枸杞泡茶4 小时前
C# 数据结构之【图】C#图
数据结构·c#·.net
YRr YRr4 小时前
深度解析神经网络中的最大池化层:工作原理、参数配置与应用示例
人工智能·深度学习·神经网络
静能生慧4 小时前
大模型-微调与对齐-非强化学习的对齐方法
人工智能·深度学习·机器学习·大模型
AI浩5 小时前
ShuffleNet:一种为移动设备设计的极致高效的卷积神经网络
人工智能·神经网络·cnn