/// <summary>
 /// 垂直方向连接张量,加在下方,外层列数必须一致
 /// </summary>
 /// <param name="down"></param>
 /// <param name="name"></param>
 /// <returns></returns>
 public Tensor VerticalConcat(Tensor down, string name = null)
 {
     if (this.DimensionY != down.DimensionY)
     {
         throw new Exception("要连接的张量外层维度不一致");
     }
     //Matrix<double>[,] newStorage = new Matrix<double>[this.DimensionX + down.DimensionX, this.DimensionY];
     //for (int i = 0; i <= this.DimensionX - 1; i++)
     //{
     //    for (int j = 0; j <= this.DimensionY - 1; j++)
     //    {
     //        newStorage[i, j] = this.Storage[i, j];
     //    }
     //}
     //for (int i = 0; i <= down.DimensionX - 1; i++)
     //{
     //    for (int j = 0; j <= this.DimensionY - 1; j++)
     //    {
     //        newStorage[i + this.DimensionX, j] = down.Storage[i, j];
     //    }
     //}
     return(TensorBuilder.FromRowMajorIEnumerable(DimensionX + down.DimensionX, DimensionY, Storage.ToRowArray().Concat(down.Storage.ToRowArray())));
     //return new Tensor(newStorage, name);
     //var newStorage = this.Storage.ToRowArray().Concat(down.Storage.ToRowArray());
     //return TensorBuilder.FromRowMajorIEnumerable(this.DimensionX + down.DimensionX, this.DimensionY, newStorage);
 }
Esempio n. 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);
     }
 }
Esempio n. 3
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);
        }
Esempio n. 4
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);
        }
Esempio n. 5
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));
        }
Esempio n. 6
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);
        }
Esempio n. 7
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);
        }
Esempio n. 8
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)));
        }
Esempio n. 9
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);
        }
Esempio n. 10
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);
        }
        /// <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);
        }
Esempio n. 13
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>
        /// 外层行切片,包括下标stop处的数据
        /// </summary>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <param name="step"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public Tensor RowSlice(int start, int stop, int step, string name = null)
        {
            List <Matrix <double> > list = new List <Matrix <double> >();
            int x = 0;//记录新张量的外层行数

            for (int i = start; i <= stop; i = i + step)
            {
                for (int j = 0; j <= DimensionY - 1; j++)
                {
                    list.Add(Storage[i, j]);
                }
                x++;
            }
            return(TensorBuilder.FromRowMajorIEnumerable(x, DimensionY, list, name));
        }
        /// <summary>
        /// 外层列切片,包括下标stop处的数据
        /// </summary>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <param name="step"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public Tensor ColumnSlice(int start, int stop, int step, string name = null)
        {
            List <Matrix <double> > list = new List <Matrix <double> >();
            int y = 0;//记录新张量的外层列数

            for (int j = start; j <= stop; j = j + step)
            {
                for (int i = 0; i <= DimensionX - 1; i++)
                {
                    list.Add(Storage[i, j]);
                }
                y++;
            }
            return(TensorBuilder.FromColumnMajorIEnumerable(y, DimensionX, list, name));
        }
Esempio n. 16
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("维度不符合");
     }
 }
Esempio n. 17
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("张量维度不匹配");
     }
 }
Esempio n. 18
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);
        }
 /// <summary>
 /// 水平方向连接张量,加在右方,外层行数必须一致
 /// </summary>
 /// <param name="right"></param>
 /// <param name="name"></param>
 /// <returns></returns>
 public Tensor HorizontalConcat(Tensor right, string name = null)
 {
     if (this.DimensionX != right.DimensionX)
     {
         throw new Exception("要连接的张量外层维度不一致");
     }
     //Matrix<double>[,] newStorage = new Matrix<double>[this.DimensionX , this.DimensionY+right.DimensionY];
     //for (int i = 0; i <= this.DimensionX - 1; i++)
     //{
     //    for (int j = 0; j <= this.DimensionY - 1; j++)
     //    {
     //        newStorage[i, j] = this.Storage[i, j];
     //    }
     //}
     //for (int i = 0; i <= this.DimensionX - 1; i++)
     //{
     //    for (int j = 0; j <= right.DimensionY- 1; j++)
     //    {
     //        newStorage[i , j+this.DimensionY] = right.Storage[i, j];
     //    }
     //}
     //return new Tensor(newStorage, name);
     return(TensorBuilder.FromRowMajorIEnumerable(DimensionX, DimensionY + right.DimensionY, Storage.ToRowArray().Concat(right.Storage.ToColumnArray())));
 }