diff --git a/README.md b/README.md index d606418cd7..1b6c9ada14 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ See the [TypeScript starter project](https://github.com/PAIR-code/deeplearnjs/tr short example that sums an array with a scalar (broadcasted): ```ts -import {Array1D, NDArrayMathGPU, Scalar} from 'deeplearn'; +import {Array1D, ENV, Scalar} from 'deeplearn'; -const math = new NDArrayMathGPU(); +const math = ENV.math; const a = Array1D.new([1, 2, 3]); const b = Scalar.new(2); @@ -63,7 +63,7 @@ After importing the library, the API will be available as `dl` in the global namespace. ```js -var math = new dl.NDArrayMathGPU(); +var math = dl.ENV.math; var a = dl.Array1D.new([1, 2, 3]); var b = dl.Scalar.new(2); diff --git a/demos/adder/adder.ts b/demos/adder/adder.ts index 55ee2cd9d9..36dc9e58ef 100644 --- a/demos/adder/adder.ts +++ b/demos/adder/adder.ts @@ -15,13 +15,13 @@ * ============================================================================= */ -import {NDArrayMathGPU, Scalar} from 'deeplearn'; +import {ENV, Scalar} from 'deeplearn'; const outputElement = document.getElementById('output'); const inA: HTMLInputElement = document.getElementById('A') as HTMLInputElement; const inB: HTMLInputElement = document.getElementById('B') as HTMLInputElement; -const math = new NDArrayMathGPU(); +const math = ENV.math; export async function execute(event?: Event) { const a = Scalar.new(+inA.value); diff --git a/demos/benchmarks/batchnormalization3d_benchmark.ts b/demos/benchmarks/batchnormalization3d_benchmark.ts index eb6fd1db62..0047bdfc34 100644 --- a/demos/benchmarks/batchnormalization3d_benchmark.ts +++ b/demos/benchmarks/batchnormalization3d_benchmark.ts @@ -15,7 +15,7 @@ * ============================================================================= */ // tslint:disable-next-line:max-line-length -import {Array1D, Array3D, NDArrayMathCPU, NDArrayMathGPU} from 'deeplearn'; +import {Array1D, Array3D, ENV, NDArrayMath} from 'deeplearn'; import {BenchmarkTest, LAST_RUN_CPU_CUTOFF_MS} from './benchmark'; import * as benchmark_util from './benchmark_util'; @@ -29,7 +29,9 @@ export class BatchNormalization3DCPUBenchmark implements BenchmarkTest { resolve(-1); }); } - const math = new NDArrayMathCPU(); + const safeMode = false; + const math = new NDArrayMath('cpu', safeMode); + ENV.setMath(math); const x = Array3D.randUniform([size, size, 8], -1, 1); const mean = Array1D.new([0]); const variance = Array1D.new([1]); @@ -48,7 +50,9 @@ export class BatchNormalization3DCPUBenchmark implements BenchmarkTest { export class BatchNormalization3DGPUBenchmark implements BenchmarkTest { async run(size: number) { - const math = new NDArrayMathGPU(); + const safeMode = false; + const math = new NDArrayMath('webgl', safeMode); + ENV.setMath(math); const x = Array3D.randUniform([size, size, 8], -1, 1); const mean = Array1D.new([0]); const variance = Array1D.new([1]); diff --git a/demos/benchmarks/benchmark_util.ts b/demos/benchmarks/benchmark_util.ts index 08c31d3f79..0db349ef11 100644 --- a/demos/benchmarks/benchmark_util.ts +++ b/demos/benchmarks/benchmark_util.ts @@ -1,35 +1,12 @@ -import {ENV, NDArray, NDArrayMathGPU} from 'deeplearn'; +import {NDArray, NDArrayMath} from 'deeplearn'; export async function warmupAndBenchmarkGPU( - math: NDArrayMathGPU, benchmark: () => NDArray): Promise { - const gpgpu = math.getGPGPUContext(); - - let out: NDArray; - const saveOutputBenchmark = () => { - out = benchmark(); - }; - + math: NDArrayMath, benchmark: () => NDArray): Promise { // Warmup. - if (ENV.get('WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_ENABLED')) { - await gpgpu.runQuery(saveOutputBenchmark); - } else { - saveOutputBenchmark(); - out.dataSync(); - } - out.dispose(); - - let totalTime: number; - if (ENV.get('WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE')) { - totalTime = await gpgpu.runQuery(saveOutputBenchmark); - } else { - const start = performance.now(); - - saveOutputBenchmark(); - out.dataSync(); - - totalTime = performance.now() - start; - } + const out = benchmark(); + await out.data(); out.dispose(); - return totalTime; + // Real timing. + return math.time(benchmark); } diff --git a/demos/benchmarks/benchmarks.ts b/demos/benchmarks/benchmarks.ts index 70fe4abb2f..529ec15dc4 100644 --- a/demos/benchmarks/benchmarks.ts +++ b/demos/benchmarks/benchmarks.ts @@ -179,7 +179,7 @@ export class MathBenchmark extends MathBenchmarkPolymer { return runNumberRowElement; } - private runBenchmarkSteps( + private async runBenchmarkSteps( chart: Chart, runGroup: BenchmarkRunGroup, benchmarkRunGroupIndex: number, step: number) { const runNumbersTable = @@ -207,7 +207,6 @@ export class MathBenchmark extends MathBenchmarkPolymer { const runNumberRowElement = document.createElement('div'); runNumberRowElement.className = 'run-numbers-row math-benchmark'; - const runPromises: Array> = []; const rowValues: string[] = [step.toString()]; for (let i = 0; i < runGroup.benchmarkRuns.length; i++) { const run = runGroup.benchmarkRuns[i]; @@ -218,48 +217,23 @@ export class MathBenchmark extends MathBenchmarkPolymer { step; const opType = runGroup.selectedOption; - runPromises.push(test.run(size, opType, runGroup.params[opType])); - } - - Promise.all(runPromises).then(results => { - for (let i = 0; i < runGroup.benchmarkRuns.length; i++) { - const benchmarkRun = runGroup.benchmarkRuns[i]; - - const size = runGroup.stepToSizeTransformation != null ? - runGroup.stepToSizeTransformation(step) : - step; - - let resultString: string; - let logString: string; - let time = 0; - let success = true; - try { - time = results[i]; - resultString = time.toFixed(3) + 'ms'; - logString = resultString; - } catch (e) { - success = false; - resultString = 'Error'; - logString = e.message; - } + const time = await test.run(size, opType, runGroup.params[opType]); + const resultString = time.toFixed(3) + 'ms'; - if (time >= 0) { - if (success) { - benchmarkRun.chartData.push({x: step, y: time}); - } - rowValues.push(resultString); - } - console.log(`${benchmarkRun.name}[${size}]: ${logString}`); + if (time >= 0) { + run.chartData.push({x: step, y: time}); + rowValues.push(resultString); } - runNumbersTable.appendChild(this.buildRunNumbersRow(rowValues)); - - step += runGroup.stepSize; - // Allow the UI to update. - setTimeout( - () => this.runBenchmarkSteps( - chart, runGroup, benchmarkRunGroupIndex, step), - 100); - }); + console.log(`${run.name}[${size}]: ${resultString}`); + } + runNumbersTable.appendChild(this.buildRunNumbersRow(rowValues)); + + step += runGroup.stepSize; + // Allow the UI to update. + setTimeout( + () => this.runBenchmarkSteps( + chart, runGroup, benchmarkRunGroupIndex, step), + 100); } } document.registerElement(MathBenchmark.prototype.is, MathBenchmark); diff --git a/demos/benchmarks/conv_benchmarks.ts b/demos/benchmarks/conv_benchmarks.ts index e9c2d6124c..4b7d33d936 100644 --- a/demos/benchmarks/conv_benchmarks.ts +++ b/demos/benchmarks/conv_benchmarks.ts @@ -16,7 +16,7 @@ */ // tslint:disable-next-line:max-line-length -import {Array1D, Array3D, Array4D, conv_util, NDArray, NDArrayMathGPU} from 'deeplearn'; +import {Array1D, Array3D, Array4D, conv_util, ENV, NDArray} from 'deeplearn'; import {BenchmarkTest} from './benchmark'; import * as benchmark_util from './benchmark_util'; @@ -34,7 +34,7 @@ export interface DepthwiseConvParams extends ConvParams { channelMul: number; } export class ConvGPUBenchmark implements BenchmarkTest { async run(size: number, opType: string, params: ConvParams): Promise { - const math = new NDArrayMathGPU(); + const math = ENV.math; const inDepth = params.inDepth; const inShape: [number, number, number] = [size, size, inDepth]; diff --git a/demos/benchmarks/matmul_benchmarks.ts b/demos/benchmarks/matmul_benchmarks.ts index e22e1ad818..a08d04a647 100644 --- a/demos/benchmarks/matmul_benchmarks.ts +++ b/demos/benchmarks/matmul_benchmarks.ts @@ -15,7 +15,8 @@ * ============================================================================= */ // tslint:disable-next-line:max-line-length -import {Array2D, NDArrayMathCPU, NDArrayMathGPU} from 'deeplearn'; +import {Array2D, ENV, NDArrayMath} from 'deeplearn'; + import {BenchmarkTest, LAST_RUN_CPU_CUTOFF_MS} from './benchmark'; import * as benchmark_util from './benchmark_util'; @@ -27,7 +28,9 @@ export class MatmulCPUBenchmark implements BenchmarkTest { resolve(-1); }); } - const math = new NDArrayMathCPU(); + const safeMode = false; + const math = new NDArrayMath('cpu', safeMode); + ENV.setMath(math); const a = Array2D.randUniform([size, size], -1, 1); const b = Array2D.randUniform([size, size], -1, 1); const start = performance.now(); @@ -41,8 +44,9 @@ export class MatmulCPUBenchmark implements BenchmarkTest { export class MatmulGPUBenchmark implements BenchmarkTest { async run(size: number): Promise { - const math = new NDArrayMathGPU(); - + const safeMode = false; + const math = new NDArrayMath('webgl', safeMode); + ENV.setMath(math); const a = Array2D.randNormal([size, size]); const b = Array2D.randNormal([size, size]); diff --git a/demos/benchmarks/pool_benchmarks.ts b/demos/benchmarks/pool_benchmarks.ts index de1b52836f..d5808edf4e 100644 --- a/demos/benchmarks/pool_benchmarks.ts +++ b/demos/benchmarks/pool_benchmarks.ts @@ -16,7 +16,7 @@ */ // tslint:disable-next-line:max-line-length -import {Array3D, conv_util, NDArrayMath, NDArrayMathCPU, NDArrayMathGPU} from 'deeplearn'; +import {Array3D, conv_util, ENV, NDArrayMath} from 'deeplearn'; import {BenchmarkTest} from './benchmark'; import * as benchmark_util from './benchmark_util'; @@ -58,7 +58,9 @@ function getPoolingOp(option: string, math: NDArrayMath): ( export class PoolCPUBenchmark implements BenchmarkTest { run(size: number, option: string, params: PoolBenchmarkParams): Promise { - const math = new NDArrayMathCPU(); + const safeMode = false; + const math = new NDArrayMath('cpu', safeMode); + ENV.setMath(math); const outputDepth = params.depth; const xShape: [number, number, number] = [size, size, outputDepth]; const fieldSize = params.fieldSize; @@ -83,8 +85,9 @@ export class PoolCPUBenchmark implements BenchmarkTest { export class PoolGPUBenchmark implements BenchmarkTest { async run(size: number, option: string, params: PoolBenchmarkParams): Promise { - const math = new NDArrayMathGPU(); - + const safeMode = false; + const math = new NDArrayMath('webgl', safeMode); + ENV.setMath(math); const outputDepth = params.depth; const xShape: [number, number, number] = [size, size, outputDepth]; const fieldSize = params.fieldSize; @@ -93,11 +96,8 @@ export class PoolGPUBenchmark implements BenchmarkTest { const op = getPoolingOp(option, math); const benchmark = () => op(x, fieldSize, stride, 'same'); - const time = await benchmark_util.warmupAndBenchmarkGPU(math, benchmark); - x.dispose(); - math.dispose(); return time; } diff --git a/demos/benchmarks/reduction_ops_benchmark.ts b/demos/benchmarks/reduction_ops_benchmark.ts index 0844bf17b8..17d815eda0 100644 --- a/demos/benchmarks/reduction_ops_benchmark.ts +++ b/demos/benchmarks/reduction_ops_benchmark.ts @@ -15,7 +15,7 @@ * ============================================================================= */ // tslint:disable-next-line:max-line-length -import {Array2D, NDArray, NDArrayMath, NDArrayMathCPU, NDArrayMathGPU, Scalar} from 'deeplearn'; +import {Array2D, ENV, NDArray, NDArrayMath, Scalar} from 'deeplearn'; import {BenchmarkTest} from './benchmark'; import * as benchmark_util from './benchmark_util'; @@ -42,7 +42,9 @@ function getReductionOp(option: string, math: NDArrayMath): (input: NDArray) => export class ReductionOpsCPUBenchmark implements BenchmarkTest { async run(size: number, option: string): Promise { - const math = new NDArrayMathCPU(); + const safeMode = false; + const math = new NDArrayMath('cpu', safeMode); + ENV.setMath(math); const input = Array2D.randUniform([size, size], -1, 1); const op = getReductionOp(option, math); const start = performance.now(); @@ -58,7 +60,9 @@ export class ReductionOpsCPUBenchmark implements BenchmarkTest { export class ReductionOpsGPUBenchmark implements BenchmarkTest { async run(size: number, option: string) { - const math = new NDArrayMathGPU(); + const safeMode = false; + const math = new NDArrayMath('webgl', safeMode); + ENV.setMath(math); const input = Array2D.randUniform([size, size], -1, 1); const op = getReductionOp(option, math); diff --git a/demos/benchmarks/unary_ops_benchmark.ts b/demos/benchmarks/unary_ops_benchmark.ts index c92070e2da..fb9c677c17 100644 --- a/demos/benchmarks/unary_ops_benchmark.ts +++ b/demos/benchmarks/unary_ops_benchmark.ts @@ -16,7 +16,8 @@ */ // tslint:disable-next-line:max-line-length -import {Array2D, NDArray, NDArrayMath, NDArrayMathCPU, NDArrayMathGPU} from 'deeplearn'; +import {Array2D, ENV, NDArray, NDArrayMath} from 'deeplearn'; + import {BenchmarkTest} from './benchmark'; import * as benchmark_util from './benchmark_util'; @@ -61,7 +62,9 @@ function getUnaryOp(option: string, math: NDArrayMath) { export class UnaryOpsCPUBenchmark implements BenchmarkTest { async run(size: number, option: string): Promise { - const math = new NDArrayMathCPU(); + const safeMode = false; + const math = new NDArrayMath('cpu', safeMode); + ENV.setMath(math); const input = Array2D.randUniform([size, size], -1, 1); const op = getUnaryOp(option, math); const start = performance.now(); @@ -77,7 +80,9 @@ export class UnaryOpsCPUBenchmark implements BenchmarkTest { export class UnaryOpsGPUBenchmark implements BenchmarkTest { async run(size: number, option: string) { - const math = new NDArrayMathGPU(); + const safeMode = false; + const math = new NDArrayMath('webgl', safeMode); + ENV.setMath(math); const input = Array2D.randUniform([size, size], -1, 1); const op = getUnaryOp(option, math); diff --git a/demos/complementary-color-prediction/complementary-color-prediction.ts b/demos/complementary-color-prediction/complementary-color-prediction.ts index e184b278dc..6fec18621e 100644 --- a/demos/complementary-color-prediction/complementary-color-prediction.ts +++ b/demos/complementary-color-prediction/complementary-color-prediction.ts @@ -16,14 +16,14 @@ */ // tslint:disable-next-line:max-line-length -import {Array1D, CostReduction, FeedEntry, Graph, InCPUMemoryShuffledInputProviderBuilder, NDArrayMath, NDArrayMathGPU, Session, SGDOptimizer, Tensor} from 'deeplearn'; +import {Array1D, CostReduction, ENV, FeedEntry, Graph, InCPUMemoryShuffledInputProviderBuilder, NDArrayMath, Session, SGDOptimizer, Tensor} from 'deeplearn'; class ComplementaryColorModel { // Runs training. session: Session; // Encapsulates math operations on the CPU and GPU. - math: NDArrayMath = new NDArrayMathGPU(); + math = ENV.math; // An optimizer with a certain initial learning rate. Used for training. initialLearningRate = 0.042; @@ -155,36 +155,39 @@ class ComplementaryColorModel { * to pass data into the model. Generates `exampleCount` data points. */ private generateTrainingData(exampleCount: number) { - this.math.scope(() => { - const rawInputs = new Array(exampleCount); - for (let i = 0; i < exampleCount; i++) { - rawInputs[i] = [ - this.generateRandomChannelValue(), this.generateRandomChannelValue(), - this.generateRandomChannelValue() - ]; - } - - // Store the data within Array1Ds so that learnjs can use it. - const inputArray: Array1D[] = - rawInputs.map(c => Array1D.new(this.normalizeColor(c))); - const targetArray: Array1D[] = rawInputs.map( - c => Array1D.new( - this.normalizeColor(this.computeComplementaryColor(c)))); - - // This provider will shuffle the training data (and will do so in a way - // that does not separate the input-target relationship). - const shuffledInputProviderBuilder = - new InCPUMemoryShuffledInputProviderBuilder( - [inputArray, targetArray]); - const [inputProvider, targetProvider] = - shuffledInputProviderBuilder.getInputProviders(); - - // Maps tensors to InputProviders. - this.feedEntries = [ - {tensor: this.inputTensor, data: inputProvider}, - {tensor: this.targetTensor, data: targetProvider} + const rawInputs = new Array(exampleCount); + const oldMath = ENV.math; + const safeMode = false; + const math = new NDArrayMath('cpu', safeMode); + ENV.setMath(math); + + for (let i = 0; i < exampleCount; i++) { + rawInputs[i] = [ + this.generateRandomChannelValue(), this.generateRandomChannelValue(), + this.generateRandomChannelValue() ]; - }); + } + + // Store the data within Array1Ds so that learnjs can use it. + const inputArray: Array1D[] = + rawInputs.map(c => Array1D.new(this.normalizeColor(c))); + const targetArray: Array1D[] = rawInputs.map( + c => Array1D.new( + this.normalizeColor(this.computeComplementaryColor(c)))); + + // This provider will shuffle the training data (and will do so in a way + // that does not separate the input-target relationship). + const shuffledInputProviderBuilder = + new InCPUMemoryShuffledInputProviderBuilder([inputArray, targetArray]); + const [inputProvider, targetProvider] = + shuffledInputProviderBuilder.getInputProviders(); + + // Maps tensors to InputProviders. + this.feedEntries = [ + {tensor: this.inputTensor, data: inputProvider}, + {tensor: this.targetTensor, data: targetProvider} + ]; + ENV.setMath(oldMath); } private generateRandomChannelValue() { diff --git a/demos/fast-style-transfer/fast-style-transfer.ts b/demos/fast-style-transfer/fast-style-transfer.ts index 7212007451..7322e27638 100644 --- a/demos/fast-style-transfer/fast-style-transfer.ts +++ b/demos/fast-style-transfer/fast-style-transfer.ts @@ -14,12 +14,9 @@ * limitations under the License. * ============================================================================= */ -// tslint:disable-next-line:max-line-length -import {Array3D, gpgpu_util, GPGPUContext, NDArrayMathGPU, render_ndarray_gpu_util} from 'deeplearn'; +import {Array3D, ENV} from 'deeplearn'; import {PolymerElement, PolymerHTMLElement} from '../polymer-spec'; - -// import * as imagenet_util from '../models/imagenet_util'; import {TransformNet} from './net'; // tslint:disable-next-line:variable-name @@ -59,11 +56,6 @@ export class StyleTransferDemo extends StyleTransferDemoPolymer { status: string; applicationState: ApplicationState; - // DeeplearnJS stuff - private math: NDArrayMathGPU; - private gpgpu: GPGPUContext; - private gl: WebGLRenderingContext; - private transformNet: TransformNet; // DOM Elements @@ -88,9 +80,6 @@ export class StyleTransferDemo extends StyleTransferDemoPolymer { ready() { // Initialize deeplearn.js stuff this.canvas = this.querySelector('#imageCanvas') as HTMLCanvasElement; - this.gl = gpgpu_util.createWebGLContext(this.canvas); - this.gpgpu = new GPGPUContext(this.gl); - this.math = new NDArrayMathGPU(this.gpgpu); // Initialize polymer properties this.applicationState = ApplicationState.IDLE; @@ -113,7 +102,7 @@ export class StyleTransferDemo extends StyleTransferDemoPolymer { this.styleImgElement.height = 250; this.transformNet = - new TransformNet(this.math, STYLE_MAPPINGS[this.selectedStyleName]); + new TransformNet(STYLE_MAPPINGS[this.selectedStyleName]); this.initWebcamVariables(); @@ -250,17 +239,11 @@ export class StyleTransferDemo extends StyleTransferDemoPolymer { } async runInference() { - await this.math.scope(async (keep, track) => { - - const preprocessed = track(Array3D.fromPixels(this.contentImgElement)); - + await ENV.math.scope(async () => { + const preprocessed = Array3D.fromPixels(this.contentImgElement); const inferenceResult = await this.transformNet.predict(preprocessed); - this.setCanvasShape(inferenceResult.shape); - this.renderShader = render_ndarray_gpu_util.getRenderRGBShader( - this.gpgpu, inferenceResult.shape[1]); - render_ndarray_gpu_util.renderToCanvas( - this.gpgpu, this.renderShader, inferenceResult.getTexture()); + renderToCanvas(inferenceResult, this.canvas); }); } @@ -277,4 +260,20 @@ export class StyleTransferDemo extends StyleTransferDemoPolymer { } } +function renderToCanvas(a: Array3D, canvas: HTMLCanvasElement) { + const [height, width, ] = a.shape; + const ctx = canvas.getContext('2d'); + const imageData = new ImageData(width, height); + const data = a.dataSync(); + for (let i = 0; i < height * width; ++i) { + const j = i * 4; + const k = i * 3; + imageData.data[j + 0] = Math.round(255 * data[k + 0]); + imageData.data[j + 1] = Math.round(255 * data[k + 1]); + imageData.data[j + 2] = Math.round(255 * data[k + 2]); + imageData.data[j + 3] = 255; + } + ctx.putImageData(imageData, 0, 0); +} + document.registerElement(StyleTransferDemo.prototype.is, StyleTransferDemo); diff --git a/demos/fast-style-transfer/net.ts b/demos/fast-style-transfer/net.ts index e7e9d77059..92a7fc03b2 100644 --- a/demos/fast-style-transfer/net.ts +++ b/demos/fast-style-transfer/net.ts @@ -15,7 +15,7 @@ * ============================================================================= */ // tslint:disable-next-line:max-line-length -import {Array1D, Array3D, Array4D, CheckpointLoader, Model, NDArray, NDArrayMathGPU, Scalar} from 'deeplearn'; +import {Array1D, Array3D, Array4D, CheckpointLoader, ENV, Model, NDArray, NDArrayMath, Scalar} from 'deeplearn'; const GOOGLE_CLOUD_STORAGE_DIR = 'https://storage.googleapis.com/learnjs-data/checkpoint_zoo/transformnet/'; @@ -27,8 +27,10 @@ export class TransformNet implements Model { private timesScalar: NDArray; private plusScalar: NDArray; private epsilonScalar: NDArray; + private math: NDArrayMath; - constructor(private math: NDArrayMathGPU, private style: string) { + constructor(private style: string) { + this.math = ENV.math; this.variableDictionary = {}; this.timesScalar = Scalar.new(150); this.plusScalar = Scalar.new(255. / 2); diff --git a/demos/imagenet/imagenet.ts b/demos/imagenet/imagenet.ts index c68bec0452..e1b5431234 100644 --- a/demos/imagenet/imagenet.ts +++ b/demos/imagenet/imagenet.ts @@ -19,7 +19,7 @@ import '../demo-header'; import '../demo-footer'; // tslint:disable-next-line:max-line-length -import {Array3D, gpgpu_util, GPGPUContext, NDArrayMathGPU} from 'deeplearn'; +import {Array3D, ENV, gpgpu_util, GPGPUContext, MathBackendWebGL, NDArrayMath} from 'deeplearn'; import {ActivationName, SqueezeNet} from 'deeplearn-squeezenet'; import {PolymerElement, PolymerHTMLElement} from '../polymer-spec'; @@ -54,8 +54,8 @@ export class ImagenetDemo extends ImagenetDemoPolymer { inputNames: string[]; selectedInputName: string; - private math: NDArrayMathGPU; - private gl: WebGLRenderingContext; + private math: NDArrayMath; + private backend: MathBackendWebGL; private gpgpu: GPGPUContext; private renderGrayscaleChannelsCollageShader: WebGLShader; @@ -101,9 +101,12 @@ export class ImagenetDemo extends ImagenetDemoPolymer { } }); - this.gl = gpgpu_util.createWebGLContext(this.inferenceCanvas); - this.gpgpu = new GPGPUContext(this.gl); - this.math = new NDArrayMathGPU(this.gpgpu); + const gl = gpgpu_util.createWebGLContext(this.inferenceCanvas); + this.gpgpu = new GPGPUContext(gl); + this.backend = new MathBackendWebGL(this.gpgpu); + const safeMode = false; + this.math = new NDArrayMath(this.backend, safeMode); + ENV.setMath(this.math); this.renderGrayscaleChannelsCollageShader = imagenet_util.getRenderGrayscaleChannelsCollageShader(this.gpgpu); @@ -174,14 +177,14 @@ export class ImagenetDemo extends ImagenetDemoPolymer { const isWebcam = this.selectedInputName === 'webcam'; - await this.math.scope(async (keep, track) => { + await this.math.scope(async keep => { if (!this.isMediaLoaded) { return; } const element = isWebcam ? this.webcamVideoElement : this.staticImgElement; - const image = track(Array3D.fromPixels(element)); + const image = Array3D.fromPixels(element); const inferenceResult = await this.squeezeNet.predictWithActivation( image, this.selectedLayerName); @@ -226,8 +229,10 @@ export class ImagenetDemo extends ImagenetDemoPolymer { imagenet_util.renderGrayscaleChannelsCollage( this.gpgpu, this.renderGrayscaleChannelsCollageShader, - activationNDArray.getTexture(), minValues.getTexture(), - maxValues.getTexture(), activationNDArray.getTextureShapeRC(), + this.backend.getTexture(activationNDArray.id), + this.backend.getTexture(minValues.id), + this.backend.getTexture(maxValues.id), + this.backend.getTextureData(activationNDArray.id).texShape, activationNDArray.shape[0], activationNDArray.shape[2], this.inferenceCanvas.width, numRows); }); diff --git a/demos/intro/intro.ts b/demos/intro/intro.ts index c47bd7c3a4..34858ed5fb 100644 --- a/demos/intro/intro.ts +++ b/demos/intro/intro.ts @@ -16,114 +16,108 @@ */ // tslint:disable-next-line:max-line-length -import {Array1D, Array2D, CostReduction, FeedEntry, Graph, InCPUMemoryShuffledInputProviderBuilder, NDArrayMathGPU, Scalar, Session, SGDOptimizer} from 'deeplearn'; +import {Array1D, Array2D, CostReduction, ENV, FeedEntry, Graph, InCPUMemoryShuffledInputProviderBuilder, Scalar, Session, SGDOptimizer} from 'deeplearn'; // This file parallels (some of) the code in the introduction tutorial. /** - * 'NDArrayMathGPU' section of tutorial + * 'NDArrayMath with WebGL backend' section of tutorial */ async function intro() { - { - const math = new NDArrayMathGPU(); + const math = ENV.math; + + const a = Array2D.new([2, 2], [1.0, 2.0, 3.0, 4.0]); + const b = Array2D.new([2, 2], [0.0, 2.0, 4.0, 6.0]); + + // Non-blocking math calls. + const diff = math.sub(a, b); + const squaredDiff = math.elementWiseMul(diff, diff); + const sum = math.sum(squaredDiff); + const size = Scalar.new(a.size); + const average = math.divide(sum, size); + + console.log(`mean squared difference: ${await average.val()}`); + + /** + * 'Graphs and Tensors' section of tutorial + */ + + const g = new Graph(); + + // Placeholders are input containers. This is the container for where we + // will feed an input NDArray when we execute the graph. + const inputShape = [3]; + const inputTensor = g.placeholder('input', inputShape); + + const labelShape = [1]; + const labelTensor = g.placeholder('label', labelShape); + + // Variables are containers that hold a value that can be updated from + // training. + // Here we initialize the multiplier variable randomly. + const multiplier = g.variable('multiplier', Array2D.randNormal([1, 3])); + + // Top level graph methods take Tensors and return Tensors. + const outputTensor = g.matmul(multiplier, inputTensor); + const costTensor = g.meanSquaredCost(labelTensor, outputTensor); + + // Tensors, like NDArrays, have a shape attribute. + console.log(outputTensor.shape); + + /** + * 'Session and FeedEntry' section of the tutorial. + */ + + const learningRate = .00001; + const batchSize = 3; + + const session = new Session(g, math); + const optimizer = new SGDOptimizer(learningRate); + + const inputs: Array1D[] = [ + Array1D.new([1.0, 2.0, 3.0]), Array1D.new([10.0, 20.0, 30.0]), + Array1D.new([100.0, 200.0, 300.0]) + ]; + + const labels: Array1D[] = + [Array1D.new([4.0]), Array1D.new([40.0]), Array1D.new([400.0])]; + + // Shuffles inputs and labels and keeps them mutually in sync. + const shuffledInputProviderBuilder = + new InCPUMemoryShuffledInputProviderBuilder([inputs, labels]); + const [inputProvider, labelProvider] = + shuffledInputProviderBuilder.getInputProviders(); + + // Maps tensors to InputProviders. + const feedEntries: FeedEntry[] = [ + {tensor: inputTensor, data: inputProvider}, + {tensor: labelTensor, data: labelProvider} + ]; + + const NUM_BATCHES = 10; + for (let i = 0; i < NUM_BATCHES; i++) { + // Wrap session.train in a scope so the cost gets cleaned up + // automatically. + await math.scope(async () => { + // Train takes a cost tensor to minimize. Trains one batch. Returns the + // average cost as a Scalar. + const cost = session.train( + costTensor, feedEntries, batchSize, optimizer, CostReduction.MEAN); + + console.log(`last average cost (${i}): ${await cost.val()}`); + }); + } - const a = Array2D.new([2, 2], [1.0, 2.0, 3.0, 4.0]); - const b = Array2D.new([2, 2], [0.0, 2.0, 4.0, 6.0]); + const testInput = Array1D.new([0.1, 0.2, 0.3]); - // Non-blocking math calls. - const diff = math.sub(a, b); - const squaredDiff = math.elementWiseMul(diff, diff); - const sum = math.sum(squaredDiff); - const size = Scalar.new(a.size); - const average = math.divide(sum, size); + // session.eval can take NDArrays as input data. + const testFeedEntries: FeedEntry[] = [{tensor: inputTensor, data: testInput}]; - console.log(`mean squared difference: ${await average.val()}`); - } + const testOutput = session.eval(outputTensor, testFeedEntries); - { - /** - * 'Graphs and Tensors' section of tutorial - */ - - const g = new Graph(); - - // Placeholders are input containers. This is the container for where we - // will feed an input NDArray when we execute the graph. - const inputShape = [3]; - const inputTensor = g.placeholder('input', inputShape); - - const labelShape = [1]; - const labelTensor = g.placeholder('label', labelShape); - - // Variables are containers that hold a value that can be updated from - // training. - // Here we initialize the multiplier variable randomly. - const multiplier = g.variable('multiplier', Array2D.randNormal([1, 3])); - - // Top level graph methods take Tensors and return Tensors. - const outputTensor = g.matmul(multiplier, inputTensor); - const costTensor = g.meanSquaredCost(labelTensor, outputTensor); - - // Tensors, like NDArrays, have a shape attribute. - console.log(outputTensor.shape); - - /** - * 'Session and FeedEntry' section of the tutorial. - */ - - const learningRate = .00001; - const batchSize = 3; - const math = new NDArrayMathGPU(); - - const session = new Session(g, math); - const optimizer = new SGDOptimizer(learningRate); - - const inputs: Array1D[] = [ - Array1D.new([1.0, 2.0, 3.0]), Array1D.new([10.0, 20.0, 30.0]), - Array1D.new([100.0, 200.0, 300.0]) - ]; - - const labels: Array1D[] = - [Array1D.new([4.0]), Array1D.new([40.0]), Array1D.new([400.0])]; - - // Shuffles inputs and labels and keeps them mutually in sync. - const shuffledInputProviderBuilder = - new InCPUMemoryShuffledInputProviderBuilder([inputs, labels]); - const [inputProvider, labelProvider] = - shuffledInputProviderBuilder.getInputProviders(); - - // Maps tensors to InputProviders. - const feedEntries: FeedEntry[] = [ - {tensor: inputTensor, data: inputProvider}, - {tensor: labelTensor, data: labelProvider} - ]; - - const NUM_BATCHES = 10; - for (let i = 0; i < NUM_BATCHES; i++) { - // Wrap session.train in a scope so the cost gets cleaned up - // automatically. - await math.scope(async () => { - // Train takes a cost tensor to minimize. Trains one batch. Returns the - // average cost as a Scalar. - const cost = session.train( - costTensor, feedEntries, batchSize, optimizer, CostReduction.MEAN); - - console.log(`last average cost (${i}): ${await cost.val()}`); - }); - } - - const testInput = Array1D.new([0.1, 0.2, 0.3]); - - // session.eval can take NDArrays as input data. - const testFeedEntries: FeedEntry[] = - [{tensor: inputTensor, data: testInput}]; - - const testOutput = session.eval(outputTensor, testFeedEntries); - - console.log('---inference output---'); - console.log(`shape: ${testOutput.shape}`); - console.log(`value: ${await testOutput.val(0)}`); - } + console.log('---inference output---'); + console.log(`shape: ${testOutput.shape}`); + console.log(`value: ${await testOutput.val(0)}`); } intro(); diff --git a/demos/latent-space-explorer/App.vue b/demos/latent-space-explorer/App.vue index 2cd4c2bf57..4b6b8bbf0b 100644 --- a/demos/latent-space-explorer/App.vue +++ b/demos/latent-space-explorer/App.vue @@ -82,8 +82,7 @@ import BasisDimensions from './components/BasisDimensions.vue'; import FontChooser from './components/FontChooser.vue'; import Alphabet from './components/Alphabet.vue'; import {FontModel} from './utils/FontModel'; - -import {Array1D, NDArray, NDArrayMathCPU} from 'deeplearn'; +import {Array1D} from 'deeplearn'; export default { components: { @@ -139,17 +138,18 @@ export default { if (event.isInitialSelection && window.location.hash) { this.parseUrlHash(); } else { - this.selectedSample = event.selectedSample + this.selectedSample = event.selectedSample; this.updateHash(); } }, updateHash: function() { if (this.selectedSample) { - const vals = this.selectedSample.getValues(); - const hashStr = '#' + Array.from(vals).map( - val => parseFloat(val).toFixed(3)) - .join(','); + this.selectedSample.data().then(vals => { + const hashStr = '#' + Array.from(vals) + .map(val => parseFloat(val).toFixed(3)) + .join(','); history.replaceState(undefined, undefined, hashStr); + }); } }, parseUrlHash: function() { diff --git a/demos/latent-space-explorer/components/BasisDimensions.vue b/demos/latent-space-explorer/components/BasisDimensions.vue index e26bfde1b5..99bd150fd5 100644 --- a/demos/latent-space-explorer/components/BasisDimensions.vue +++ b/demos/latent-space-explorer/components/BasisDimensions.vue @@ -39,14 +39,23 @@ limitations under the License. import Sample from './Sample.vue'; import Tray from './Tray.vue'; import {range} from 'd3-array'; -import {Array1D, NDArrayMathCPU} from 'deeplearn'; +import {Array1D, ENV} from 'deeplearn'; -const math = new NDArrayMathCPU(false); +const math = ENV.math; export default { components: {Sample, Tray}, data() { return { + basisDimensions: [] + }; + }, + watch: { + model: function(m) { + const dims = m ? m.dimensions: 0; + this.basisDimensions = range(dims).map(dim => { + return math.oneHot(Array1D.new([dim]), dims).as1D(); + }); } }, props: { @@ -59,19 +68,6 @@ export default { vals: { type: Array, default: function() { return []; }}, scrollY: {default: 0} }, - computed: { - dimensions: function() { - return this.model ? this.model.dimensions : 0; - }, - basisDimensions: function() { - let output = range(this.dimensions).map(dim => { - let dir = Array1D.zeros([this.dimensions]); - dir.set(1, dim); - return dir; - }); - return output; - } - }, methods: { select: function(event) { this.$emit("select", event); diff --git a/demos/latent-space-explorer/components/Tray.vue b/demos/latent-space-explorer/components/Tray.vue index 5ac3e30aa4..8505baddb0 100644 --- a/demos/latent-space-explorer/components/Tray.vue +++ b/demos/latent-space-explorer/components/Tray.vue @@ -30,7 +30,6 @@ limitations under the License. :sample="sample.sample" />
{{format(selectedValue)}}
@@ -43,14 +42,12 @@ limitations under the License. + diff --git a/models/knn_image_classifier/knn_image_classifier.ts b/models/knn_image_classifier/knn_image_classifier.ts index ccd66b63b1..5f37fbccc8 100644 --- a/models/knn_image_classifier/knn_image_classifier.ts +++ b/models/knn_image_classifier/knn_image_classifier.ts @@ -15,8 +15,9 @@ * ============================================================================= */ // tslint:disable-next-line:max-line-length -import {Array1D, Array2D, Array3D, initializeGPU, Model, NDArrayMath, NDArrayMathCPU, NDArrayMathGPU, Scalar} from 'deeplearn'; +import {Array1D, Array2D, Array3D, Model, NDArrayMath, Scalar} from 'deeplearn'; import {SqueezeNet} from 'deeplearn-squeezenet'; +import * as model_util from '../util'; export class KNNImageClassifier implements Model { private squeezeNet: SqueezeNet; @@ -29,8 +30,6 @@ export class KNNImageClassifier implements Model { private classExampleCount: number[] = []; private varsLoaded = false; - private mathCPU: NDArrayMathCPU; - private squashLogitsDenominator = Scalar.new(300); /** @@ -43,16 +42,6 @@ export class KNNImageClassifier implements Model { constructor( private numClasses: number, private k: number, private math: NDArrayMath) { - // TODO(nsthorat): This awful hack is because we need to share the global - // GPGPU between deeplearn loaded from standalone as well as the internal - // deeplearn that gets compiled as part of this model. Remove this once we - // decouple NDArray from storage mechanism. - initializeGPU( - (this.math as NDArrayMathGPU).getGPGPUContext(), - (this.math as NDArrayMathGPU).getTextureManager()); - - this.mathCPU = new NDArrayMathCPU(); - for (let i = 0; i < this.numClasses; i++) { this.classLogitsMatrices.push(null); this.classExampleCount.push(0); @@ -187,24 +176,17 @@ export class KNNImageClassifier implements Model { throw new Error('Cannot predict until vars have been loaded.'); } - const topKIndices = await this.math.scope(async (keep) => { - const knn = this.predict(image); - // mathCPU downloads the values, so we should wait until the GPU isdone - // so we don't block the UI thread. - await knn.data(); - - const numExamples = this.getNumExamples(); - - const kVal = Math.min(this.k, numExamples); - const topK = this.mathCPU.topK(knn, kVal); - return topK.indices; - }); + const knn = this.predict(image).asType('float32'); + const numExamples = this.getNumExamples(); + const kVal = Math.min(this.k, numExamples); + const topK = model_util.topK(await knn.data(), kVal); + knn.dispose(); + const topKIndices = topK.indices; if (topKIndices == null) { return {classIndex: imageClass, confidences}; } - const indices = topKIndices.dataSync(); const indicesForClasses = []; const topKCountsForClasses = []; for (let i = 0; i < this.numClasses; i++) { @@ -216,10 +198,10 @@ export class KNNImageClassifier implements Model { indicesForClasses.push(num); } - for (let i = 0; i < indices.length; i++) { + for (let i = 0; i < topKIndices.length; i++) { for (let classForEntry = 0; classForEntry < indicesForClasses.length; classForEntry++) { - if (indices[i] < indicesForClasses[classForEntry]) { + if (topKIndices[i] < indicesForClasses[classForEntry]) { topKCountsForClasses[classForEntry]++; break; } @@ -227,7 +209,6 @@ export class KNNImageClassifier implements Model { } let topConfidence = 0; - const kVal = Math.min(this.k, this.getNumExamples()); for (let i = 0; i < this.numClasses; i++) { const probability = topKCountsForClasses[i] / kVal; if (probability > topConfidence) { diff --git a/models/knn_image_classifier/package.json b/models/knn_image_classifier/package.json index 535312edf0..4c54884037 100644 --- a/models/knn_image_classifier/package.json +++ b/models/knn_image_classifier/package.json @@ -6,7 +6,7 @@ "unpkg": "dist/bundle.js", "types": "dist/index.d.ts", "peerDependencies": { - "deeplearn": "~0.3.13" + "deeplearn": "0.3.15" }, "dependencies": { "deeplearn-squeezenet": "~0.1.6" @@ -16,8 +16,9 @@ "url": "https://github.com/PAIR-code/deeplearnjs.git" }, "devDependencies": { - "browserify": "~14.4.0", - "deeplearn": "0.3.13", + "browserify": "~14.5.0", + "browserify-shim": "~3.8.14", + "deeplearn": "0.3.15", "mkdirp": "~0.5.1", "tsify": "~3.0.3", "tslint": "~5.8.0", @@ -27,9 +28,17 @@ }, "scripts": { "prep": "yarn && mkdirp dist", - "build": "tsc --sourceMap false && browserify --standalone knn_image_classifier knn_image_classifier.ts -p [tsify] -o dist/bundle.js", + "build": "tsc --sourceMap false && browserify -g browserify-shim --standalone knn_image_classifier index.ts -p [tsify] -o dist/bundle.js", "lint": "tslint -p . -t verbose", "publish-npm": "yarn build && yarn publish" }, + "browserify-shim": { + "deeplearn": "global:dl" + }, + "browserify": { + "global-transform": [ + "browserify-shim" + ] + }, "license": "Apache-2.0" } diff --git a/models/knn_image_classifier/tsconfig.json b/models/knn_image_classifier/tsconfig.json index ca81ff5c4d..ac3fc54cf1 100644 --- a/models/knn_image_classifier/tsconfig.json +++ b/models/knn_image_classifier/tsconfig.json @@ -5,7 +5,8 @@ }, "include": [ "index.ts", - "knn_image_classifier.ts" + "knn_image_classifier.ts", + "../util.ts" ], "exclude": [ "node_modules/", diff --git a/models/knn_image_classifier/yarn.lock b/models/knn_image_classifier/yarn.lock index e93b7f4874..131697ec10 100644 --- a/models/knn_image_classifier/yarn.lock +++ b/models/knn_image_classifier/yarn.lock @@ -13,10 +13,22 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" +accessory@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/accessory/-/accessory-1.1.0.tgz#7833e9839a32ded76d26021f36a41707a520f593" + dependencies: + ap "~0.2.0" + balanced-match "~0.2.0" + dot-parts "~1.0.0" + acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" +acorn@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7" + ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" @@ -24,6 +36,10 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -49,6 +65,10 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +ap@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -146,6 +166,10 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" +balanced-match@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.2.1.tgz#7bc658b4bed61eee424ad74f75f5c3e2c4df3cc7" + base64-js@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" @@ -245,6 +269,16 @@ browserify-rsa@^4.0.0: bn.js "^4.1.0" randombytes "^2.0.1" +browserify-shim@~3.8.14: + version "3.8.14" + resolved "https://registry.yarnpkg.com/browserify-shim/-/browserify-shim-3.8.14.tgz#bf1057026932d3253c75ef7dd714f3b877edec6b" + dependencies: + exposify "~0.5.0" + mothership "~0.2.0" + rename-function-calls "~0.1.0" + resolve "~0.6.1" + through "~2.3.4" + browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" @@ -257,19 +291,13 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@~0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" - dependencies: - pako "~0.2.0" - browserify-zlib@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" dependencies: pako "~1.0.5" -browserify@^14.0.0: +browserify@^14.0.0, browserify@~14.5.0: version "14.5.0" resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.5.0.tgz#0bbbce521acd6e4d1d54d8e9365008efb85a9cc5" dependencies: @@ -321,58 +349,6 @@ browserify@^14.0.0: vm-browserify "~0.0.1" xtend "^4.0.0" -browserify@~14.4.0: - version "14.4.0" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.4.0.tgz#089a3463af58d0e48d8cd4070b3f74654d5abca9" - dependencies: - JSONStream "^1.0.3" - assert "^1.4.0" - browser-pack "^6.0.1" - browser-resolve "^1.11.0" - browserify-zlib "~0.1.2" - buffer "^5.0.2" - cached-path-relative "^1.0.0" - concat-stream "~1.5.1" - console-browserify "^1.1.0" - constants-browserify "~1.0.0" - crypto-browserify "^3.0.0" - defined "^1.0.0" - deps-sort "^2.0.0" - domain-browser "~1.1.0" - duplexer2 "~0.1.2" - events "~1.1.0" - glob "^7.1.0" - has "^1.0.0" - htmlescape "^1.1.0" - https-browserify "^1.0.0" - inherits "~2.0.1" - insert-module-globals "^7.0.0" - labeled-stream-splicer "^2.0.0" - module-deps "^4.0.8" - os-browserify "~0.1.1" - parents "^1.0.1" - path-browserify "~0.0.0" - process "~0.11.0" - punycode "^1.3.2" - querystring-es3 "~0.2.0" - read-only-stream "^2.0.0" - readable-stream "^2.0.2" - resolve "^1.1.4" - shasum "^1.0.0" - shell-quote "^1.6.1" - stream-browserify "^2.0.0" - stream-http "^2.0.0" - string_decoder "~1.0.0" - subarg "^1.0.0" - syntax-error "^1.1.1" - through2 "^2.0.0" - timers-browserify "^1.0.1" - tty-browserify "~0.0.0" - url "~0.11.0" - util "~0.10.1" - vm-browserify "~0.0.1" - xtend "^4.0.0" - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -588,9 +564,9 @@ deeplearn-squeezenet@~0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/deeplearn-squeezenet/-/deeplearn-squeezenet-0.1.6.tgz#f73c25d8627de514d72425471a3d69436c754ecf" -deeplearn@~0.3.13: - version "0.3.13" - resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.13.tgz#12033ab21581fb277dede662250bd58d86457d44" +deeplearn@0.3.15: + version "0.3.15" + resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.15.tgz#0cdc7a5171e932dbb312914b56ccdec2dbd873bc" dependencies: seedrandom "~2.4.3" @@ -633,6 +609,20 @@ detective@^4.0.0: acorn "^4.0.3" defined "^1.0.0" +detective@^4.5.0: + version "4.7.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" + dependencies: + acorn "^5.2.1" + defined "^1.0.0" + +detective@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-3.1.0.tgz#77782444ab752b88ca1be2e9d0a0395f1da25eed" + dependencies: + escodegen "~1.1.0" + esprima-fb "3001.1.0-dev-harmony-fb" + diff@^3.2.0: version "3.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" @@ -649,6 +639,10 @@ domain-browser@~1.1.0: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" +dot-parts@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dot-parts/-/dot-parts-1.0.1.tgz#884bd7bcfc3082ffad2fe5db53e494d8f3e0743f" + duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -679,14 +673,40 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +escodegen@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.1.0.tgz#c663923f6e20aad48d0c0fa49f31c6d4f49360cf" + dependencies: + esprima "~1.0.4" + estraverse "~1.5.0" + esutils "~1.0.0" + optionalDependencies: + source-map "~0.1.30" + +esprima-fb@3001.1.0-dev-harmony-fb: + version "3001.1.0-dev-harmony-fb" + resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz#b77d37abcd38ea0b77426bb8bc2922ce6b426411" + +esprima@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" + +estraverse@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" +esutils@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" + events@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -710,6 +730,16 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +exposify@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/exposify/-/exposify-0.5.0.tgz#f92d0094c265b3f553e1fa456a03a1883d1059cc" + dependencies: + globo "~1.1.0" + map-obj "~1.0.1" + replace-requires "~1.0.3" + through2 "~0.4.0" + transformify "~0.1.1" + extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -738,6 +768,10 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +find-parent-dir@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -835,6 +869,14 @@ glob@^7.0.5, glob@^7.1.0, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +globo@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/globo/-/globo-1.1.0.tgz#0d26098955dea422eb2001b104898b0a101caaf3" + dependencies: + accessory "~1.1.0" + is-defined "~1.0.0" + ternary "~1.0.0" + graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -860,6 +902,12 @@ has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-require@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/has-require/-/has-require-1.2.2.tgz#921675ab130dbd9768fc8da8f1a8e242dfa41774" + dependencies: + escape-string-regexp "^1.0.3" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -987,6 +1035,10 @@ is-buffer@^1.1.0, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-defined/-/is-defined-1.0.0.tgz#1f07ca67d571f594c4b14415a45f7bef88f92bf5" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -1045,14 +1097,14 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +isarray@0.0.1, isarray@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isarray@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -1138,6 +1190,10 @@ lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" +map-obj@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" @@ -1228,6 +1284,12 @@ module-deps@^4.0.8: through2 "^2.0.0" xtend "^4.0.0" +mothership@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/mothership/-/mothership-0.2.0.tgz#93d48a2fbc3e50e2a5fc8ed586f5bc44c65f9a99" + dependencies: + find-parent-dir "~0.3.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1286,6 +1348,10 @@ object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1299,10 +1365,6 @@ once@^1.3.0, once@^1.3.3: dependencies: wrappy "1" -os-browserify@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54" - os-browserify@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" @@ -1328,10 +1390,6 @@ outpipe@^1.1.0: dependencies: shell-quote "^1.4.2" -pako@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" @@ -1367,6 +1425,10 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +patch-text@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/patch-text/-/patch-text-1.0.2.tgz#4bf36e65e51733d6e98f0cf62e09034daa0348ac" + path-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" @@ -1486,6 +1548,24 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable string_decoder "~1.0.3" util-deprecate "~1.0.1" +readable-stream@~1.0.17: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readable-stream@~2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -1516,6 +1596,12 @@ remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" +rename-function-calls@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/rename-function-calls/-/rename-function-calls-0.1.1.tgz#7f83369c007a3007f6abe3033ccf81686a108e01" + dependencies: + detective "~3.1.0" + repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" @@ -1524,6 +1610,15 @@ repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" +replace-requires@~1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/replace-requires/-/replace-requires-1.0.4.tgz#014b7330b6b9e2557b71043b66fb02660c3bf667" + dependencies: + detective "^4.5.0" + has-require "~1.2.1" + patch-text "~1.0.2" + xtend "~4.0.0" + request@2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -1561,6 +1656,10 @@ resolve@^1.1.3, resolve@^1.1.4, resolve@^1.3.2: dependencies: path-parse "^1.0.5" +resolve@~0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" + rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" @@ -1627,6 +1726,12 @@ sntp@1.x.x: dependencies: hoek "2.x.x" +source-map@~0.1.30: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -1757,6 +1862,10 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" +ternary@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ternary/-/ternary-1.0.0.tgz#45702725608c9499d46a9610e9b0e49ff26f789e" + through2@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" @@ -1764,7 +1873,14 @@ through2@^2.0.0: readable-stream "^2.1.5" xtend "~4.0.1" -"through@>=2.2.7 <3": +through2@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" + dependencies: + readable-stream "~1.0.17" + xtend "~2.1.1" + +"through@>=2.2.7 <3", through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -1784,6 +1900,12 @@ tough-cookie@~2.3.0: dependencies: punycode "^1.4.1" +transformify@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/transformify/-/transformify-0.1.2.tgz#9a4f42a154433dd727b80575428a3c9e5489ebf1" + dependencies: + readable-stream "~1.1.9" + tsconfig@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-5.0.3.tgz#5f4278e701800967a8fc383fd19648878f2a6e3a" @@ -1921,6 +2043,12 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + dependencies: + object-keys "~0.4.0" diff --git a/models/mobilenet/demo.html b/models/mobilenet/demo.html index 9d3bd61cd6..c35a088dc1 100644 --- a/models/mobilenet/demo.html +++ b/models/mobilenet/demo.html @@ -1,6 +1,5 @@ - - +
@@ -12,7 +11,7 @@ resultElement.innerText = 'Loading mobilenet...'; - const math = new dl.NDArrayMathGPU(); + const math = dl.ENV.math; const mobileNet = new mobilenet.MobileNet(math); await mobileNet.load(); diff --git a/models/mobilenet/mobilenet.ts b/models/mobilenet/mobilenet.ts index f3aaa18a3f..e9cf49f56b 100644 --- a/models/mobilenet/mobilenet.ts +++ b/models/mobilenet/mobilenet.ts @@ -14,36 +14,29 @@ * limitations under the License. * ============================================================================= */ -// tslint:disable-next-line:max-line-length -import {Array1D, Array3D, Array4D, CheckpointLoader, initializeGPU, Model, NDArray, NDArrayMathCPU, NDArrayMath, NDArrayMathGPU, Scalar} from 'deeplearn'; -import {IMAGENET_CLASSES} from './imagenet_classes'; +// tslint:disable-next-line:max-line-length +import {Array1D, Array3D, Array4D, CheckpointLoader, Model, NDArray, NDArrayMath, Scalar} from 'deeplearn'; +import * as model_util from '../util'; +import {IMAGENET_CLASSES} from './imagenet_classes'; -const GOOGLE_CLOUD_STORAGE_DIR = +const GOOGLE_CLOUD_STORAGE_DIR = 'https://storage.googleapis.com/learnjs-data/checkpoint_zoo/'; - -export class MobileNet implements Model { + +export class MobileNet implements Model { private variables: {[varName: string]: NDArray}; // yolo variables - private PREPROCESS_DIVISOR = Scalar.new(255.0/2); - private ONE = Scalar.ONE; - - constructor(private math: NDArrayMath) { - // TODO(nsthorat): This awful hack is because we need to share the global - // GPGPU between deeplearn loaded from standalone as well as the internal - // deeplearn that gets compiled as part of this model. Remove this once we - // decouple NDArray from storage mechanism. - initializeGPU( - (this.math as NDArrayMathGPU).getGPGPUContext(), - (this.math as NDArrayMathGPU).getTextureManager()); - } + private PREPROCESS_DIVISOR = Scalar.new(255.0 / 2); + private ONE = Scalar.new(1); + + constructor(private math: NDArrayMath) {} /** * Loads necessary variables for MobileNet. */ async load(): Promise { - const checkpointLoader = new CheckpointLoader(GOOGLE_CLOUD_STORAGE_DIR + - 'mobilenet_v1_1.0_224/'); + const checkpointLoader = new CheckpointLoader( + GOOGLE_CLOUD_STORAGE_DIR + 'mobilenet_v1_1.0_224/'); this.variables = await checkpointLoader.getAllVariables(); } @@ -59,96 +52,91 @@ export class MobileNet implements Model { // Keep a map of named activations for rendering purposes. const netout = this.math.scope((keep) => { // Preprocess the input. - const preprocessedInput = this.math.subtract( - this.math.arrayDividedByScalar(input, - this.PREPROCESS_DIVISOR), this.ONE) as Array3D; + const preprocessedInput = + this.math.subtract( + this.math.arrayDividedByScalar(input, this.PREPROCESS_DIVISOR), + this.ONE) as Array3D; - const x1 = this.convBlock(preprocessedInput, [2, 2]); - const x2 = this.depthwiseConvBlock(x1, [1, 1], 1); + const x1 = this.convBlock(preprocessedInput, [2, 2]); + const x2 = this.depthwiseConvBlock(x1, [1, 1], 1); - const x3 = this.depthwiseConvBlock(x2, [2, 2], 2); - const x4 = this.depthwiseConvBlock(x3, [1, 1], 3); + const x3 = this.depthwiseConvBlock(x2, [2, 2], 2); + const x4 = this.depthwiseConvBlock(x3, [1, 1], 3); - const x5 = this.depthwiseConvBlock(x4, [2, 2], 4); - const x6 = this.depthwiseConvBlock(x5, [1, 1], 5); + const x5 = this.depthwiseConvBlock(x4, [2, 2], 4); + const x6 = this.depthwiseConvBlock(x5, [1, 1], 5); - const x7 = this.depthwiseConvBlock(x6, [2, 2], 6); - const x8 = this.depthwiseConvBlock(x7, [1, 1], 7); - const x9 = this.depthwiseConvBlock(x8, [1, 1], 8); - const x10 = this.depthwiseConvBlock(x9, [1, 1], 9); + const x7 = this.depthwiseConvBlock(x6, [2, 2], 6); + const x8 = this.depthwiseConvBlock(x7, [1, 1], 7); + const x9 = this.depthwiseConvBlock(x8, [1, 1], 8); + const x10 = this.depthwiseConvBlock(x9, [1, 1], 9); const x11 = this.depthwiseConvBlock(x10, [1, 1], 10); const x12 = this.depthwiseConvBlock(x11, [1, 1], 11); const x13 = this.depthwiseConvBlock(x12, [2, 2], 12); const x14 = this.depthwiseConvBlock(x13, [1, 1], 13); - const x15 = this.math.avgPool(x14, x14.shape[0], 1, 0); - const x16 = this.math.conv2d(x15, - this.variables['MobilenetV1/Logits/Conv2d_1c_1x1/weights'] as Array4D, - this.variables['MobilenetV1/Logits/Conv2d_1c_1x1/biases'] as Array1D, - 1, - 'same'); + const x15 = this.math.avgPool(x14, x14.shape[0], 1, 0); + const x16 = this.math.conv2d( + x15, + this.variables['MobilenetV1/Logits/Conv2d_1c_1x1/weights'] as Array4D, + this.variables['MobilenetV1/Logits/Conv2d_1c_1x1/biases'] as Array1D, + 1, 'same'); return x16.as1D(); }); return netout; - } + } - private convBlock(inputs: Array3D, strides: [number, number]) { + private convBlock(inputs: Array3D, strides: [number, number]) { const convPadding = 'MobilenetV1/Conv2d_0'; - const x1 = this.math.conv2d(inputs, - this.variables[convPadding + '/weights'] as Array4D, - null, // this convolutional layer does not use bias - strides, - 'same'); + const x1 = this.math.conv2d( + inputs, this.variables[convPadding + '/weights'] as Array4D, + null, // this convolutional layer does not use bias + strides, 'same'); - const x2 = this.math.batchNormalization3D(x1, - this.variables[convPadding + '/BatchNorm/moving_mean'] as Array1D, - this.variables[convPadding + '/BatchNorm/moving_variance'] as Array1D, - .001, - this.variables[convPadding + '/BatchNorm/gamma'] as Array1D, - this.variables[convPadding + '/BatchNorm/beta'] as Array1D); + const x2 = this.math.batchNormalization3D( + x1, this.variables[convPadding + '/BatchNorm/moving_mean'] as Array1D, + this.variables[convPadding + '/BatchNorm/moving_variance'] as Array1D, + .001, this.variables[convPadding + '/BatchNorm/gamma'] as Array1D, + this.variables[convPadding + '/BatchNorm/beta'] as Array1D); - return this.math.clip(x2, 0, 6); // simple implementation of Relu6 + return this.math.clip(x2, 0, 6); // simple implementation of Relu6 } - private depthwiseConvBlock(inputs: Array3D, - strides: [number, number], - blockID: number) { + private depthwiseConvBlock( + inputs: Array3D, strides: [number, number], blockID: number) { const dwPadding = 'MobilenetV1/Conv2d_' + String(blockID) + '_depthwise'; const pwPadding = 'MobilenetV1/Conv2d_' + String(blockID) + '_pointwise'; - const x1 = this.math.depthwiseConv2D(inputs, - this.variables[dwPadding + '/depthwise_weights'] as Array4D, - strides, - 'same') as Array3D; + const x1 = + this.math.depthwiseConv2D( + inputs, this.variables[dwPadding + '/depthwise_weights'] as Array4D, + strides, 'same') as Array3D; - const x2 = this.math.batchNormalization3D(x1, - this.variables[dwPadding + '/BatchNorm/moving_mean'] as Array1D, - this.variables[dwPadding + '/BatchNorm/moving_variance'] as Array1D, - .001, - this.variables[dwPadding + '/BatchNorm/gamma'] as Array1D, - this.variables[dwPadding + '/BatchNorm/beta'] as Array1D); + const x2 = this.math.batchNormalization3D( + x1, this.variables[dwPadding + '/BatchNorm/moving_mean'] as Array1D, + this.variables[dwPadding + '/BatchNorm/moving_variance'] as Array1D, + .001, this.variables[dwPadding + '/BatchNorm/gamma'] as Array1D, + this.variables[dwPadding + '/BatchNorm/beta'] as Array1D); const x3 = this.math.clip(x2, 0, 6); - const x4 = this.math.conv2d(x3, - this.variables[pwPadding + '/weights'] as Array4D, - null, // this convolutional layer does not use bias - [1, 1], - 'same'); + const x4 = this.math.conv2d( + x3, this.variables[pwPadding + '/weights'] as Array4D, + null, // this convolutional layer does not use bias + [1, 1], 'same'); - const x5 = this.math.batchNormalization3D(x4, - this.variables[pwPadding + '/BatchNorm/moving_mean'] as Array1D, - this.variables[pwPadding + '/BatchNorm/moving_variance'] as Array1D, - .001, - this.variables[pwPadding + '/BatchNorm/gamma'] as Array1D, - this.variables[pwPadding + '/BatchNorm/beta'] as Array1D); + const x5 = this.math.batchNormalization3D( + x4, this.variables[pwPadding + '/BatchNorm/moving_mean'] as Array1D, + this.variables[pwPadding + '/BatchNorm/moving_variance'] as Array1D, + .001, this.variables[pwPadding + '/BatchNorm/gamma'] as Array1D, + this.variables[pwPadding + '/BatchNorm/beta'] as Array1D); return this.math.clip(x5, 0, 6); - } + } /** * Get the topK classes for pre-softmax logits. Returns a map of className @@ -159,21 +147,21 @@ export class MobileNet implements Model { */ async getTopKClasses(logits: Array1D, topK: number): Promise<{[className: string]: number}> { - const predictions = this.math.softmax(logits); - const topk = new NDArrayMathCPU().topK(predictions, topK); - const topkIndices = await topk.indices.data(); - const topkValues = await topk.values.data(); + const predictions = this.math.softmax(logits).asType('float32'); + const topk = model_util.topK(await predictions.data(), topK); + const topkIndices = topk.indices; + const topkValues = topk.values; const topClassesToProbability: {[className: string]: number} = {}; for (let i = 0; i < topkIndices.length; i++) { topClassesToProbability[IMAGENET_CLASSES[topkIndices[i]]] = topkValues[i]; } return topClassesToProbability; - } + } dispose() { for (const varName in this.variables) { this.variables[varName].dispose(); } } -} \ No newline at end of file +} diff --git a/models/mobilenet/package.json b/models/mobilenet/package.json index b6f6451cb5..834570191e 100644 --- a/models/mobilenet/package.json +++ b/models/mobilenet/package.json @@ -6,14 +6,16 @@ "unpkg": "dist/bundle.js", "types": "dist/index.d.ts", "peerDependencies": { - "deeplearn": "~0.3.11" + "deeplearn": "0.3.15" }, "repository": { "type": "git", "url": "https://github.com/PAIR-code/deeplearnjs.git" }, "devDependencies": { - "deeplearn": "0.3.13", + "browserify": "~14.5.0", + "browserify-shim": "~3.8.14", + "deeplearn": "0.3.15", "mkdirp": "~0.5.1", "tsify": "~3.0.3", "tslint": "~5.8.0", @@ -23,9 +25,17 @@ }, "scripts": { "prep": "yarn && mkdirp dist", - "build": "browserify --standalone mobilenet mobilenet.ts -p [tsify] -o dist/bundle.js", + "build": "browserify -g browserify-shim --standalone mobilenet index.ts -p [tsify] -o dist/bundle.js", "lint": "tslint -p . -t verbose", "publish-npm": "tsc --sourceMap false && yarn build && npm publish" }, + "browserify-shim": { + "deeplearn": "global:dl" + }, + "browserify": { + "global-transform": [ + "browserify-shim" + ] + }, "license": "Apache-2.0" } diff --git a/models/mobilenet/tsconfig.json b/models/mobilenet/tsconfig.json index ad8576b059..6ccd57ef0c 100644 --- a/models/mobilenet/tsconfig.json +++ b/models/mobilenet/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "include": [ - "index.ts", "mobiletnet.ts" + "index.ts", + "mobiletnet.ts", + "../util.ts" ], "exclude": [ "node_modules/", diff --git a/models/mobilenet/yarn.lock b/models/mobilenet/yarn.lock index 11adbb8d8f..f4c21dfa9a 100644 --- a/models/mobilenet/yarn.lock +++ b/models/mobilenet/yarn.lock @@ -13,6 +13,14 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" +accessory@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/accessory/-/accessory-1.1.0.tgz#7833e9839a32ded76d26021f36a41707a520f593" + dependencies: + ap "~0.2.0" + balanced-match "~0.2.0" + dot-parts "~1.0.0" + acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" @@ -28,6 +36,10 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -53,6 +65,10 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +ap@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -150,6 +166,10 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" +balanced-match@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.2.1.tgz#7bc658b4bed61eee424ad74f75f5c3e2c4df3cc7" + base64-js@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" @@ -249,6 +269,16 @@ browserify-rsa@^4.0.0: bn.js "^4.1.0" randombytes "^2.0.1" +browserify-shim@~3.8.14: + version "3.8.14" + resolved "https://registry.yarnpkg.com/browserify-shim/-/browserify-shim-3.8.14.tgz#bf1057026932d3253c75ef7dd714f3b877edec6b" + dependencies: + exposify "~0.5.0" + mothership "~0.2.0" + rename-function-calls "~0.1.0" + resolve "~0.6.1" + through "~2.3.4" + browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" @@ -267,7 +297,7 @@ browserify-zlib@~0.2.0: dependencies: pako "~1.0.5" -browserify@^14.0.0: +browserify@^14.0.0, browserify@~14.5.0: version "14.5.0" resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.5.0.tgz#0bbbce521acd6e4d1d54d8e9365008efb85a9cc5" dependencies: @@ -530,9 +560,9 @@ deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" -deeplearn@~0.3.11: - version "0.3.13" - resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.13.tgz#12033ab21581fb277dede662250bd58d86457d44" +deeplearn@0.3.15: + version "0.3.15" + resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.15.tgz#0cdc7a5171e932dbb312914b56ccdec2dbd873bc" dependencies: seedrandom "~2.4.3" @@ -575,6 +605,20 @@ detective@^4.0.0: acorn "^5.2.1" defined "^1.0.0" +detective@^4.5.0: + version "4.7.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" + dependencies: + acorn "^5.2.1" + defined "^1.0.0" + +detective@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-3.1.0.tgz#77782444ab752b88ca1be2e9d0a0395f1da25eed" + dependencies: + escodegen "~1.1.0" + esprima-fb "3001.1.0-dev-harmony-fb" + diff@^3.2.0: version "3.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" @@ -591,6 +635,10 @@ domain-browser@~1.1.0: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" +dot-parts@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dot-parts/-/dot-parts-1.0.1.tgz#884bd7bcfc3082ffad2fe5db53e494d8f3e0743f" + duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -621,14 +669,40 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +escodegen@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.1.0.tgz#c663923f6e20aad48d0c0fa49f31c6d4f49360cf" + dependencies: + esprima "~1.0.4" + estraverse "~1.5.0" + esutils "~1.0.0" + optionalDependencies: + source-map "~0.1.30" + +esprima-fb@3001.1.0-dev-harmony-fb: + version "3001.1.0-dev-harmony-fb" + resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz#b77d37abcd38ea0b77426bb8bc2922ce6b426411" + +esprima@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" + +estraverse@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" +esutils@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" + events@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -652,6 +726,16 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +exposify@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/exposify/-/exposify-0.5.0.tgz#f92d0094c265b3f553e1fa456a03a1883d1059cc" + dependencies: + globo "~1.1.0" + map-obj "~1.0.1" + replace-requires "~1.0.3" + through2 "~0.4.0" + transformify "~0.1.1" + extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -684,6 +768,10 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +find-parent-dir@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -781,6 +869,14 @@ glob@^7.0.5, glob@^7.1.0, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +globo@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/globo/-/globo-1.1.0.tgz#0d26098955dea422eb2001b104898b0a101caaf3" + dependencies: + accessory "~1.1.0" + is-defined "~1.0.0" + ternary "~1.0.0" + graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -806,6 +902,12 @@ has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-require@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/has-require/-/has-require-1.2.2.tgz#921675ab130dbd9768fc8da8f1a8e242dfa41774" + dependencies: + escape-string-regexp "^1.0.3" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -933,6 +1035,10 @@ is-buffer@^1.1.0, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-defined/-/is-defined-1.0.0.tgz#1f07ca67d571f594c4b14415a45f7bef88f92bf5" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -991,14 +1097,14 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +isarray@0.0.1, isarray@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isarray@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -1084,6 +1190,10 @@ lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" +map-obj@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" @@ -1174,6 +1284,12 @@ module-deps@^4.0.8: through2 "^2.0.0" xtend "^4.0.0" +mothership@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/mothership/-/mothership-0.2.0.tgz#93d48a2fbc3e50e2a5fc8ed586f5bc44c65f9a99" + dependencies: + find-parent-dir "~0.3.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1232,6 +1348,10 @@ object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1305,6 +1425,10 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +patch-text@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/patch-text/-/patch-text-1.0.2.tgz#4bf36e65e51733d6e98f0cf62e09034daa0348ac" + path-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" @@ -1424,6 +1548,24 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable string_decoder "~1.0.3" util-deprecate "~1.0.1" +readable-stream@~1.0.17: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readable-stream@~2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -1454,6 +1596,12 @@ remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" +rename-function-calls@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/rename-function-calls/-/rename-function-calls-0.1.1.tgz#7f83369c007a3007f6abe3033ccf81686a108e01" + dependencies: + detective "~3.1.0" + repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" @@ -1462,6 +1610,15 @@ repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" +replace-requires@~1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/replace-requires/-/replace-requires-1.0.4.tgz#014b7330b6b9e2557b71043b66fb02660c3bf667" + dependencies: + detective "^4.5.0" + has-require "~1.2.1" + patch-text "~1.0.2" + xtend "~4.0.0" + request@2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -1499,6 +1656,10 @@ resolve@^1.1.3, resolve@^1.1.4, resolve@^1.3.2: dependencies: path-parse "^1.0.5" +resolve@~0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" + rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" @@ -1565,6 +1726,12 @@ sntp@1.x.x: dependencies: hoek "2.x.x" +source-map@~0.1.30: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -1695,6 +1862,10 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" +ternary@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ternary/-/ternary-1.0.0.tgz#45702725608c9499d46a9610e9b0e49ff26f789e" + through2@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" @@ -1702,7 +1873,14 @@ through2@^2.0.0: readable-stream "^2.1.5" xtend "~4.0.1" -"through@>=2.2.7 <3": +through2@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" + dependencies: + readable-stream "~1.0.17" + xtend "~2.1.1" + +"through@>=2.2.7 <3", through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -1722,6 +1900,12 @@ tough-cookie@~2.3.0: dependencies: punycode "^1.4.1" +transformify@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/transformify/-/transformify-0.1.2.tgz#9a4f42a154433dd727b80575428a3c9e5489ebf1" + dependencies: + readable-stream "~1.1.9" + tsconfig@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-5.0.3.tgz#5f4278e701800967a8fc383fd19648878f2a6e3a" @@ -1859,6 +2043,12 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + dependencies: + object-keys "~0.4.0" diff --git a/models/package.json b/models/package.json new file mode 100644 index 0000000000..ffac19ec2e --- /dev/null +++ b/models/package.json @@ -0,0 +1,6 @@ +{ + "browserify-shim": { + "deeplearn": "global:dl" + }, + "license": "Apache-2.0" +} diff --git a/models/squeezenet/demo.html b/models/squeezenet/demo.html index 38a753ff7a..32de48adaa 100644 --- a/models/squeezenet/demo.html +++ b/models/squeezenet/demo.html @@ -1,6 +1,5 @@ - - +
@@ -16,7 +15,7 @@ if (dl == null) { await new Promise(resolve => setTimeout(resolve, 1000)); } - const math = new dl.NDArrayMathGPU(); + const math = dl.ENV.math; const squeezeNet = new squeezenet.SqueezeNet(math); await squeezeNet.load(); diff --git a/models/squeezenet/package.json b/models/squeezenet/package.json index 4a24d14f0d..3e944c558d 100644 --- a/models/squeezenet/package.json +++ b/models/squeezenet/package.json @@ -6,15 +6,16 @@ "unpkg": "dist/bundle.js", "types": "dist/index.d.ts", "peerDependencies": { - "deeplearn": "~0.3.13" + "deeplearn": "0.3.15" }, "repository": { "type": "git", "url": "https://github.com/PAIR-code/deeplearnjs.git" }, "devDependencies": { - "browserify": "~14.4.0", - "deeplearn": "0.3.13", + "browserify": "~14.5.0", + "browserify-shim": "~3.8.14", + "deeplearn": "0.3.15", "mkdirp": "~0.5.1", "tsify": "~3.0.3", "tslint": "~5.8.0", @@ -24,9 +25,12 @@ }, "scripts": { "prep": "yarn && mkdirp dist", - "build": "tsc --sourceMap false && browserify --standalone squeezenet squeezenet.ts -p [tsify] -o dist/bundle.js", + "build": "tsc --sourceMap false && browserify -g browserify-shim --standalone squeezenet index.ts -p [tsify] -o dist/bundle.js", "lint": "tslint -p . -t verbose", "publish-npm": "yarn build && yarn publish" }, + "browserify-shim": { + "deeplearn": "global:dl" + }, "license": "Apache-2.0" } diff --git a/models/squeezenet/squeezenet.ts b/models/squeezenet/squeezenet.ts index 03c7640d07..4f3fdf5a12 100644 --- a/models/squeezenet/squeezenet.ts +++ b/models/squeezenet/squeezenet.ts @@ -15,8 +15,8 @@ * ============================================================================= */ // tslint:disable-next-line:max-line-length -import {Array1D, Array3D, Array4D, CheckpointLoader, initializeGPU, Model, NDArray, NDArrayMath, NDArrayMathCPU, NDArrayMathGPU} from 'deeplearn'; - +import {Array1D, Array3D, Array4D, CheckpointLoader, Model, NDArray, NDArrayMath} from 'deeplearn'; +import * as model_util from '../util'; import {IMAGENET_CLASSES} from './imagenet_classes'; const GOOGLE_CLOUD_STORAGE_DIR = @@ -30,15 +30,7 @@ export class SqueezeNet implements Model { private preprocessOffset = Array1D.new([103.939, 116.779, 123.68]); - constructor(private math: NDArrayMath) { - // TODO(nsthorat): This awful hack is because we need to share the global - // GPGPU between deeplearn loaded from standalone as well as the internal - // deeplearn that gets compiled as part of this model. Remove this once we - // decouple NDArray from storage mechanism. - initializeGPU( - (this.math as NDArrayMathGPU).getGPGPUContext(), - (this.math as NDArrayMathGPU).getTextureManager()); - } + constructor(private math: NDArrayMath) {} /** * Loads necessary variables for SqueezeNet. @@ -184,10 +176,10 @@ export class SqueezeNet implements Model { */ async getTopKClasses(logits: Array1D, topK: number): Promise<{[className: string]: number}> { - const predictions = this.math.softmax(logits); - const topk = new NDArrayMathCPU().topK(predictions, topK); - const topkIndices = await topk.indices.data(); - const topkValues = await topk.values.data(); + const predictions = this.math.softmax(logits).asType('float32'); + const topk = model_util.topK(await predictions.data(), topK); + const topkIndices = topk.indices; + const topkValues = topk.values; const topClassesToProbability: {[className: string]: number} = {}; for (let i = 0; i < topkIndices.length; i++) { @@ -202,4 +194,4 @@ export class SqueezeNet implements Model { this.variables[varName].dispose(); } } -} \ No newline at end of file +} diff --git a/models/squeezenet/tsconfig.json b/models/squeezenet/tsconfig.json index fe7dab1c9c..29a71963a9 100644 --- a/models/squeezenet/tsconfig.json +++ b/models/squeezenet/tsconfig.json @@ -5,7 +5,8 @@ }, "include": [ "index.ts", - "squeezenet.ts" + "squeezenet.ts", + "../util.ts" ], "exclude": [ "node_modules/", diff --git a/models/squeezenet/yarn.lock b/models/squeezenet/yarn.lock index 2b1d2a7e56..3c301c006d 100644 --- a/models/squeezenet/yarn.lock +++ b/models/squeezenet/yarn.lock @@ -13,6 +13,14 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" +accessory@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/accessory/-/accessory-1.1.0.tgz#7833e9839a32ded76d26021f36a41707a520f593" + dependencies: + ap "~0.2.0" + balanced-match "~0.2.0" + dot-parts "~1.0.0" + acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" @@ -28,6 +36,10 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -53,6 +65,10 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +ap@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -150,6 +166,10 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" +balanced-match@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.2.1.tgz#7bc658b4bed61eee424ad74f75f5c3e2c4df3cc7" + base64-js@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" @@ -249,6 +269,16 @@ browserify-rsa@^4.0.0: bn.js "^4.1.0" randombytes "^2.0.1" +browserify-shim@~3.8.14: + version "3.8.14" + resolved "https://registry.yarnpkg.com/browserify-shim/-/browserify-shim-3.8.14.tgz#bf1057026932d3253c75ef7dd714f3b877edec6b" + dependencies: + exposify "~0.5.0" + mothership "~0.2.0" + rename-function-calls "~0.1.0" + resolve "~0.6.1" + through "~2.3.4" + browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" @@ -261,19 +291,13 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@~0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" - dependencies: - pako "~0.2.0" - browserify-zlib@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" dependencies: pako "~1.0.5" -browserify@^14.0.0: +browserify@^14.0.0, browserify@~14.5.0: version "14.5.0" resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.5.0.tgz#0bbbce521acd6e4d1d54d8e9365008efb85a9cc5" dependencies: @@ -325,58 +349,6 @@ browserify@^14.0.0: vm-browserify "~0.0.1" xtend "^4.0.0" -browserify@~14.4.0: - version "14.4.0" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.4.0.tgz#089a3463af58d0e48d8cd4070b3f74654d5abca9" - dependencies: - JSONStream "^1.0.3" - assert "^1.4.0" - browser-pack "^6.0.1" - browser-resolve "^1.11.0" - browserify-zlib "~0.1.2" - buffer "^5.0.2" - cached-path-relative "^1.0.0" - concat-stream "~1.5.1" - console-browserify "^1.1.0" - constants-browserify "~1.0.0" - crypto-browserify "^3.0.0" - defined "^1.0.0" - deps-sort "^2.0.0" - domain-browser "~1.1.0" - duplexer2 "~0.1.2" - events "~1.1.0" - glob "^7.1.0" - has "^1.0.0" - htmlescape "^1.1.0" - https-browserify "^1.0.0" - inherits "~2.0.1" - insert-module-globals "^7.0.0" - labeled-stream-splicer "^2.0.0" - module-deps "^4.0.8" - os-browserify "~0.1.1" - parents "^1.0.1" - path-browserify "~0.0.0" - process "~0.11.0" - punycode "^1.3.2" - querystring-es3 "~0.2.0" - read-only-stream "^2.0.0" - readable-stream "^2.0.2" - resolve "^1.1.4" - shasum "^1.0.0" - shell-quote "^1.6.1" - stream-browserify "^2.0.0" - stream-http "^2.0.0" - string_decoder "~1.0.0" - subarg "^1.0.0" - syntax-error "^1.1.1" - through2 "^2.0.0" - timers-browserify "^1.0.1" - tty-browserify "~0.0.0" - url "~0.11.0" - util "~0.10.1" - vm-browserify "~0.0.1" - xtend "^4.0.0" - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -588,9 +560,9 @@ deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" -deeplearn@~0.3.11: - version "0.3.13" - resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.13.tgz#12033ab21581fb277dede662250bd58d86457d44" +deeplearn@0.3.15: + version "0.3.15" + resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.15.tgz#0cdc7a5171e932dbb312914b56ccdec2dbd873bc" dependencies: seedrandom "~2.4.3" @@ -633,6 +605,20 @@ detective@^4.0.0: acorn "^5.2.1" defined "^1.0.0" +detective@^4.5.0: + version "4.7.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" + dependencies: + acorn "^5.2.1" + defined "^1.0.0" + +detective@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-3.1.0.tgz#77782444ab752b88ca1be2e9d0a0395f1da25eed" + dependencies: + escodegen "~1.1.0" + esprima-fb "3001.1.0-dev-harmony-fb" + diff@^3.2.0: version "3.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" @@ -649,6 +635,10 @@ domain-browser@~1.1.0: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" +dot-parts@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dot-parts/-/dot-parts-1.0.1.tgz#884bd7bcfc3082ffad2fe5db53e494d8f3e0743f" + duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -679,14 +669,40 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +escodegen@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.1.0.tgz#c663923f6e20aad48d0c0fa49f31c6d4f49360cf" + dependencies: + esprima "~1.0.4" + estraverse "~1.5.0" + esutils "~1.0.0" + optionalDependencies: + source-map "~0.1.30" + +esprima-fb@3001.1.0-dev-harmony-fb: + version "3001.1.0-dev-harmony-fb" + resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz#b77d37abcd38ea0b77426bb8bc2922ce6b426411" + +esprima@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" + +estraverse@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" +esutils@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" + events@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -710,6 +726,16 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +exposify@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/exposify/-/exposify-0.5.0.tgz#f92d0094c265b3f553e1fa456a03a1883d1059cc" + dependencies: + globo "~1.1.0" + map-obj "~1.0.1" + replace-requires "~1.0.3" + through2 "~0.4.0" + transformify "~0.1.1" + extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -742,6 +768,10 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +find-parent-dir@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -839,6 +869,14 @@ glob@^7.0.5, glob@^7.1.0, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +globo@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/globo/-/globo-1.1.0.tgz#0d26098955dea422eb2001b104898b0a101caaf3" + dependencies: + accessory "~1.1.0" + is-defined "~1.0.0" + ternary "~1.0.0" + graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -864,6 +902,12 @@ has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-require@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/has-require/-/has-require-1.2.2.tgz#921675ab130dbd9768fc8da8f1a8e242dfa41774" + dependencies: + escape-string-regexp "^1.0.3" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -991,6 +1035,10 @@ is-buffer@^1.1.0, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-defined/-/is-defined-1.0.0.tgz#1f07ca67d571f594c4b14415a45f7bef88f92bf5" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -1049,14 +1097,14 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +isarray@0.0.1, isarray@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isarray@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -1142,6 +1190,10 @@ lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" +map-obj@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" @@ -1232,6 +1284,12 @@ module-deps@^4.0.8: through2 "^2.0.0" xtend "^4.0.0" +mothership@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/mothership/-/mothership-0.2.0.tgz#93d48a2fbc3e50e2a5fc8ed586f5bc44c65f9a99" + dependencies: + find-parent-dir "~0.3.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1290,6 +1348,10 @@ object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1303,10 +1365,6 @@ once@^1.3.0, once@^1.3.3: dependencies: wrappy "1" -os-browserify@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54" - os-browserify@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" @@ -1332,10 +1390,6 @@ outpipe@^1.1.0: dependencies: shell-quote "^1.4.2" -pako@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - pako@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" @@ -1371,6 +1425,10 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +patch-text@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/patch-text/-/patch-text-1.0.2.tgz#4bf36e65e51733d6e98f0cf62e09034daa0348ac" + path-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" @@ -1490,6 +1548,24 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable string_decoder "~1.0.3" util-deprecate "~1.0.1" +readable-stream@~1.0.17: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readable-stream@~2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -1520,6 +1596,12 @@ remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" +rename-function-calls@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/rename-function-calls/-/rename-function-calls-0.1.1.tgz#7f83369c007a3007f6abe3033ccf81686a108e01" + dependencies: + detective "~3.1.0" + repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" @@ -1528,6 +1610,15 @@ repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" +replace-requires@~1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/replace-requires/-/replace-requires-1.0.4.tgz#014b7330b6b9e2557b71043b66fb02660c3bf667" + dependencies: + detective "^4.5.0" + has-require "~1.2.1" + patch-text "~1.0.2" + xtend "~4.0.0" + request@2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -1565,6 +1656,10 @@ resolve@^1.1.3, resolve@^1.1.4, resolve@^1.3.2: dependencies: path-parse "^1.0.5" +resolve@~0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" + rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" @@ -1631,6 +1726,12 @@ sntp@1.x.x: dependencies: hoek "2.x.x" +source-map@~0.1.30: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -1761,6 +1862,10 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" +ternary@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ternary/-/ternary-1.0.0.tgz#45702725608c9499d46a9610e9b0e49ff26f789e" + through2@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" @@ -1768,7 +1873,14 @@ through2@^2.0.0: readable-stream "^2.1.5" xtend "~4.0.1" -"through@>=2.2.7 <3": +through2@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" + dependencies: + readable-stream "~1.0.17" + xtend "~2.1.1" + +"through@>=2.2.7 <3", through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -1788,6 +1900,12 @@ tough-cookie@~2.3.0: dependencies: punycode "^1.4.1" +transformify@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/transformify/-/transformify-0.1.2.tgz#9a4f42a154433dd727b80575428a3c9e5489ebf1" + dependencies: + readable-stream "~1.1.9" + tsconfig@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-5.0.3.tgz#5f4278e701800967a8fc383fd19648878f2a6e3a" @@ -1925,6 +2043,12 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + dependencies: + object-keys "~0.4.0" diff --git a/models/util.ts b/models/util.ts new file mode 100644 index 0000000000..1e2927c734 --- /dev/null +++ b/models/util.ts @@ -0,0 +1,34 @@ +/** + * @license + * Copyright 2017 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + +export function topK(values: Float32Array, k: number): + {values: Float32Array, indices: Int32Array} { + const valuesAndIndices: Array<{value: number, index: number}> = []; + for (let i = 0; i < values.length; i++) { + valuesAndIndices.push({value: values[i], index: i}); + } + valuesAndIndices.sort((a, b) => { + return b.value - a.value; + }); + const topkValues = new Float32Array(k); + const topkIndices = new Int32Array(k); + for (let i = 0; i < k; i++) { + topkValues[i] = valuesAndIndices[i].value; + topkIndices[i] = valuesAndIndices[i].index; + } + return {values: topkValues, indices: topkIndices}; +} diff --git a/models/yolo_mobilenet/demo.html b/models/yolo_mobilenet/demo.html index 0f298f1816..5e1dce1281 100644 --- a/models/yolo_mobilenet/demo.html +++ b/models/yolo_mobilenet/demo.html @@ -1,22 +1,20 @@ + - - -
@@ -39,8 +37,8 @@ width = canvas.width; height = canvas.height; - const math = new dl.NDArrayMathGPU(); - const yoloMobileNet = new yolo_mobilenet.YoloMobileNetDetection(math); + const math = dl.ENV.math; + const yoloMobileNet = new yolo_mobilenet.YoloMobileNetDetection(math); resultElement.innerText = 'Downloading weights ...'; yoloMobileNet.load().then(loadImage); @@ -79,7 +77,7 @@ context.strokeStyle = box.getColor(); context.lineWidth = 5; context.rect(x,y,w,h); - context.stroke(); + context.stroke(); // draw the label and the probability const label = box.getLabel() + ' ' + box.getMaxProb().toFixed(2).toString(); @@ -90,13 +88,13 @@ context.fillStyle = box.getColor(); const textWidth = context.measureText(label).width; context.fillRect(x-2, y-24, textWidth, parseInt(font, 10)); - + context.fillStyle = 'rgb(255,255,255)'; - context.fillText(label, x-2, y-24); + context.fillText(label, x-2, y-24); } resultElement.innerText = 'Complete!, Inference time: ' + Math.round(inferenceTime) + 'ms' + - ', Post precessing time: ' + Math.round(postProcessingTime) + 'ms'; + ', Post precessing time: ' + Math.round(postProcessingTime) + 'ms'; } diff --git a/models/yolo_mobilenet/mobilenet_utils.ts b/models/yolo_mobilenet/mobilenet_utils.ts index 4525f7a84d..4147599e94 100644 --- a/models/yolo_mobilenet/mobilenet_utils.ts +++ b/models/yolo_mobilenet/mobilenet_utils.ts @@ -1,10 +1,27 @@ +/** + * @license + * Copyright 2017 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + export class BoundingBox { - public x : number; - public y : number; - public w : number; - public h : number; - public c : number; - public probs : Float32Array; + public x: number; + public y: number; + public w: number; + public h: number; + public c: number; + public probs: Float32Array; private maxProb = -1; private maxIndx = -1; @@ -12,12 +29,9 @@ export class BoundingBox { public static LABELS = ['raccoon']; public static COLORS = ['rgb(43,206,72)']; - constructor(x: number, - y: number, - w: number, - h: number, - conf: number, - probs: Float32Array) { + constructor( + x: number, y: number, w: number, h: number, conf: number, + probs: Float32Array) { this.x = x; this.y = y; this.w = w; @@ -27,52 +41,50 @@ export class BoundingBox { this.probs = probs; } - public getMaxProb() : number { + public getMaxProb(): number { if (this.maxProb === -1) { - this.maxProb = this.probs.reduce((a,b) => Math.max(a,b)); + this.maxProb = this.probs.reduce((a, b) => Math.max(a, b)); } return this.maxProb; } - public getLabel() : string { + public getLabel(): string { if (this.maxIndx === -1) { this.maxIndx = this.probs.indexOf(this.getMaxProb()); } - + return BoundingBox.LABELS[this.maxIndx]; } - public getColor() : string { + public getColor(): string { if (this.maxIndx === -1) { this.maxIndx = this.probs.indexOf(this.getMaxProb()); } - + return BoundingBox.COLORS[this.maxIndx]; } public iou(box: BoundingBox): number { const intersection = this.intersect(box); - const union = this.w*this.h + box.w*box.h - intersection; + const union = this.w * this.h + box.w * box.h - intersection; - return intersection/union; + return intersection / union; } private intersect(box: BoundingBox): number { - const width = this.overlap([this.x-this.w/2, - this.x+this.w/2], - [box.x-box.w/2, - box.x+box.w/2]); - const height = this.overlap([this.y-this.h/2, - this.y+this.h/2], - [box.y-box.h/2, - box.y+box.h/2]); + const width = this.overlap( + [this.x - this.w / 2, this.x + this.w / 2], + [box.x - box.w / 2, box.x + box.w / 2]); + const height = this.overlap( + [this.y - this.h / 2, this.y + this.h / 2], + [box.y - box.h / 2, box.y + box.h / 2]); return width * height; } - private overlap(intervalA: [number, number], - intervalB: [number, number]): number { + private overlap(intervalA: [number, number], intervalB: [number, number]): + number { const [x1, x2] = intervalA; const [x3, x4] = intervalB; @@ -80,13 +92,13 @@ export class BoundingBox { if (x4 < x1) { return 0; } else { - return Math.min(x2,x4) - x1; + return Math.min(x2, x4) - x1; } } else { if (x2 < x3) { return 0; } else { - return Math.min(x2,x4) - x3; + return Math.min(x2, x4) - x3; } } } diff --git a/models/yolo_mobilenet/package.json b/models/yolo_mobilenet/package.json index fbaa7b6f6d..51a3c7276b 100644 --- a/models/yolo_mobilenet/package.json +++ b/models/yolo_mobilenet/package.json @@ -6,14 +6,16 @@ "unpkg": "dist/bundle.js", "types": "dist/index.d.ts", "peerDependencies": { - "deeplearn": "~0.3.11" + "deeplearn": "0.3.15" }, "repository": { "type": "git", "url": "https://github.com/PAIR-code/deeplearnjs.git" }, "devDependencies": { - "deeplearn": "0.3.13", + "browserify": "~14.5.0", + "browserify-shim": "~3.8.14", + "deeplearn": "0.3.15", "mkdirp": "~0.5.1", "tsify": "~3.0.3", "tslint": "~5.8.0", @@ -23,9 +25,17 @@ }, "scripts": { "prep": "yarn && mkdirp dist", - "build": "browserify --standalone yolo_mobilenet yolo_mobilenet.ts -p [tsify] -o dist/bundle.js", + "build": "browserify -g browserify-shim --standalone yolo_mobilenet index.ts -p [tsify] -o dist/bundle.js", "lint": "tslint -p . -t verbose", "publish-npm": "tsc --sourceMap false && yarn build && npm publish" }, + "browserify-shim": { + "deeplearn": "global:dl" + }, + "browserify": { + "global-transform": [ + "browserify-shim" + ] + }, "license": "Apache-2.0" } diff --git a/models/yolo_mobilenet/tsconfig.json b/models/yolo_mobilenet/tsconfig.json index bd8dee0ff4..131cbb176b 100644 --- a/models/yolo_mobilenet/tsconfig.json +++ b/models/yolo_mobilenet/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.json", "include": [ - "index.ts", "yolo_mobilenet.ts" + "index.ts", + "yolo_mobilenet.ts" ], "exclude": [ "node_modules/", diff --git a/models/yolo_mobilenet/yarn.lock b/models/yolo_mobilenet/yarn.lock index 11adbb8d8f..f4c21dfa9a 100644 --- a/models/yolo_mobilenet/yarn.lock +++ b/models/yolo_mobilenet/yarn.lock @@ -13,6 +13,14 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" +accessory@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/accessory/-/accessory-1.1.0.tgz#7833e9839a32ded76d26021f36a41707a520f593" + dependencies: + ap "~0.2.0" + balanced-match "~0.2.0" + dot-parts "~1.0.0" + acorn@^4.0.3: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" @@ -28,6 +36,10 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -53,6 +65,10 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +ap@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -150,6 +166,10 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" +balanced-match@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.2.1.tgz#7bc658b4bed61eee424ad74f75f5c3e2c4df3cc7" + base64-js@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" @@ -249,6 +269,16 @@ browserify-rsa@^4.0.0: bn.js "^4.1.0" randombytes "^2.0.1" +browserify-shim@~3.8.14: + version "3.8.14" + resolved "https://registry.yarnpkg.com/browserify-shim/-/browserify-shim-3.8.14.tgz#bf1057026932d3253c75ef7dd714f3b877edec6b" + dependencies: + exposify "~0.5.0" + mothership "~0.2.0" + rename-function-calls "~0.1.0" + resolve "~0.6.1" + through "~2.3.4" + browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" @@ -267,7 +297,7 @@ browserify-zlib@~0.2.0: dependencies: pako "~1.0.5" -browserify@^14.0.0: +browserify@^14.0.0, browserify@~14.5.0: version "14.5.0" resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.5.0.tgz#0bbbce521acd6e4d1d54d8e9365008efb85a9cc5" dependencies: @@ -530,9 +560,9 @@ deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" -deeplearn@~0.3.11: - version "0.3.13" - resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.13.tgz#12033ab21581fb277dede662250bd58d86457d44" +deeplearn@0.3.15: + version "0.3.15" + resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.15.tgz#0cdc7a5171e932dbb312914b56ccdec2dbd873bc" dependencies: seedrandom "~2.4.3" @@ -575,6 +605,20 @@ detective@^4.0.0: acorn "^5.2.1" defined "^1.0.0" +detective@^4.5.0: + version "4.7.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" + dependencies: + acorn "^5.2.1" + defined "^1.0.0" + +detective@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-3.1.0.tgz#77782444ab752b88ca1be2e9d0a0395f1da25eed" + dependencies: + escodegen "~1.1.0" + esprima-fb "3001.1.0-dev-harmony-fb" + diff@^3.2.0: version "3.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" @@ -591,6 +635,10 @@ domain-browser@~1.1.0: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" +dot-parts@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dot-parts/-/dot-parts-1.0.1.tgz#884bd7bcfc3082ffad2fe5db53e494d8f3e0743f" + duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -621,14 +669,40 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +escodegen@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.1.0.tgz#c663923f6e20aad48d0c0fa49f31c6d4f49360cf" + dependencies: + esprima "~1.0.4" + estraverse "~1.5.0" + esutils "~1.0.0" + optionalDependencies: + source-map "~0.1.30" + +esprima-fb@3001.1.0-dev-harmony-fb: + version "3001.1.0-dev-harmony-fb" + resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz#b77d37abcd38ea0b77426bb8bc2922ce6b426411" + +esprima@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" + +estraverse@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71" + esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" +esutils@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" + events@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -652,6 +726,16 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +exposify@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/exposify/-/exposify-0.5.0.tgz#f92d0094c265b3f553e1fa456a03a1883d1059cc" + dependencies: + globo "~1.1.0" + map-obj "~1.0.1" + replace-requires "~1.0.3" + through2 "~0.4.0" + transformify "~0.1.1" + extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -684,6 +768,10 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +find-parent-dir@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -781,6 +869,14 @@ glob@^7.0.5, glob@^7.1.0, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +globo@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/globo/-/globo-1.1.0.tgz#0d26098955dea422eb2001b104898b0a101caaf3" + dependencies: + accessory "~1.1.0" + is-defined "~1.0.0" + ternary "~1.0.0" + graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -806,6 +902,12 @@ has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-require@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/has-require/-/has-require-1.2.2.tgz#921675ab130dbd9768fc8da8f1a8e242dfa41774" + dependencies: + escape-string-regexp "^1.0.3" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -933,6 +1035,10 @@ is-buffer@^1.1.0, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-defined/-/is-defined-1.0.0.tgz#1f07ca67d571f594c4b14415a45f7bef88f92bf5" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -991,14 +1097,14 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +isarray@0.0.1, isarray@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isarray@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -1084,6 +1190,10 @@ lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" +map-obj@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" @@ -1174,6 +1284,12 @@ module-deps@^4.0.8: through2 "^2.0.0" xtend "^4.0.0" +mothership@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/mothership/-/mothership-0.2.0.tgz#93d48a2fbc3e50e2a5fc8ed586f5bc44c65f9a99" + dependencies: + find-parent-dir "~0.3.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1232,6 +1348,10 @@ object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1305,6 +1425,10 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +patch-text@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/patch-text/-/patch-text-1.0.2.tgz#4bf36e65e51733d6e98f0cf62e09034daa0348ac" + path-browserify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" @@ -1424,6 +1548,24 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable string_decoder "~1.0.3" util-deprecate "~1.0.1" +readable-stream@~1.0.17: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readable-stream@~2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -1454,6 +1596,12 @@ remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" +rename-function-calls@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/rename-function-calls/-/rename-function-calls-0.1.1.tgz#7f83369c007a3007f6abe3033ccf81686a108e01" + dependencies: + detective "~3.1.0" + repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" @@ -1462,6 +1610,15 @@ repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" +replace-requires@~1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/replace-requires/-/replace-requires-1.0.4.tgz#014b7330b6b9e2557b71043b66fb02660c3bf667" + dependencies: + detective "^4.5.0" + has-require "~1.2.1" + patch-text "~1.0.2" + xtend "~4.0.0" + request@2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -1499,6 +1656,10 @@ resolve@^1.1.3, resolve@^1.1.4, resolve@^1.3.2: dependencies: path-parse "^1.0.5" +resolve@~0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" + rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" @@ -1565,6 +1726,12 @@ sntp@1.x.x: dependencies: hoek "2.x.x" +source-map@~0.1.30: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -1695,6 +1862,10 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" +ternary@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ternary/-/ternary-1.0.0.tgz#45702725608c9499d46a9610e9b0e49ff26f789e" + through2@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" @@ -1702,7 +1873,14 @@ through2@^2.0.0: readable-stream "^2.1.5" xtend "~4.0.1" -"through@>=2.2.7 <3": +through2@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" + dependencies: + readable-stream "~1.0.17" + xtend "~2.1.1" + +"through@>=2.2.7 <3", through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -1722,6 +1900,12 @@ tough-cookie@~2.3.0: dependencies: punycode "^1.4.1" +transformify@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/transformify/-/transformify-0.1.2.tgz#9a4f42a154433dd727b80575428a3c9e5489ebf1" + dependencies: + readable-stream "~1.1.9" + tsconfig@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-5.0.3.tgz#5f4278e701800967a8fc383fd19648878f2a6e3a" @@ -1859,6 +2043,12 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + dependencies: + object-keys "~0.4.0" diff --git a/models/yolo_mobilenet/yolo_mobilenet.ts b/models/yolo_mobilenet/yolo_mobilenet.ts index 53406484cd..185bda9652 100644 --- a/models/yolo_mobilenet/yolo_mobilenet.ts +++ b/models/yolo_mobilenet/yolo_mobilenet.ts @@ -14,40 +14,34 @@ * limitations under the License. * ============================================================================= */ -// tslint:disable-next-line:max-line-length -import {Array1D, Array3D, Array4D, CheckpointLoader, initializeGPU, Model, NDArray, NDArrayMath, NDArrayMathGPU, Scalar} from 'deeplearn'; -import {BoundingBox} from './mobilenet_utils'; +// tslint:disable-next-line:max-line-length +import {Array1D, Array3D, Array4D, CheckpointLoader, Model, NDArray, NDArrayMath, Scalar} from 'deeplearn'; +import {BoundingBox} from './mobilenet_utils'; -const GOOGLE_CLOUD_STORAGE_DIR = +const GOOGLE_CLOUD_STORAGE_DIR = 'https://storage.googleapis.com/learnjs-data/checkpoint_zoo/'; - + export class YoloMobileNetDetection implements Model { private variables: {[varName: string]: NDArray}; // yolo variables - private PREPROCESS_DIVISOR = Scalar.new(255.0/2); - private ONE = Scalar.ONE; + private PREPROCESS_DIVISOR = Scalar.new(255.0 / 2); + private ONE = Scalar.new(1); private THRESHOLD = 0.3; private THRESHOLD_SCALAR = Scalar.new(this.THRESHOLD); - private ANCHORS: number[] = [0.57273, 0.677385, 1.87446, 2.06253, 3.33843, - 5.47434, 7.88282, 3.52778, 9.77052, 9.16828]; - - constructor(private math: NDArrayMath) { - // TODO(nsthorat): This awful hack is because we need to share the global - // GPGPU between deeplearn loaded from standalone as well as the internal - // deeplearn that gets compiled as part of this model. Remove this once we - // decouple NDArray from storage mechanism. - initializeGPU( - (this.math as NDArrayMathGPU).getGPGPUContext(), - (this.math as NDArrayMathGPU).getTextureManager()); - } + private ANCHORS: number[] = [ + 0.57273, 0.677385, 1.87446, 2.06253, 3.33843, 5.47434, 7.88282, 3.52778, + 9.77052, 9.16828 + ]; + + constructor(private math: NDArrayMath) {} /** * Loads necessary variables for MobileNet. */ async load(): Promise { - const checkpointLoader = new CheckpointLoader(GOOGLE_CLOUD_STORAGE_DIR + - 'yolo_mobilenet_v1_1.0_416/'); + const checkpointLoader = new CheckpointLoader( + GOOGLE_CLOUD_STORAGE_DIR + 'yolo_mobilenet_v1_1.0_416/'); this.variables = await checkpointLoader.getAllVariables(); } @@ -63,96 +57,88 @@ export class YoloMobileNetDetection implements Model { // Keep a map of named activations for rendering purposes. const netout = this.math.scope((keep) => { // Preprocess the input. - const preprocessedInput = this.math.subtract( - this.math.arrayDividedByScalar(input, this.PREPROCESS_DIVISOR), - this.ONE) as Array3D; + const preprocessedInput = + this.math.subtract( + this.math.arrayDividedByScalar(input, this.PREPROCESS_DIVISOR), + this.ONE) as Array3D; - const x1 = this.convBlock(preprocessedInput, [2, 2]); - const x2 = this.depthwiseConvBlock(x1, [1, 1], 1); + const x1 = this.convBlock(preprocessedInput, [2, 2]); + const x2 = this.depthwiseConvBlock(x1, [1, 1], 1); - const x3 = this.depthwiseConvBlock(x2, [2, 2], 2); - const x4 = this.depthwiseConvBlock(x3, [1, 1], 3); + const x3 = this.depthwiseConvBlock(x2, [2, 2], 2); + const x4 = this.depthwiseConvBlock(x3, [1, 1], 3); - const x5 = this.depthwiseConvBlock(x4, [2, 2], 4); - const x6 = this.depthwiseConvBlock(x5, [1, 1], 5); + const x5 = this.depthwiseConvBlock(x4, [2, 2], 4); + const x6 = this.depthwiseConvBlock(x5, [1, 1], 5); - const x7 = this.depthwiseConvBlock(x6, [2, 2], 6); - const x8 = this.depthwiseConvBlock(x7, [1, 1], 7); - const x9 = this.depthwiseConvBlock(x8, [1, 1], 8); - const x10 = this.depthwiseConvBlock(x9, [1, 1], 9); + const x7 = this.depthwiseConvBlock(x6, [2, 2], 6); + const x8 = this.depthwiseConvBlock(x7, [1, 1], 7); + const x9 = this.depthwiseConvBlock(x8, [1, 1], 8); + const x10 = this.depthwiseConvBlock(x9, [1, 1], 9); const x11 = this.depthwiseConvBlock(x10, [1, 1], 10); const x12 = this.depthwiseConvBlock(x11, [1, 1], 11); const x13 = this.depthwiseConvBlock(x12, [2, 2], 12); const x14 = this.depthwiseConvBlock(x13, [1, 1], 13); - const x15 = this.math.conv2d(x14, - this.variables['conv_23/kernel'] as Array4D, - this.variables['conv_23/bias'] as Array1D, - [1,1], - 'same'); - + const x15 = this.math.conv2d( + x14, this.variables['conv_23/kernel'] as Array4D, + this.variables['conv_23/bias'] as Array1D, [1, 1], 'same'); + return x15.as4D(13, 13, 5, 6); }); return netout; - } - - private convBlock(inputs: Array3D, strides: [number, number]) { + } - const x1 = this.math.conv2d(inputs, - this.variables['conv1/kernel'] as Array4D, - null, // this convolutional layer does not use bias - strides, - 'same'); + private convBlock(inputs: Array3D, strides: [number, number]) { + const x1 = this.math.conv2d( + inputs, this.variables['conv1/kernel'] as Array4D, + null, // this convolutional layer does not use bias + strides, 'same'); - const x2 = this.math.batchNormalization3D(x1, - this.variables['conv1_bn/moving_mean'] as Array1D, - this.variables['conv1_bn/moving_variance'] as Array1D, - .001, + const x2 = this.math.batchNormalization3D( + x1, this.variables['conv1_bn/moving_mean'] as Array1D, + this.variables['conv1_bn/moving_variance'] as Array1D, .001, this.variables['conv1_bn/gamma'] as Array1D, this.variables['conv1_bn/beta'] as Array1D); - return this.math.clip(x2, 0, 6); // simple implementation of Relu6 + return this.math.clip(x2, 0, 6); // simple implementation of Relu6 } - private depthwiseConvBlock(inputs: Array3D, - strides: [number, number], - blockID: number) { + private depthwiseConvBlock( + inputs: Array3D, strides: [number, number], blockID: number) { const dwPadding = 'conv_dw_' + String(blockID) + ''; - const pwPadding = 'conv_pw_' + String(blockID) + ''; + const pwPadding = 'conv_pw_' + String(blockID) + ''; - const x1 = this.math.depthwiseConv2D(inputs, - this.variables[dwPadding + '/depthwise_kernel'] as Array4D, - strides, - 'same') as Array3D; + const x1 = + this.math.depthwiseConv2D( + inputs, this.variables[dwPadding + '/depthwise_kernel'] as Array4D, + strides, 'same') as Array3D; - const x2 = this.math.batchNormalization3D(x1, - this.variables[dwPadding + '_bn/moving_mean'] as Array1D, - this.variables[dwPadding + '_bn/moving_variance'] as Array1D, - .001, + const x2 = this.math.batchNormalization3D( + x1, this.variables[dwPadding + '_bn/moving_mean'] as Array1D, + this.variables[dwPadding + '_bn/moving_variance'] as Array1D, .001, this.variables[dwPadding + '_bn/gamma'] as Array1D, this.variables[dwPadding + '_bn/beta'] as Array1D); const x3 = this.math.clip(x2, 0, 6); - const x4 = this.math.conv2d(x3, - this.variables[pwPadding + '/kernel'] as Array4D, - null, // this convolutional layer does not use bias - [1, 1], - 'same'); + const x4 = this.math.conv2d( + x3, this.variables[pwPadding + '/kernel'] as Array4D, + null, // this convolutional layer does not use bias + [1, 1], 'same'); - const x5 = this.math.batchNormalization3D(x4, - this.variables[pwPadding + '_bn/moving_mean'] as Array1D, - this.variables[pwPadding + '_bn/moving_variance'] as Array1D, - .001, + const x5 = this.math.batchNormalization3D( + x4, this.variables[pwPadding + '_bn/moving_mean'] as Array1D, + this.variables[pwPadding + '_bn/moving_variance'] as Array1D, .001, this.variables[pwPadding + '_bn/gamma'] as Array1D, this.variables[pwPadding + '_bn/beta'] as Array1D); return this.math.clip(x5, 0, 6); } - async interpretNetout(netout: Array4D): Promise { + async interpretNetout(netout: Array4D): Promise { // interpret the output by the network const GRID_H = netout.shape[0]; const GRID_W = netout.shape[1]; @@ -161,16 +147,15 @@ export class YoloMobileNetDetection implements Model { const boxes: BoundingBox[] = []; // adjust confidence predictions - const confidence = this.math.sigmoid(this.math.slice4D(netout, - [0, 0, 0, 4], - [GRID_H, GRID_W, BOX, 1])); + const confidence = this.math.sigmoid( + this.math.slice4D(netout, [0, 0, 0, 4], [GRID_H, GRID_W, BOX, 1])); // adjust class prediction - let classes = this.math.softmax(this.math.slice4D(netout, [0, 0, 0, 5], - [GRID_H, GRID_W, BOX, CLASS])); + let classes = this.math.softmax( + this.math.slice4D(netout, [0, 0, 0, 5], [GRID_H, GRID_W, BOX, CLASS])); classes = this.math.multiply(classes, confidence) as Array4D; - const mask = this.math.step(this.math.relu(this.math.subtract(classes, - this.THRESHOLD_SCALAR))); + const mask = this.math.step( + this.math.relu(this.math.subtract(classes, this.THRESHOLD_SCALAR))); classes = this.math.multiply(classes, mask) as Array4D; const objectLikelihood = this.math.sum(classes, 3); @@ -181,10 +166,11 @@ export class YoloMobileNetDetection implements Model { const [row, col, box] = objectLikelihood.indexToLoc(i) as number[]; const conf = confidence.get(row, col, box, 0); - const probs = this.math.slice4D(classes, - [row, col, box, 0], [1, 1, 1, CLASS]).getValues() as Float32Array; - const xywh = this.math.slice4D(netout, - [row, col, box, 0], [1, 1, 1, 4]).getValues(); + const probs = + this.math.slice4D(classes, [row, col, box, 0], [1, 1, 1, CLASS]) + .getValues() as Float32Array; + const xywh = this.math.slice4D(netout, [row, col, box, 0], [1, 1, 1, 4]) + .getValues(); let x = xywh[0]; let y = xywh[1]; @@ -195,7 +181,7 @@ export class YoloMobileNetDetection implements Model { w = this.ANCHORS[2 * box + 0] * Math.exp(w) / GRID_W; h = this.ANCHORS[2 * box + 1] * Math.exp(h) / GRID_H; - boxes.push(new BoundingBox(x, y, w, h, conf, probs)); + boxes.push(new BoundingBox(x, y, w, h, conf, probs)); } } @@ -208,7 +194,7 @@ export class YoloMobileNetDetection implements Model { indices[i] = i; } - indices.sort((a,b) => allProbs[a] > allProbs[b] ? 1 : 0); + indices.sort((a, b) => allProbs[a] > allProbs[b] ? 1 : 0); for (let i = 0; i < allProbs.length; i++) { const indexI = indices[i]; @@ -216,7 +202,7 @@ export class YoloMobileNetDetection implements Model { if (boxes[indexI].probs[cls] === 0) { continue; } else { - for (let j = i+1; j < allProbs.length; j++){ + for (let j = i + 1; j < allProbs.length; j++) { const indexJ = indices[j]; if (boxes[indexI].iou(boxes[indexJ]) > 0.4) { @@ -225,14 +211,13 @@ export class YoloMobileNetDetection implements Model { } } } - - } + } // obtain the most likely boxes const likelyBoxes = []; for (const box of boxes) { - if (box.getMaxProb() > this.THRESHOLD) { + if (box.getMaxProb() > this.THRESHOLD) { likelyBoxes.push(box); } } @@ -241,12 +226,12 @@ export class YoloMobileNetDetection implements Model { } private sigmoid(x: number): number { - return 1./ (1. + Math.exp(-x)); - } + return 1. / (1. + Math.exp(-x)); + } dispose() { for (const varName in this.variables) { this.variables[varName].dispose(); } } -} \ No newline at end of file +} diff --git a/scripts/build_and_lint_all b/scripts/build_and_lint_all index 3fd7a4c281..3cae8ab379 100755 --- a/scripts/build_and_lint_all +++ b/scripts/build_and_lint_all @@ -56,5 +56,7 @@ function runYarn(filePath) { shell.cd(cwd); } -const dirs = getPackageDirs(process.cwd()); +let dirs = getPackageDirs(process.cwd()); +// Keep only packages that have the 'name' property. +dirs = dirs.filter(dir => require(path.join(dir, 'package.json')).name); dirs.forEach(dir => runYarn(dir)); diff --git a/src/graph/session_util_test.ts b/src/graph/session_util_test.ts index acb82a916d..2b0311f498 100644 --- a/src/graph/session_util_test.ts +++ b/src/graph/session_util_test.ts @@ -183,7 +183,7 @@ describe('loadInputsFromFeedDictionaryToTensorArrayMap', () => { // right value. return ndarray; }, - // No need to dispose when not using NDArrayMathGPU. + // No need to dispose when not using the webgl backend. disposeCopy() {} }; const fd = new FeedDictionary([{tensor, data: provider}]); diff --git a/starter/es6/main.js b/starter/es6/main.js index 8dbcc1b99f..bb0668cb69 100644 --- a/starter/es6/main.js +++ b/starter/es6/main.js @@ -1,9 +1,9 @@ import 'babel-polyfill'; -import {Array1D, NDArrayMathGPU, Scalar} from 'deeplearn'; +import {Array1D, ENV, Scalar} from 'deeplearn'; /** Runs the example. */ async function runExample() { - const math = new NDArrayMathGPU(); + const math = ENV.math; const a = Array1D.new([1, 2, 3]); const b = Scalar.new(2); diff --git a/starter/es6/package.json b/starter/es6/package.json index 211bbc8229..b8ccdebd7c 100644 --- a/starter/es6/package.json +++ b/starter/es6/package.json @@ -4,7 +4,7 @@ "description": "Starter project for using deeplearn.js with es6", "dependencies": { "babel-polyfill": "~6.26.0", - "deeplearn": "~0.3.3" + "deeplearn": "0.3.15" }, "devDependencies": { "babel-plugin-syntax-async-functions": "~6.13.0", diff --git a/starter/es6/yarn.lock b/starter/es6/yarn.lock index c138675080..55ca02219e 100644 --- a/starter/es6/yarn.lock +++ b/starter/es6/yarn.lock @@ -1036,9 +1036,9 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -deeplearn@~0.3.3: - version "0.3.11" - resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.11.tgz#b851281158da16d6745f490dc6ae8c9db851bc03" +deeplearn@0.3.15: + version "0.3.15" + resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.15.tgz#0cdc7a5171e932dbb312914b56ccdec2dbd873bc" dependencies: seedrandom "~2.4.3" diff --git a/starter/typescript/main.ts b/starter/typescript/main.ts index cec37399ad..adb600ad29 100644 --- a/starter/typescript/main.ts +++ b/starter/typescript/main.ts @@ -1,7 +1,7 @@ -import {Array1D, NDArrayMathGPU, Scalar} from 'deeplearn'; +import {Array1D, ENV, Scalar} from 'deeplearn'; async function runExample() { - const math = new NDArrayMathGPU(); + const math = ENV.math; const a = Array1D.new([1, 2, 3]); const b = Scalar.new(2); diff --git a/starter/typescript/package.json b/starter/typescript/package.json index 611aa3522d..aca6255d29 100644 --- a/starter/typescript/package.json +++ b/starter/typescript/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Starter project for using deeplearn.js with TypeScript", "dependencies": { - "deeplearn": "~0.3.3" + "deeplearn": "0.3.15" }, "devDependencies": { "mkdirp": "~0.5.1", diff --git a/starter/typescript/yarn.lock b/starter/typescript/yarn.lock index 76ee3e67ea..fc3a874639 100644 --- a/starter/typescript/yarn.lock +++ b/starter/typescript/yarn.lock @@ -526,9 +526,9 @@ deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" -deeplearn@~0.3.3: - version "0.3.11" - resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.11.tgz#b851281158da16d6745f490dc6ae8c9db851bc03" +deeplearn@0.3.15: + version "0.3.15" + resolved "https://registry.yarnpkg.com/deeplearn/-/deeplearn-0.3.15.tgz#0cdc7a5171e932dbb312914b56ccdec2dbd873bc" dependencies: seedrandom "~2.4.3"