我正在研究 Tarik Rashid 的书《构建神经网络》。书上有python的例子,我想用c#实现,矩阵乘法函数也是我自己的。训练通过,但网络未训练。 我想出了一个小数据集,但是通过 Predict 函数后,没有返回任何目标值。请帮助我了解错误在哪里。
public class NeuralNetwork
{
private int InCount { get; }
private int OutCount { get; }
private int HiddenCount { get;}
private double LearningRate { get; set; }
private double[,] wih;
private double[,] who;
public NeuralNetwork(int In, int Hid, int Out)
{
InCount = In;
OutCount = Out;
HiddenCount = Hid;
wih = new double[HiddenCount, InCount];
who = new double[OutCount, HiddenCount];
Random rand = new Random();
for (int i = 0; i < wih.GetLength(0); i++)
for (int j = 0; j < wih.GetLength(1); j++)
wih[i, j] = rand.NextDouble() - 0.5;
for(int i = 0; i < who.GetLength(0); i++)
for (int j = 0; j < who.GetLength(1); j++)
who[i, j] = rand.NextDouble() - 0.5;
}
public double [,] Predict (double [,] Inputs_list)
{
double[,] hidden_inputs = Dot(wih, Inputs_list);
double[,] hidden_outputs = Sigma(hidden_inputs);
double [,] final_inputs = Dot(who, hidden_outputs);
double[,] final_outputs = Sigma(final_inputs);
return final_outputs;
}
#region Matrix Operations
static double[,] Dot(double[,] a, double[,] b)
{
if (a.GetLength(1) != b.GetLength(0)) throw new Exception("The number of columns in the first matrix must be equal to the number of rows in the second matrix.");
double[,] r = new double[a.GetLength(0), b.GetLength(1)];
for(int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < b.GetLength(1); j++)
{
for (int k = 0; k < a.GetLength(1); k++)
{
r[i, j] += a[i, k] * b[k, j];
}
}
}
return r;
}
static double [,] Multiplacation(double b, double[,] a)
{
double [,] r = new double[a.GetLength(0), a.GetLength(1)];
for(int i = 0; i < a.GetLength(0); i++)
for(int j = 0; j < a.GetLength(1); j++)
r[i, j] = a[i, j] * b;
return r;
}
static double[,] Multiplacation(double [,] a, double[] b)
{
double[,] r = new double[a.GetLength(0), a.GetLength(1)];
for (int i = 0; i < a.GetLength(0); i++)
for (int j = 0; j < a.GetLength(1); j++)
r[i, j] = a[i, j] * b[j];
return r;
}
static double[,] Multiplacation(double[,] a, double[,] b)
{
double[,] r = new double[a.GetLength(0), a.GetLength(1)];
for (int i = 0; i < a.GetLength(0); i++)
for (int j = 0; j < b.GetLength(1); j++) //a.GetLength
r [i,j] = a[i, j] * b[i, j];
return r;
}
static double[,] Transpose (double [,] matrix)
{
int rows = matrix.GetLength(1);
int cols = matrix.GetLength(0);
double[,] result = new double[rows, cols];
for(int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
{
result[j, i] = matrix[i, j];
}
}
return result;
}
private double[,] Difference(double[,] a, double[,] b)
{
double[,] r = new double[a.GetLength(0), b.GetLength(1)];
for (int i = 0; i < a.GetLength(0); i++)
for (int j = 0; j < a.GetLength(1); j++)
{
r[i, j] = a[i, j] - b[i, j];
}
return r;
}
static double[,] Difference(double[,] a, double[] b)
{
double[,] r = new double[a.GetLength(0), b.GetLength(0)];
for (int i = 0; i < a.GetLength(0); i++)
for (int j = 0; j < a.GetLength(1); j++)
{
r[i, j] = a[i, j] - b[i];
}
return r;
}
double [,] Add (double[,] a, double[,] b)
{
double[,] r = new double [a.GetLength(0), a.GetLength(1)];
for(int i = 0; i < a.GetLength(0); i++)
for(int j = 0; j < a.GetLength(1); j++)
{
r[i, j] = a[i, j] + b[i,j];
}
return r;
}
#endregion
#region Sigma
private double[,] Sigma(double[,] matrix) //исправлено
{
double [,] result = new double[matrix.GetLength(0), matrix.GetLength(1)];
for (int i = 0; i < matrix.GetLength(0); i++)
for (int j = 0; j < matrix.GetLength(1); j++)
{ double x = matrix[i, j];
result[i, j] = 1 / (1 + Math.Exp(-(matrix[i, j])));
}
return result;
}
private double[,] SigmaGradient(double [,] matrix)
{
double [,] result = new double[matrix.GetLength(0), matrix.GetLength(1)];
for (int i = 0; i < matrix.GetLength(0); i++)
for (int j = 0; j < matrix.GetLength(1); j++)
{
double sigmoid = 1 / (1 + Math.Exp(-(matrix[i, j])));
result[i, j] = sigmoid * (1 - sigmoid);
}
return result;
}
#endregion
public void Training (double [,] inputs_list,double [,] target_list, double lr, int epoch)
{
LearningRate = lr;
for (int e = 0; e < epoch; e++)
{
double[,] hidden_inputs = Dot(wih, inputs_list);
double[,] hidden_outputs = Sigma(hidden_inputs); //
double[,] final_inputs = Dot(who, hidden_outputs);
double[,] final_outputs = Sigma(final_inputs); //
double[,] outputs_errors = Difference(target_list, final_outputs);
double[,] outputGrad = SigmaGradient(outputs_errors);
double[,] outputDelta = Multiplacation(outputs_errors, outputGrad);
who = Add(who, Transpose(Multiplacation(LearningRate, Dot(hidden_outputs, outputDelta)))); //Update weights between hidden layer and output layer
double[,] hidden_errors = Dot(outputDelta, who); // Update weights between input layer and hidden layer
double[,] hiddenGrad = SigmaGradient(hidden_outputs);
double[,] hiddenDelta = Multiplacation(hidden_errors, hiddenGrad);
wih = Add(wih, Transpose(Multiplacation(LearningRate, Dot(inputs_list, hiddenDelta))));
}
}
static void Main(string[] args)
{
double[,] inputData = new double[4,2]; //[][] 4,2
double [,] targetData = new double[2,2]; //2,2
#region fill
inputData[0, 0] = 0.5;
inputData[0, 1] = 0;
inputData[1, 0] = 1;
inputData [1, 1] = 0.6;
inputData[2, 0] = 0;
inputData[2, 1] = 1;
inputData[3, 0] = 0.4;
inputData[3, 1] = 1;
targetData [0, 0] = 0.9;
targetData[0, 1] = 1;
targetData[1, 0] = 0;
targetData[1, 1] = 1;
#endregion
NeuralNetwork network = new NeuralNetwork(4, 3, 2);
network.Training(inputData, targetData, 0.07, 2000); //0.2 100
network.Predict(inputData);
}