Java ND4J阵列&;它们的形状:将数据放入列表

Java ND4J阵列&;它们的形状:将数据放入列表,java,scala,deeplearning4j,nd4j,Java,Scala,Deeplearning4j,Nd4j,考虑以下代码,该代码使用创建的更简单版本: val n=100 val n1:Int=n/2 val n2:Int=n-n1 val outerX=Nd4j.getExecutioner.ExecuteReturn(新的Cos(Nd4j.linspace(0,Math.PI,n1))) val outerY=Nd4j.getExecutioner.ExecuteReturn(新的Sin(Nd4j.linspace(0,Math.PI,n1))) val innerX=Nd4j.getExecut

考虑以下代码,该代码使用创建的更简单版本:

val n=100
val n1:Int=n/2
val n2:Int=n-n1
val outerX=Nd4j.getExecutioner.ExecuteReturn(新的Cos(Nd4j.linspace(0,Math.PI,n1)))
val outerY=Nd4j.getExecutioner.ExecuteReturn(新的Sin(Nd4j.linspace(0,Math.PI,n1)))
val innerX=Nd4j.getExecutioner.execAndReturn(新的Cos(Nd4j.linspace(0,Math.PI,n2))).mul(-1).添加(1)
val innerY=Nd4j.getExecutioner.execAndReturn(新Sin(Nd4j.linspace(0,Math.PI,n2))).mul(-1).添加(1)
val X:INDArray=Nd4j.vstack(
Nd4j.concat(1,outerX,innerX),//1 x n
Nd4j.concat(1,外层,内层)//1 x n
)//2 x n
val y:INDArray=Nd4j.hstack(
Nd4j.零(n1),//1 x n1
Nd4j.ones(n2)//1 x n2
)//1 x n
println(s“#y形状:${y.shape().toList}”)//1x100
println(s“#y数据长度:${y.data().length()}”)//100
println(s“#X shape:${X.shape().toList}”)//2x100
println(s“#X行0形状:${X.getRow(0.shape().toList}”)//1x100
println(s“#X行1形状:${X.getRow(1.shape().toList}”)//1x100
println(s“#X row 0数据长度:${X.getRow(0).data().length()}”)//200.data()为您提供一个直行。
见:

数组的形状只是底层数据缓冲区的视图。 我通常不建议在没有充分理由的情况下做你想做的事情。所有数据都存储在堆外。那本书很贵

在堆上做任何一种数学都不好。这里唯一的用例是集成。我建议尽可能直接操作阵列。从序列化到索引,一切都是为您处理的

如果你真的需要某种形式的整合,使用番石榴,你可以在一行中完成: Doubles.asList(arr.data().dup().asDouble())

其中,arr是要操作的数据数组。

.data()为您提供了一条直线。 见:

数组的形状只是底层数据缓冲区的视图。 我通常不建议在没有充分理由的情况下做你想做的事情。所有数据都存储在堆外。那本书很贵

在堆上做任何一种数学都不好。这里唯一的用例是集成。我建议尽可能直接操作阵列。从序列化到索引,一切都是为您处理的

如果你真的需要某种形式的整合,使用番石榴,你可以在一行中完成: Doubles.asList(arr.data().dup().asDouble())


其中arr是您要操作的ndarray。

是的,事实证明,使用ND4J的
.data()
并不是您真正应该用于任何非常严重的事情。这对于我试图做的事情来说有点丢脸:编写不真正依赖ND4J的单元测试,以及ND4J内部如何处理数据

作为这里的问题的另一个例子,考虑这个代码:

import org.nd4j.linalg.factory.Nd4j

object foo extends App {

  val x = Nd4j.create(Array[Double](1,2, 3,4, 5,6), Array(3,2))
  // 1,2
  // 3,4
  // 5,6
  println(x)
  val xArr = x.data().asDouble().toList
  // 1,2,  3,4,  5,6 - row-wise
  println(xArr)

  val w = Nd4j.create(Array[Double](10,20,30, 40,50,60), Array(2,3))
  // 10,20,30
  // 40,50,60
  println(w)
  val wArr = w.data().asDouble().toList
  // 10,20,30,  40,50,60 - row-wise
  println(wArr)

  val wx = w.mmul(x)
  /*
   *  10,20,30   1,2     10*1+20*3+30*5  10*2+20*4+30*6      220  280
   *  40,50,60   3,4  =  40*1+50*3+60*5  40*2+50*4+60*6  =   490  640
   *             5,6
   */
  println(wx)
  val wxArr = wx.data().asDouble().toList
  // 220, 490,  280, 640 - column-wise
  println(wxArr)
  val wxTArr = wx.transpose().data().asDouble().toList
  // 220, 490,  280, 640 - still column-wise
  println(wxTArr)
  val wxTIArr = wx.transposei().data().asDouble().toList
  // 220, 490,  280, 640 - still column-wise
  println(wxTIArr)

}
正如您所看到的,ND4J基本上在内部实现了它想要的功能,当您使用
.data()
时,它只会给出它的内部表示;这种表示形式不会被任何转置或您要求它执行的任何其他操作所改变,因为它们实际上不会移动底层数据

这一切都很好,但我想做的基本上是:制作一个普通双打的Scala列表;把它给我的图书馆用品;让图书馆做自己的事;获取其输出并将其转换为另一个Scala Double列表;验证这些双精度是我期望它计算的。相反,我要做的是将预期的内容放入ND4J数组中,这样我就可以正确地将其与实际输出进行比较,因此我的测试现在依赖于ND4J,这是我库的内部技术选择


无论如何,这是一个相对较小的抱怨,教训是,避免使用
.data()
,相反,如果您使用ND4J,则在整个过程中使用它(即使您认为这有点不雅观)。

是的,事实证明,使用ND4J的
.data()
并不是什么非常严肃的事情。这对于我试图做的事情来说有点丢脸:编写不真正依赖ND4J的单元测试,以及ND4J内部如何处理数据

作为这里的问题的另一个例子,考虑这个代码:

import org.nd4j.linalg.factory.Nd4j

object foo extends App {

  val x = Nd4j.create(Array[Double](1,2, 3,4, 5,6), Array(3,2))
  // 1,2
  // 3,4
  // 5,6
  println(x)
  val xArr = x.data().asDouble().toList
  // 1,2,  3,4,  5,6 - row-wise
  println(xArr)

  val w = Nd4j.create(Array[Double](10,20,30, 40,50,60), Array(2,3))
  // 10,20,30
  // 40,50,60
  println(w)
  val wArr = w.data().asDouble().toList
  // 10,20,30,  40,50,60 - row-wise
  println(wArr)

  val wx = w.mmul(x)
  /*
   *  10,20,30   1,2     10*1+20*3+30*5  10*2+20*4+30*6      220  280
   *  40,50,60   3,4  =  40*1+50*3+60*5  40*2+50*4+60*6  =   490  640
   *             5,6
   */
  println(wx)
  val wxArr = wx.data().asDouble().toList
  // 220, 490,  280, 640 - column-wise
  println(wxArr)
  val wxTArr = wx.transpose().data().asDouble().toList
  // 220, 490,  280, 640 - still column-wise
  println(wxTArr)
  val wxTIArr = wx.transposei().data().asDouble().toList
  // 220, 490,  280, 640 - still column-wise
  println(wxTIArr)

}
正如您所看到的,ND4J基本上在内部实现了它想要的功能,当您使用
.data()
时,它只会给出它的内部表示;这种表示形式不会被任何转置或您要求它执行的任何其他操作所改变,因为它们实际上不会移动底层数据

这一切都很好,但我想做的基本上是:制作一个普通双打的Scala列表;把它给我的图书馆用品;让图书馆做自己的事;获取其输出并将其转换为另一个Scala Double列表;验证这些双精度是我期望它计算的。相反,我要做的是将预期的内容放入ND4J数组中,这样我就可以正确地将其与实际输出进行比较,因此我的测试现在依赖于ND4J,这是我库的内部技术选择

无论如何,这是一个相对较小的抱怨,教训是,避免使用
.data()
,相反,如果您使用的是ND4J,请始终使用它(即使您认为这有点不雅观)