Каков наилучший способ обработки больших данных с помощью Tensorflow.js и tf.Tensor? - PullRequest
3 голосов
/ 01 мая 2019

Вопрос

Я использую tf.Tensor и tf.concat() для обработки больших тренировочных данных, и я обнаружил, что непрерывное использование tf.concat() становится медленным.Каков наилучший способ загрузки больших данных из файла в tf.Tensor?

Фон

Я думаю, что это распространенный способ обработки данных по массивам в Javascript.чтобы достичь этого, вот грубые шаги, которые нужно сделать.

шаги для загрузки данных из файла в массив

  1. чтение строки из файла
  2. строка анализа для объекта Javascript
  3. добавить этот объект в массив на Array.push()
  4. после окончания чтения строки до конца, мы можем использовать этот массив с циклом for.

, так что я думаю, что яможно использовать tf.concat() аналогично описанному выше.

шагов для загрузки данных из файла в tf.Tensor

  1. чтение строки из файла
  2. анализ строки в JavascriptОбъект
  3. анализирует объект в tf.Tensor
  4. добавляет тензор к исходному тензору на tf.concat()
  5. после окончания чтения строки до конца, мы можем использовать этот tf.Tensor

Какой-то код

Вот некоторый код для измерения скорости Array.push() и tf.concat()

import * as tf from "@tensorflow/tfjs"

let t = tf.tensor1d([1])
let addT = tf.tensor1d([2])

console.time()
for (let idx = 0; idx < 50000; idx++) {
    if (idx % 1000 == 0) {
        console.timeEnd()
        console.time()
        console.log(idx)
    }
    t = tf.tidy(() => t.concat(addT))
}


let arr = []
let addA = 1
console.time()
for (let idx = 0; idx < 50000; idx++) {
    if (idx % 1000 == 0) {
        console.timeEnd()
        console.time()
        console.log(idx)
    }
    arr.push(addA)
}

Измерение

Мы видимстабильный процесс на Array.push(), но замедляется на tf.concat()

для tf.concat ()

default: 0.150ms
0
default: 68.725ms
1000
default: 62.922ms
2000
default: 23.199ms
3000
default: 21.093ms
4000
default: 27.808ms
5000
default: 39.689ms
6000
default: 34.798ms
7000
default: 45.502ms
8000
default: 94.526ms
9000
default: 51.996ms
10000
default: 76.529ms
11000
default: 83.662ms
12000
default: 45.730ms
13000
default: 89.119ms
14000
default: 49.171ms
15000
default: 48.555ms
16000
default: 55.686ms
17000
default: 54.857ms
18000
default: 54.801ms
19000
default: 55.312ms
20000
default: 65.760ms

для Array.push ()

default: 0.009ms
0
default: 0.388ms
1000
default: 0.340ms
2000
default: 0.333ms
3000
default: 0.317ms
4000
default: 0.330ms
5000
default: 0.289ms
6000
default: 0.299ms
7000
default: 0.291ms
8000
default: 0.320ms
9000
default: 0.284ms
10000
default: 0.343ms
11000
default: 0.327ms
12000
default: 0.317ms
13000
default: 0.329ms
14000
default: 0.307ms
15000
default: 0.218ms
16000
default: 0.193ms
17000
default: 0.234ms
18000
default: 1.943ms
19000
default: 0.164ms
20000
default: 0.148ms

Ответы [ 2 ]

1 голос
/ 01 мая 2019

Хотя функции tf.concat и Array.push выглядят и ведут себя одинаково, есть одно большое отличие:

  • tf.concat создает новый тензор из ввода
  • Array.push добавляет ввод в первый массив

Примеры

tf.concat

const a = tf.tensor1d([1, 2]);
const b = tf.tensor1d([3]);
const c = tf.concat([a, b]);

a.print(); // Result: Tensor [1, 2]
b.print(); // Result: Tensor [3]
c.print(); // Result: Tensor [1, 2, 3]

Результирующая переменная c является новым тензором, а a и b не изменяются.

Array.push

const a = [1,2];
a.push(3);

console.log(a); // Result: [1,2,3]

Здесь переменная a напрямую изменяется.

Влияние на время выполнения

Для скорости выполнения это означает, что tf.concat копирует все значения тензора в новый тензор перед добавлением ввода. Очевидно, это занимает больше времени, чем больше массив, который нужно скопировать. В отличие от этого, Array.push не создает копию массива, и поэтому время выполнения будет более или менее одинаковым, независимо от размера массива.

