Я играю с 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. Любая помощь приветствуется.