Beispiel #1
0
        /// <summary>
        /// 卷积,外层是乘积法则,内层是卷积
        /// </summary>
        /// <param name="core">卷积核平面</param>
        /// <param name="mode">卷积模式</param>
        /// <returns></returns>
        public Tensor Convolve(Tensor core, ConvolutionMode mode)
        {
            if (this.DimensionY != core.DimensionX)
            {
                throw new Exception("进行卷积的两个向量外层维度必须符合矩阵乘法规律");
            }
            Tensor newTensor = TensorBuilder.Empty(this.DimensionX, core.DimensionY);
            //创建一个与后续卷积结果大小相等的0矩阵
            Matrix <double> temp = this[0, 0].Convolve(core[0, 0], mode).Map(r => 0.0);

            for (int i = 0; i <= newTensor.DimensionX - 1; i++)
            {
                for (int j = 0; j <= newTensor.DimensionY - 1; j++)
                {
                    for (int k = 0; k <= this.DimensionY - 1; k++)
                    {
                        temp = temp + this[i, k].Convolve(core[k, j], mode);
                    }
                    newTensor[i, j] = temp;
                    temp            = temp.Map(r => 0.0);
                }
            }
            newTensor.OuterAct(r => r.CoerceZero(1e-15));
            return(newTensor);
        }
Beispiel #2
0
 public static Tensor operator -(Tensor leftSide, Tensor rightSide)
 {
     if ((rightSide.DimensionX != 1 || rightSide.DimensionY != 1) &&
         (leftSide.DimensionX != rightSide.DimensionX || leftSide.DimensionY != rightSide.DimensionY))
     {
         throw new Exception($"张量外层维度错误,左侧为{leftSide.DimensionX}*{leftSide.DimensionY},右侧为{rightSide.DimensionX}*{rightSide.DimensionY}");
     }
     if (rightSide.DimensionX == 1 && rightSide.DimensionY == 1)
     {
         Tensor newTensor = TensorBuilder.Empty(leftSide.DimensionX, leftSide.DimensionY);
         for (int i = 0; i <= newTensor.Storage.Length - 1; i++)
         {
             newTensor.Storage[i] = leftSide.Storage[i] - rightSide.Storage[0];
         }
         newTensor.OuterAct(r => r.CoerceZero(1e-15));
         return(newTensor);
     }
     else
     {
         Tensor newTensor = TensorBuilder.Empty(leftSide.DimensionX, leftSide.DimensionY);
         for (int i = 0; i <= newTensor.Storage.Length - 1; i++)
         {
             newTensor.Storage[i] = leftSide.Storage[i] - rightSide.Storage[i];
         }
         newTensor.OuterAct(r => r.CoerceZero(1e-15));
         return(newTensor);
     }
 }
Beispiel #3
0
        /// <summary>
        /// 对张量中的每个矩阵按照下标执行操作
        /// </summary>
        /// <param name="f"></param>
        /// <param name="keepName"></param>
        /// <param name="newName"></param>
        /// <returns></returns>
        public Tensor MapIndexed(Func <int, int, double, double> f)
        {
            Tensor newTensor = TensorBuilder.Empty(this.DimensionX, this.DimensionY);

            for (int i = 0; i <= Storage.Length - 1; i++)
            {
                newTensor.Storage[i] = this.Storage[i].MapIndexed(f);
            }
            return(newTensor);
        }
Beispiel #4
0
        public static Tensor operator -(Tensor rightSide)
        {
            Tensor newTensor = TensorBuilder.Empty(rightSide.DimensionX, rightSide.DimensionY);

            for (int i = 0; i <= newTensor.Storage.Length - 1; i++)
            {
                newTensor.Storage[i] = -rightSide.Storage[i];
            }
            newTensor.OuterAct(r => r.CoerceZero(1e-15));
            return(newTensor);
        }
Beispiel #5
0
        public Tensor Stretch()
        {
            Tensor newTensor = TensorBuilder.Empty(1, 1);
            var    temp      = Storage[0].ToRowMajorArray().AsEnumerable();

            for (int i = 1; i <= this.Storage.Length - 1; i++)
            {
                temp = temp.Concat(Storage[i].ToRowMajorArray());
            }
            return(TensorBuilder.FromMatrix(Matrix <double> .Build.DenseOfRowMajor(temp.Count(), 1, temp)));
        }
Beispiel #6
0
        /// <summary>
        /// 将每个矩阵转置并乘以一个矩阵
        /// </summary>
        /// <param name="rightSide"></param>
        /// <returns></returns>
        public Tensor InnerTransposeAndMultiply(Tensor rightSide)
        {
            Tensor newTensor = TensorBuilder.Empty(this.DimensionX, this.DimensionY);

            for (int i = 0; i <= this.Storage.Length - 1; i++)
            {
                newTensor.Storage[i] = this.Storage[i].TransposeThisAndMultiply(rightSide.Storage[i]);
            }
            newTensor.OuterAct(r => r.CoerceZero(1e-15));
            return(newTensor);
        }
Beispiel #7
0
        /// <summary>
        /// 最大池化
        /// </summary>
        /// <param name="poolSize"></param>
        /// <returns>第一个为池化后张量,第二个为掩码表</returns>
        public Tuple <Tensor, Tensor> MaxPool(int poolSize)
        {
            Tensor pooledTensor = TensorBuilder.Empty(DimensionX, DimensionY);
            Tensor maskTensor   = TensorBuilder.Empty(DimensionX, DimensionY);

            for (int i = 0; i <= this.Storage.Length - 1; i++)
            {
                (pooledTensor.Storage[i], maskTensor.Storage[i]) = this.Storage[i].MaxPooling(poolSize);
            }
            return(new Tuple <Tensor, Tensor>(pooledTensor, maskTensor));
        }
