自学内容网 自学内容网

c#构建一个简单的神经网络

1. 神经网络的基本概念

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

2. 神经元

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

3. 前向传播

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

4. 反向传播

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

    /// <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()
        {
            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 + 1]][];
                biases[i] = new double[layers[i + 1]];

                for (int j = 0; j < layers[i + 1]; j++)
                {
                    weights[i][j] = new double[layers[i]];
                    biases[i][j] = 0;

                    for (int k = 0; k < layers[i]; k++)
                    {
                        weights[i][j][k] = (new 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)
        {
            double s = Sigmoid(x);
            return s * (1 - s);
        }

        /// <summary>
        /// 前向传播,计算输出
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public double[] Forward(double[] input)
        {
            neurons[0] = input;
            for (int i = 0; i < layers.Length - 1; i++)
            {
                for (int j = 0; j < layers[i + 1]; j++)
                {
                    double sum = 0;
                    for (int k = 0; k < layers[i]; k++)
                    {
                        sum += neurons[i][k] * weights[i][j][k];
                    }
                    neurons[i + 1][j] = Sigmoid(sum + biases[i][j]);
                }
            }
            return neurons[layers.Length - 1];
        }

        /// <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++)
                {
                    double[] output = Forward(inputs[i]);
                    double[][] errors = new double[layers.Length][];

                    // 计算输出层误差
                    errors[layers.Length - 1] = new double[layers[layers.Length - 1]];
                    for (int j = 0; j < layers[layers.Length - 1]; j++)
                    {
                        errors[layers.Length - 1][j] = targets[i][j] - output[j];
                    }

                    // 反向传播误差
                    for (int l = layers.Length - 2; l >= 0; l--)
                    {
                        errors[l] = new double[layers[l]];
                        for (int j = 0; j < layers[l]; j++)
                        {
                            double error = 0;
                            for (int k = 0; k < layers[l + 1]; k++)
                            {
                                error += errors[l + 1][k] * weights[l][k][j];
                            }
                            errors[l][j] = error * SigmoidDerivative(neurons[l][j]);
                        }
                    }

                    // 更新权重和偏置
                    for (int l = 0; l < layers.Length - 1; l++)
                    {
                        for (int j = 0; j < layers[l + 1]; j++)
                        {
                            for (int k = 0; k < layers[l]; k++)
                            {
                                weights[l][j][k] += learningRate * errors[l + 1][j] * neurons[l][k];
                            }
                            biases[l][j] += learningRate * errors[l + 1][j];
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 使用训练好的模型进行预测
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public double[] Predict(double[] input)
        {
            return Forward(input);
        }
    }
  • 准备训练数据
  • 训练网络
  • 测试网络并输出结果
            //1. 数据准备
            //首先,我们需要准备一些训练数据。这些数据通常包含用户的输入(文本)和对应的标签(意图)。
            var data = new List<Tuple<string[], string[]>>
            {
                 Tuple.Create(new string[] { "早安" }, new string[] { "早上好" }),
                Tuple.Create(new string[] { "午安" }, new string[] { "中午好" }),
                Tuple.Create(new string[] { "晚安" }, new string[] { "晚上好" }),
                Tuple.Create(new string[] { "你好吗?" }, new string[] { "我很好,谢谢。" })
            };
            //2. 文本预处理
            //将文本数据转换为神经网络可以处理的数值形式,例如词袋模型(Bag of Words)或词嵌入(Word Embeddings)。
            var vocab = new HashSet<string>();
            foreach (var item in data)
            {
                vocab.UnionWith(item.Item1);
                vocab.UnionWith(item.Item2);
            }
            // 创建词汇索引映射
            var wordToIndex = vocab.Select((value, index) => new { value, index }).ToDictionary(p => p.value, p => p.index);
            var indexToWord = vocab.Select((value, index) => new { value, index }).ToDictionary(p => p.index, p => p.value);
            // 转换数据为索引序列
            var inputs = data.Select(d => d.Item1.Select(word => (double)wordToIndex[word]).ToArray()).ToArray();
            var targets = data.Select(d => d.Item2.Select(word => (double)wordToIndex[word]).ToArray()).ToArray();
            //3. 构建神经网络
            //构建一个简单的前馈神经网络,用于训练和预测意图。
            // 输入层大小
            int inputSize = vocab.Count;
            // 隐藏层大小
            int hiddenSize = vocab.Count;
            // 输出层大小
            int outputSize = vocab.Count;
            NeuralNetwork model = new NeuralNetwork(new int[] { inputSize, hiddenSize, outputSize });
            //4. 训练和评估
            //使用训练数据训练神经网络,并评估其性能。
            model.Train(inputs, targets, 10000, 0.1);

            //5. 对话系统
            //将训练好的模型集成到一个简单的对话系统中,使其能够根据用户输入生成相应的回复。
            string input = "早安";
            double[] inputIndices = input.Split(' ').Select(word => (double)wordToIndex[word]).ToArray();
            var outputIndices = model.Predict(inputIndices);
            var outputWords = outputIndices.Select(index => wordToIndex.FirstOrDefault(x => x.Value == index).Key).ToArray();
            Console.WriteLine($"输入: {input}, 输出: {string.Join(" ", outputWords)}");


原文地址:https://blog.csdn.net/w1824575989/article/details/143921088

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!