From dc5dc748552aca8a5317d4c14c70b96ce6c1153d Mon Sep 17 00:00:00 2001 From: yansh Date: Mon, 26 Sep 2016 13:21:27 +0800 Subject: [PATCH 1/4] add tensor document --- doc/tensor.md | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 doc/tensor.md diff --git a/doc/tensor.md b/doc/tensor.md new file mode 100644 index 00000000000..d2184dbeb3c --- /dev/null +++ b/doc/tensor.md @@ -0,0 +1,209 @@ + +# Tensor # + +__Tensors of different types__ + +Actually, several types of `Tensor` exists: + +```scala +DenseTensor +SparseTensor +``` + +The data type of Tensor are implemented _only_ for `Float` and `Double`. + + +## Tensor constructors ## + +Tensor constructors, create new Tensor object, optionally, allocating new memory. By default the elements of a newly allocated memory are +not initialized, therefore, might contain arbitrary numbers. Here are several ways to construct a new `Tensor`. + +Please be attention to that the data type of Tensor are implemented _only_ for `Float` and `Double`. So the following T can only be Double or Float + + +### Tensor[T] () ### + +Returns an empty tensor. + +```scala +import com.intel.analytics.sparkdl.tensor +var y = Tensor[T]() +``` + + +### Tensor[T] (d1 : Int [,d2 : Int [,d3 : Int [,d4 : Int [,d5 : Int ]]]]]) ### + +Create a tensor up to 5 dimensions. The tensor size will be `d1 x d2 x d3 x d4 x d5`. + + +### Tensor[T] (dims : Int *) ### + + +### Tensor[T] (sizes : Array[Int]) ### + + +### Tensor[T] (storage : Storage[T]) ### + + +### Tensor[T] (storage : Storage[T], storageOffset : Int, size : Array[Int] = null, stride : Array[Int] = null) ### + +Convenience constructor (for the previous constructor) assuming a number of dimensions. + + +### Tensor[T] (tensor : Tensor[T]) ### + +Returns a new tensor which reference the same +[Storage](#storage) than the given `tensor`. The +[size](#Tensor.size), [stride](#Tensor.stride), and +[storage offset](#storageOffset) are the same than the +given tensor. + +The new `Tensor` is now going to "view" the same [storage](storage.md) +as the given `tensor`. As a result, any modification in the elements +of the `Tensor` will have a impact on the elements of the given +`tensor`, and vice-versa. No memory copy! + +```scala +x = Tensor[T](2,5) // DenseTensor of dimension 2x5 +y = Tensor[T](x) // y is same as x +``` + + +### Tensor[T](vector : DenseVector[T]) ### + + +### Tensor(vector : DenseVector) ### + + +### Tensor[T](vector : DenseMatrix[T]) ### + + +### Tensor(vector : DenseMatrix) ### + + +### Tensor[T](indices : Array[Array[Int]], values : Storage[T], shape : Array[Int]) ### + + +### Tensor[T](rowIndices : Array[Int], columns: Array[Int],values : Storage[T], shape : Array[Int]) ### + +## A note on function calls ## + +The rest of this guide will present many functions that can be used to manipulate tensors. + + +### nDimension() : Int ### + +Return the dimension number of the tensor. For empty tensor, its dimension number is 0. + + +### dim() : Int ### + +A shortcut of nDimension(). + + +### size() : Array[Int] ### + +Return the size of tensor. Return an array of which each value represent the size on the dimension(i + 1), i is the index of the corresponding value. It will generate a new array each time you invoke the method. + + +### size(dim : Int) : Int ### + +Return the size of the tensor on the given dimension. + + +### stride() : Array[Int] ### + +Jumps between element on the each dimension in the storage. It will generate a new array each time you invoke the method. + + +### stride(dim : Int) : Int ### + +Jumps between element on the given dimension in the storage. + + +### fill(v : T) : Tensor[T] ### + +Fill the tensor with a given value. It will change the value of the current tensor and return itself. + + +### zero() : Tensor[T] ### + +Fill the tensor with zero. It will change the value of the current tensor and return itself. + + +### randn() : Tensor[T] ### + +Fill the tensor with random value(normal gaussian distribution). It will change the value of the current tensor and return itself. + + +### rand() : Tensor[T] ### + +Fill the tensor with random value(uniform distribution). It will change the value of the current tensor and return itself. + + +### bernoulli(p : Double) : Tensor[T] ### + +Fill with random value(bernoulli distribution). It will change the value of the current tensor and return itself. + + +### transpose(dim1 : Int, dim2 : Int) : Tensor[T] ### + +Create a new tensor which exchanges the given dimensions of the current tensor. + + +### t() : Tensor[T] ### + +Shortcut of transpose(1, 2) for 2D tensor. + + +### valueAt(d1 : Int [,d2 : Int [,d3 : Int [,d4 : Int [,d5 : Int ]]]]) : T ### + +Query the value on a given position. Tensor should not be empty. + + +### apply(index: Int) : Tensor[T] ### + +Query tensor on a given index. Tensor should not be empty. + + +### apply(indexes: Array[Int])) : Tensor[T] ### + +Query the value on a given index. Tensor should not be empty. + + +### apply(t: Table)) : Tensor[T] ### + +Subset the tensor by apply the element of the given table to corresponding dimension of the tensor. The element of the given table can be an Int or another Table. An Int means select on current dimension; A table means narrow on current dimension, the table should has two elements, of which the first is start index and the second is the end index. An empty table is equals to Table(1, size_of_current_dimension) If the table length is less than the tensor dimension, the missing dimension is applied by an empty table + + +### setValue(d1 : Int [,d2 : Int [,d3 : Int [,d4 : Int [,d5 : Int ]]]]): Unit ### + +Write the value on a given position. + + +### update(index: Int, value: T): Unit ### + +For tensor(i) = value. If tensor(i) is another tensor, it will fill the selected subset by the given value. + +### update(index: Int, src: Tensor[T]): Unit ### + +Copy the give tensor value to the select subset of the current tensor by the given index. The subset should has the same size of the given tensor. + +### update(indexes: Array[Int], value: T): Unit ### + +Write the value to the value indexed by the given index array. + +### update(t: Table, value: T): Unit ### + +Fill the select subset of the current tensor with the given value. The element of the given table can be an Int or another Table. An Int means select on current dimension; A tablemeans narrow on current dimension, the table should has two elements, of which the first is start index and the second is the end index. An empty table is equals to Table(1, size_of_current_dimension) If the table length is less than the tensor dimension, the missing dimension is applied by an empty table. + +### update(t: Table, src: Tensor[T]): Unit ### + +Copy the given tensor value to the select subset of the current tensor The element of the given table can be an Int or another Table. An Int means select on current dimension; A table means narrow on current dimension, the table should has two elements, of which the first is start index and the second is the end index. An empty table is equals to Table(1, size_of_current_dimension) If the table length is less than the tensor dimension, the missing dimension is applied by an empty table. + +### update(filter: T => Boolean, value: T): Unit ### + +Update the value meeting the filter criteria with the give value. + + +### isContiguous(): Boolean ### \ No newline at end of file From 98701713e3c2b91e54b41259554a571d233bcc42 Mon Sep 17 00:00:00 2001 From: yansh Date: Sun, 9 Oct 2016 10:18:57 +0800 Subject: [PATCH 2/4] doc --- .../analytics/sparkdl/tensor/Tensor.scala | 15 +++ doc/tensor.md | 115 +++++++++++++++++- 2 files changed, 126 insertions(+), 4 deletions(-) diff --git a/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/Tensor.scala b/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/Tensor.scala index f649d17f9f8..1741f850329 100644 --- a/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/Tensor.scala +++ b/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/Tensor.scala @@ -26,6 +26,10 @@ import org.apache.spark.mllib.linalg.{DenseMatrix, DenseVector, Matrix, Vector} import scala.reflect.ClassTag +/** + * + * @tparam T + */ trait Tensor[T] extends Serializable with TensorMath[T] { /** * Dimension number of the tensor. For empty tensor, its dimension number is 0 @@ -146,6 +150,12 @@ trait Tensor[T] extends Serializable with TensorMath[T] { */ def apply(indexes: Array[Int]): T + /** + * + * @param d1 + * @return + */ + def valueAt(d1: Int): T def valueAt(d1: Int, d2: Int): T @@ -454,6 +464,11 @@ trait Tensor[T] extends Serializable with TensorMath[T] { def expandAs(template: Tensor[T]): Tensor[T] + /** + * + * @param sizes + * @return + */ def expand(sizes: Array[Int]): Tensor[T] /** diff --git a/doc/tensor.md b/doc/tensor.md index d2184dbeb3c..7acd0705407 100644 --- a/doc/tensor.md +++ b/doc/tensor.md @@ -193,17 +193,124 @@ Copy the give tensor value to the select subset of the current tensor by the giv Write the value to the value indexed by the given index array. -### update(t: Table, value: T): Unit ### +### update(t: Table, value: T): Unit ### Fill the select subset of the current tensor with the given value. The element of the given table can be an Int or another Table. An Int means select on current dimension; A tablemeans narrow on current dimension, the table should has two elements, of which the first is start index and the second is the end index. An empty table is equals to Table(1, size_of_current_dimension) If the table length is less than the tensor dimension, the missing dimension is applied by an empty table. -### update(t: Table, src: Tensor[T]): Unit ### +### update(t: Table, src: Tensor[T]): Unit ### Copy the given tensor value to the select subset of the current tensor The element of the given table can be an Int or another Table. An Int means select on current dimension; A table means narrow on current dimension, the table should has two elements, of which the first is start index and the second is the end index. An empty table is equals to Table(1, size_of_current_dimension) If the table length is less than the tensor dimension, the missing dimension is applied by an empty table. -### update(filter: T => Boolean, value: T): Unit ### +### update(filter: T => Boolean, value: T): Unit ### Update the value meeting the filter criteria with the give value. -### isContiguous(): Boolean ### \ No newline at end of file +### isContiguous(): Boolean ### + +Check if the tensor is contiguous on the storage + + +### contiguous(): Tensor[T] ### + +Get a contiguous tensor from current tensor + + +### isSameSizeAs(other: Tensor[_]): Boolean ### + +Check if the size is same with the give tensor + + +### clone(): Tensor[T] ### + +Get a new tensor with same value and different storage + + +### resizeAs(src: Tensor[_]): Tensor[T] ### + +Resize the current tensor to the same size of the given tensor. It will still use the same storage if the storage is sufficient for the new size. + + +### resize(d1 : Int [,d2 : Int [,d3 : Int [,d4 : Int [,d5 : Int ]]]]): Tensor[T] ### + +Resize the current tensor to the give shape + +### resize(sizes: Array[Int], strides: Array[Int] = null): Tensor[T] ### + +Resize the current tensor to the give shape + + +### nElement(): Int ### + +Element number + + +### select(dim: Int, index: Int): Tensor[T] ### + +Remove the dim-th dimension and return the subset part. + + +### storage(): Storage[T] ### + +Get the storage. + + +### storageOffset(): Int ### + +Return tensor offset on the storage, count from 1 + + +### set(other: Tensor[T]): Tensor[T] ### + +The Tensor is now going to "view" the same storage as the given tensor. As the result, any modification in the elements of the Tensor will have an impact on the elements of the given tensor, and vice-versa. This is an efficient method, as there is no memory copy! + +### set(storage: Storage[T], storageOffset: Int = 1, sizes: Array[Int] = null, strides: Array[Int] = null): Tensor[T] ### + +The Tensor is now going to "view" the given storage, starting at position storageOffset (>=1) with the given dimension sizes and the optional given strides. As the result, any modification in the elements of the Storage will have a impact on the elements of the Tensor, and vice-versa. This is an efficient method, as there is no memory copy! +If only storage is provided, the whole storage will be viewed as a 1D Tensor. + + +### narrow(dim: Int, index: Int, size: Int): Tensor[T] ### + +Get a subset of the tensor on dim-th dimension. The offset is given by index, and length is give by size. The important difference with select is that it will not reduce the dimension number. For Instance +tensor = + 1 2 3 + 4 5 6 +tensor.narrow(1, 1, 1) is + [1 2 3] +tensor.narrow(2, 2, 3) is + 2 3 + 5 6 + + +### copy(other: Tensor[T]): Tensor[T] ### + +Copy the value of the given tensor to the current. They should have same size. It will use the old storage + + +### apply1(func: T => T): Tensor[T] ### + +Apply a function to each element of the tensor and modified it value if it return a double. + + +### map(other: Tensor[T], func: (T, T) => T): Tensor[T] ### + +Map value of another tensor to corresponding value of current tensor and apply function on the two value and change the value of the current tensor. The another tensor should has the same size of the current tensor. + + +### squeeze(): Tensor[T] ### + +Removes all singleton dimensions of the tensor + +### squeeze(dim: Int): Tensor[T] ### + +Removes given dimensions of the tensor if it's singleton + + +### view(sizes: Int*): Tensor[T] ### + +Return a new tensor with specified sizes. The input tensor must be contiguous, and the elements number in the given sizes must be equal to the current tensor + +### view(sizes: Array[Int]): Tensor[T] ### + +Return a new tensor with specified sizes. The input tensor must be contiguous, and the elements number in the given sizes must be equal to the current tensor From 8707ef4c123ba22c4cfda98aa43c3c7127a74b22 Mon Sep 17 00:00:00 2001 From: yansh Date: Sun, 9 Oct 2016 16:06:21 +0800 Subject: [PATCH 3/4] add Tensor and TensorMath commits --- .../analytics/sparkdl/tensor/Tensor.scala | 180 +++++++++++++++++- .../analytics/sparkdl/tensor/TensorMath.scala | 131 +++++++++++++ 2 files changed, 306 insertions(+), 5 deletions(-) diff --git a/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/Tensor.scala b/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/Tensor.scala index 1741f850329..bc85c015b73 100644 --- a/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/Tensor.scala +++ b/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/Tensor.scala @@ -27,8 +27,8 @@ import org.apache.spark.mllib.linalg.{DenseMatrix, DenseVector, Matrix, Vector} import scala.reflect.ClassTag /** - * - * @tparam T + * It is the class for handling numeric data. + * @tparam T should be Double or Float */ trait Tensor[T] extends Serializable with TensorMath[T] { /** @@ -151,9 +151,12 @@ trait Tensor[T] extends Serializable with TensorMath[T] { def apply(indexes: Array[Int]): T /** + * Query the value on a given position. The number of parameters + * should be equal to the dimension number of the tensor. + * Tensor should not be empty. * - * @param d1 - * @return + * @param d1,( d2, d3, d4, d5) the given position + * @return the value on a given position */ def valueAt(d1: Int): T @@ -209,6 +212,13 @@ trait Tensor[T] extends Serializable with TensorMath[T] { */ def update(indexes: Array[Int], value: T): Unit + /** + * Write the value on a given position. The number of parameters + * should be equal to the dimension number of the tensor. + * @param d1,( d2, d3, d4, d5) the given position + * @param value the written value + * @return + */ def setValue(d1: Int, value: T): this.type def setValue(d1: Int, d2: Int, value: T): this.type @@ -451,6 +461,14 @@ trait Tensor[T] extends Serializable with TensorMath[T] { def view(sizes: Array[Int]): Tensor[T] + /** + * Returns a tensor which contains all slices of size size + * in the dimension dim. Step between two slices is given by step. + * @param dim + * @param size + * @param step Step between two slices + * @return new tensor + */ def unfold(dim: Int, size: Int, step: Int): Tensor[T] /** @@ -462,11 +480,21 @@ trait Tensor[T] extends Serializable with TensorMath[T] { */ def repeatTensor(sizes: Array[Int]): Tensor[T] + /** + * This is equivalent to this.expand(template.size()) + * + * @param template the given tensor + * @return + */ def expandAs(template: Tensor[T]): Tensor[T] /** + * Expanding a tensor allocates new memory, tensor where singleton dimensions can be expanded + * to multiple ones by setting the stride to 0. Any dimension that has size 1 can be expanded + * to arbitrary value with new memory allocation. Attempting to expand along a dimension that + * does not have size 1 will result in an error. * - * @param sizes + * @param sizes the size that tensor will expend to * @return */ def expand(sizes: Array[Int]): Tensor[T] @@ -476,17 +504,43 @@ trait Tensor[T] extends Serializable with TensorMath[T] { * (a number) or less (in the case of the last Tensor). The sizes of the non-dim dimensions * remain unchanged. Internally, a series of narrows are performed along dimensions dim. * Argument dim defaults to 1. + * + * @param size + * @param dim + * @return */ def split(size: Int, dim: Int = 1): Array[Tensor[T]] + /** + * convert the tensor to BreezeVector, the dimension of the tensor need to be 1. + * @return BrzDenseVector + */ def toBreezeVector(): BrzDenseVector[T] + /** + * convert the tensor to MLlibVector, the dimension of the + * tensor need to be 1, and tensor need to be continuous. + * @return Vector + */ def toMLlibVector(): Vector + /** + * convert the tensor to BreezeMatrix, the dimension of the tensor need to be 2. + * @return BrzDenseMatrix + */ def toBreezeMatrix(): BrzDenseMatrix[T] + /** + * convert the tensor to MLlibMatrix, the dimension of the + * tensor need to be 2, and tensor need to be continuous. + * @return Matrix + */ def toMLlibMatrix(): Matrix + /** + * return the tensor datatype( DoubleType or FloatType) + * @return + */ def getType(): TensorDataType /** @@ -506,9 +560,22 @@ object DoubleType extends TensorDataType object FloatType extends TensorDataType object Tensor { + /** + * Returns an empty tensor. + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag]()( implicit ev: TensorNumeric[T]): Tensor[T] = new DenseTensor[T]() + /** + * Create a tensor up to 5 dimensions. The tensor size will be `d1 x d2 x d3 x d4 x d5`. + * @param d1,(d2, d3, d4, d5) + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag](d1: Int)( implicit ev: TensorNumeric[T]): Tensor[T] = new DenseTensor[T](d1) @@ -524,21 +591,60 @@ object Tensor { def apply[@specialized(Float, Double) T: ClassTag](d1: Int, d2: Int, d3: Int, d4: Int, d5: Int)( implicit ev: TensorNumeric[T]): Tensor[T] = new DenseTensor[T](d1, d2, d3, d4, d5) + /** + * Create a tensor on an given dimensions. The tensor size will be the product of dims + * @param dims + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag](dims: Int*)( implicit ev: TensorNumeric[T]): Tensor[T] = new DenseTensor[T](new ArrayStorage[T](new Array[T](dims.product)), 0, dims.toArray, DenseTensor.size2Stride(dims.toArray), dims.length) + /** + * Create a tensor on an given sizes. The tensor size will be the product of sizes + * @param sizes + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag](sizes: Array[Int])( implicit ev: TensorNumeric[T]): Tensor[T] = new DenseTensor(new ArrayStorage[T](new Array[T](sizes.product)), 0, sizes.clone(), DenseTensor.size2Stride(sizes.clone()), sizes.length) + /** + * Returns a tensor which uses the existing Storage storage. + * + * @param storage the given storage + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag](storage: Storage[T])( implicit ev: TensorNumeric[T]): Tensor[T] = { new DenseTensor(storage.asInstanceOf[Storage[T]]) } + /** + * Returns a tensor which uses the existing Storage storage, starting at + * position storageOffset (>=1). The size of each dimension of the tensor + * is given by the optional Array size. If not given, the size will be computed + * as the length of storage. The jump necessary to go from one element to the + * next one in each dimension is given by the optional Array stride. If not + * given, the stride() will be computed such that the tensor is as contiguous + * as possible in memory. + * + * @param storage + * @param storageOffset + * @param size + * @param stride + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag](storage: Storage[T], storageOffset: Int, size: Array[Int] = null, @@ -547,21 +653,57 @@ object Tensor { new DenseTensor(storage.asInstanceOf[Storage[T]], storageOffset, size, stride) } + /** + * create a tensor with an given tensor. The tensor will have same size + * with the given tensor. + * @param other the given tensor + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag](other: Tensor[T])( implicit ev: TensorNumeric[T]): Tensor[T] = new DenseTensor(other) + /** + * create a tensor with an given breeze vector. The tensor will have same size + * with the given breeze vector. + * @param vector the given breeze vector + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag](vector: BrzDenseVector[T])( implicit ev: TensorNumeric[T]): Tensor[T] = apply(Storage(vector.data), vector.offset + 1, Array(vector.length), Array(vector.stride)) + /** + * create a tensor with an given spark Densevector. The tensor will have same size + * with the given spark Densevector. + * @param vector the given spark Densevector + * @return + */ def apply(vector: DenseVector): Tensor[Double] = apply[Double](Storage(vector.toArray)) + /** + * create a tensor with an given breeze matrix. The tensor will have same size with + * the given breeze matrix. + * @param matrix the given breeze matrix + * @param ev + * @tparam T + * @return + */ def apply[@specialized(Float, Double) T: ClassTag](matrix: BrzDenseMatrix[T])( implicit ev: TensorNumeric[T]): Tensor[T] = apply(Storage(matrix.data), matrix.offset + 1, Array(matrix.rows, matrix.cols), if (matrix.isTranspose) Array(1, matrix.majorStride) else Array(matrix.majorStride, 1)) + /** + * create a tensor with an given spark Densematrix. The tensor will have same size with + * the given spark Densematrix. + * @param matrix + * @return + */ def apply(matrix: DenseMatrix): Tensor[Double] = { val strides = if (matrix.isTransposed) { Array(matrix.numCols, 1) @@ -571,13 +713,41 @@ object Tensor { apply(Storage(matrix.toArray), 1, Array(matrix.numRows, matrix.numCols), strides) } + /** + * This is equivalent to DenseTensor.randperm[T](size) + * @param size + * @param ev + * @tparam T + * @return + */ def randperm[@specialized(Float, Double) T: ClassTag](size: Int)( implicit ev: TensorNumeric[T]): Tensor[T] = DenseTensor.randperm[T](size) + /** + * This is equivalent to tensor.expand(sizes.toArray) + * @param tensor + * @param sizes + * @tparam T + * @return + */ def expand[T](tensor: Tensor[T], sizes: Int*): Tensor[T] = tensor.expand(sizes.toArray) + /** + * This is equivalent to tensor.expandAs(template) + * @param tensor + * @param template + * @tparam T + * @return + */ def expandAs[T](tensor: Tensor[T], template: Tensor[T]): Tensor[T] = tensor.expandAs(template) + /** + * This is equivalent to tensor.repeatTensor(sizes.toArray) + * @param tensor + * @param sizes + * @tparam T + * @return + */ def repeatTensor[T](tensor: Tensor[T], sizes: Int*): Tensor[T] = tensor.repeatTensor(sizes.toArray) } diff --git a/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/TensorMath.scala b/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/TensorMath.scala index d6a08e1d011..7567042a0d2 100644 --- a/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/TensorMath.scala +++ b/dl/src/main/scala/com/intel/analytics/sparkdl/tensor/TensorMath.scala @@ -17,10 +17,34 @@ package com.intel.analytics.sparkdl.tensor +/** + * It provides multiple math operation function for manipulating Tensor objects. + * All functions support both allocating a new Tensor to return the result + * and treating the caller as the target Tensor, in which case the target Tensor(s) + * will be resized accordingly and filled with result. This property is especially + * useful when one wants have tight control over when memory is allocated. + * + * @tparam T should be double or float + */ trait TensorMath[T] { // scalastyle:off methodName + + /** + * Add all elements of this with value not in place. + * It will allocate new memory. + * @param s + * @return + */ + def +(s: T): Tensor[T] + /** + * Add a Tensor to another one, return the result in new allocated memory. + * The number of elements in the Tensors must match, but the sizes do not matter. + * The size of the returned Tensor will be the size of the first Tensor + * @param t + * @return + */ def +(t: Tensor[T]): Tensor[T] def +(e: Either[Tensor[T], T]): Tensor[T] = { @@ -30,39 +54,133 @@ trait TensorMath[T] { } } + /** + * subtract all elements of this with value not in place. + * It will allocate new memory. + * @param s + * @return + */ def -(s: T): Tensor[T] + /** + * Subtract a Tensor from another one, return the result in new allocated memory. + * The number of elements in the Tensors must match, but the sizes do not matter. + * The size of the returned Tensor will be the size of the first Tensor + * @param t + * @return + */ def -(t: Tensor[T]): Tensor[T] def unary_-(): Tensor[T] + /** + * divide all elements of this with value not in place. + * It will allocate new memory. + * @param s + * @return + */ def /(s: T): Tensor[T] + /** + * Divide a Tensor by another one, return the result in new allocated memory. + * The number of elements in the Tensors must match, but the sizes do not matter. + * The size of the returned Tensor will be the size of the first Tensor + * @param t + * @return + */ def /(t: Tensor[T]): Tensor[T] + /** + * multiply all elements of this with value not in place. + * It will allocate new memory. + * @param s + * @return + */ def *(s: T): Tensor[T] + /** + * Multiply a Tensor by another one, return the result in new allocated memory. + * The number of elements in the Tensors must match, but the sizes do not matter. + * The size of the returned Tensor will be the size of the first Tensor + * @param t + * @return + */ def *(t: Tensor[T]): Tensor[T] // scalastyle:on methodName + /** + * returns the sum of the elements of this + * @return + */ def sum(): T + /** + * performs the sum operation over the dimension dim + * @param dim + * @return + */ def sum(dim: Int): Tensor[T] + /** + * returns the mean of all elements of this. + * @return + */ def mean(): T + /** + * performs the mean operation over the dimension dim. + * + * @param dim + * @return + */ def mean(dim: Int): Tensor[T] + /** + * returns the single biggest element of x + * @return + */ def max(): T + /** + * performs the max operation over the dimension n + * @param dim + * @return + */ def max(dim: Int): (Tensor[T], Tensor[T]) + /** + * This function computes 2 dimensional convolution of a single image + * with a single kernel (2D output). the dimensions of input and kernel + * need to be 2, and Input image needs to be bigger than kernel. The + * last argument controls if the convolution is a full ('F') or valid + * ('V') convolution. The default is valid convolution. + * + * @param kernel + * @param vf full ('F') or valid ('V') convolution. + * @return + */ def conv2(kernel: Tensor[T], vf: Char = 'V'): Tensor[T] + /** + * This function operates with same options and input/output configurations as conv2, + * but performs cross-correlation of the input with the kernel k. + * + * @param kernel + * @param vf full ('F') or valid ('V') convolution. + * @return + */ def xcorr2(kernel: Tensor[T], vf: Char = 'V'): Tensor[T] + /** + * replaces all elements in-place with the square root of the elements of this. + * @return + */ def sqrt(): Tensor[T] + /** + * replaces all elements in-place with the absolute values of the elements of this. + * @return + */ def abs(): Tensor[T] /** @@ -75,8 +193,21 @@ trait TensorMath[T] { def add(value: T, y: Tensor[T]): Tensor[T] // Puts the result of x + value * y in current tensor + /** + * z.add(x, value, y) puts the result of x + value * y in z. + * + * @param x + * @param value + * @param y + * @return + */ def add(x: Tensor[T], value: T, y: Tensor[T]): Tensor[T] + /** + * x.add(value) : add value to all elements of x in place. + * @param value + * @return + */ def add(value: T): Tensor[T] /** From f5d219dcb306addd5f23b717225576252dea8f14 Mon Sep 17 00:00:00 2001 From: yansh Date: Sun, 9 Oct 2016 16:09:04 +0800 Subject: [PATCH 4/4] delete doc --- doc/tensor.md | 316 -------------------------------------------------- 1 file changed, 316 deletions(-) delete mode 100644 doc/tensor.md diff --git a/doc/tensor.md b/doc/tensor.md deleted file mode 100644 index 7acd0705407..00000000000 --- a/doc/tensor.md +++ /dev/null @@ -1,316 +0,0 @@ - -# Tensor # - -__Tensors of different types__ - -Actually, several types of `Tensor` exists: - -```scala -DenseTensor -SparseTensor -``` - -The data type of Tensor are implemented _only_ for `Float` and `Double`. - - -## Tensor constructors ## - -Tensor constructors, create new Tensor object, optionally, allocating new memory. By default the elements of a newly allocated memory are -not initialized, therefore, might contain arbitrary numbers. Here are several ways to construct a new `Tensor`. - -Please be attention to that the data type of Tensor are implemented _only_ for `Float` and `Double`. So the following T can only be Double or Float - - -### Tensor[T] () ### - -Returns an empty tensor. - -```scala -import com.intel.analytics.sparkdl.tensor -var y = Tensor[T]() -``` - - -### Tensor[T] (d1 : Int [,d2 : Int [,d3 : Int [,d4 : Int [,d5 : Int ]]]]]) ### - -Create a tensor up to 5 dimensions. The tensor size will be `d1 x d2 x d3 x d4 x d5`. - - -### Tensor[T] (dims : Int *) ### - - -### Tensor[T] (sizes : Array[Int]) ### - - -### Tensor[T] (storage : Storage[T]) ### - - -### Tensor[T] (storage : Storage[T], storageOffset : Int, size : Array[Int] = null, stride : Array[Int] = null) ### - -Convenience constructor (for the previous constructor) assuming a number of dimensions. - - -### Tensor[T] (tensor : Tensor[T]) ### - -Returns a new tensor which reference the same -[Storage](#storage) than the given `tensor`. The -[size](#Tensor.size), [stride](#Tensor.stride), and -[storage offset](#storageOffset) are the same than the -given tensor. - -The new `Tensor` is now going to "view" the same [storage](storage.md) -as the given `tensor`. As a result, any modification in the elements -of the `Tensor` will have a impact on the elements of the given -`tensor`, and vice-versa. No memory copy! - -```scala -x = Tensor[T](2,5) // DenseTensor of dimension 2x5 -y = Tensor[T](x) // y is same as x -``` - - -### Tensor[T](vector : DenseVector[T]) ### - - -### Tensor(vector : DenseVector) ### - - -### Tensor[T](vector : DenseMatrix[T]) ### - - -### Tensor(vector : DenseMatrix) ### - - -### Tensor[T](indices : Array[Array[Int]], values : Storage[T], shape : Array[Int]) ### - - -### Tensor[T](rowIndices : Array[Int], columns: Array[Int],values : Storage[T], shape : Array[Int]) ### - -## A note on function calls ## - -The rest of this guide will present many functions that can be used to manipulate tensors. - - -### nDimension() : Int ### - -Return the dimension number of the tensor. For empty tensor, its dimension number is 0. - - -### dim() : Int ### - -A shortcut of nDimension(). - - -### size() : Array[Int] ### - -Return the size of tensor. Return an array of which each value represent the size on the dimension(i + 1), i is the index of the corresponding value. It will generate a new array each time you invoke the method. - - -### size(dim : Int) : Int ### - -Return the size of the tensor on the given dimension. - - -### stride() : Array[Int] ### - -Jumps between element on the each dimension in the storage. It will generate a new array each time you invoke the method. - - -### stride(dim : Int) : Int ### - -Jumps between element on the given dimension in the storage. - - -### fill(v : T) : Tensor[T] ### - -Fill the tensor with a given value. It will change the value of the current tensor and return itself. - - -### zero() : Tensor[T] ### - -Fill the tensor with zero. It will change the value of the current tensor and return itself. - - -### randn() : Tensor[T] ### - -Fill the tensor with random value(normal gaussian distribution). It will change the value of the current tensor and return itself. - - -### rand() : Tensor[T] ### - -Fill the tensor with random value(uniform distribution). It will change the value of the current tensor and return itself. - - -### bernoulli(p : Double) : Tensor[T] ### - -Fill with random value(bernoulli distribution). It will change the value of the current tensor and return itself. - - -### transpose(dim1 : Int, dim2 : Int) : Tensor[T] ### - -Create a new tensor which exchanges the given dimensions of the current tensor. - - -### t() : Tensor[T] ### - -Shortcut of transpose(1, 2) for 2D tensor. - - -### valueAt(d1 : Int [,d2 : Int [,d3 : Int [,d4 : Int [,d5 : Int ]]]]) : T ### - -Query the value on a given position. Tensor should not be empty. - - -### apply(index: Int) : Tensor[T] ### - -Query tensor on a given index. Tensor should not be empty. - - -### apply(indexes: Array[Int])) : Tensor[T] ### - -Query the value on a given index. Tensor should not be empty. - - -### apply(t: Table)) : Tensor[T] ### - -Subset the tensor by apply the element of the given table to corresponding dimension of the tensor. The element of the given table can be an Int or another Table. An Int means select on current dimension; A table means narrow on current dimension, the table should has two elements, of which the first is start index and the second is the end index. An empty table is equals to Table(1, size_of_current_dimension) If the table length is less than the tensor dimension, the missing dimension is applied by an empty table - - -### setValue(d1 : Int [,d2 : Int [,d3 : Int [,d4 : Int [,d5 : Int ]]]]): Unit ### - -Write the value on a given position. - - -### update(index: Int, value: T): Unit ### - -For tensor(i) = value. If tensor(i) is another tensor, it will fill the selected subset by the given value. - -### update(index: Int, src: Tensor[T]): Unit ### - -Copy the give tensor value to the select subset of the current tensor by the given index. The subset should has the same size of the given tensor. - -### update(indexes: Array[Int], value: T): Unit ### - -Write the value to the value indexed by the given index array. - -### update(t: Table, value: T): Unit ### - -Fill the select subset of the current tensor with the given value. The element of the given table can be an Int or another Table. An Int means select on current dimension; A tablemeans narrow on current dimension, the table should has two elements, of which the first is start index and the second is the end index. An empty table is equals to Table(1, size_of_current_dimension) If the table length is less than the tensor dimension, the missing dimension is applied by an empty table. - -### update(t: Table, src: Tensor[T]): Unit ### - -Copy the given tensor value to the select subset of the current tensor The element of the given table can be an Int or another Table. An Int means select on current dimension; A table means narrow on current dimension, the table should has two elements, of which the first is start index and the second is the end index. An empty table is equals to Table(1, size_of_current_dimension) If the table length is less than the tensor dimension, the missing dimension is applied by an empty table. - -### update(filter: T => Boolean, value: T): Unit ### - -Update the value meeting the filter criteria with the give value. - - -### isContiguous(): Boolean ### - -Check if the tensor is contiguous on the storage - - -### contiguous(): Tensor[T] ### - -Get a contiguous tensor from current tensor - - -### isSameSizeAs(other: Tensor[_]): Boolean ### - -Check if the size is same with the give tensor - - -### clone(): Tensor[T] ### - -Get a new tensor with same value and different storage - - -### resizeAs(src: Tensor[_]): Tensor[T] ### - -Resize the current tensor to the same size of the given tensor. It will still use the same storage if the storage is sufficient for the new size. - - -### resize(d1 : Int [,d2 : Int [,d3 : Int [,d4 : Int [,d5 : Int ]]]]): Tensor[T] ### - -Resize the current tensor to the give shape - -### resize(sizes: Array[Int], strides: Array[Int] = null): Tensor[T] ### - -Resize the current tensor to the give shape - - -### nElement(): Int ### - -Element number - - -### select(dim: Int, index: Int): Tensor[T] ### - -Remove the dim-th dimension and return the subset part. - - -### storage(): Storage[T] ### - -Get the storage. - - -### storageOffset(): Int ### - -Return tensor offset on the storage, count from 1 - - -### set(other: Tensor[T]): Tensor[T] ### - -The Tensor is now going to "view" the same storage as the given tensor. As the result, any modification in the elements of the Tensor will have an impact on the elements of the given tensor, and vice-versa. This is an efficient method, as there is no memory copy! - -### set(storage: Storage[T], storageOffset: Int = 1, sizes: Array[Int] = null, strides: Array[Int] = null): Tensor[T] ### - -The Tensor is now going to "view" the given storage, starting at position storageOffset (>=1) with the given dimension sizes and the optional given strides. As the result, any modification in the elements of the Storage will have a impact on the elements of the Tensor, and vice-versa. This is an efficient method, as there is no memory copy! -If only storage is provided, the whole storage will be viewed as a 1D Tensor. - - -### narrow(dim: Int, index: Int, size: Int): Tensor[T] ### - -Get a subset of the tensor on dim-th dimension. The offset is given by index, and length is give by size. The important difference with select is that it will not reduce the dimension number. For Instance -tensor = - 1 2 3 - 4 5 6 -tensor.narrow(1, 1, 1) is - [1 2 3] -tensor.narrow(2, 2, 3) is - 2 3 - 5 6 - - -### copy(other: Tensor[T]): Tensor[T] ### - -Copy the value of the given tensor to the current. They should have same size. It will use the old storage - - -### apply1(func: T => T): Tensor[T] ### - -Apply a function to each element of the tensor and modified it value if it return a double. - - -### map(other: Tensor[T], func: (T, T) => T): Tensor[T] ### - -Map value of another tensor to corresponding value of current tensor and apply function on the two value and change the value of the current tensor. The another tensor should has the same size of the current tensor. - - -### squeeze(): Tensor[T] ### - -Removes all singleton dimensions of the tensor - -### squeeze(dim: Int): Tensor[T] ### - -Removes given dimensions of the tensor if it's singleton - - -### view(sizes: Int*): Tensor[T] ### - -Return a new tensor with specified sizes. The input tensor must be contiguous, and the elements number in the given sizes must be equal to the current tensor - -### view(sizes: Array[Int]): Tensor[T] ### - -Return a new tensor with specified sizes. The input tensor must be contiguous, and the elements number in the given sizes must be equal to the current tensor