Beispiel #8
0
        /// <summary>
        /// 根据下标对张量中的每个矩阵进行整体操作
        /// </summary>
        /// <param name="f"></param>
        /// <param name="keepName"></param>
        /// <param name="newName"></param>
        /// <returns></returns>
        public Tensor OuterMapIndexed(Func <int, int, Matrix <double>, Matrix <double> > f, bool keepName = true, string newName = null)
        {
            Tensor newTensor = TensorBuilder.Empty(this.DimensionX, this.DimensionY);

            for (int i = 0; i <= Storage.Length - 1; i++)
            {
                newTensor.Storage[i] = f(i / DimensionY, i % DimensionY, this.Storage[i]);
            }
            newTensor.OuterAct(r => r.CoerceZero(1e-15));
            return(newTensor);
        }
Beispiel #9
0
        /// <summary>
        /// 对张量中的每个矩阵进行整体操作
        /// </summary>
        /// <param name="f"></param>
        /// <param name="keepName"></param>
        /// <param name="newName"></param>
        /// <returns></returns>
        public Tensor OuterMap(Func <Matrix <double>, Matrix <double> > f)
        {
            Tensor newTensor = TensorBuilder.Empty(this.DimensionX, this.DimensionY);

            for (int i = 0; i <= Storage.Length - 1; i++)
            {
                newTensor.Storage[i] = f(this.Storage[i]);
            }
            newTensor.OuterAct(r => r.CoerceZero(1e-15));
            return(newTensor);
        }
Beispiel #10
0
        /// <summary>
        /// 外层转置
        /// </summary>
        /// <returns></returns>
        public Tensor OuterTranspose()
        {
            var newTensor = TensorBuilder.Empty(this.DimensionY, this.DimensionX);

            for (int i = 0; i <= DimensionX - 1; i++)
            {
                for (int j = 0; j <= DimensionY - 1; j++)
                {
                    newTensor[j, i] = this[i, j];
                }
            }
            return(newTensor);
        }
        /// <summary>
        /// 对张量中的每个矩阵按照下标执行操作
        /// </summary>
        /// <param name="f"></param>
        /// <param name="keepName"></param>
        /// <param name="newName"></param>
        /// <returns></returns>
        public Tensor MapIndexed(Func <int, int, double, double> f)
        {
            Tensor newTensor = TensorBuilder.Empty(this.DimensionX, this.DimensionY);

            for (int i = 0; i <= DimensionX - 1; i++)
            {
                for (int j = 0; j <= DimensionY - 1; j++)
                {
                    newTensor[i, j] = Storage[i, j].MapIndexed(f);
                }
            }
            return(newTensor);
        }
        /// <summary>
        /// 对张量中的每个矩阵的每个元素执行一个操作
        /// </summary>
        /// <param name="f"></param>
        /// <returns>新的张量</returns>
        public Tensor Map(Func <double, double> f, bool keepName = true, string newName = null)
        {
            Tensor newTensor = TensorBuilder.Empty(this.DimensionX, this.DimensionY, keepName ? this.Name : newName);

            for (int i = 0; i <= DimensionX - 1; i++)
            {
                for (int j = 0; j <= DimensionY - 1; j++)
                {
                    newTensor[i, j] = Storage[i, j].Map(f);
                }
            }
            return(newTensor);
        }
Beispiel #13
0
 /// <summary>
 /// 外层点积,内层矩阵乘法
 /// </summary>
 /// <param name="leftSide"></param>
 /// <param name="rightSide"></param>
 /// <returns></returns>
 public static Tensor operator *(Tensor leftSide, Tensor rightSide)
 {
     if (leftSide.DimensionX == rightSide.DimensionX && leftSide.DimensionY == rightSide.DimensionY)
     {
         Tensor newTensor = TensorBuilder.Empty(leftSide.DimensionX, leftSide.DimensionY);
         for (int i = 0; i <= newTensor.Storage.Length - 1; i++)
         {
             newTensor.Storage[i] = leftSide.Storage[i] * rightSide.Storage[i];
         }
         newTensor.OuterAct(r => r.CoerceZero(1e-15));
         return(newTensor);
     }
     else
     {
         throw new Exception("维度不符合");
     }
 }
Beispiel #14
0
 /// <summary>
 /// 内外部同时点除
 /// </summary>
 /// <param name="rightSide"></param>
 /// <returns></returns>
 public Tensor PointDivide(Tensor rightSide)
 {
     if (this.DimensionX == rightSide.DimensionX && this.DimensionY == rightSide.DimensionY)
     {
         Tensor newTensor = TensorBuilder.Empty(this.DimensionX, this.DimensionY);
         for (int i = 0; i <= this.Storage.Length - 1; i++)
         {
             newTensor.Storage[i] = this.Storage[i].PointwiseDivide(rightSide.Storage[i]);
         }
         newTensor.OuterAct(r => r.CoerceZero(1e-15));
         return(newTensor);
     }
     else
     {
         throw new Exception("张量维度不匹配");
     }
 }
Beispiel #15
0
        public Tensor Fold(int x, int y, int p, int q)
        {
            Tensor newTensor = TensorBuilder.Empty(x, y);
            var    temp      = this.Storage[0].ToRowMajorArray();

            if (this.Storage.Length == 1 && Storage[0].RowCount * Storage[0].ColumnCount == x * y * p * q)
            {
                for (int i = 0; i <= x * y - 1; i++)
                {
                    newTensor.Storage[i] = Matrix <double> .Build.DenseOfRowMajor(p, q, temp.AsSpan().Slice(i *p *q, p *q).ToArray());
                }
            }
            else
            {
                throw new Exception("要折叠的张量必须是1*1");
            }
            return(newTensor);
        }