eaplatanios / tensorflow_scala

TensorFlow API for the Scala Programming Language
http://platanios.org/tensorflow_scala/
Apache License 2.0
936 stars 96 forks source link

Does the package have matrix operations? #129

Closed git4sun closed 5 years ago

git4sun commented 5 years ago

Like factorization_ops.WALSModel in python version?

eaplatanios commented 5 years ago

No I haven't really worked on adding support for those, but it shouldn't be too hard to do that, if you need them for your work. I can help with any issues that may come up.

git4sun commented 5 years ago

I am currently using the python version. I would love to have it in the scala version since the data pipeline is in java world. It will be much easier to code everything in one language. But I don't know how to wrap .so in scala. If you don't have the plan to include it in this package, could you please point me to resources about how to do that? Thanks

git4sun commented 5 years ago

Hi @eaplatanios, Would you please let me know if you have the plan to incorporate these ops? Thanks.

eaplatanios commented 5 years ago

@git4sun I've been working on some major design changes in #131. I'll soon finish that and then make a guide that shows have you can add support for the functionality you need.

cosmir17 commented 5 years ago

Hi @eaplatanios, can I ask a numpy question(matrix)?

I have the following variable. val myMatrix: Tensor[Float] = session.run(targets = trainOp, fetches = q, feeds = feeds)

How would you do something like :

np.argmax(myMatrix)

https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argmax.html

there is 'tf.argmax(...) method' but it seems not what I am looking for because the method requires two parameters. I don't know what I need to provide for 'axes'. def argmax[...]( input: Output[T], axes: Output[I], outputDataType: DataType[R], name: String = "ArgMax" ): Output[R] = {

also, if I can ask a second question.., how would I create a copy of 'myMatrix' with a specific coordinate(0, someIndex) value replaced?

Hope this helps for the community..

Thank you, cosmir17

//the first question has been solved by help from the Gitter channel. The followings are solutions. argmax(myMatrix, null) or argmax(myMatrix, Tensor[Int](0 until myMatrix.rank) )

eaplatanios commented 5 years ago

@cosmir17 regarding your second question, TensorFlow tensors are immutable and thus you cannot replace the value at a specific coordinate. You should use tf.Variable if you want to change it's values, but you should also probably consider restructuring your code so that you don't have to (sometimes this is possible).

cosmir17 commented 5 years ago

@eaplatanios, I thought so. Therefore, I asked 'how would I create a copy of...'? Would you be able to help me with the following transportation, please? I would like to do something like, matrix(0, something) = assignment <= python code

val matrix = session.run(feeds = Map(x -> state), q);
val something: ndarray[int] <= python code

I really appreciate your kindness. Would you mind if I ask another question, please? How can I translate the following code into Scala?

**current_state = np.asmatrix(np.hstack((a[i:i+number], b, c)))**
action_q_vals = self.sess.run(q, feed_dict={x: current_state}) //this is already done

Thank you, cosmir17

cosmir17 commented 5 years ago

@eaplatanios, for the first part, I did the following,

import org.platanios.tensorflow.api.tensors.ops.Basic._
val remaingOldPart = matrix(something, matrix.size.toInt)
val newReplacingPart = matrix(0, something)
val newMatrix = concatenate(Seq(newReplacingPart, remaingOldPart), 0)

Hope this will work :)

I am still trying to translate the following current_state = np.asmatrix(np.hstack((a[i:i+number], b, c))) //python code

eaplatanios commented 5 years ago

@cosmir17 I believe this might work for you:

val currentState = tf.stack(Seq(a(i::i+number), b, c)), axis=1)

I'll close this for now. Please feel free to reopen if the issue persists.

cosmir17 commented 5 years ago

@eaplatanios It was perfectly fine to close this ticket. I used this ticket as a Q&A board as it dealt with a Matrix question. Thank you for your answer. I tried, val currentState = tf.stack(Seq(a.slice(i,i+number +1), b, c), axis=1) (I think a[i:i+number] returns a sublist in Python so I used 'slice' method) ('a(i :: i + number :: Nil)' compiled too but I didn't know what it did, 'a(i::i + number)' didn't compile)

