Tensorflow.js: контекст WebGL потерян при конкатенации тензоров - PullRequest
0 голосов
/ 12 октября 2018

Я играю с tenorflow.js. Изучаю исходный код учебное пособие / руководство и получаю следующую ошибку при объединении двух тензоров:

Couldn't parse line number in error:                      tfjs@0.13.0:2 

  precision highp float;                                  tfjs@0.13.0:2 
  precision highp int;
  varying vec2 resultUV;
  const vec2 halfCR = vec2(0.5, 0.5);

  struct ivec5
  {
    int x;
    int y;
    int z;
    int w;
    int u;
  };

  struct ivec6
  {
    int x;
    int y;
    int z;
    int w;
    int u;
    int v;
  };

  bool isNaN(float val) {
    return (val < 0.0 || 0.0 < val || val == 0.0) ? false : true;
  }

  bool hasNaN(vec4 values) {
    vec4 v1 = values * values;
    vec4 v2 = values * values;
    return any(notEqual(v1, v2));
  }

  float getNaN(vec4 values) {
    return dot(vec4(1), values);
  }

  int round(float value) {
    return int(floor(value + 0.5));
  }

  int imod(int x, int y) {
    return x - y * (x / y);
  }

  //Based on the work of Dave Hoskins
  //https://www.shadertoy.com/view/4djSRW
  #define HASHSCALE1 443.8975
  float random(float seed){
    vec2 p = resultUV * seed;
    vec3 p3  = fract(vec3(p.xyx) * HASHSCALE1);
    p3 += dot(p3, p3.yzx + 19.19);
    return fract((p3.x + p3.y) * p3.z);
  }


vec2 UVfrom1D(int texNumR, int texNumC, int index) {
  int texR = index / texNumC;
  int texC = index - texR * texNumC;
  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
}


vec2 UVfrom2D(int texNumR, int texNumC, int numC, int row, int col) {
  int index = row * numC + col;
  int texR = index / texNumC;
  int texC = index - texR * texNumC;
  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
}


vec2 UVfrom3D(int texNumR, int texNumC, int stride0,
    int stride1, int row, int col, int depth) {
  // Explicitly use integer operations as dot() only works on floats.
  int index = row * stride0 + col * stride1 + depth;
  int texR = index / texNumC;
  int texC = index - texR * texNumC;
  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
}


vec2 UVfrom4D(int texNumR, int texNumC, int stride0,
    int stride1, int stride2, int row, int col, int depth,
    int depth2) {
  // Explicitly use integer operations as dot() only works on floats.
  int index = row * stride0 + col * stride1 + depth * stride2 + depth2;
  int texR = index / texNumC;
  int texC = index - texR * texNumC;
  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
}


vec2 UVfrom5D(int texNumR, int texNumC, int stride0,
    int stride1, int stride2, int stride3, int row, int col, int depth,
    int depth2, int depth3) {
  // Explicitly use integer operations as dot() only works on floats.
  int index = row * stride0 + col * stride1 +
              depth * stride2 + depth2 * stride3 + depth3;
  int texR = index / texNumC;
  int texC = index - texR * texNumC;
  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
}


vec2 UVfrom6D(int texNumR, int texNumC, int stride0,
    int stride1, int stride2, int stride3, int stride4,
    int row, int col, int depth, int depth2, int depth3, int depth4) {
  // Explicitly use integer operations as dot() only works on floats.
  int index = row * stride0 + col * stride1 + depth * stride2 + depth2 *
    stride3 + depth3 * stride4 + depth4;
  int texR = index / texNumC;
  int texC = index - texR * texNumC;
  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
}



  float sampleTexture(sampler2D textureSampler, vec2 uv) {
    return texture2D(textureSampler, uv).r;
  }


  void setOutput(float val) {
    gl_FragColor = vec4(val, 0, 0, 0);
  }

uniform sampler2D A;
uniform sampler2D B;

      ivec2 getOutputCoords() {
        ivec2 resTexRC = ivec2(resultUV.yx *
                               vec2(1984, 2352));
        int index = resTexRC.x * 2352 + resTexRC.y;
        return ivec2(0, index);
      }


    float getAFlat(int index) {
      vec2 uv = UVfrom1D(1792, 2597, index);
      return sampleTexture(A, uv);
    }


    float getA(int index) {
      return getAFlat(index);
    }

      float getA(int row, int col) {
        return getA(col);
      }


    float getBFlat(int index) {
      vec2 uv = UVfrom1D(7, 1792, index);
      return sampleTexture(B, uv);
    }


    float getB(int index) {
      return getBFlat(index);
    }

      float getB(int row, int col) {
        return getB(col);
      }


      void main() {
        ivec2 coords = getOutputCoords();
        int yR = coords.x;
        int yC = coords.y;

        float value = 0.0;
        if (yC < 4653824) {
          value = getA(yR, yC);
        } else {
          yC -= 4653824;
          value = getB(yR, yC);
        }

        setOutput(value);
      }


