Служба TensorFlow в Java - несколько прогнозов за один сеанс - PullRequest
2 голосов
/ 12 марта 2019

У меня есть сохраненная модель, которую мне удается загрузить, запустить и получить прогноз для 1 ряда из 9 функций. (Вход) теперь я пытаюсь предсказать 100 строк, как это, но при попытке прочитать результаты из Tensor.copyTo () в массив результатов я получаю несовместимые формы

java.lang.IllegalArgumentException: cannot copy Tensor with shape [1, 1] into object with shape [100, 1]

очевидно, что мне удалось запустить это одно предсказание в цикле - но это в 20 раз медленнее, чем эквивалентное выполнение Python 100 за один запуск.

вот информация о сохраненной модели, сообщаемая /saved_model_cli.py

MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['input'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 9)
        name: dense_1_input:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['output'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: dense_4/BiasAdd:0
  Method name is: tensorflow/serving/predict

Вопрос в том - нужно ли мне запускать () для каждой строки, которую я хочу предсказать, как вопрос здесь

1 Ответ

2 голосов
/ 17 марта 2019

ОК, поэтому я обнаружил проблему, которую я не смог запустить один раз для всех строк (прогнозов), которые я хотел. вероятно, проблема новичка в тензорном потоке, которую я перепутал с матрицей ввода и вывода. когда инструмент отчета (python) скажет, что у вас есть входной Тензор с формой (-1,9), которая отображается на java long [] {1,9}, это не означает, что вы не можете передавать ввод как long [] {1000,9} - это означает 1000 строк для прогнозов. после этого ввода выходной тензор, который определяется как [1,1], может быть [1000,1].

Этот код на самом деле работает намного быстрее, чем Python (1,2 секунды против 7 секунд) вот код (может, лучше объясню)

public Tensor prepareData(){
    Random r = new Random();
    float[]inputArr = new float[NUMBER_OF_KEWORDS*NUMBER_OF_FIELDS];
    for (int i=0;i<NUMBER_OF_KEWORDS * NUMBER_OF_FIELDS;i++){
        inputArr[i] = r.nextFloat();
    }

    FloatBuffer inputBuff = FloatBuffer.wrap(inputArr, 0, NUMBER_OF_KEWORDS*NUMBER_OF_FIELDS);
    return Tensor.create(new long[]{NUMBER_OF_KEWORDS,NUMBER_OF_FIELDS}, inputBuff);
}

public void predict (Tensor inputTensor){
    try ( Session s = savedModelBundle.session()) {
        Tensor result;
        long globalStart = System.nanoTime();
            result = s.runner().feed("dense_1_input", inputTensor).fetch("dense_4/BiasAdd").run().get(0);

            final long[] rshape = result.shape();
            if (result.numDimensions() != 2 || rshape[0] <= NUMBER_OF_KEWORDS) {
                throw new RuntimeException(
                        String.format(
                                "Expected model to produce a [N,1] shaped tensor where N is the number of labels, instead it produced one with shape %s",
                                Arrays.toString(rshape)));
            }


        float[][] resultArray = (float[][]) result.copyTo(new float[NUMBER_OF_KEWORDS][1]);
        System.out.println(String.format("Total of %d,  took : %.4f ms", NUMBER_OF_KEWORDS, ((double) System.nanoTime() - globalStart) / 1000000));
        for (int i=0;i<10;i++){
            System.out.println(resultArray[i][0]);
        }
    }
}
...