This returned 'Output[Float]' I need, Tensor[Float] in order to use it in val actionQVals = session.run(feeds = Map(x -> currentState), q). It doesn't matter if 'currentState' is not 'Tensor[Float]', it's good as long as I can use it for session.run(...).

Thank you, cosmir17

eaplatanios commented 5 years ago

If you want to deal with Tensors instead of Outputs try replacing tf.stack and tf.slice with tfi.stack and tfi.slice. :)

cosmir17 commented 5 years ago

Thank you. It compiles!

cosmir17 commented 5 years ago

@eaplatanios One more question, if you don't mind. It regards to a previous comment you made.

@cosmir17 regarding your second question, TensorFlow tensors are immutable and thus you cannot replace the value at a specific coordinate. You should use tf.Variable if you want to change it's values, but you should also probably consider restructuring your code so that you don't have to (sometimes this is possible).

Yes, it's immutable and I don't want to modify it (also as a Scala dev, side effect ..etc). I want to create a new Tensor from an existing one (copying it & modify a specific coordinate value)

val myTensor: Tensor[Float] = ???
val floatValue: Float = 1.3f
Something like ====>     'myTensor.copy(myTensor(index1)(index2) = floatValue)'

Tensor[Float] is a wrapper. There must be a way.

eaplatanios commented 5 years ago

So there didn't use to be a way to do that, but I think there might be one now. I'll look into it and try to add support within the next week.

cosmir17 commented 5 years ago

I see. I appreciate your support.

DirkToewe commented 5 years ago

@cosmir17 You may have already noticed that nested Seqs and Arrays can be easily converted to Tensors. The other way is also possible (albeit not as easily). So if You need to to random access read and write, You can do the following:

val input: Tensor[Int] = Array(
  Array(1,2, 3),
  Array(5,6, 7),
  Array(8,9,10)
)

val Array(m,n) = input.shape.asArray

// convert Tensor[Int] to Array[Array[Int]]
val arr = Array.tabulate(m,n)(
  (i,j) => input(i,j).scalar
)

for( i <- 0 until m )
  for( j <- 0 until n )
    arr(i)(j) *= 2

// implicitly convert Array[Array[Int]] back to Tensor[Int]
val output: Tensor[Int] = arr

println( output.summarize() )

In case You run into memory or performance issues - like I did - there's also a more low-level approach to creating new Tensor. If You do not have such issues it's much, much, muuuuuch, cleaner and more stable to use the approach above.

val input: Tensor[Int] = Array(
  Array(1,2, 3),
  Array(5,6, 7),
  Array(8,9,10)
)

val Array(m,n) = input.shape.asArray
val iter = input.entriesIterator

val buf = java.nio.ByteBuffer allocateDirect m*n*FLOAT32.byteSize.get
buf order java.nio.ByteOrder.nativeOrder

for( i <- 0 until m )
  for( j <- 0 until n )
    buf.putFloat( iter.next*7 )
buf.position(0)

val output: Tensor[Float] = Tensor fromBuffer ( Shape(m,n), buf.capacity(), buf )
print( output.summarize() )

P.S.: If you need indexed access inside the computation graph, that's also possible but way more complicated. Let me know if You need to do that.

Hope this helps

cosmir17 commented 5 years ago

Hi @DirkToewe, thank you for your kind help. I really appreciate it. I had not been well since yesterday night. I will try it soon. Also, thank you for introducing the low level approach 👍

cosmir17 commented 5 years ago

Hi @DirkToewe, It works. Thank you very much 👍 I am glad that it works!!!

P.S. I didn't want to use a mutable object (arr) so I was looking for an option. The following code works for a 2d tensor.

val Array(m, n) = input.shape.asArray
val seq = Seq.tabulate(m, n)((i, j) => input(i, j).scalar)
seq.updated(x , seq(x).updated(y, replacingValue))

x, y are indices that I want to change*