Java 数组到 NumPy 数组的快速转换 (Py4J)

Posted

技术标签:

【中文标题】Java 数组到 NumPy 数组的快速转换 (Py4J)【英文标题】:Fast conversion of Java array to NumPy array (Py4J) 【发布时间】:2016-12-29 23:26:17 【问题描述】:

有一些很好的示例如何将 NumPy 数组转换为 Java 数组,但反之亦然 - 如何将数据从 Java 对象转换回 NumPy 数组。我有一个这样的 Python 脚本:

    from py4j.java_gateway import JavaGateway
    gateway = JavaGateway()            # connect to the JVM
    my_java = gateway.jvm.JavaClass();  # my Java object
    ....
    int_array=my_java.doSomething(int_array); # do something

    my_numpy=np.zeros((size_y,size_x));
    for jj in range(size_y):
        for ii in range(size_x):
            my_numpy[jj,ii]=int_array[jj][ii];

my_numpy 是 Numpy 数组,int_array 是 Java 整数数组 - int[ ][ ] 类型的数组。在 Python 脚本中初始化为:

    int_class=gateway.jvm.int       # make int class
    double_class=gateway.jvm.double # make double class

    int_array = gateway.new_array(int_class,size_y,size_x)
    double_array = gateway.new_array(double_class,size_y,size_x)

虽然它按原样工作,但它不是最快的方式,而且工作速度相当慢 - 对于 ~1000x1000 阵列,转换需要 5 多分钟。

有什么方法可以在合理的时间内完成这个吗?

如果我尝试:

    test=np.array(int_array)

我明白了:

    ValueError: invalid __array_struct__

【问题讨论】:

【参考方案1】:

我遇到了类似的问题,并找到了一个解决方案,它比我测试的案例快了大约 220 倍:对于将 1628x120 短整数数组从 Java 传输到 Numpy,运行时间从 11 秒减少到 0.05 秒。感谢this related *** question,我开始研究py4j byte arrays,结果发现py4j 有效地将Java 字节数组转换为Python 字节对象,反之亦然(通过值传递,而不是通过引用传递)。这是一种相当迂回的做事方式,但并不太难。

因此,如果您想传输维度为iMaxxjMax 的整数数组intArray(并且为了示例,我假设这些都作为实例变量存储在您的对象中),您可以先写一个Java函数把它转换成byte[],像这样:

public byte[] getByteArray() 
    // Set up a ByteBuffer called intBuffer
    ByteBuffer intBuffer = ByteBuffer.allocate(4*iMax*jMax); // 4 bytes in an int
    intBuffer.order(ByteOrder.LITTLE_ENDIAN); // Java's default is big-endian

    // Copy ints from intArray into intBuffer as bytes
    for (int i = 0; i < iMax; i++) 
        for (int j = 0; j < jMax; j++)
            intBuffer.putInt(intArray[i][j]);
        
    

    // Convert the ByteBuffer to a byte array and return it
    byte[] byteArray = intBuffer.array();
    return byteArray;

然后,您可以编写 Python 3 代码来接收字节数组并将其转换为正确形状的 numpy 数组:

byteArray = gateway.entry_point.getByteArray()
intArray = np.frombuffer(byteArray, dtype=np.int32)
intArray = intArray.reshape((iMax, jMax))

【讨论】:

您的回答肯定对我有帮助,谢谢。但稍作修正 intArray = intArray.reshape((iMax, jMax)) 重塑应该有两个大括号 你是对的,@VenkataramanaMadugula,感谢您的纠正!我现在已经相应地编辑了我的答案。【参考方案2】:

我有一个类似的问题,只是试图绘制我通过 py4j 从 Java 端获得的光谱向量(Java 数组)。 在这里,从 Java Array 到 Python 列表的转换是通过 list() 函数实现的。这可能会为如何使用它来填充 NumPy 数组提供一些线索...

vectors = space.getVectorsAsArray(); # Java array (MxN)
wvl = space.getAverageWavelengths(); # Java array (N)

wavelengths = list(wvl)

import matplotlib.pyplot as mp
mp.hold
for i, dataset in enumerate(vectors):
    mp.plot(wavelengths, list(dataset))

我不能说这是否比您使用的嵌套 for 循环更快,但它也可以解决问题:

import numpy
from numpy  import array
x = array(wavelengths)
v = array(list(vectors))

mp.plot(x, numpy.rot90(v))

【讨论】:

以上是关于Java 数组到 NumPy 数组的快速转换 (Py4J)的主要内容,如果未能解决你的问题,请参考以下文章

如何快速将返回的 Python-in-Lua numpy 数组转换为 Lua Torch 张量?

C中的numpy数组类型转换

正确将 png 转换为 npy numpy 数组(图像到数组)

使用 ctypes 从 C 结构数组到 NumPy 数组的高效转换

numpy 数组中非唯一行的快速组合,映射到列(即快速数据透视表问题,没有 Pandas)

PIL 图像到数组(numpy 数组到数组) - Python