Ejemplo n.º 1
0
        /// <summary>
        /// 创建一个二维的单位矩阵
        /// </summary>
        /// <param name="width">矩阵的宽度和高度</param>
        /// <returns></returns>
        public static TensorOld I(int width)
        {
            var result = new TensorOld(width, width);

            for (int i = 0; i < width; i++)
            {
                result.SetValueFast(1, i, i);
            }
            return(result);
        }
Ejemplo n.º 2
0
 private static bool RowEqual(TensorOld t1, TensorOld t2, int start, int len)
 {
     for (int i = 0; i < len; i++)
     {
         if (t1.GetRawValues()[start + i] != t2.GetRawValues()[start + i])
         {
             return(false);
         }
     }
     return(true);
 }
Ejemplo n.º 3
0
        /// <summary>
        /// 当前Tensor和t的点积,结果保存在当前Tensor,要求两个Tensor结构一致
        /// </summary>
        /// <param name="t">乘上的Tensor</param>
        /// <returns>当前Tensor</returns>
        public TensorOld MultipleElementWise(TensorOld t)
        {
            if (t.ElementCount == 1)
            {
                return(Multiple(t.GetValue()));
            }

            CheckShape(shape, t.shape);

            MultipleElementWise(this, t, this);
            return(this);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 把t加到当前Tensor,t和当前Tensor必须要有相同的结构
        /// </summary>
        /// <param name="t">要加的Tensor</param>
        /// <returns>当前Tensor</returns>
        public TensorOld Add(TensorOld t)
        {
            if (t.ElementCount == 1)
            {
                return(Add(t.GetValue()));
            }

            CheckShape(shape, t.shape);

            Add(this, t, this);
            return(this);
        }
Ejemplo n.º 5
0
        public static void CheckMultipleShape(TensorOld a, TensorOld b)
        {
            if (a.Rank != 2 || b.Rank != 2)
            {
                throw new NotImplementedException("only suport multiple between scalar, vector and matrix!");
            }

            if (a.shape[1] != b.shape[0])
            {
                throw new TensorShapeException($"can't multiple matrix between {a.shape.ToString()} and {b.shape.ToString()}");
            }
        }
Ejemplo n.º 6
0
 public TensorOld Apply(TensorOld a, Func <double, double, double> function)
 {
     Parallel.ForEach(Partitioner.Create(0, values.Length),
                      arg =>
     {
         for (long i = arg.Item1; i < arg.Item2; i++)
         {
             values[i] = function(values[i], a.values[i]);
         }
     });
     return(this);
 }
Ejemplo n.º 7
0
        /// <summary>
        /// 把当前Tensor转置,转置后返回的是一个新的Tensor
        /// </summary>
        /// <returns>转置后的Tensor</returns>
        public TensorOld Transpose()
        {
            var result = new TensorOld(shape.Reverse().ToArray());

            for (int i = 0; i < ElementCount; i++)
            {
                var index      = GetIndex(i);
                var transIndex = index.Reverse().ToArray();
                result[transIndex] = values[i];
            }
            return(result);
        }
Ejemplo n.º 8
0
        public void StartTrain(TensorOld trainX, TensorOld trainY, TensorOld testX, TensorOld testY)
        {
            Console.WriteLine("Preparing data...");
            SetTrainingData(trainX, trainY, testX, testY);
            Console.WriteLine("Complete!");

            Training     = true;
            epochCounter = 0;
            batchCounter = 1;
            startTime    = DateTime.Now;
            var lastSave = false;

            while (Training && epochCounter < Epoch)
            {
                Console.WriteLine($"\n==================== Epoch {epochCounter + 1} ====================\n");
                var epochStart = DateTime.Now;
                TrainEpoch();
                ShowTime(epochStart);

                var trainYHat = Model.Predict(TrainX);
                LastTrainLoss     = Model.GetLoss(TrainY, trainYHat);
                LastTrainAccuracy = Model.GetAccuracy(TrainY, trainYHat);
                ShowTrainLossAll();

                //test the test data when one Epoch complete
                if (TestX != null && TestY != null)
                {
                    var testYHat = Model.Predict(TestX);
                    LastTestLoss     = Model.GetLoss(TestY, testYHat);
                    LastTestAccuracy = Model.GetAccuracy(TestY, testYHat);
                    ShowTestLoss();
                }

                if (SaveTrainerEpochs > 0 && epochCounter % SaveTrainerEpochs == 0)
                {
                    SaveTrainer();
                    if (Epoch - epochCounter == 1)
                    {
                        lastSave = true;
                    }
                }

                epochCounter++;
            }

            if (SaveTrainerEpochs > 0 && !lastSave)
            {
                SaveTrainer();
            }

            ShowCompelteInfo();
        }
Ejemplo n.º 9
0
        public List <string> Predict(TensorOld X)
        {
            X             = Normalize(X);
            LastRawResult = Model.Predict(X);

            LastCodecResult = Utilities.ProbabilityToCode(LastRawResult);

            if (LabelCodec != null)
            {
                return(LabelCodec.Decode(LastCodecResult));
            }
            return(LastRawResult.GetRawValues().Select(a => a.ToString()).ToList());
        }
Ejemplo n.º 10
0
        public static double ComputeAccuracy(TensorOld y, TensorOld yHat)
        {
            var count = y.shape[0];
            var eq    = 0d;

            for (int i = 0; i < count; i++)
            {
                if (RowEqual(y, yHat, i * y.shape[1], y.shape[1]))
                {
                    eq++;
                }
            }
            return(eq / count);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// 训练前的准备工作,检查并确定所需Tensor的结构并分配好内存
        /// </summary>
        /// <param name="y">样本标签</param>
        /// <param name="yHat">输出标签</param>
        public override void PrepareTrain(TensorOld y, TensorOld yHat)
        {
            TensorOld.CheckShape(y, yHat);
            if (y.Rank != 2)
            {
                throw new TensorShapeException("y and yHat must Rank=2");
            }

            ForwardOutput  = new TensorOld(y.shape[0]);
            BackwardOutput = yHat.GetSameShape();
            yBuff          = new double[y.shape[1]];
            yHatBuff       = new double[y.shape[1]];
            derBuff        = new double[y.shape[1]];
            sampleNumber   = y.Shape[0];
        }
Ejemplo n.º 12
0
        private void ComputeCrossEntropy(TensorOld y, TensorOld yHat)
        {
            var foreoutData = ForwardOutput.GetRawValues();

            for (int i = 0; i < sampleNumber; i++)
            {
                //取出一个样本及其对应的Label
                y.GetByDim1(i, yBuff);
                yHat.GetByDim1(i, yHatBuff);
                //计算交叉熵
                foreoutData[i] = Functions.CrossEntropy(yBuff, yHatBuff);
            }

            Array.Copy(y.values, 0, BackwardOutput.values, 0, y.ElementCount);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// a和b对应位置元素执行function操作,结果写入result对应位置,要求a,b,result结构一致
        /// 该方法不做结构一致性检查,必要时在调用之前检查。
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="result"></param>
        /// <param name="function"></param>
        public static void Apply(TensorOld a, TensorOld b, TensorOld result, Func <double, double, double> function)
        {
            //这个方法中不进行Tensor结构一致性的检查
            //所有的Tensor结构的问题都放到Prepare过程中
            //或者必要的时候在调用这个函数之前执行Tensor结构一致性的检查

            Parallel.ForEach(Partitioner.Create(0, result.values.Length),
                             arg =>
            {
                for (long i = arg.Item1; i < arg.Item2; i++)
                {
                    result.values[i] = function(a.values[i], b.values[i]);
                }
            });
        }
Ejemplo n.º 14
0
        /// <summary>
        /// 两个Tensor的点积,结果返回为新的Tensor,要求两个Tensor结构一致
        /// </summary>
        /// <param name="a">Tensor1</param>
        /// <param name="b">Tensor2</param>
        /// <returns>包含结果的新的Tensor</returns>
        public static TensorOld MultipleElementWise(TensorOld a, TensorOld b)
        {
            if (a.ElementCount == 1)
            {
                return(Multiple(b, a.GetValue()));
            }
            if (b.ElementCount == 1)
            {
                return(Multiple(a, b.GetValue()));
            }

            var result = a.GetSameShape();

            MultipleElementWise(a, b, result);
            return(result);
        }
Ejemplo n.º 15
0
        public static bool CheckShapeBool(TensorOld t1, TensorOld t2)
        {
            if (t1.shape.Length != t2.shape.Length)
            {
                return(false);
            }

            for (int i = 0; i < t1.shape.Length; i++)
            {
                if (t1.shape[i] != t2.shape[i])
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 16
0
        public override double  GetLoss(TensorOld y, TensorOld yHat)
        {
            var outData = ForwardOutput.GetRawValues();

            var result = 0d;

            for (int i = 0; i < y.shape[0]; i++)
            {
                //取出一个样本及其对应的Label
                y.GetByDim1(i, yBuff);
                yHat.GetByDim1(i, yHatBuff);
                //计算交叉熵
                result += Functions.CrossEntropy(yBuff, yHatBuff);
            }

            return(result / sampleNumber);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Tensor和Tensor对应元素相加,结果返回为新的Tensor,要求两个Tensor结构相同
        /// </summary>
        /// <param name="a">Tensor</param>
        /// <param name="b">Tensor</param>
        /// <returns>相加后的结果</returns>
        public static TensorOld Add(TensorOld a, TensorOld b)
        {
            if (a.ElementCount == 1)
            {
                return(Add(b, a.GetValue()));
            }
            if (b.ElementCount == 1)
            {
                return(Add(a, b.GetValue()));
            }

            CheckShape(a, b);
            var result = a.GetSameShape();

            Add(a, b, result);
            return(result);
        }
Ejemplo n.º 18
0
        private void SetTrainingData(TensorOld trainX, TensorOld trainY, TensorOld testX, TensorOld testY)
        {
            if (Normalizer != null)
            {
                TrainX = Normalizer.Normalize(trainX);
                if (testX != null)
                {
                    TestX = Normalizer.Normalize(testX);
                }
            }
            else
            {
                TrainX = trainX;
                TestX  = testX;
            }
            if (LabelCodec != null)
            {
                TrainY = LabelCodec.Encode(trainY.GetRawValues());
                if (testY != null)
                {
                    TestY = LabelCodec.Encode(testY.GetRawValues());
                }
            }
            else
            {
                TrainY = trainY;
                TestY  = testY;
            }

            var shape = TrainX.Shape;

            shape[0] = BatchSize;
            xBuff    = new TensorOld(shape);
            yBuff    = new TensorOld(BatchSize, TrainY.shape[1]);

            sampleCount = TrainX.shape[0];
            xWidth      = TrainX.ElementCount / TrainX.shape[0];
            yWidth      = TrainY.ElementCount / TrainY.shape[0];

            batchPerEpoch = trainX.shape[0] / BatchSize;
            if (trainX.shape[0] % BatchSize != 0)
            {
                batchPerEpoch++;
            }
        }
Ejemplo n.º 19
0
        private void ComputeCrossEntropy(TensorOld y, TensorOld yHat)
        {
            var forwardoutData  = ForwardOutput.GetRawValues();
            var backwardoutData = BackwardOutput.GetRawValues();

            for (int i = 0; i < sampleNumber; i++)
            {
                //取出一个样本及其对应的Label
                y.GetByDim1(i, yBuff);
                yHat.GetByDim1(i, yHatBuff);
                //计算交叉熵
                forwardoutData[i] = Functions.CrossEntropy(yBuff, yHatBuff);

                //计算损失函数关于输入的导数
                Derivatives.CrossEntropy(yBuff, yHatBuff, derBuff);
                Array.Copy(derBuff, 0, backwardoutData, i * derBuff.Length, derBuff.Length);
            }
        }
Ejemplo n.º 20
0
        public static void Multiple(TensorOld a, TensorOld b, TensorOld result)
        {
            var rows  = a.shape[0];
            var cols  = b.shape[1];
            var bStep = a.shape[1];

            Parallel.For(0, rows, i =>
            {
                var aStart      = a.GetRawOffset(i, 0);
                var resultStart = result.GetRawOffset(i, 0);
                Parallel.For(0, cols, j =>
                {
                    var sum    = 0d;
                    var bStart = b.GetRawOffset(0, j);
                    for (int k = 0; k < bStep; k++)
                    {
                        sum += a.values[aStart + k] * b.values[k * cols + j];
                    }
                    //result.values[i * cols + j] = sum;
                    result.SetValueFast(sum, i, j);
                });
            });
        }
Ejemplo n.º 21
0
 /// <summary>
 /// 计算Loss和Loss对yHat的导数(梯度)
 /// </summary>
 /// <param name="y"></param>
 /// <param name="yHat"></param>
 public override void Compute(TensorOld y, TensorOld yHat)
 {
     LastY    = y;
     LastYHat = yHat;
     ComputeCrossEntropy(y, yHat);
 }
Ejemplo n.º 22
0
        /// <summary>
        /// a和b相加结果写入result参数
        /// 必要的时候在调用这个方法前进行Tensor结构一致性检查
        /// </summary>
        /// <param name="a">加数1</param>
        /// <param name="b">加数2</param>
        /// <param name="result">结果</param>
        public static void Add(TensorOld a, TensorOld b, TensorOld result)
        {
            //放弃Tensor结构的检查

            Apply(a, b, result, (x, y) => x + y);
        }
Ejemplo n.º 23
0
 public List <double> Predict(TensorOld X)
 {
     X             = Normalize(X);
     LastRawResult = Model.Predict(X);
     return(LastRawResult.GetRawValues().ToList());
 }
Ejemplo n.º 24
0
 public static void Add(TensorOld t, double d, TensorOld result)
 {
     Apply(t, result, a => a + d);
 }
Ejemplo n.º 25
0
 /// <summary>
 /// 两个Tensor对应元素相除,结果保存在当前Tensor
 /// 还不知道有什么用 ;)
 /// </summary>
 /// <param name="t">除数</param>
 /// <returns>当前Tensor</returns>
 public TensorOld DivideElementWise(TensorOld t)
 {
     DivideElementWise(this, t, this);
     return(this);
 }
Ejemplo n.º 26
0
 /// <summary>
 /// a每个元素除以b对应元素,结果写入result
 /// 必要的时候在调用这个方法前进行Tensor结构一致性检查
 /// </summary>
 /// <param name="a">被除数</param>
 /// <param name="b">除数</param>
 /// <param name="result">结果</param>
 public static void DivideElementWise(TensorOld a, TensorOld b, TensorOld result)
 {
     Apply(a, b, result, (x, y) => x / y);
 }
Ejemplo n.º 27
0
 public static void MeanSquareError(TensorOld y, TensorOld yHat, TensorOld result)
 {
     //因为存在learning rate,所以梯度前面的系数不那么重要,但最好和损失函数一致,
     TensorOld.Minus(yHat, y, result);
     result.Multiple(2d / y.ElementCount);
 }
Ejemplo n.º 28
0
 /// <summary>
 /// a和b的点积,结果写入result
 /// 必要的时候在调用这个方法前进行Tensor结构一致性检查
 /// </summary>
 /// <param name="a"></param>
 /// <param name="b"></param>
 /// <param name="result"></param>
 public static void MultipleElementWise(TensorOld a, TensorOld b, TensorOld result)
 {
     Apply(a, b, result, (x, y) => x * y);
 }
Ejemplo n.º 29
0
 /// <summary>
 /// Tensor每个元素乘上d,结果写入result
 /// </summary>
 /// <param name="t">Tensor乘数</param>
 /// <param name="d">标量乘数</param>
 /// <param name="result">结果</param>
 public static void Multiple(TensorOld t, double d, TensorOld result)
 {
     Apply(t, result, a => a * d);
 }
Ejemplo n.º 30
0
        public override double GetAccuracy(TensorOld y, TensorOld yHat)
        {
            var code = Utilities.ProbabilityToCode(yHat);

            return(ComputeAccuracy(y, code));
        }