请考虑以下代码,该代码使用ND4J库创建更简单版本的“moons”测试数据集:
val n = 100val n1:Int = n / 2val n2:Int = n-n1val outerX = Nd4j.getExecutioner ….
是的,事实证明 .data() 使用ND4J不是你真正应该用于任何非常严重的事情。这对我试图做的事情有点遗憾:编写不依赖于ND4J的单元测试以及它如何在内部处理数据。
.data()
作为此处问题的另一个示例,请考虑以下代码:
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双打列表;验证这些双打是我预期的计算。相反,我需要做的是将预期的东西放在ND4J数组中,这样我就可以正确地将它与实际输出进行比较,所以我的测试现在依赖于ND4J,这是我库的内部技术选择。
无论如何,这是一个相对较小的抱怨,教训是,避免 .data() 相反,如果你使用的是ND4J,请在整个过程中使用它(即使你认为它有点不优雅)。
.data()给你一排直线。 看到: http://nd4j.org/tensor
数组的形状只是底层数据缓冲区的视图。 我通常不建议在没有充分理由的情况下做你想做的事情。所有数据都存储在堆中。那份副本很贵。
在堆上做任何数学都是不好的。这里唯一的用例是集成。我建议尽可能直接在阵列上操作。从序列化到索引的所有内容都是为您处理的。
如果你 真 需要它进行某种集成,使用番石榴,你可以在一行中做到: Doubles.asList(arr.data()DUP()asDouble());
其中arr是你的ndarray来操作。