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)!