Обратите внимание, что это «по замыслу», поскольку тензоры неизменны, поэтому каждая операция над существующим тензором всегда создает новый тензор. Цитата из документов :

Тензорные переменные являются неизменяемыми, поэтому все операции всегда возвращают новые Тензорные и никогда не изменяют входные Тензорные.

Поэтому, если вам нужно создать большой тензор из входных данных, рекомендуется сначала прочитать все данные из вашего файла и объединить их с «ванильными» функциями JavaScript, прежде чем создавать из них тензор.

Обработка данных слишком велика для памяти

Если у вас такой большой набор данных, что вам нужно обрабатывать его порциями из-за ограничений памяти, у вас есть два варианта:

  1. Используйте функцию trainOnBatch
  2. Использовать генератор набора данных

Вариант 1: trainOnBatch

Функция trainOnBatch позволяет обучаться на пакете данных вместо использования полного набора данных к нему. Таким образом, вы можете разбить свой код на разумные партии перед их обучением, чтобы вам не приходилось объединять данные одновременно.

Вариант 2: генератор наборов данных

Другой ответ уже прошел основы. Это позволит вам использовать функцию генератора JavaScript для подготовки данных. Я рекомендую использовать синтаксис генератора вместо фабрики итераторов (используется в другом ответе), поскольку это более современный синтаксис JavaScript.

Пример (взято из документов ):

function* dataGenerator() {
  const numElements = 10;
  let index = 0;
  while (index < numElements) {
    const x = index;
    index++;
    yield x;
  }
}

const ds = tf.data.generator(dataGenerator);

Затем вы можете использовать функцию fitDataset для обучения вашей модели.

0 голосов
/ 01 мая 2019

Хотя не существует единого способа создания тензора, ответ на вопрос заключается в том, что делается с созданными тензорами.

Производительность

тензоры неизменны, поэтому каждый раз, когда tf.concat называется, создается новый тензор.

let x = tf.tensor1d([2]);
console.log(tf.memory()) // "numTensors": 1
const y = tf.tensor1d([3])
x = tf.concat([x, y])
console.log(tf.memory()) // "numTensors": 3, 
<html>
  <head>
    <!-- Load TensorFlow.js -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.14.1"> </script>
  </head>

  <body>
  </body>
</html>

Как видно из приведенного выше фрагмента, число тензоров, создаваемых при вызове tf.concat, равно 3 , а не 2 .Это правда, что tf.tidy избавится от неиспользованных тензоров.Но эта операция создания и удаления тензоров станет самой дорогостоящей, поскольку создаваемый тензор становится все больше и больше.Это является проблемой потребления памяти и вычислений, поскольку создание нового тензора всегда делегирует бэкэнду.


создание тензора из больших данных

Теперь, когда проблема производительности понятнаКаков наилучший способ продолжить?

  • создать весь массив в js, а когда весь массив будет завершен, затем создать тензор.
for (i= 0; i < data.length; i++) {
  // fill array x
  x.push(dataValue)
}
// create the tensor
tf.tensor(x)

Хотя, это тривиальное решение, это не всегда возможно.Потому что создание массива будет хранить данные в памяти, и мы можем легко исчерпать память с большими записями данных.Поэтому иногда может быть лучше вместо создания всего массива javascript создать массив массивов, создать тензор из этих массивов и начать обрабатывать их, как только они будут созданы.При необходимости можно объединить тензоры порций, используя tf.concat.Но это может не всегда требоваться.

Например, мы можем вызывать model.fit () многократно, используя кусок тензоров, вместо того, чтобы вызывать его один раз с большим тензором, создание которого может занять много времени.В этом случае нет необходимости объединять тензоры порций.

  • , если возможно, создать набор данных с использованием tf.data.Это идеальное решение, если мы рядом с моделью для данных.
function makeIterator() {

  const iterator = {
    next: () => {
      let result;
      if (index < data.length) {
        result = {value: dataValue, done: false};
        index++;
        return result;
      }
      return {value: dataValue, done: true};
    }
  };
  return iterator;
}
const ds = tf.data.generator(makeIterator);

Преимущество использования tf.data состоит в том, что весь набор данных создается пакетами, когда это необходимо во время model.fit звонок.

...