UNPKG

@tensorflow/tfjs-core

Version:

Hardware-accelerated JavaScript library for machine intelligence

363 lines 16.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tf = require("../index"); var test_util_1 = require("../test_util"); var jasmine_util_1 = require("../jasmine_util"); var matmul_1 = require("./matmul"); jasmine_util_1.describeWithFlags('matmul', test_util_1.ALL_ENVS, function () { it('A x B', function () { var a = tf.tensor2d([1, 2, 3, 4, 5, 6], [2, 3]); var b = tf.tensor2d([0, 1, -3, 2, 2, 1], [3, 2]); var c = tf.matMul(a, b); expect(c.shape).toEqual([2, 2]); test_util_1.expectArraysClose(c, [0, 8, -3, 20]); }); it('A x B^t', function () { var a = tf.tensor2d([1, 2, 3, 4, 5, 6], [2, 3]); var b = tf.tensor2d([1, 0, 2, 4, 3, 0], [2, 3]); var transposeA = false; var transposeB = true; var c = tf.matMul(a, b, transposeA, transposeB); var expected = [7, 10, 16, 31]; test_util_1.expectArraysClose(c, expected); }); it('A^t x B', function () { var a = tf.tensor2d([1, 2, 3, 4, 5, 6], [2, 3]); var b = tf.tensor2d([1, 0, 2, 4, 3, 0], [2, 3]); var transposeA = true; var transposeB = false; var c = tf.matMul(a, b, transposeA, transposeB); var expected = [17, 12, 2, 22, 15, 4, 27, 18, 6]; test_util_1.expectArraysClose(c, expected); }); it('A^t x B^t', function () { var a = tf.tensor2d([1, 2, 3, 4, 5, 6], [3, 2]); var b = tf.tensor2d([1, 0, 2, 4, 3, 0], [2, 3]); var transposeA = true; var transposeB = true; var c = tf.matMul(a, b, transposeA, transposeB); var expected = [11, 13, 14, 20]; test_util_1.expectArraysClose(c, expected); }); it('A x B^t shapes do not match', function () { var a = tf.zeros([2, 3]); var b = tf.zeros([3, 2]); var f = function () { var transposeA = false; var transposeB = true; tf.matMul(a, b, transposeA, transposeB); }; expect(f).toThrowError(); }); it('A^t x B shapes do not match', function () { var a = tf.zeros([2, 3]); var b = tf.zeros([3, 2]); var f = function () { var transposeA = true; var transposeB = false; tf.matMul(a, b, transposeA, transposeB); }; expect(f).toThrowError(); }); it('A^t x B^t shapes do not match', function () { var a = tf.zeros([3, 2]); var b = tf.zeros([3, 2]); var f = function () { var transposeA = true; var transposeB = true; tf.matMul(a, b, transposeA, transposeB); }; expect(f).toThrowError(); }); it('matmul throws when inner dimensions dont match', function () { var a = tf.tensor2d([1, 2, 3, 4, 5, 6], [2, 3]); var b = tf.tensor2d([0, 1, -3, 2, 2, 1, 2, 2], [4, 2]); expect(function () { return tf.matMul(a, b); }).toThrowError(); }); it('matmul throws when passed non matrices', function () { var a = tf.tensor3d([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [2, 3, 2]); var b = tf.tensor2d([0, 1, -3, 2, 2, 1, 2, 2], [4, 2]); expect(function () { return tf.matMul(a, b); }).toThrowError(); expect(function () { return tf.matMul(b, a); }).toThrowError(); }); it('Vector times matrix', function () { var v = tf.tensor1d([2, 3]); var matrix = tf.tensor2d([1, 2, 3, 4], [2, 2]); var result = tf.vectorTimesMatrix(v, matrix); var expected = [11, 16]; test_util_1.expectArraysClose(result, expected); }); it('Vector times matrix with implicit reshape', function () { var v = tf.tensor1d([2, 3]); var matrix = tf.tensor2d([1, 2, 3, 4], [2, 2]); var result = tf.vectorTimesMatrix(v, matrix); var expected = [11, 16]; test_util_1.expectArraysClose(result, expected); }); it('Vector times matrix throws when not passed a vector', function () { var v = tf.tensor2d([1, 2, 3, 4], [2, 2]); var matrix = tf.tensor2d([1, 2, 3, 4], [2, 2]); expect(function () { return tf.vectorTimesMatrix(v, matrix); }).toThrowError(); }); it('Vector times matrix throws when not passed a matrix', function () { var v = tf.tensor1d([2, 3]); var matrix = tf.tensor3d([1, 2, 3, 4, 5, 6, 7, 8], [2, 2, 2]); expect(function () { return tf.vectorTimesMatrix(v, matrix); }).toThrowError(); }); it('Matrix times vector', function () { var matrix = tf.tensor2d([1, 2, 3, 4], [2, 2]); var v = tf.tensor1d([2, 3]); var result = tf.matrixTimesVector(matrix, v); var expected = [8, 18]; test_util_1.expectArraysClose(result, expected); }); it('Matrix * vector propagates NaNs', function () { var matrix = tf.tensor2d([1, 2, 3, 4], [2, 2]); var v = tf.tensor1d([2, NaN]); var result = tf.matrixTimesVector(matrix, v); var expected = [NaN, NaN]; test_util_1.expectArraysClose(result, expected); }); it('matrix times vector throws when not passed a vector', function () { var v = tf.tensor2d([1, 2, 3, 4], [2, 2]); var matrix = tf.tensor2d([1, 2, 3, 4], [2, 2]); expect(function () { return tf.matrixTimesVector(matrix, v); }).toThrowError(); }); it('matrix times vector throws when not passed a matrix', function () { var v = tf.tensor1d([2, 3]); var matrix = tf.tensor3d([1, 2, 3, 4, 5, 6, 7, 8], [2, 2, 2]); expect(function () { return tf.matrixTimesVector(matrix, v); }).toThrowError(); }); it('Dot product', function () { var v1 = tf.tensor1d([2, 3]); var v2 = tf.tensor1d([2, 1]); var result = matmul_1.MatmulOps.dotProduct(v1, v2); test_util_1.expectNumbersClose(result.get(), 7); }); it('Dot product propagates NaNs', function () { var v1 = tf.tensor1d([2, NaN]); var v2 = tf.tensor1d([2, 1]); var result = matmul_1.MatmulOps.dotProduct(v1, v2); expect(result.get()).toEqual(NaN); }); it('Dot product throws when vectors are different size', function () { var v1 = tf.tensor1d([2, 3, 3]); var v2 = tf.tensor1d([2, 1]); expect(function () { return matmul_1.MatmulOps.dotProduct(v1, v2); }).toThrowError(); expect(function () { return matmul_1.MatmulOps.dotProduct(v2, v1); }).toThrowError(); }); it('Dot product throws when passed non vectors', function () { var v1 = tf.tensor2d([1, 2, 3, 3], [2, 2]); var v2 = tf.tensor1d([2, 1]); expect(function () { return matmul_1.MatmulOps.dotProduct(v1, v2); }).toThrowError(); expect(function () { return matmul_1.MatmulOps.dotProduct(v2, v1); }).toThrowError(); }); it('Outer product', function () { var v1 = tf.tensor1d([2, 3]); var v2 = tf.tensor1d([2, 1]); var result = tf.outerProduct(v1, v2); var expected = [4, 2, 6, 3]; expect(result.shape).toEqual([2, 2]); test_util_1.expectArraysClose(result, expected); }); it('gradients: A * B', function () { var a = tf.tensor2d([1, 2, 3, 10, 20, 30], [2, 3]); var b = tf.tensor2d([2, 3, 4, 1, 2, 3], [3, 2]); var dy = tf.tensor2d([1, 10, 20, 30], [2, 2]); var transposeA = false; var transposeB = false; var grads = tf.grads(function (a, b) { return tf.matMul(a, b, transposeA, transposeB); }); var _a = grads([a, b], dy), da = _a[0], db = _a[1]; expect(da.shape).toEqual(a.shape); test_util_1.expectArraysClose(da, [ dy.get(0, 0) * b.get(0, 0) + dy.get(0, 1) * b.get(0, 1), dy.get(0, 0) * b.get(1, 0) + dy.get(0, 1) * b.get(1, 1), dy.get(0, 0) * b.get(2, 0) + dy.get(0, 1) * b.get(2, 1), dy.get(1, 0) * b.get(0, 0) + dy.get(1, 1) * b.get(0, 1), dy.get(1, 0) * b.get(1, 0) + dy.get(1, 1) * b.get(1, 1), dy.get(1, 0) * b.get(2, 0) + dy.get(1, 1) * b.get(2, 1) ], 1e-1); expect(db.shape).toEqual(b.shape); test_util_1.expectArraysClose(db, [ a.get(0, 0) * dy.get(0, 0) + a.get(1, 0) * dy.get(1, 0), a.get(0, 0) * dy.get(0, 1) + a.get(1, 0) * dy.get(1, 1), a.get(0, 1) * dy.get(0, 0) + a.get(1, 1) * dy.get(1, 0), a.get(0, 1) * dy.get(0, 1) + a.get(1, 1) * dy.get(1, 1), a.get(0, 2) * dy.get(0, 0) + a.get(1, 2) * dy.get(1, 0), a.get(0, 2) * dy.get(0, 1) + a.get(1, 2) * dy.get(1, 1) ]); }); it('gradients: a * bT', function () { var a = tf.tensor2d([1, 2, 3, 10, 20, 30], [3, 2]); var b = tf.tensor2d([2, 3, 4, 1, 2, 3], [3, 2]); var dy = tf.tensor2d([1, 10, 20, 30, 40, 50, 60, 70, 80], [3, 3]); var transposeA = false; var transposeB = true; var grads = tf.grads(function (a, b) { return tf.matMul(a, b, transposeA, transposeB); }); var _a = grads([a, b], dy), da = _a[0], db = _a[1]; expect(da.shape).toEqual(a.shape); test_util_1.expectArraysClose(da, [ dy.get(0, 0) * b.get(0, 0) + dy.get(0, 1) * b.get(1, 0) + dy.get(0, 2) * b.get(2, 0), dy.get(0, 0) * b.get(0, 1) + dy.get(0, 1) * b.get(1, 1) + dy.get(0, 2) * b.get(2, 1), dy.get(1, 0) * b.get(0, 0) + dy.get(1, 1) * b.get(1, 0) + dy.get(1, 2) * b.get(2, 0), dy.get(1, 0) * b.get(0, 1) + dy.get(1, 1) * b.get(1, 1) + dy.get(1, 2) * b.get(2, 1), dy.get(2, 0) * b.get(0, 0) + dy.get(2, 1) * b.get(1, 0) + dy.get(2, 2) * b.get(2, 0), dy.get(2, 0) * b.get(0, 1) + dy.get(2, 1) * b.get(1, 1) + dy.get(2, 2) * b.get(2, 1) ]); expect(db.shape).toEqual(b.shape); test_util_1.expectArraysClose(db, [ dy.get(0, 0) * a.get(0, 0) + dy.get(1, 0) * a.get(1, 0) + dy.get(2, 0) * a.get(2, 0), dy.get(0, 0) * a.get(0, 1) + dy.get(1, 0) * a.get(1, 1) + dy.get(2, 0) * a.get(2, 1), dy.get(0, 1) * a.get(0, 0) + dy.get(1, 1) * a.get(1, 0) + dy.get(2, 1) * a.get(2, 0), dy.get(0, 1) * a.get(0, 1) + dy.get(1, 1) * a.get(1, 1) + dy.get(2, 1) * a.get(2, 1), dy.get(0, 2) * a.get(0, 0) + dy.get(1, 2) * a.get(1, 0) + dy.get(2, 2) * a.get(2, 0), dy.get(0, 2) * a.get(0, 1) + dy.get(1, 2) * a.get(1, 1) + dy.get(2, 2) * a.get(2, 1) ]); }); it('gradients: aT * b', function () { var a = tf.tensor2d([1, 2, 3, 10, 20, 30], [3, 2]); var b = tf.tensor2d([2, 3, 4, 1, 2, 3], [3, 2]); var dy = tf.tensor2d([1, 10, 20, 30], [2, 2]); var transposeA = true; var transposeB = false; var grads = tf.grads(function (a, b) { return tf.matMul(a, b, transposeA, transposeB); }); var _a = grads([a, b], dy), da = _a[0], db = _a[1]; expect(da.shape).toEqual(a.shape); test_util_1.expectArraysClose(da, [ dy.get(0, 0) * b.get(0, 0) + dy.get(0, 1) * b.get(0, 1), dy.get(1, 0) * b.get(0, 0) + dy.get(1, 1) * b.get(0, 1), dy.get(0, 0) * b.get(1, 0) + dy.get(0, 1) * b.get(1, 1), dy.get(1, 0) * b.get(1, 0) + dy.get(1, 1) * b.get(1, 1), dy.get(0, 0) * b.get(2, 0) + dy.get(0, 1) * b.get(2, 1), dy.get(1, 0) * b.get(2, 0) + dy.get(1, 1) * b.get(2, 1) ]); expect(db.shape).toEqual(b.shape); test_util_1.expectArraysClose(db, [ dy.get(0, 0) * a.get(0, 0) + dy.get(1, 0) * a.get(0, 1), dy.get(0, 1) * a.get(0, 0) + dy.get(1, 1) * a.get(0, 1), dy.get(0, 0) * a.get(1, 0) + dy.get(1, 0) * a.get(1, 1), dy.get(0, 1) * a.get(1, 0) + dy.get(1, 1) * a.get(1, 1), dy.get(0, 0) * a.get(2, 0) + dy.get(1, 0) * a.get(2, 1), dy.get(0, 1) * a.get(2, 0) + dy.get(1, 1) * a.get(2, 1) ]); }); it('gradients: aT * bT', function () { var a = tf.tensor2d([1, 2, 3, 10, 20, 30], [3, 2]); var b = tf.tensor2d([2, 3, 4, 1, 2, 3], [2, 3]); var dy = tf.tensor2d([1, 10, 20, 30], [2, 2]); var transposeA = true; var transposeB = true; var grads = tf.grads(function (a, b) { return tf.matMul(a, b, transposeA, transposeB); }); var _a = grads([a, b], dy), da = _a[0], db = _a[1]; expect(da.shape).toEqual(a.shape); test_util_1.expectArraysClose(da, [ dy.get(0, 0) * b.get(0, 0) + dy.get(0, 1) * b.get(1, 0), dy.get(1, 0) * b.get(0, 0) + dy.get(1, 1) * b.get(1, 0), dy.get(0, 0) * b.get(0, 1) + dy.get(0, 1) * b.get(1, 1), dy.get(1, 0) * b.get(0, 1) + dy.get(1, 1) * b.get(1, 1), dy.get(0, 0) * b.get(0, 2) + dy.get(0, 1) * b.get(1, 2), dy.get(1, 0) * b.get(0, 2) + dy.get(1, 1) * b.get(1, 2) ]); expect(db.shape).toEqual(b.shape); test_util_1.expectArraysClose(db, [ dy.get(0, 0) * a.get(0, 0) + dy.get(1, 0) * a.get(0, 1), dy.get(0, 0) * a.get(1, 0) + dy.get(1, 0) * a.get(1, 1), dy.get(0, 0) * a.get(2, 0) + dy.get(1, 0) * a.get(2, 1), dy.get(0, 1) * a.get(0, 0) + dy.get(1, 1) * a.get(0, 1), dy.get(0, 1) * a.get(1, 0) + dy.get(1, 1) * a.get(1, 1), dy.get(0, 1) * a.get(2, 0) + dy.get(1, 1) * a.get(2, 1) ]); }); it('throws when passed a as a non-tensor', function () { expect(function () { return tf.matMul({}, tf.tensor2d([2], [1, 1])); }) .toThrowError(/Argument 'a' passed to 'matMul' must be a Tensor/); }); it('throws when passed b as a non-tensor', function () { expect(function () { return tf.matMul(tf.tensor2d([2], [1, 1]), {}); }) .toThrowError(/Argument 'b' passed to 'matMul' must be a Tensor/); }); }); jasmine_util_1.describeWithFlags('matmul webgl-only', test_util_1.WEBGL_ENVS, function () { it('Matrix times vector, large matrix', function () { var maxTexSize = 16000; var sharedDim = maxTexSize + 4; var matrix = tf.buffer([2, sharedDim], 'float32'); matrix.set(1, 0, sharedDim - 3); matrix.set(1, 0, sharedDim - 2); var v = tf.buffer([sharedDim], 'float32'); v.set(1, sharedDim - 3); v.set(1, sharedDim - 2); var result = tf.matrixTimesVector(matrix.toTensor(), v.toTensor()); var expected = [2, 0]; test_util_1.expectArraysClose(result, expected); }); }); jasmine_util_1.describeWithFlags('dot', test_util_1.ALL_ENVS, function () { var a; var b; var c; var d; var e; beforeEach(function () { a = tf.tensor1d([1, 2]); b = tf.tensor2d([[1, 2], [3, 4]]); c = tf.tensor2d([[1, 2, 3], [4, 5, 6]]); d = tf.tensor3d([1, 2], [1, 1, 2]); e = tf.scalar(1); }); it('vector-vector', function () { var aa = tf.dot(a, a); test_util_1.expectArraysClose(aa, [5]); expect(aa.shape).toEqual([]); }); it('vector-matrix', function () { var ab = tf.dot(a, b); var ac = tf.dot(a, c); expect(ab.shape).toEqual([2]); expect(ac.shape).toEqual([3]); test_util_1.expectArraysClose(ab, [7, 10]); test_util_1.expectArraysClose(ac, [9, 12, 15]); }); it('matrix-vector', function () { var ba = b.dot(a); expect(ba.shape).toEqual([2]); test_util_1.expectArraysClose(ba, [5, 11]); }); it('matrix-matrix', function () { var bb = tf.dot(b, b); var bc = tf.dot(b, c); expect(bb.shape).toEqual([2, 2]); expect(bc.shape).toEqual([2, 3]); test_util_1.expectArraysClose(bb, [7, 10, 15, 22]); test_util_1.expectArraysClose(bc, [9, 12, 15, 19, 26, 33]); }); it('throws error on incompatible dimensions', function () { expect(function () { return tf.dot(c, a); }).toThrowError(); expect(function () { return tf.dot(c, b); }).toThrowError(); }); it('throws error when inputs are not rank 1 or 2', function () { expect(function () { return tf.dot(a, d); }).toThrowError(); expect(function () { return tf.dot(a, e); }).toThrowError(); }); }); //# sourceMappingURL=matmul_test.js.map