C# Math.Net矩阵维度必须匹配。

3

我尝试将这个Python神经网络代码翻译为C#。我正在使用Math.Net Numerics处理矩阵,这是我目前在C#中编写的代码:

https://gist.github.com/miloharper/c5db6590f26d99ab2670#file-main-py
using System;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra.Double;

namespace NeuralNetwork
{
    class Program
    {
        static void Main(string[] args)
        {
            NeuralNetwork NN = new NeuralNetwork();

            Console.WriteLine("Random starting synaptic weights: ");
            Console.WriteLine(NN.SynapticWeights);

            Matrix<double> TrainingSetInput = DenseMatrix.OfArray(new double[,] { { 0, 0, 1 }, { 1, 1, 1 }, { 1, 0, 1 }, { 0, 1, 1 } });
            Matrix<double> TrainingSetOutput = DenseMatrix.OfArray(new double[,] { { 0, 1, 1, 0 } }).Transpose();

            NN.Train(TrainingSetInput, TrainingSetOutput, 10000);

            Console.WriteLine("New synaptic weights after training: ");
            Console.WriteLine(NN.SynapticWeights);

            Console.WriteLine("Considering new situation {1, 0, 0} -> ?: ");
            Console.WriteLine(NN.Think(DenseMatrix.OfArray(new double[,] { { 1, 0, 0 } })));

            Console.ReadLine();
        }
    }

    class NeuralNetwork
    {
        private Matrix<double> _SynapticWeights;

        public NeuralNetwork()
        {
            _SynapticWeights = 2 * Matrix<double>.Build.Random(3, 1) - 1;
        }

        private Matrix<double> Sigmoid(Matrix<double> Input)
        {
            return 1 / (1 + Matrix<double>.Exp(-Input));
        }

        private Matrix<double> SigmoidDerivative(Matrix<double> Input)
        {
            return Input * (1 - Input); //NEW Exception here
        }

        public Matrix<double> Think(Matrix<double> Input)
        {
            return Sigmoid((Input * _SynapticWeights)); //Exception here (Solved)
        }

        public void Train(Matrix<double> TrainingInput, Matrix<double> TrainingOutput, int TrainingIterations)
        {
            for (int Index = 0; Index < TrainingIterations; Index++)
            {
                Matrix<double> Output = Think(TrainingInput);
                Matrix<double> Error = TrainingOutput - Output;
                Matrix<double> Adjustment = Matrix<double>.op_DotMultiply(TrainingInput.Transpose(), Error * SigmoidDerivative(Output));

                _SynapticWeights += Adjustment;
            }
        }

        public Matrix<double> SynapticWeights { get { return _SynapticWeights; } set { _SynapticWeights = value; } }
    }
}

当我执行它时,它在第53行显示了一个异常(代码中该行有注释)。它说:
“矩阵维度必须一致:op1为4x3,op2为3x1”
我是复制错了还是Math.Net库出了问题?
提前感谢 :D

虽然Python代码实际上写的是“点”,但它明显意味着简单的矩阵*向量乘法,而不是点积。因此,请尝试这个(我找到的Matrix类定义了一个operator *)。 - tevemadar
我尝试了*运算符,但它仍然不起作用。 - prenone
另一个可能的问题是行和列的不同解释。虽然这将破坏数学背后的内容,但您可以快速测试交换参数顺序是否突然“修复”了点或*。如果有效,则一切都相对于原始Python代码的期望进行了转置。 - tevemadar
好的,我尝试交换行和列,但是它没有做任何事情。一个矩阵是3x1(SynapticWeights),另一个是4x3(TrainingSetInput)。显然我不知道如何正确地将它们进行点乘。 - prenone
1
嗯,我真的很好奇昨天你尝试了什么,如果你现在只是按照下面的讨论尝试return Sigmoid(Input * _SynapticsWeights); - tevemadar
抱歉,我现在不在家,无法查看代码 - prenone
1个回答

0
据我所见,问题不在库代码中。您正在尝试使用op_DotMultiply函数(第53行)执行逐元素矩阵乘法。在这种情况下,从错误消息中可以明显看出,由于大小差异,矩阵无法相乘:第一个矩阵为4x3,第二个矩阵为3x1。
我建议查看这些矩阵的大小:TrainingSetInput_SynapticWeights(查看Train函数,在其中调用了带有错误大小矩阵的Think)。检查它们是否生成正确。并且考虑一下您是否真正需要逐元素矩阵乘法或通常的乘法。 如果您需要更多关于矩阵乘法的信息,可以使用以下链接:

Element-wise: https://en.wikipedia.org/wiki/Hadamard_product_(matrices)

Usual: https://en.wikipedia.org/wiki/Matrix_multiplication


矩阵也以不同的大小正确生成,我认为我无法做太多事情。 - prenone
你正在生成一个4x3的“TrainingSetInput”矩阵,并将其传递到名为“Train”的函数中,在其中一个“for”循环中,你调用了“Think”函数,并再次将“TrainingSetInput”矩阵传递给它。在这个函数内部,你的4x3矩阵与3x1矩阵“_SynapticWeights”进行点乘。不幸的是,这在数学上是不可能的。对于点乘,你确实需要具有相同大小的矩阵。如果我错过了一些显而易见的东西,我很抱歉,我可能是错的。 - NamiraJV
在numpy中,dot函数执行的是通常的矩阵乘法,而不是逐元素操作。而Math.Net中的类似函数是*运算符,而不是op_dotMultiply。因此,在你的“Think”函数中,请尝试使用以下代码替换:return Sigmoid(Input * _SynapticsWeights); - NamiraJV
谢谢,我回到家后会尝试一下。 - prenone
好的,我再次尝试了一下(正如tevemadar指出的那样),现在它显示了同样的异常,但是文本不同:“矩阵维度必须一致:op1为4x1,op2为4x1”,这是什么意思? - prenone
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接