java - 将 float 组发送到部署在 Google Cloud ML-Engine 上的 Tensorflow 模型

标签 java android arrays tensorflow google-cloud-ml

我创建了一个虚拟模型,该模型返回数组输入并将其部署在 google-cloud ML-engine 上,以便我可以检查它如何解码请求中发送的音频。我无法以正确解码的方式将存储在 float 组中的音频从 Android 应用程序发送到模型。虽然我从 Python 发送请求时没有任何问题。

我提出请求如下: 音频被录制到

short[] inputBuffer = new short[RECORDING_LENGTH];

转换为 float 组

float[] floatInputBuffer = new float[RECORDING_LENGTH];
for (int i = 0; i < RECORDING_LENGTH; ++i) {
    floatInputBuffer[i] = (float) inputBuffer[i];
}

谷歌云期望的预测形式是 (see data encoding section) :

{"instances": [{"b64": "X5ad6u"}, {"b64": "IA9j4nx"}]}

所以我将音频放入模仿此的 map 中。

  public static String convertToBase64Bytes(float[] audio) {
    ByteBuffer byteBuffer = ByteBuffer.allocate(4 * audio.length);
    for (int i = 0; i < audio.length; i++) {
      float amplitude = audio[i];
      byteBuffer.putFloat(amplitude);
    }
    byte[] data = byteBuffer.array();
    String rtn = Base64.encodeToString(data, Base64.DEFAULT);
    return rtn;
  }

  String audioByteString = convertToBase64Bytes(floatInputBuffer);
  final ArrayList<HashMap<String, String>> requestList = new ArrayList<>();
  HashMap<String, String> singleRequest = new HashMap<>();
  singleRequest.put("b64", audioByteString);
  requestList.add(singleRequest);
  HashMap<String, ArrayList<HashMap<String, String>>> jsonRequest = new HashMap<>();
  jsonRequest.put("instances", requestList);

然后我调用这个函数来发送请求并返回结果

public String sendRequest(HashMap<String, ArrayList<HashMap<String, String>>> jsonRequest) throws Exception {
    HttpContent content = new JsonHttpContent(new JacksonFactory(), jsonRequest);
    HttpRequest request = requestFactory.buildRequest(method.getHttpMethod(), url, content);
    return request.execute().parseAsString();
}

检查模型的输出。数组的形状是正确的,但浮点值不正确。它们通常几乎为零(e 的 -26 次方左右)。

在模型方面,处理请求的模型的服务输入函数(使用自定义 tensorflow 估计器创建)是

def serving_input_fn():
    feature_placeholders = {'b64': tf.placeholder(dtype=tf.string,
                                                  shape=[None],
                                                  name='source')}
    audio_samples = tf.decode_raw(feature_placeholders['b64'], tf.float32)
    inputs = {'inarray': audio_samples}
    return tf.estimator.export.ServingInputReceiver(inputs, feature_placeholders)

我认为我错误地将编码的 float 组作为base64字符串传递,因为谷歌云应该由于“b64”键而自动解码base64字符串,并且在从Python发送请求时这可以正常工作。

有谁知道如何将 float 组从 android 发送到谷歌云上的模型,以便正确解码?

最佳答案

这似乎是 BytesOrder/endian-ness 问题。来自 ByteBuffer javadocs :

Primitive values are translated to (or from) sequences of bytes according to the buffer's current byte order, which may be retrieved and modified via the order methods. Specific byte orders are represented by instances of the ByteOrder class. The initial order of a byte buffer is always BIG_ENDIAN.

但是 TensorFlow 的 decode_raw默认为小尾数

little_endian: An optional bool. Defaults to True. Whether the input bytes are in little-endian order. Ignored for out_type values that are stored in a single byte like uint8.

解决方案是覆盖一个或另一个默认值。由于 ARM 处理器本身就是大端字节序,因此也许在您的 Android 代码中坚持使用 BigEndian,并修改您的 TF 代码:

def serving_input_fn():
    feature_placeholders = {
        'audio_bytes': tf.placeholder(
            dtype=tf.string,
            shape=[None],
            name='source'
         )
    }
    audio_samples = tf.decode_raw(
        feature_placeholders['audio_bytes'],
        tf.float32,
        little_endian=False
    )
    return tf.estimator.export.ServingInputReceiver(
        feature_placeholders,
        feature_placeholders
    )

(我对该函数进行了一些其他更改,如单独的 SO post 中所述)

关于java - 将 float 组发送到部署在 Google Cloud ML-Engine 上的 Tensorflow 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49170040/

相关文章:

java - 将 cacert curl 到 Java HttpClient 等价物

android - Activity 和服务之间的通信

java - 不兼容的类型 : BigInteger cannot be converted to int

mysql - Nodejs中从mySQL获取数据时如何获取Async/await函数的返回值

javascript - ReactJS + JavaScript : How to parse array into a new array?

java - 在 ubuntu 14.04 中下载所有包后无法初始化 opennms 数据库 postgres

java - 用于 Netbeans/Swing 的类似 GUI 库的 WireIt

java - 如何计算该字符串中每个单词的大小?

android - 屏幕中央的TextView

java - Android Studio 无法识别 "task.isSuccesful"( "Cannot resolve symbol ' 任务 ' ")