Uncaught Error: Failed to compile fragment shader.
at createFragmentShader (tfjs@0.13.0:2)
at e.createProgram (tfjs@0.13.0:2)
at compileProgram (tfjs@0.13.0:2)
at tfjs@0.13.0:2
at e.getAndSaveBinary (tfjs@0.13.0:2)
at e.compileAndRun (tfjs@0.13.0:2)
at e.concat2Tensors (tfjs@0.13.0:2)
at e.concat (tfjs@0.13.0:2)
at tfjs@0.13.0:2
at tfjs@0.13.0:2

WebGL: CONTEXT_LOST_WEBGL: loseContext: context lost

Uncaught Error: Unable to create fragment WebGLShader.
at throwIfNull (tfjs@0.13.0:2)
at createFragmentShader (tfjs@0.13.0:2)
at e.createProgram (tfjs@0.13.0:2)
at compileProgram (tfjs@0.13.0:2)
at tfjs@0.13.0:2
at e.getAndSaveBinary (tfjs@0.13.0:2)
at e.compileAndRun (tfjs@0.13.0:2)
at e.concat2Tensors (tfjs@0.13.0:2)
at e.concat (tfjs@0.13.0:2)
at tfjs@0.13.0:2

Я создаю приложение, котороепринимает аудиосигнал через микрофонный вход ноутбука и связывает частоты сигнала с изображениями, снятыми с веб-камеры ноутбука.Я подаю сигнал электрогитары на микрофонный вход для ручного управления частотой, и у меня есть функция onaudioprocess API-интерфейса Web audio API для захвата частотных данных.

Когда частота достаточно чистая, изображение захватывается из потока веб-камеры, а затем преобразуется в тензор с помощью метода tf.fromPixels и передается через усеченную модель мобильной сети для получения внутренних активаций для последующего использования.В первом раунде внутренние активации из усеченной модели сохраняются в переменную, и после первого раза новые внутренние активации объединяются с предыдущей активацией с помощью метода concat ().Все это происходит много раз в секунду, если частота входного сигнала стабильна и чиста.Это прекрасно работает некоторое время, но после того, как конкатенированный тензор достиг размера 4678912, программа вылетает и выдает ошибку, подробно описанную выше.Я не уверен, что здесь важен размер тензора.

Я запускаю приложение в браузере Chrome.

Вот функция конкатенации, которая вызывает ошибку, которую я предполагаю:

addExample(example, label) {
// One-hot encode the label.

    const y = tf.tidy(() => tf.oneHot(tf.tensor1d([label]).toInt(), this.numClasses));

    if (this.xs == null) {

      // For the first example that gets added, keep example and y so that the
      // ControllerDataset owns the memory of the inputs. This makes sure that
      // if addExample() is called in a tf.tidy(), these Tensors will not get
      // disposed.
      this.xs = tf.keep(example);
      this.ys = tf.keep(y);

    } else {
      const oldX = this.xs;
      this.xs = tf.keep(oldX.concat(example, 0));

      const oldY = this.ys;
      this.ys = tf.keep(oldY.concat(y, 0));

      oldX.dispose();
      oldY.dispose();
      y.dispose();
    }
}

А вот конкатенированный тензор непосредственно перед сбоем:

e {isDisposedInternal: false, shape: Array(4), dtype: "float32", size: 
4678912, strides: Array(3), …}
dataId: {}
dtype: "float32"
id: 117079
isDisposed: (...)
isDisposedInternal: false
rank: (...)
rankType: "4"
shape: Array(4)
    0: 373
    1: 7
    2: 7
    3: 256
    length: 4
    __proto__: Array(0)
size: 4678912
strides: Array(3)
    0: 12544
    1: 1792
    2: 256
    length: 3
    __proto__: Array(0)
__proto__: Object

Ошибка появляется также, когда я пытаюсь оригинальная демоверсия (Pacman-game) и добавить 300-400примеры для одного из четырех контроллеров.Основная логика в моем приложении такая же, как и в оригинальной демоверсии.Отличается количество классов (48 классов, представляющих разные частоты нот от электрогитары) и способ добавления примеров в ScriptProcessorNode.Также объем необходимых примеров гораздо больше.

Я не знаю, с чего начать копаться в ошибке.Мои знания webGL - 0. Любая помощь приветствуется.

...