diff --git a/.gitignore b/.gitignore index b899f89b51f1efee5dd6faae0b675a525813d55a..ea4170641b8aa2fd92f7476510eba1b36944a824 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,4 @@ tags test models -terraform.tfstate -terraform.tfstate.backup -terraform.tfvars .idea diff --git a/README.md b/README.md index 4ca23bf632bc54c90f3e04bf573fbd8c88b98579..c7282686da9a66e55ac23927785115af6413103b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Based on [pix2pix](https://phillipi.github.io/pix2pix/) by Isola et al. [Article about this implemention](https://affinelayer.com/pix2pix/) +[Interactive Demo](https://affinelayer.com/pixsrv/) + Tensorflow implementation of pix2pix. Learns a mapping from input images to output images, like these examples from the original paper: <img src="docs/examples.jpg" width="900px"/> @@ -13,7 +15,7 @@ This port is based directly on the torch implementation, and not on an existing ## Setup ### Prerequisites -- Tensorflow 1.0.0 +- Tensorflow 1.4.1 ### Recommended - Linux with Tensorflow GPU edition + cuDNN @@ -71,15 +73,15 @@ For example: <img src="docs/418.png" width="256px"/> -Some datasets have been made available by the authors of the pix2pix paper. To download those datasets, use the included script `tools/download-dataset.py`. There are also links to pre-trained models alongside each dataset, note that these pre-trained models require the Tensorflow 0.12.1 version of pix2pix.py since they have not been regenerated with the 1.0.0 release: +Some datasets have been made available by the authors of the pix2pix paper. To download those datasets, use the included script `tools/download-dataset.py`. There are also links to pre-trained models alongside each dataset, note that these pre-trained models require the current version of pix2pix.py: | dataset | example | | --- | --- | -| `python tools/download-dataset.py facades` <br> 400 images from [CMP Facades dataset](http://cmp.felk.cvut.cz/~tylecr1/facade/). (31MB) <br> Pre-trained: [BtoA](https://mega.nz/#!2xpyQBoK!GVtkZN7lqY4aaZltMFdZsPNVE6bUsWyiVUN6RwJtIxQ) | <img src="docs/facades.jpg" width="256px"/> | -| `python tools/download-dataset.py cityscapes` <br> 2975 images from the [Cityscapes training set](https://www.cityscapes-dataset.com/). (113M) <br> Pre-trained: [AtoB](https://mega.nz/#!rxByxK6S!W9ZBUqgdGTFDWVlOE_ljVt1G3bU89bdu_nS9Bi1ujiA) [BtoA](https://mega.nz/#!b1olDbhL!mxsYC5AF_WH64CXoukN0KB-nw15kLQ0Etii-F-HDTps) | <img src="docs/cityscapes.jpg" width="256px"/> | -| `python tools/download-dataset.py maps` <br> 1096 training images scraped from Google Maps (246M) <br> Pre-trained: [AtoB](https://mega.nz/#!i8pkkBJT!3NKLar9sUr-Vh_vNVQF-xwK9-D9iCqaCmj1T27xRf4w) [BtoA](https://mega.nz/#!r8xwCBCD!lNBrY_2QO6pyUJziGj7ikPheUL_yXA8xGXFlM3GPL3c) | <img src="docs/maps.jpg" width="256px"/> | -| `python tools/download-dataset.py edges2shoes` <br> 50k training images from [UT Zappos50K dataset](http://vision.cs.utexas.edu/projects/finegrained/utzap50k/). Edges are computed by [HED](https://github.com/s9xie/hed) edge detector + post-processing. (2.2GB) <br> Pre-trained: [AtoB](https://mega.nz/#!OoYT3QiQ!8y3zLESvhOyeA6UsjEbcJphi3_uEt534waSL5_f_D4Y) | <img src="docs/edges2shoes.jpg" width="256px"/> | -| `python tools/download-dataset.py edges2handbags` <br> 137K Amazon Handbag images from [iGAN project](https://github.com/junyanz/iGAN). Edges are computed by [HED](https://github.com/s9xie/hed) edge detector + post-processing. (8.6GB) <br> Pre-trained: [AtoB](https://mega.nz/#!KlpBHKrZ!iJ3x6xzgk0wnJkPiAf0UxPzhYSmpC3kKH1DY5n_dd0M) | <img src="docs/edges2handbags.jpg" width="256px"/> | +| `python tools/download-dataset.py facades` <br> 400 images from [CMP Facades dataset](http://cmp.felk.cvut.cz/~tylecr1/facade/). (31MB) <br> Pre-trained: [BtoA]() | <img src="docs/facades.jpg" width="256px"/> | +| `python tools/download-dataset.py cityscapes` <br> 2975 images from the [Cityscapes training set](https://www.cityscapes-dataset.com/). (113M) <br> Pre-trained: [AtoB]() [BtoA]() | <img src="docs/cityscapes.jpg" width="256px"/> | +| `python tools/download-dataset.py maps` <br> 1096 training images scraped from Google Maps (246M) <br> Pre-trained: [AtoB]() [BtoA]() | <img src="docs/maps.jpg" width="256px"/> | +| `python tools/download-dataset.py edges2shoes` <br> 50k training images from [UT Zappos50K dataset](http://vision.cs.utexas.edu/projects/finegrained/utzap50k/). Edges are computed by [HED](https://github.com/s9xie/hed) edge detector + post-processing. (2.2GB) <br> Pre-trained: [AtoB]() | <img src="docs/edges2shoes.jpg" width="256px"/> | +| `python tools/download-dataset.py edges2handbags` <br> 137K Amazon Handbag images from [iGAN project](https://github.com/junyanz/iGAN). Edges are computed by [HED](https://github.com/s9xie/hed) edge detector + post-processing. (8.6GB) <br> Pre-trained: [AtoB]() | <img src="docs/edges2handbags.jpg" width="256px"/> | The `facades` dataset is the smallest and easiest to get started with. diff --git a/docker/Dockerfile b/docker/Dockerfile index 8d1ab044e695f732ce4ffa29354be88541dcd173..2a0bc78c946fc808fe04329af8175d797bd1c26f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04 +FROM nvidia/cuda:8.0-cudnn6-devel-ubuntu16.04 WORKDIR /root @@ -11,6 +11,7 @@ RUN apt-get install -y --no-install-recommends \ cmake \ git \ wget \ + curl \ libatlas-base-dev \ libboost-all-dev \ libgflags-dev \ @@ -80,7 +81,6 @@ RUN curl -O https://raw.githubusercontent.com/pdollar/edges/master/private/edges # from https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tools/docker/Dockerfile.gpu RUN apt-get install -y --no-install-recommends \ build-essential \ - curl \ libfreetype6-dev \ libpng12-dev \ libzmq3-dev \ @@ -116,8 +116,4 @@ RUN pip install \ rsa==3.4.2 \ six==1.10.0 \ uritemplate==3.0.0 \ - tensorflow-gpu==1.0.0 - -RUN curl -O https://releases.hashicorp.com/terraform/0.8.7/terraform_0.8.7_linux_amd64.zip && \ - unzip terraform_0.8.7_linux_amd64.zip -d /usr/local/bin && \ - rm terraform_0.8.7_linux_amd64.zip \ No newline at end of file + tensorflow-gpu==1.4.1 \ No newline at end of file diff --git a/pix2pix.py b/pix2pix.py index 20ba819340c414b14ba753047919744e14a777f4..291543fa5a08e44d8b223b31b488ef387f9a7098 100644 --- a/pix2pix.py +++ b/pix2pix.py @@ -91,14 +91,9 @@ def augment(image, brightness): def conv(batch_input, out_channels, stride): - with tf.variable_scope("conv"): - in_channels = batch_input.get_shape()[3] - filter = tf.get_variable("filter", [4, 4, in_channels, out_channels], dtype=tf.float32, initializer=tf.random_normal_initializer(0, 0.02)) - # [batch, in_height, in_width, in_channels], [filter_width, filter_height, in_channels, out_channels] - # => [batch, out_height, out_width, out_channels] - padded_input = tf.pad(batch_input, [[0, 0], [1, 1], [1, 1], [0, 0]], mode="CONSTANT") - conv = tf.nn.conv2d(padded_input, filter, [1, stride, stride, 1], padding="VALID") - return conv + # [batch, in_height, in_width, in_channels] => [batch, out_height, out_width, out_channels] + padded_input = tf.pad(batch_input, [[0, 0], [1, 1], [1, 1], [0, 0]], mode="CONSTANT") + return tf.layers.conv2d(padded_input, out_channels, kernel_size=4, strides=(stride, stride), padding="valid", kernel_initializer=tf.random_normal_initializer(0, 0.02)) def lrelu(x, a): @@ -113,28 +108,13 @@ def lrelu(x, a): return (0.5 * (1 + a)) * x + (0.5 * (1 - a)) * tf.abs(x) -def batchnorm(input): - with tf.variable_scope("batchnorm"): - # this block looks like it has 3 inputs on the graph unless we do this - input = tf.identity(input) - - channels = input.get_shape()[3] - offset = tf.get_variable("offset", [channels], dtype=tf.float32, initializer=tf.zeros_initializer()) - scale = tf.get_variable("scale", [channels], dtype=tf.float32, initializer=tf.random_normal_initializer(1.0, 0.02)) - mean, variance = tf.nn.moments(input, axes=[0, 1, 2], keep_dims=False) - variance_epsilon = 1e-5 - normalized = tf.nn.batch_normalization(input, mean, variance, offset, scale, variance_epsilon=variance_epsilon) - return normalized +def batchnorm(inputs): + return tf.layers.batch_normalization(inputs, axis=3, epsilon=1e-5, momentum=0.1, training=True, gamma_initializer=tf.random_normal_initializer(1.0, 0.02)) def deconv(batch_input, out_channels): - with tf.variable_scope("deconv"): - batch, in_height, in_width, in_channels = [int(d) for d in batch_input.get_shape()] - filter = tf.get_variable("filter", [4, 4, out_channels, in_channels], dtype=tf.float32, initializer=tf.random_normal_initializer(0, 0.02)) - # [batch, in_height, in_width, in_channels], [filter_width, filter_height, out_channels, in_channels] - # => [batch, out_height, out_width, out_channels] - conv = tf.nn.conv2d_transpose(batch_input, filter, [batch, in_height * 2, in_width * 2, out_channels], [1, 2, 2, 1], padding="SAME") - return conv + # [batch, in_height, in_width, in_channels] => [batch, out_height, out_width, out_channels] + return tf.layers.conv2d_transpose(batch_input, out_channels, kernel_size=4, strides=(2, 2), padding="same", kernel_initializer=tf.random_normal_initializer(0, 0.02)) def check_image(image): @@ -430,7 +410,7 @@ def create_model(inputs, targets): return layers[-1] - with tf.variable_scope("generator") as scope: + with tf.variable_scope("generator"): out_channels = int(targets.get_shape()[-1]) outputs = create_generator(inputs, out_channels) @@ -475,7 +455,7 @@ def create_model(inputs, targets): ema = tf.train.ExponentialMovingAverage(decay=0.99) update_losses = ema.apply([discrim_loss, gen_loss_GAN, gen_loss_L1]) - global_step = tf.contrib.framework.get_or_create_global_step() + global_step = tf.train.get_or_create_global_step() incr_global_step = tf.assign(global_step, global_step+1) return Model( @@ -539,9 +519,6 @@ def append_index(filesets, step=False): def main(): - if tf.__version__.split('.')[0] != "1": - raise Exception("Tensorflow version 1 required") - if a.seed is None: a.seed = random.randint(0, 2**31 - 1) @@ -741,7 +718,6 @@ def main(): for i, f in enumerate(filesets): print("evaluated image", f["name"]) index_path = append_index(filesets) - print("wrote index at", index_path) else: # training diff --git a/server/Dockerfile b/server/Dockerfile deleted file mode 100644 index ad9910fe50227ccadbb17c918cd1764d05ba4561..0000000000000000000000000000000000000000 --- a/server/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM ubuntu:xenial-20170119 - -RUN apt-get update - -RUN apt-get install -y --no-install-recommends \ - python-dev \ - python-pip \ - python-setuptools \ - python-wheel - -RUN pip install \ - scipy==0.18.1 \ - appdirs==1.4.0 \ - funcsigs==1.0.2 \ - google-api-python-client==1.6.2 \ - google-auth==0.7.0 \ - google-auth-httplib2==0.0.2 \ - google-cloud-core==0.22.1 \ - google-cloud-storage==0.22.0 \ - googleapis-common-protos==1.5.2 \ - httplib2==0.10.3 \ - mock==2.0.0 \ - numpy==1.12.0 \ - oauth2client==4.0.0 \ - packaging==16.8 \ - pbr==1.10.0 \ - protobuf==3.2.0 \ - pyasn1==0.2.2 \ - pyasn1-modules==0.0.8 \ - pyparsing==2.1.10 \ - rsa==3.4.2 \ - six==1.10.0 \ - uritemplate==3.0.0 \ - tensorflow==1.0.0 - -WORKDIR /server -COPY models models -COPY static static -COPY serve.py serve.py \ No newline at end of file diff --git a/server/README.md b/server/README.md index f5fac9be602501ece825ff5be1a19c45dc635c15..2993d3497ff3e4e330687505bafe5d8242bbb76e 100644 --- a/server/README.md +++ b/server/README.md @@ -2,193 +2,28 @@ Host pix2pix-tensorflow models to be used with something like the [Image-to-Image Demo](https://affinelayer.com/pixsrv/). -This is a simple python server that serves models exported from `pix2pix.py --mode export`. It can serve local models or use [Cloud ML](https://cloud.google.com/ml/) to run the model. +This is a simple python server that uses [deeplearn.js](https://deeplearnjs.org/) exported from pix2pix checkpoints using `tools/export-checkpoint.py`. ## Exporting -You can export a model to be served with `--mode export`. As with testing, you should specify the checkpoint to use with `--checkpoint`. +You can export a model to be served with `tools/export-checkpoint.py`. ```sh -python ../pix2pix.py \ - --mode export \ - --output_dir models/facades \ - --checkpoint ../facades_train +python tools/export-checkpoint.py \ + --checkpoint facades_BtoA \ + --output_file static/models/facades_BtoA.bin ``` -## Local Serving - -Using the [pix2pix-tensorflow Docker image](https://hub.docker.com/r/affinelayer/pix2pix-tensorflow/): - -```sh -# export a model to upload (if you did not export one above) -python ../tools/dockrun.py python tools/export-example-model.py --output_dir models/example -# process an image with the model using local tensorflow -python ../tools/dockrun.py python tools/process-local.py \ - --model_dir models/example \ - --input_file static/facades-input.png \ - --output_file output.png -# run local server -python ../tools/dockrun.py --port 8000 python serve.py --port 8000 --local_models_dir models -# test the local server -python tools/process-remote.py \ - --input_file static/facades-input.png \ - --url http://localhost:8000/example \ - --output_file output.png -``` - -If you open [http://localhost:8000/](http://localhost:8000/) in a browser, you should see an interactive demo, though this expects the server to be hosting the exported models available here: - -- [edges2shoes](https://mega.nz/#!HtYwAZTY!5tBLYt_6HFj9u2Kxgp4-I36O4EV9r3bDP44ztX3qesI) -- [edges2handbags](https://mega.nz/#!Clg3EaLA!YW2jfRHvwpJn5Elww_wM-f3eRzKiGHLw-F4A3eQCceI) -- [facades](https://mega.nz/#!f1ZjmZoa!mCSxFRxt1WLBpNFsv5raoroEigxomDVpdi40aOG1KMc) - -Extract those to the models directory and restart the server to have it host the models. - -## Cloud ML Serving - -For this you'll want to generate a service account JSON file from https://console.cloud.google.com/iam-admin/serviceaccounts/project (select "Furnish a new private key"). If you are already logged in with the gcloud SDK, the script will auto-detect credentials from that if you leave off the `--credentials` option. +You can also copy models from the `pix2pix-tensorflow-models` repo: ```sh -# upload model to google cloud ml -python ../tools/dockrun.py python tools/upload-model.py \ - --bucket your-models-bucket-name-here \ - --model_name example \ - --model_dir models/example \ - --credentials service-account.json -# process an image with the model using google cloud ml -python ../tools/dockrun.py python tools/process-cloud.py \ - --model example \ - --input_file static/facades-input.png \ - --output_file output.png \ - --credentials service-account.json +git clone git@github.com:affinelayer/pix2pix-tensorflow-models.git static/models ``` -## Running serve.py on Google Cloud Platform - -Assuming you have gcloud and docker setup: +## Serving ```sh -export GOOGLE_PROJECT=<project name> -# build image -# make sure models are in a directory called "models" in the current directory -sudo docker build --rm --tag us.gcr.io/$GOOGLE_PROJECT/pix2pix-server . -# test image locally -sudo docker run --publish 8080:8080 --rm --name server us.gcr.io/$GOOGLE_PROJECT/pix2pix-server python -u serve.py \ - --port 8080 \ - --local_models_dir models -python tools/process-remote.py \ - --input_file static/facades-input.png \ - --url http://localhost:8080/example \ - --output_file output.png -# publish image to private google container repository -python tools/upload-image.py --project $GOOGLE_PROJECT --version v1 -# setup server -cp terraform.tfvars.example terraform.tfvars -# edit terraform.tfvars to put your cloud info in there -python ../tools/dockrun.py terraform plan -python ../tools/dockrun.py terraform apply +python serve.py --port 8000 ``` -## Full training + exporting + hosting commands - -Tested with Python 3.6, Tensorflow 1.0.0, Docker, gcloud, and Terraform (https://www.terraform.io/downloads.html) - -```sh -git clone https://github.com/affinelayer/pix2pix-tensorflow.git -cd pix2pix-tensorflow - -# get some images (only 2 for testing) -mkdir source -curl -o source/cat1.jpg https://farm5.staticflickr.com/4032/4394955222_eea73818d9_o.jpg -curl -o source/cat2.jpg http://wallpapercave.com/wp/ePMeSmp.jpg - -# resize source images -python tools/process.py \ - --input_dir source \ - --operation resize \ - --output_dir resized - -# create edges from resized images (uses docker container since compiling the dependencies is annoying) -python tools/dockrun.py python tools/process.py \ - --input_dir resized \ - --operation edges \ - --output_dir edges - -# combine resized with edges -python tools/process.py \ - --input_dir edges \ - --b_dir resized \ - --operation combine \ - --output_dir combined - -# train on images (only 1 epoch for testing) -python pix2pix.py \ - --mode train \ - --output_dir train \ - --max_epochs 1 \ - --input_dir combined \ - --which_direction AtoB - -# export model (creates a version of the model that works with the server in server/serve.py as well as google hosted tensorflow) -python pix2pix.py \ - --mode export \ - --output_dir server/models/edges2cats_AtoB \ - --checkpoint train - -# process image locally using exported model -python server/tools/process-local.py \ - --model_dir server/models/edges2cats_AtoB \ - --input_file edges/cat1.png \ - --output_file output.png - -# serve model locally -cd server -python serve.py --port 8000 --local_models_dir models - -# open http://localhost:8000 in a browser, and scroll to the bottom, you should be able to process an edges2cat image and get a bunch of noise as output - -# serve model remotely - -export GOOGLE_PROJECT=<project name> - -# build image -# make sure models are in a directory called "models" in the current directory -docker build --rm --tag us.gcr.io/$GOOGLE_PROJECT/pix2pix-server . - -# test image locally -docker run --publish 8000:8000 --rm --name server us.gcr.io/$GOOGLE_PROJECT/pix2pix-server python -u serve.py \ - --port 8000 \ - --local_models_dir models - -# run this while the above server is running -python tools/process-remote.py \ - --input_file static/edges2cats-input.png \ - --url http://localhost:8000/edges2cats_AtoB \ - --output_file output.png - -# publish image to private google container repository -python tools/upload-image.py --project $GOOGLE_PROJECT --version v1 - -# create a google cloud server -cp terraform.tfvars.example terraform.tfvars -# edit terraform.tfvars to put your cloud info in there -# get the service-account.json from the google cloud console -# make sure GCE is enabled on your account as well -python terraform plan -python terraform apply - -# get name of server -gcloud compute instance-groups list-instances pix2pix-manager -# ssh to server -gcloud compute ssh <name of instance here> -# look at the logs (can take awhile to load docker image) -sudo journalctl -f -u pix2pix -# if you have never made an http-server before, apparently you may need this rule -gcloud compute firewall-rules create http-server --allow=tcp:80 --target-tags http-server -# get ip address of load balancer -gcloud compute forwarding-rules list -# open that in the browser, should see the same page you saw locally - -# to destroy the GCP resources, use this -terraform destroy -``` \ No newline at end of file +If you open [http://localhost:8000/](http://localhost:8000/) in a browser, you should see an interactive demo. diff --git a/server/deployment.tf b/server/deployment.tf deleted file mode 100644 index 228dbe87661eb2572a0d5d840c88e1b7903cf301..0000000000000000000000000000000000000000 --- a/server/deployment.tf +++ /dev/null @@ -1,134 +0,0 @@ -variable "google_project" {} -variable "google_credentials_file" {} -variable "server_image_version" {} - -provider "google" { - region = "us-central1" - credentials = "${file(var.google_credentials_file)}" - project = "${var.google_project}" -} - -# cluster - -resource "google_compute_instance_template" "cluster" { - name_prefix = "pix2pix-template-" - machine_type = "n1-highcpu-2" - - tags = ["http-server"] - can_ip_forward = false - - scheduling { - automatic_restart = true - on_host_maintenance = "MIGRATE" - } - - disk { - source_image = "cos-cloud/cos-stable" - } - - network_interface { - network = "default" - - access_config { - // Ephemeral IP - } - } - - metadata { - user-data = <<EOF -#cloud-config - -users: -- name: pix2pix - uid: 2000 - -write_files: -- path: /etc/systemd/system/pix2pix.service - permissions: 0644 - owner: root - content: | - [Unit] - Description=Run pix2pix - - [Service] - Environment="HOME=/home/pix2pix" - ExecStartPre=/usr/share/google/dockercfg_update.sh - ExecStart=/usr/bin/docker run --rm --log-driver=gcplogs -u 2000 --publish 80:8080 --name=pix2pix us.gcr.io/${var.google_project}/pix2pix-server:${var.server_image_version} python -u serve.py --port 8080 --local_models_dir models --origin https://affinelayer.com - ExecStop=/usr/bin/docker stop pix2pix - ExecStopPost=/usr/bin/docker rm pix2pix - Restart=always - RestartSec=30 - -runcmd: -- iptables -A INPUT -p tcp --dport 80 -j ACCEPT -- systemctl daemon-reload -- systemctl start pix2pix.service -EOF - } - - service_account { - scopes = ["https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/devstorage.read_only", "https://www.googleapis.com/auth/cloud-platform"] - } - - lifecycle { - create_before_destroy = true - } -} - -resource "google_compute_http_health_check" "cluster" { - name = "pix2pix-check" - request_path = "/health" - - timeout_sec = 5 - check_interval_sec = 10 - unhealthy_threshold = 3 -} - -resource "google_compute_target_pool" "cluster" { - name = "pix2pix-pool" - - health_checks = [ - "${google_compute_http_health_check.cluster.name}", - ] -} - -resource "google_compute_instance_group_manager" "cluster" { - name = "pix2pix-manager" - instance_template = "${google_compute_instance_template.cluster.self_link}" - base_instance_name = "pix2pix" - zone = "us-central1-c" - - target_pools = ["${google_compute_target_pool.cluster.self_link}"] - - // don't update instances with terraform, which supposedly can't do a rolling restart - // use this to update them instead: - // gcloud compute instance-groups managed recreate-instances pix2pix-manager --zone us-central1-c --instances pix2pix-frfh - update_strategy = "NONE" -} - -resource "google_compute_address" "cluster" { - name = "pix2pix-cluster" -} - -resource "google_compute_forwarding_rule" "cluster" { - name = "pix2pix-balancer" - target = "${google_compute_target_pool.cluster.self_link}" - port_range = "80-80" - ip_address = "${google_compute_address.cluster.address}" -} - -resource "google_compute_autoscaler" "cluster" { - name = "pix2pix-autoscaler" - zone = "us-central1-c" - target = "${google_compute_instance_group_manager.cluster.self_link}" - - autoscaling_policy = { - max_replicas = 8 - min_replicas = 1 - cooldown_period = 60 - - cpu_utilization { - target = 0.7 - } - } -} diff --git a/server/serve.py b/server/serve.py index f0241fe93d35868f3d92061a7916ea1163007a32..e6fb921c47cb29771e169be6890dfad730c46a3a 100644 --- a/server/serve.py +++ b/server/serve.py @@ -1,298 +1,18 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import socket -import time -import argparse -import base64 import os -import json -import traceback -import threading -import multiprocessing -import random - - -# https://github.com/Nakiami/MultithreadedSimpleHTTPServer/blob/master/MultithreadedSimpleHTTPServer.py -try: - # Python 2 - from SocketServer import ThreadingMixIn - from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -except ImportError: - # Python 3 - from socketserver import ThreadingMixIn - from http.server import HTTPServer, BaseHTTPRequestHandler - -socket.setdefaulttimeout(30) - -parser = argparse.ArgumentParser() -parser.add_argument("--local_models_dir", help="directory containing local models to serve (either this or --cloud_model_names must be specified)") -parser.add_argument("--cloud_model_names", help="comma separated list of cloud models to serve (either this or --local_models_dir must be specified)") -parser.add_argument("--origin", help="allowed origin") -parser.add_argument("--addr", default="", help="address to listen on") -parser.add_argument("--port", default=8000, type=int, help="port to listen on") -parser.add_argument("--wait", default=0, type=int, help="time to wait for each request") -parser.add_argument("--credentials", help="JSON credentials for a Google Cloud Platform service account, generate this at https://console.cloud.google.com/iam-admin/serviceaccounts/project (select \"Furnish a new private key\")") -parser.add_argument("--project", help="Google Cloud Project to use, only necessary if using default application credentials") -a = parser.parse_args() - -jobs = threading.Semaphore(multiprocessing.cpu_count() * 4) -models = {} -ml = None -project_id = None -build_cloud_client = None - - -class RateCounter(object): - def __init__(self, window_us, granularity=1000): - self.granularity = granularity - self.width_us = int(window_us) // self.granularity - self.buckets = [0] * self.granularity - self.updated = 0 - self.lock = threading.RLock() - - def incr(self, amt=1): - with self.lock: - now_us = int(time.time() * 1e6) - now = now_us // self.width_us - - if now > self.updated: - # need to clear any buckets between the update time and now - if now - self.updated > self.granularity: - self.buckets = [0] * self.granularity - self.updated = now - else: - while self.updated <= now: - self.updated += 1 - self.buckets[self.updated % self.granularity] = 0 - - self.buckets[now % self.granularity] += amt - - def value(self): - with self.lock: - # update any expired buckets - self.incr(amt=0) - return sum(self.buckets) - - -successes = RateCounter(1 * 60 * 1e6) -failures = RateCounter(1 * 60 * 1e6) -cloud_requests = RateCounter(5 * 60 * 1e6) -cloud_accepts = RateCounter(5 * 60 * 1e6) - - -class Handler(BaseHTTPRequestHandler): - def do_GET(self): - if self.path == "/health": - self.send_response(200) - self.end_headers() - self.wfile.write("OK") - return - - if not os.path.exists("static"): - self.send_response(404) - return - - if self.path == "/": - self.send_response(200) - self.send_header("Content-Type", "text/html") - self.end_headers() - with open("static/index.html", "rb") as f: - self.wfile.write(f.read()) - return - - filenames = [name for name in os.listdir("static") if not name.startswith(".")] - path = self.path[1:] - if path not in filenames: - self.send_response(404) - return - - self.send_response(200) - if path.endswith(".png"): - self.send_header("Content-Type", "image/png") - elif path.endswith(".jpg"): - self.send_header("Content-Type", "image/jpeg") - else: - self.send_header("Content-Type", "application/octet-stream") - self.end_headers() - with open("static/" + path, "rb") as f: - self.wfile.write(f.read()) - - - def do_OPTIONS(self): - self.send_response(200) - if "origin" in self.headers: - if a.origin is not None and self.headers["origin"] != a.origin: - print("invalid origin %s" % self.headers["origin"]) - self.send_response(400) - return - self.send_header("access-control-allow-origin", self.headers["origin"]) - - allow_headers = self.headers.get("access-control-request-headers", "*") - self.send_header("access-control-allow-headers", allow_headers) - self.send_header("access-control-allow-methods", "POST, OPTIONS") - self.send_header("access-control-max-age", "3600") - self.end_headers() - - - def do_POST(self): - start = time.time() - - status = 200 - headers = {} - if "origin" in self.headers: - headers = {"access-control-allow-origin": self.headers["origin"]} - body = "" - - try: - name = self.path[1:] - - if name not in models: - raise Exception("invalid model") - - variants = models[name] # "cloud" and "local" are the two possible variants - - content_len = int(self.headers.get("content-length", "0")) - if content_len > 1 * 1024 * 1024: - raise Exception("post body too large") - input_data = self.rfile.read(content_len) - input_b64data = base64.urlsafe_b64encode(input_data) - - time.sleep(a.wait) - - cloud_reject_prob = max(0, (cloud_requests.value() - 1.1 * cloud_accepts.value()) / (cloud_requests.value() + 1)) - # print("requests=%d accepts=%d cloud_reject_prob=%f" % (cloud_requests.value(), cloud_accepts.value(), cloud_reject_prob)) - - output_b64data = None - if "cloud" in variants and random.random() > cloud_reject_prob: - input_instance = dict(input=input_b64data, key="0") - # the client does not seem to be threadsafe, so make one for each request - # also the cache is broken by oauth2client 4.0.0, so use a memory cache - request = build_cloud_client().projects().predict(name="projects/" + project_id + "/models/" + name, body={"instances": [input_instance]}) - try: - cloud_requests.incr() - response = request.execute() - output_instance = response["predictions"][0] - output_b64data = output_instance["output"].encode("ascii") - cloud_accepts.incr() - except Exception as e: - print("exception while running cloud model", traceback.format_exc()) - print("falling back to local") - - if output_b64data is None and "local" in variants and jobs.acquire(blocking=False): - m = variants["local"] - try: - output_b64data = m["sess"].run(m["output"], feed_dict={m["input"]: [input_b64data]})[0] - finally: - jobs.release() - - if output_b64data is None: - raise Exception("too many requests") - - # add any missing padding - output_b64data += b"=" * (-len(output_b64data) % 4) - output_data = base64.urlsafe_b64decode(output_b64data) - if output_data.startswith(b"\x89PNG"): - headers["content-type"] = "image/png" - else: - headers["content-type"] = "image/jpeg" - body = output_data - successes.incr() - except Exception as e: - failures.incr() - print("exception", traceback.format_exc()) - status = 500 - body = "server error" - - self.send_response(status) - for key, value in headers.items(): - self.send_header(key, value) - self.end_headers() - self.wfile.write(body) - - print("finished in %0.1fs successes=%d failures=%d" % (time.time() - start, successes.value(), failures.value())) - - -class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): - pass +import argparse +from http.server import HTTPServer, SimpleHTTPRequestHandler def main(): - if a.local_models_dir is None and a.cloud_model_names is None: - raise Exception("must specify --local_models_dir or --cloud_model_names") - - if a.local_models_dir is not None: - import tensorflow as tf - for name in os.listdir(a.local_models_dir): - if name.startswith("."): - continue - - print("loading model", name) - - with tf.Graph().as_default() as graph: - sess = tf.Session(graph=graph) - saver = tf.train.import_meta_graph(os.path.join(a.local_models_dir, name, "export.meta")) - - saver.restore(sess, os.path.join(a.local_models_dir, name, "export")) - input_vars = json.loads(tf.get_collection("inputs")[0]) - output_vars = json.loads(tf.get_collection("outputs")[0]) - input = graph.get_tensor_by_name(input_vars["input"]) - output = graph.get_tensor_by_name(output_vars["output"]) - - if name not in models: - models[name] = {} - - models[name]["local"] = dict( - sess=sess, - input=input, - output=output, - ) - - if a.cloud_model_names is not None: - import oauth2client.service_account - import googleapiclient.discovery - import googleapiclient.discovery_cache.base - import httplib2 - - for name in a.cloud_model_names.split(","): - if name not in models: - models[name] = {} - models[name]["cloud"] = None - - scopes = ["https://www.googleapis.com/auth/cloud-platform"] - global project_id - if a.credentials is None: - credentials = oauth2client.client.GoogleCredentials.get_application_default() - # use this only to detect the project - import google.cloud.storage - storage = google.cloud.storage.Client() - project_id = storage.project - if a.project is not None: - project_id = a.project - else: - credentials = oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name(a.credentials, scopes) - with open(a.credentials, "r") as f: - project_id = json.loads(f.read())["project_id"] - - # due to what appears to be a bug, we cannot get the discovery document when specifying an http client - # so grab it first, then the second build should use the cache - class Cache(googleapiclient.discovery_cache.base.Cache): - def __init__(self): - self.cache = {} - - def get(self, url): - return self.cache.get(url) - - def set(self, url, content): - self.cache[url] = content + parser = argparse.ArgumentParser() + parser.add_argument("--port", default=8000, type=int, help="port to listen on") + args = parser.parse_args() - cache = Cache() - googleapiclient.discovery.build("ml", "v1beta1", credentials=credentials, cache=cache) - global build_cloud_client - build_cloud_client = lambda: googleapiclient.discovery.build("ml", "v1beta1", http=credentials.authorize(httplib2.Http(timeout=10)), cache=cache) + os.chdir('static') + server_address = ('', args.port) + httpd = HTTPServer(server_address, SimpleHTTPRequestHandler) + print('serving at http://127.0.0.1:%d' % args.port) + httpd.serve_forever() - print("listening on %s:%s" % (a.addr, a.port)) - ThreadedHTTPServer((a.addr, a.port), Handler).serve_forever() main() diff --git a/server/static/deeplearn-0.3.15.js b/server/static/deeplearn-0.3.15.js new file mode 100644 index 0000000000000000000000000000000000000000..f2d6e9fd5075c8df43860df35a0a8aec71c8f32b --- /dev/null +++ b/server/static/deeplearn-0.3.15.js @@ -0,0 +1,12900 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.deeplearn = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ + +},{}],2:[function(require,module,exports){ +// A library of seedable RNGs implemented in Javascript. +// +// Usage: +// +// var seedrandom = require('seedrandom'); +// var random = seedrandom(1); // or any seed. +// var x = random(); // 0 <= x < 1. Every bit is random. +// var x = random.quick(); // 0 <= x < 1. 32 bits of randomness. + +// alea, a 53-bit multiply-with-carry generator by Johannes Baagøe. +// Period: ~2^116 +// Reported to pass all BigCrush tests. +var alea = require('./lib/alea'); + +// xor128, a pure xor-shift generator by George Marsaglia. +// Period: 2^128-1. +// Reported to fail: MatrixRank and LinearComp. +var xor128 = require('./lib/xor128'); + +// xorwow, George Marsaglia's 160-bit xor-shift combined plus weyl. +// Period: 2^192-2^32 +// Reported to fail: CollisionOver, SimpPoker, and LinearComp. +var xorwow = require('./lib/xorwow'); + +// xorshift7, by François Panneton and Pierre L'ecuyer, takes +// a different approach: it adds robustness by allowing more shifts +// than Marsaglia's original three. It is a 7-shift generator +// with 256 bits, that passes BigCrush with no systmatic failures. +// Period 2^256-1. +// No systematic BigCrush failures reported. +var xorshift7 = require('./lib/xorshift7'); + +// xor4096, by Richard Brent, is a 4096-bit xor-shift with a +// very long period that also adds a Weyl generator. It also passes +// BigCrush with no systematic failures. Its long period may +// be useful if you have many generators and need to avoid +// collisions. +// Period: 2^4128-2^32. +// No systematic BigCrush failures reported. +var xor4096 = require('./lib/xor4096'); + +// Tyche-i, by Samuel Neves and Filipe Araujo, is a bit-shifting random +// number generator derived from ChaCha, a modern stream cipher. +// https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf +// Period: ~2^127 +// No systematic BigCrush failures reported. +var tychei = require('./lib/tychei'); + +// The original ARC4-based prng included in this library. +// Period: ~2^1600 +var sr = require('./seedrandom'); + +sr.alea = alea; +sr.xor128 = xor128; +sr.xorwow = xorwow; +sr.xorshift7 = xorshift7; +sr.xor4096 = xor4096; +sr.tychei = tychei; + +module.exports = sr; + +},{"./lib/alea":3,"./lib/tychei":4,"./lib/xor128":5,"./lib/xor4096":6,"./lib/xorshift7":7,"./lib/xorwow":8,"./seedrandom":9}],3:[function(require,module,exports){ +// A port of an algorithm by Johannes Baagøe <baagoe@baagoe.com>, 2010 +// http://baagoe.com/en/RandomMusings/javascript/ +// https://github.com/nquinlan/better-random-numbers-for-javascript-mirror +// Original work is under MIT license - + +// Copyright (C) 2010 by Johannes Baagøe <baagoe@baagoe.org> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + + + +(function(global, module, define) { + +function Alea(seed) { + var me = this, mash = Mash(); + + me.next = function() { + var t = 2091639 * me.s0 + me.c * 2.3283064365386963e-10; // 2^-32 + me.s0 = me.s1; + me.s1 = me.s2; + return me.s2 = t - (me.c = t | 0); + }; + + // Apply the seeding algorithm from Baagoe. + me.c = 1; + me.s0 = mash(' '); + me.s1 = mash(' '); + me.s2 = mash(' '); + me.s0 -= mash(seed); + if (me.s0 < 0) { me.s0 += 1; } + me.s1 -= mash(seed); + if (me.s1 < 0) { me.s1 += 1; } + me.s2 -= mash(seed); + if (me.s2 < 0) { me.s2 += 1; } + mash = null; +} + +function copy(f, t) { + t.c = f.c; + t.s0 = f.s0; + t.s1 = f.s1; + t.s2 = f.s2; + return t; +} + +function impl(seed, opts) { + var xg = new Alea(seed), + state = opts && opts.state, + prng = xg.next; + prng.int32 = function() { return (xg.next() * 0x100000000) | 0; } + prng.double = function() { + return prng() + (prng() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 + }; + prng.quick = prng; + if (state) { + if (typeof(state) == 'object') copy(state, xg); + prng.state = function() { return copy(xg, {}); } + } + return prng; +} + +function Mash() { + var n = 0xefc8249d; + + var mash = function(data) { + data = data.toString(); + for (var i = 0; i < data.length; i++) { + n += data.charCodeAt(i); + var h = 0.02519603282416938 * n; + n = h >>> 0; + h -= n; + h *= n; + n = h >>> 0; + h -= n; + n += h * 0x100000000; // 2^32 + } + return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 + }; + + return mash; +} + + +if (module && module.exports) { + module.exports = impl; +} else if (define && define.amd) { + define(function() { return impl; }); +} else { + this.alea = impl; +} + +})( + this, + (typeof module) == 'object' && module, // present in node.js + (typeof define) == 'function' && define // present with an AMD loader +); + + + +},{}],4:[function(require,module,exports){ +// A Javascript implementaion of the "Tyche-i" prng algorithm by +// Samuel Neves and Filipe Araujo. +// See https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf + +(function(global, module, define) { + +function XorGen(seed) { + var me = this, strseed = ''; + + // Set up generator function. + me.next = function() { + var b = me.b, c = me.c, d = me.d, a = me.a; + b = (b << 25) ^ (b >>> 7) ^ c; + c = (c - d) | 0; + d = (d << 24) ^ (d >>> 8) ^ a; + a = (a - b) | 0; + me.b = b = (b << 20) ^ (b >>> 12) ^ c; + me.c = c = (c - d) | 0; + me.d = (d << 16) ^ (c >>> 16) ^ a; + return me.a = (a - b) | 0; + }; + + /* The following is non-inverted tyche, which has better internal + * bit diffusion, but which is about 25% slower than tyche-i in JS. + me.next = function() { + var a = me.a, b = me.b, c = me.c, d = me.d; + a = (me.a + me.b | 0) >>> 0; + d = me.d ^ a; d = d << 16 ^ d >>> 16; + c = me.c + d | 0; + b = me.b ^ c; b = b << 12 ^ d >>> 20; + me.a = a = a + b | 0; + d = d ^ a; me.d = d = d << 8 ^ d >>> 24; + me.c = c = c + d | 0; + b = b ^ c; + return me.b = (b << 7 ^ b >>> 25); + } + */ + + me.a = 0; + me.b = 0; + me.c = 2654435769 | 0; + me.d = 1367130551; + + if (seed === Math.floor(seed)) { + // Integer seed. + me.a = (seed / 0x100000000) | 0; + me.b = seed | 0; + } else { + // String seed. + strseed += seed; + } + + // Mix in string seed, then discard an initial batch of 64 values. + for (var k = 0; k < strseed.length + 20; k++) { + me.b ^= strseed.charCodeAt(k) | 0; + me.next(); + } +} + +function copy(f, t) { + t.a = f.a; + t.b = f.b; + t.c = f.c; + t.d = f.d; + return t; +}; + +function impl(seed, opts) { + var xg = new XorGen(seed), + state = opts && opts.state, + prng = function() { return (xg.next() >>> 0) / 0x100000000; }; + prng.double = function() { + do { + var top = xg.next() >>> 11, + bot = (xg.next() >>> 0) / 0x100000000, + result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (typeof(state) == 'object') copy(state, xg); + prng.state = function() { return copy(xg, {}); } + } + return prng; +} + +if (module && module.exports) { + module.exports = impl; +} else if (define && define.amd) { + define(function() { return impl; }); +} else { + this.tychei = impl; +} + +})( + this, + (typeof module) == 'object' && module, // present in node.js + (typeof define) == 'function' && define // present with an AMD loader +); + + + +},{}],5:[function(require,module,exports){ +// A Javascript implementaion of the "xor128" prng algorithm by +// George Marsaglia. See http://www.jstatsoft.org/v08/i14/paper + +(function(global, module, define) { + +function XorGen(seed) { + var me = this, strseed = ''; + + me.x = 0; + me.y = 0; + me.z = 0; + me.w = 0; + + // Set up generator function. + me.next = function() { + var t = me.x ^ (me.x << 11); + me.x = me.y; + me.y = me.z; + me.z = me.w; + return me.w ^= (me.w >>> 19) ^ t ^ (t >>> 8); + }; + + if (seed === (seed | 0)) { + // Integer seed. + me.x = seed; + } else { + // String seed. + strseed += seed; + } + + // Mix in string seed, then discard an initial batch of 64 values. + for (var k = 0; k < strseed.length + 64; k++) { + me.x ^= strseed.charCodeAt(k) | 0; + me.next(); + } +} + +function copy(f, t) { + t.x = f.x; + t.y = f.y; + t.z = f.z; + t.w = f.w; + return t; +} + +function impl(seed, opts) { + var xg = new XorGen(seed), + state = opts && opts.state, + prng = function() { return (xg.next() >>> 0) / 0x100000000; }; + prng.double = function() { + do { + var top = xg.next() >>> 11, + bot = (xg.next() >>> 0) / 0x100000000, + result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (typeof(state) == 'object') copy(state, xg); + prng.state = function() { return copy(xg, {}); } + } + return prng; +} + +if (module && module.exports) { + module.exports = impl; +} else if (define && define.amd) { + define(function() { return impl; }); +} else { + this.xor128 = impl; +} + +})( + this, + (typeof module) == 'object' && module, // present in node.js + (typeof define) == 'function' && define // present with an AMD loader +); + + + +},{}],6:[function(require,module,exports){ +// A Javascript implementaion of Richard Brent's Xorgens xor4096 algorithm. +// +// This fast non-cryptographic random number generator is designed for +// use in Monte-Carlo algorithms. It combines a long-period xorshift +// generator with a Weyl generator, and it passes all common batteries +// of stasticial tests for randomness while consuming only a few nanoseconds +// for each prng generated. For background on the generator, see Brent's +// paper: "Some long-period random number generators using shifts and xors." +// http://arxiv.org/pdf/1004.3115v1.pdf +// +// Usage: +// +// var xor4096 = require('xor4096'); +// random = xor4096(1); // Seed with int32 or string. +// assert.equal(random(), 0.1520436450538547); // (0, 1) range, 53 bits. +// assert.equal(random.int32(), 1806534897); // signed int32, 32 bits. +// +// For nonzero numeric keys, this impelementation provides a sequence +// identical to that by Brent's xorgens 3 implementaion in C. This +// implementation also provides for initalizing the generator with +// string seeds, or for saving and restoring the state of the generator. +// +// On Chrome, this prng benchmarks about 2.1 times slower than +// Javascript's built-in Math.random(). + +(function(global, module, define) { + +function XorGen(seed) { + var me = this; + + // Set up generator function. + me.next = function() { + var w = me.w, + X = me.X, i = me.i, t, v; + // Update Weyl generator. + me.w = w = (w + 0x61c88647) | 0; + // Update xor generator. + v = X[(i + 34) & 127]; + t = X[i = ((i + 1) & 127)]; + v ^= v << 13; + t ^= t << 17; + v ^= v >>> 15; + t ^= t >>> 12; + // Update Xor generator array state. + v = X[i] = v ^ t; + me.i = i; + // Result is the combination. + return (v + (w ^ (w >>> 16))) | 0; + }; + + function init(me, seed) { + var t, v, i, j, w, X = [], limit = 128; + if (seed === (seed | 0)) { + // Numeric seeds initialize v, which is used to generates X. + v = seed; + seed = null; + } else { + // String seeds are mixed into v and X one character at a time. + seed = seed + '\0'; + v = 0; + limit = Math.max(limit, seed.length); + } + // Initialize circular array and weyl value. + for (i = 0, j = -32; j < limit; ++j) { + // Put the unicode characters into the array, and shuffle them. + if (seed) v ^= seed.charCodeAt((j + 32) % seed.length); + // After 32 shuffles, take v as the starting w value. + if (j === 0) w = v; + v ^= v << 10; + v ^= v >>> 15; + v ^= v << 4; + v ^= v >>> 13; + if (j >= 0) { + w = (w + 0x61c88647) | 0; // Weyl. + t = (X[j & 127] ^= (v + w)); // Combine xor and weyl to init array. + i = (0 == t) ? i + 1 : 0; // Count zeroes. + } + } + // We have detected all zeroes; make the key nonzero. + if (i >= 128) { + X[(seed && seed.length || 0) & 127] = -1; + } + // Run the generator 512 times to further mix the state before using it. + // Factoring this as a function slows the main generator, so it is just + // unrolled here. The weyl generator is not advanced while warming up. + i = 127; + for (j = 4 * 128; j > 0; --j) { + v = X[(i + 34) & 127]; + t = X[i = ((i + 1) & 127)]; + v ^= v << 13; + t ^= t << 17; + v ^= v >>> 15; + t ^= t >>> 12; + X[i] = v ^ t; + } + // Storing state as object members is faster than using closure variables. + me.w = w; + me.X = X; + me.i = i; + } + + init(me, seed); +} + +function copy(f, t) { + t.i = f.i; + t.w = f.w; + t.X = f.X.slice(); + return t; +}; + +function impl(seed, opts) { + if (seed == null) seed = +(new Date); + var xg = new XorGen(seed), + state = opts && opts.state, + prng = function() { return (xg.next() >>> 0) / 0x100000000; }; + prng.double = function() { + do { + var top = xg.next() >>> 11, + bot = (xg.next() >>> 0) / 0x100000000, + result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (state.X) copy(state, xg); + prng.state = function() { return copy(xg, {}); } + } + return prng; +} + +if (module && module.exports) { + module.exports = impl; +} else if (define && define.amd) { + define(function() { return impl; }); +} else { + this.xor4096 = impl; +} + +})( + this, // window object or global + (typeof module) == 'object' && module, // present in node.js + (typeof define) == 'function' && define // present with an AMD loader +); + +},{}],7:[function(require,module,exports){ +// A Javascript implementaion of the "xorshift7" algorithm by +// François Panneton and Pierre L'ecuyer: +// "On the Xorgshift Random Number Generators" +// http://saluc.engr.uconn.edu/refs/crypto/rng/panneton05onthexorshift.pdf + +(function(global, module, define) { + +function XorGen(seed) { + var me = this; + + // Set up generator function. + me.next = function() { + // Update xor generator. + var X = me.x, i = me.i, t, v, w; + t = X[i]; t ^= (t >>> 7); v = t ^ (t << 24); + t = X[(i + 1) & 7]; v ^= t ^ (t >>> 10); + t = X[(i + 3) & 7]; v ^= t ^ (t >>> 3); + t = X[(i + 4) & 7]; v ^= t ^ (t << 7); + t = X[(i + 7) & 7]; t = t ^ (t << 13); v ^= t ^ (t << 9); + X[i] = v; + me.i = (i + 1) & 7; + return v; + }; + + function init(me, seed) { + var j, w, X = []; + + if (seed === (seed | 0)) { + // Seed state array using a 32-bit integer. + w = X[0] = seed; + } else { + // Seed state using a string. + seed = '' + seed; + for (j = 0; j < seed.length; ++j) { + X[j & 7] = (X[j & 7] << 15) ^ + (seed.charCodeAt(j) + X[(j + 1) & 7] << 13); + } + } + // Enforce an array length of 8, not all zeroes. + while (X.length < 8) X.push(0); + for (j = 0; j < 8 && X[j] === 0; ++j); + if (j == 8) w = X[7] = -1; else w = X[j]; + + me.x = X; + me.i = 0; + + // Discard an initial 256 values. + for (j = 256; j > 0; --j) { + me.next(); + } + } + + init(me, seed); +} + +function copy(f, t) { + t.x = f.x.slice(); + t.i = f.i; + return t; +} + +function impl(seed, opts) { + if (seed == null) seed = +(new Date); + var xg = new XorGen(seed), + state = opts && opts.state, + prng = function() { return (xg.next() >>> 0) / 0x100000000; }; + prng.double = function() { + do { + var top = xg.next() >>> 11, + bot = (xg.next() >>> 0) / 0x100000000, + result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (state.x) copy(state, xg); + prng.state = function() { return copy(xg, {}); } + } + return prng; +} + +if (module && module.exports) { + module.exports = impl; +} else if (define && define.amd) { + define(function() { return impl; }); +} else { + this.xorshift7 = impl; +} + +})( + this, + (typeof module) == 'object' && module, // present in node.js + (typeof define) == 'function' && define // present with an AMD loader +); + + +},{}],8:[function(require,module,exports){ +// A Javascript implementaion of the "xorwow" prng algorithm by +// George Marsaglia. See http://www.jstatsoft.org/v08/i14/paper + +(function(global, module, define) { + +function XorGen(seed) { + var me = this, strseed = ''; + + // Set up generator function. + me.next = function() { + var t = (me.x ^ (me.x >>> 2)); + me.x = me.y; me.y = me.z; me.z = me.w; me.w = me.v; + return (me.d = (me.d + 362437 | 0)) + + (me.v = (me.v ^ (me.v << 4)) ^ (t ^ (t << 1))) | 0; + }; + + me.x = 0; + me.y = 0; + me.z = 0; + me.w = 0; + me.v = 0; + + if (seed === (seed | 0)) { + // Integer seed. + me.x = seed; + } else { + // String seed. + strseed += seed; + } + + // Mix in string seed, then discard an initial batch of 64 values. + for (var k = 0; k < strseed.length + 64; k++) { + me.x ^= strseed.charCodeAt(k) | 0; + if (k == strseed.length) { + me.d = me.x << 10 ^ me.x >>> 4; + } + me.next(); + } +} + +function copy(f, t) { + t.x = f.x; + t.y = f.y; + t.z = f.z; + t.w = f.w; + t.v = f.v; + t.d = f.d; + return t; +} + +function impl(seed, opts) { + var xg = new XorGen(seed), + state = opts && opts.state, + prng = function() { return (xg.next() >>> 0) / 0x100000000; }; + prng.double = function() { + do { + var top = xg.next() >>> 11, + bot = (xg.next() >>> 0) / 0x100000000, + result = (top + bot) / (1 << 21); + } while (result === 0); + return result; + }; + prng.int32 = xg.next; + prng.quick = prng; + if (state) { + if (typeof(state) == 'object') copy(state, xg); + prng.state = function() { return copy(xg, {}); } + } + return prng; +} + +if (module && module.exports) { + module.exports = impl; +} else if (define && define.amd) { + define(function() { return impl; }); +} else { + this.xorwow = impl; +} + +})( + this, + (typeof module) == 'object' && module, // present in node.js + (typeof define) == 'function' && define // present with an AMD loader +); + + + +},{}],9:[function(require,module,exports){ +/* +Copyright 2014 David Bau. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +(function (pool, math) { +// +// The following constants are related to IEEE 754 limits. +// +var global = this, + width = 256, // each RC4 output is 0 <= x < 256 + chunks = 6, // at least six RC4 outputs for each double + digits = 52, // there are 52 significant digits in a double + rngname = 'random', // rngname: name for Math.random and Math.seedrandom + startdenom = math.pow(width, chunks), + significance = math.pow(2, digits), + overflow = significance * 2, + mask = width - 1, + nodecrypto; // node.js crypto module, initialized at the bottom. + +// +// seedrandom() +// This is the seedrandom function described above. +// +function seedrandom(seed, options, callback) { + var key = []; + options = (options == true) ? { entropy: true } : (options || {}); + + // Flatten the seed string or build one from local entropy if needed. + var shortseed = mixkey(flatten( + options.entropy ? [seed, tostring(pool)] : + (seed == null) ? autoseed() : seed, 3), key); + + // Use the seed to initialize an ARC4 generator. + var arc4 = new ARC4(key); + + // This function returns a random double in [0, 1) that contains + // randomness in every bit of the mantissa of the IEEE 754 value. + var prng = function() { + var n = arc4.g(chunks), // Start with a numerator n < 2 ^ 48 + d = startdenom, // and denominator d = 2 ^ 48. + x = 0; // and no 'extra last byte'. + while (n < significance) { // Fill up all significant digits by + n = (n + x) * width; // shifting numerator and + d *= width; // denominator and generating a + x = arc4.g(1); // new least-significant-byte. + } + while (n >= overflow) { // To avoid rounding up, before adding + n /= 2; // last byte, shift everything + d /= 2; // right using integer math until + x >>>= 1; // we have exactly the desired bits. + } + return (n + x) / d; // Form the number within [0, 1). + }; + + prng.int32 = function() { return arc4.g(4) | 0; } + prng.quick = function() { return arc4.g(4) / 0x100000000; } + prng.double = prng; + + // Mix the randomness into accumulated entropy. + mixkey(tostring(arc4.S), pool); + + // Calling convention: what to return as a function of prng, seed, is_math. + return (options.pass || callback || + function(prng, seed, is_math_call, state) { + if (state) { + // Load the arc4 state from the given state if it has an S array. + if (state.S) { copy(state, arc4); } + // Only provide the .state method if requested via options.state. + prng.state = function() { return copy(arc4, {}); } + } + + // If called as a method of Math (Math.seedrandom()), mutate + // Math.random because that is how seedrandom.js has worked since v1.0. + if (is_math_call) { math[rngname] = prng; return seed; } + + // Otherwise, it is a newer calling convention, so return the + // prng directly. + else return prng; + })( + prng, + shortseed, + 'global' in options ? options.global : (this == math), + options.state); +} +math['seed' + rngname] = seedrandom; + +// +// ARC4 +// +// An ARC4 implementation. The constructor takes a key in the form of +// an array of at most (width) integers that should be 0 <= x < (width). +// +// The g(count) method returns a pseudorandom integer that concatenates +// the next (count) outputs from ARC4. Its return value is a number x +// that is in the range 0 <= x < (width ^ count). +// +function ARC4(key) { + var t, keylen = key.length, + me = this, i = 0, j = me.i = me.j = 0, s = me.S = []; + + // The empty key [] is treated as [0]. + if (!keylen) { key = [keylen++]; } + + // Set up S using the standard key scheduling algorithm. + while (i < width) { + s[i] = i++; + } + for (i = 0; i < width; i++) { + s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))]; + s[j] = t; + } + + // The "g" method returns the next (count) outputs as one number. + (me.g = function(count) { + // Using instance members instead of closure state nearly doubles speed. + var t, r = 0, + i = me.i, j = me.j, s = me.S; + while (count--) { + t = s[i = mask & (i + 1)]; + r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))]; + } + me.i = i; me.j = j; + return r; + // For robust unpredictability, the function call below automatically + // discards an initial batch of values. This is called RC4-drop[256]. + // See http://google.com/search?q=rsa+fluhrer+response&btnI + })(width); +} + +// +// copy() +// Copies internal state of ARC4 to or from a plain object. +// +function copy(f, t) { + t.i = f.i; + t.j = f.j; + t.S = f.S.slice(); + return t; +}; + +// +// flatten() +// Converts an object tree to nested arrays of strings. +// +function flatten(obj, depth) { + var result = [], typ = (typeof obj), prop; + if (depth && typ == 'object') { + for (prop in obj) { + try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {} + } + } + return (result.length ? result : typ == 'string' ? obj : obj + '\0'); +} + +// +// mixkey() +// Mixes a string seed into a key that is an array of integers, and +// returns a shortened string seed that is equivalent to the result key. +// +function mixkey(seed, key) { + var stringseed = seed + '', smear, j = 0; + while (j < stringseed.length) { + key[mask & j] = + mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++)); + } + return tostring(key); +} + +// +// autoseed() +// Returns an object for autoseeding, using window.crypto and Node crypto +// module if available. +// +function autoseed() { + try { + var out; + if (nodecrypto && (out = nodecrypto.randomBytes)) { + // The use of 'out' to remember randomBytes makes tight minified code. + out = out(width); + } else { + out = new Uint8Array(width); + (global.crypto || global.msCrypto).getRandomValues(out); + } + return tostring(out); + } catch (e) { + var browser = global.navigator, + plugins = browser && browser.plugins; + return [+new Date, global, plugins, global.screen, tostring(pool)]; + } +} + +// +// tostring() +// Converts an array of charcodes to a string +// +function tostring(a) { + return String.fromCharCode.apply(0, a); +} + +// +// When seedrandom.js is loaded, we immediately mix a few bits +// from the built-in RNG into the entropy pool. Because we do +// not want to interfere with deterministic PRNG state later, +// seedrandom will not call math.random on its own again after +// initialization. +// +mixkey(math.random(), pool); + +// +// Nodejs and AMD support: export the implementation as a module using +// either convention. +// +if ((typeof module) == 'object' && module.exports) { + module.exports = seedrandom; + // When in node.js, try using crypto package for autoseeding. + try { + nodecrypto = require('crypto'); + } catch (ex) {} +} else if ((typeof define) == 'function' && define.amd) { + define(function() { return seedrandom; }); +} + +// End anonymous scope, and pass initial values. +})( + [], // pool: entropy pool starts empty + Math // math: package containing random, pow, and seedrandom +); + +},{"crypto":1}],10:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../math/ndarray"); +var MANIFEST_FILE = 'manifest.json'; +var CheckpointLoader = (function () { + function CheckpointLoader(urlPath) { + this.urlPath = urlPath; + if (this.urlPath.charAt(this.urlPath.length - 1) !== '/') { + this.urlPath += '/'; + } + } + CheckpointLoader.prototype.loadManifest = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', _this.urlPath + MANIFEST_FILE); + xhr.onload = function () { + _this.checkpointManifest = JSON.parse(xhr.responseText); + resolve(); + }; + xhr.onerror = function (error) { + throw new Error(MANIFEST_FILE + " not found at " + _this.urlPath + ". " + error); + }; + xhr.send(); + }); + }; + CheckpointLoader.prototype.getCheckpointManifest = function () { + var _this = this; + if (this.checkpointManifest == null) { + return new Promise(function (resolve, reject) { + _this.loadManifest().then(function () { + resolve(_this.checkpointManifest); + }); + }); + } + return new Promise(function (resolve, reject) { + resolve(_this.checkpointManifest); + }); + }; + CheckpointLoader.prototype.getAllVariables = function () { + var _this = this; + if (this.variables != null) { + return new Promise(function (resolve, reject) { + resolve(_this.variables); + }); + } + return new Promise(function (resolve, reject) { + _this.getCheckpointManifest().then(function (checkpointDefinition) { + var variableNames = Object.keys(_this.checkpointManifest); + var variablePromises = []; + for (var i = 0; i < variableNames.length; i++) { + variablePromises.push(_this.getVariable(variableNames[i])); + } + Promise.all(variablePromises).then(function (variables) { + _this.variables = {}; + for (var i = 0; i < variables.length; i++) { + _this.variables[variableNames[i]] = variables[i]; + } + resolve(_this.variables); + }); + }); + }); + }; + CheckpointLoader.prototype.getVariable = function (varName) { + var _this = this; + if (!(varName in this.checkpointManifest)) { + throw new Error('Cannot load non-existant variable ' + varName); + } + var variableRequestPromiseMethod = function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.responseType = 'arraybuffer'; + var fname = _this.checkpointManifest[varName].filename; + xhr.open('GET', _this.urlPath + fname); + xhr.onload = function () { + if (xhr.status === 404) { + throw new Error("Not found variable " + varName); + } + var values = new Float32Array(xhr.response); + var ndarray = ndarray_1.NDArray.make(_this.checkpointManifest[varName].shape, { values: values }); + resolve(ndarray); + }; + xhr.onerror = function (error) { + throw new Error("Could not fetch variable " + varName + ": " + error); + }; + xhr.send(); + }; + if (this.checkpointManifest == null) { + return new Promise(function (resolve, reject) { + _this.loadManifest().then(function () { + new Promise(variableRequestPromiseMethod).then(resolve); + }); + }); + } + return new Promise(variableRequestPromiseMethod); + }; + return CheckpointLoader; +}()); +exports.CheckpointLoader = CheckpointLoader; + +},{"../math/ndarray":95}],11:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../math/ndarray"); +var util = require("../util"); +var STATS_SAMPLE_PERCENTAGE = 0.1; +var InMemoryDataset = (function () { + function InMemoryDataset(dataShapes, math) { + this.dataShapes = dataShapes; + this.math = math; + this.normalizationInfo = {}; + } + InMemoryDataset.prototype.getDataShape = function (dataIndex) { + return this.dataShapes[dataIndex]; + }; + InMemoryDataset.prototype.getData = function () { + return this.dataset; + }; + InMemoryDataset.prototype.getStats = function () { + var _this = this; + if (this.dataset == null) { + throw new Error('Data is null.'); + } + return this.dataset.map(function (d) { return _this.getStatsForData(d); }); + }; + InMemoryDataset.prototype.getStatsForData = function (data) { + var inputMin = Number.POSITIVE_INFINITY; + var inputMax = Number.NEGATIVE_INFINITY; + var exampleIndices = data.map(function (example, i) { return i; }); + util.shuffle(exampleIndices); + exampleIndices = + exampleIndices.slice(exampleIndices.length * STATS_SAMPLE_PERCENTAGE); + for (var i = 0; i < exampleIndices.length; i++) { + var inputValues = data[exampleIndices[i]].getValues(); + for (var j = 0; j < inputValues.length; j++) { + inputMin = Math.min(inputMin, inputValues[j]); + inputMax = Math.max(inputMax, inputValues[j]); + } + } + return { + inputMin: inputMin, + inputMax: inputMax, + exampleCount: data.length, + shape: data[0].shape, + }; + }; + InMemoryDataset.prototype.normalizeExamplesToRange = function (examples, curLowerBounds, curUpperBounds, newLowerBounds, newUpperBounds) { + var _this = this; + var curBoundsIsPerDimension = (curUpperBounds instanceof Float32Array && + curLowerBounds instanceof Float32Array); + var newBoundsIsPerDimension = (newLowerBounds instanceof Float32Array && + newUpperBounds instanceof Float32Array); + var inputSize = util.sizeFromShape(examples[0].shape); + var newExamples = []; + examples.forEach(function (example) { + var inputValues = example.getValues(); + var normalizedValues = new Float32Array(inputSize); + for (var j = 0; j < inputSize; j++) { + var curLowerBound = curBoundsIsPerDimension ? + curLowerBounds[j] : + curLowerBounds; + var curUpperBound = curBoundsIsPerDimension ? + curUpperBounds[j] : + curUpperBounds; + var curRange = curUpperBound - curLowerBound; + var newLowerBound = newBoundsIsPerDimension ? + newLowerBounds[j] : + newLowerBounds; + var newUpperBound = newBoundsIsPerDimension ? + newUpperBounds[j] : + newUpperBounds; + var newRange = newUpperBound - newLowerBound; + if (curRange === 0) { + normalizedValues[j] = newLowerBound; + } + else { + normalizedValues[j] = newLowerBound + + newRange * (inputValues[j] - curLowerBound) / curRange; + } + } + newExamples.push(ndarray_1.NDArray.make(example.shape, { values: normalizedValues }, 'float32', _this.math)); + }); + return newExamples; + }; + InMemoryDataset.prototype.computeBounds = function (dataIndex) { + var _this = this; + if (this.dataset == null) { + throw new Error('Data is null.'); + } + var size = util.sizeFromShape(this.dataset[dataIndex][0].shape); + this.normalizationInfo[dataIndex] = { + isNormalized: false, + minValues: new Float32Array(size), + maxValues: new Float32Array(size) + }; + for (var i = 0; i < size; i++) { + this.normalizationInfo[dataIndex].minValues[i] = Number.POSITIVE_INFINITY; + this.normalizationInfo[dataIndex].maxValues[i] = Number.NEGATIVE_INFINITY; + } + this.dataset[dataIndex].forEach(function (example) { + var inputValues = example.getValues(); + for (var k = 0; k < size; k++) { + _this.normalizationInfo[dataIndex].minValues[k] = Math.min(_this.normalizationInfo[dataIndex].minValues[k], inputValues[k]); + _this.normalizationInfo[dataIndex].maxValues[k] = Math.max(_this.normalizationInfo[dataIndex].maxValues[k], inputValues[k]); + } + }); + }; + InMemoryDataset.prototype.normalizeWithinBounds = function (dataIndex, lowerBound, upperBound) { + if (this.dataset == null) { + throw new Error('Data is null.'); + } + if (dataIndex >= this.dataset.length) { + throw new Error('dataIndex out of bounds.'); + } + if (this.normalizationInfo[dataIndex] == null) { + this.computeBounds(dataIndex); + } + var curLowerBounds; + var curUpperBounds; + if (this.normalizationInfo[dataIndex].isNormalized) { + curLowerBounds = this.normalizationInfo[dataIndex].lowerBound; + curUpperBounds = this.normalizationInfo[dataIndex].upperBound; + } + else { + curLowerBounds = this.normalizationInfo[dataIndex].minValues; + curUpperBounds = this.normalizationInfo[dataIndex].maxValues; + } + this.dataset[dataIndex] = this.normalizeExamplesToRange(this.dataset[dataIndex], curLowerBounds, curUpperBounds, lowerBound, upperBound); + this.normalizationInfo[dataIndex].isNormalized = true; + this.normalizationInfo[dataIndex].lowerBound = lowerBound; + this.normalizationInfo[dataIndex].upperBound = upperBound; + }; + InMemoryDataset.prototype.isNormalized = function (dataIndex) { + return this.normalizationInfo != null && + this.normalizationInfo[dataIndex].isNormalized; + }; + InMemoryDataset.prototype.removeNormalization = function (dataIndex) { + if (this.dataset == null) { + throw new Error('Training or test data is null.'); + } + if (!this.isNormalized(dataIndex)) { + return; + } + this.dataset[dataIndex] = this.normalizeExamplesToRange(this.dataset[dataIndex], this.normalizationInfo[dataIndex].lowerBound, this.normalizationInfo[dataIndex].upperBound, this.normalizationInfo[dataIndex].minValues, this.normalizationInfo[dataIndex].maxValues); + this.normalizationInfo[dataIndex].isNormalized = false; + }; + InMemoryDataset.prototype.unnormalizeExamples = function (examples, dataIndex) { + if (!this.isNormalized(dataIndex)) { + return examples; + } + return this.normalizeExamplesToRange(examples, this.normalizationInfo[dataIndex].lowerBound, this.normalizationInfo[dataIndex].upperBound, this.normalizationInfo[dataIndex].minValues, this.normalizationInfo[dataIndex].maxValues); + }; + InMemoryDataset.prototype.dispose = function () { + if (this.dataset == null) { + return; + } + for (var i = 0; i < this.dataset.length; i++) { + for (var j = 0; j < this.dataset[i].length; j++) { + this.dataset[i][j].dispose(); + } + } + this.dataset = []; + }; + return InMemoryDataset; +}()); +exports.InMemoryDataset = InMemoryDataset; + +},{"../math/ndarray":95,"../util":101}],12:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../math/ndarray"); +var util = require("../util"); +var InMemoryShuffledInputProviderBuilder = (function () { + function InMemoryShuffledInputProviderBuilder(inputs) { + this.inputs = inputs; + this.idx = 0; + this.inputCounter = 0; + this.epoch = 0; + this.shuffledIndices = util.createShuffledIndices(inputs[0].length); + this.numInputs = inputs.length; + var numExamples = this.inputs[0].length; + for (var i = 0; i < this.numInputs; i++) { + util.assert(this.inputs[i].length === numExamples, 'Number of examples must match across different inputs.'); + } + for (var i = 0; i < this.numInputs; i++) { + var inputShape = this.inputs[i][0].shape; + for (var j = 0; j < this.inputs[i].length; j++) { + util.assertShapesMatch(inputShape, this.inputs[i][j].shape); + } + } + } + InMemoryShuffledInputProviderBuilder.prototype.getCurrentExampleIndex = function () { + var returnIdx = this.idx; + this.inputCounter++; + if (this.inputCounter >= this.numInputs) { + this.idx++; + this.inputCounter = 0; + if (this.idx >= this.inputs[0].length) { + this.idx = 0; + this.epoch++; + } + } + return returnIdx; + }; + InMemoryShuffledInputProviderBuilder.prototype.getNextInput = function (inputId) { + var currentExampleIndex = this.getCurrentExampleIndex(); + return this.inputs[inputId][this.shuffledIndices[currentExampleIndex]]; + }; + InMemoryShuffledInputProviderBuilder.prototype.getEpoch = function () { + return this.epoch; + }; + InMemoryShuffledInputProviderBuilder.prototype.getInputProviders = function () { + var inputProviders = []; + for (var i = 0; i < this.numInputs; i++) { + inputProviders.push(this.getInputProvider(i)); + } + return inputProviders; + }; + return InMemoryShuffledInputProviderBuilder; +}()); +exports.InMemoryShuffledInputProviderBuilder = InMemoryShuffledInputProviderBuilder; +var InCPUMemoryShuffledInputProviderBuilder = (function (_super) { + __extends(InCPUMemoryShuffledInputProviderBuilder, _super); + function InCPUMemoryShuffledInputProviderBuilder() { + return _super !== null && _super.apply(this, arguments) || this; + } + InCPUMemoryShuffledInputProviderBuilder.prototype.getInputProvider = function (inputId) { + var shuffledInputProvider = this; + return { + getNextCopy: function (math) { + return ndarray_1.NDArray.like(shuffledInputProvider.getNextInput(inputId)); + }, + disposeCopy: function (math, copy) { + copy.dispose(); + } + }; + }; + return InCPUMemoryShuffledInputProviderBuilder; +}(InMemoryShuffledInputProviderBuilder)); +exports.InCPUMemoryShuffledInputProviderBuilder = InCPUMemoryShuffledInputProviderBuilder; +var InGPUMemoryShuffledInputProviderBuilder = (function (_super) { + __extends(InGPUMemoryShuffledInputProviderBuilder, _super); + function InGPUMemoryShuffledInputProviderBuilder() { + return _super !== null && _super.apply(this, arguments) || this; + } + InGPUMemoryShuffledInputProviderBuilder.prototype.getInputProvider = function (inputId) { + var shuffledInputProvider = this; + return { + getNextCopy: function (math) { + return math.clone(shuffledInputProvider.getNextInput(inputId)); + }, + disposeCopy: function (math, copy) { + copy.dispose(); + } + }; + }; + return InGPUMemoryShuffledInputProviderBuilder; +}(InMemoryShuffledInputProviderBuilder)); +exports.InGPUMemoryShuffledInputProviderBuilder = InGPUMemoryShuffledInputProviderBuilder; + +},{"../math/ndarray":95,"../util":101}],13:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var math_1 = require("../math/math"); +var ndarray_1 = require("../math/ndarray"); +var util = require("../util"); +var dataset_1 = require("./dataset"); +var PARSING_IMAGE_CANVAS_HEIGHT_PX = 1000; +function getXhrDatasetConfig(jsonConfigPath) { + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', jsonConfigPath); + xhr.onload = function () { + resolve(JSON.parse(xhr.responseText)); + }; + xhr.onerror = function (error) { + reject(error); + }; + xhr.send(); + }); +} +exports.getXhrDatasetConfig = getXhrDatasetConfig; +var XhrDataset = (function (_super) { + __extends(XhrDataset, _super); + function XhrDataset(xhrDatasetConfig) { + var _this = this; + var safeMode = false; + _this = _super.call(this, xhrDatasetConfig.data.map(function (x) { return x.shape; }), new math_1.NDArrayMath('cpu', safeMode)) || this; + _this.xhrDatasetConfig = xhrDatasetConfig; + return _this; + } + XhrDataset.prototype.getNDArray = function (info) { + var _this = this; + var dataPromise = info.dataType === 'png' ? + parseTypedArrayFromPng(info, info.shape) : + parseTypedArrayFromBinary(info); + var inputSize = util.sizeFromShape(info.shape); + return dataPromise.then(function (data) { + var ndarrays = []; + for (var i = 0; i < data.length / inputSize; i++) { + var values = data.subarray(i * inputSize, (i + 1) * inputSize); + var ndarray = ndarray_1.NDArray.make(info.shape, { values: new Float32Array(values) }, 'float32', _this.math); + ndarrays.push(ndarray); + } + return ndarrays; + }); + }; + XhrDataset.prototype.fetchData = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var promises = _this.xhrDatasetConfig.data.map(function (x) { return _this.getNDArray(x); }); + Promise.all(promises).then(function (data) { + _this.dataset = data; + resolve(); + }); + }); + }; + return XhrDataset; +}(dataset_1.InMemoryDataset)); +exports.XhrDataset = XhrDataset; +function parseTypedArrayFromBinary(info) { + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', info.path); + xhr.responseType = 'arraybuffer'; + xhr.onload = function (event) { + var data = (info.dataType === 'float32') ? + new Float32Array(xhr.response) : + new Uint8Array(xhr.response); + resolve(data); + }; + xhr.onerror = function (err) { return reject(err); }; + xhr.send(); + }); +} +function parseGrayscaleImageData(data, result, resultOffset) { + var idx = resultOffset; + for (var i = 0; i < data.length; i += 4) { + result[idx++] = data[i]; + } +} +function parseRGBImageData(data, result, resultOffset) { + var idx = resultOffset; + for (var i = 0; i < data.length; i += 4) { + result[idx] = data[i]; + result[idx + 1] = data[i + 1]; + result[idx + 2] = data[i + 2]; + idx += 3; + } +} +function parseImage(img, shape) { + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var N = img.height; + var inputSize = util.sizeFromShape(shape); + var result = new Uint8Array(N * inputSize); + if (img.width !== shape[0] * shape[1]) { + throw new Error("Image width (" + img.width + ") must be multiple of " + + ("rows*columns (" + shape[0] + "*" + shape[1] + ") of the ndarray")); + } + canvas.width = img.width; + canvas.height = PARSING_IMAGE_CANVAS_HEIGHT_PX; + var sx = 0; + var sWidth = canvas.width; + var sHeight = canvas.height; + var dx = 0; + var dy = 0; + var dWidth = sWidth; + var dHeight = sHeight; + var depth = shape[2]; + var offset = 0; + var numPasses = Math.ceil(N / canvas.height); + for (var pass = 0; pass < numPasses; ++pass) { + var sy = pass * canvas.height; + if ((pass === numPasses - 1) && (N % canvas.height > 0)) { + canvas.height = N % canvas.height; + sHeight = canvas.height; + dHeight = sHeight; + } + ctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); + var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data; + (depth === 1) ? parseGrayscaleImageData(data, result, offset) : + parseRGBImageData(data, result, offset); + offset += canvas.height * inputSize; + } + return result; +} +function parseTypedArrayFromPng(info, shape) { + return new Promise(function (resolve, reject) { + var img = new Image(); + img.setAttribute('crossOrigin', ''); + img.onload = function () { + var result = parseImage(img, shape); + img.src = ''; + img = null; + resolve(result); + }; + img.src = info.path; + }); +} + +},{"../math/math":94,"../math/ndarray":95,"../util":101,"./dataset":11}],14:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function isMobile() { + var a = navigator.userAgent || navigator.vendor || window.opera; + return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i + .test(a) || + /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i + .test(a.substr(0, 4)); +} +exports.isMobile = isMobile; + +},{}],15:[function(require,module,exports){ +(function (global){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var device_util = require("./device_util"); +var math_1 = require("./math/math"); +var util = require("./util"); +var Type; +(function (Type) { + Type[Type["NUMBER"] = 0] = "NUMBER"; + Type[Type["BOOLEAN"] = 1] = "BOOLEAN"; +})(Type = exports.Type || (exports.Type = {})); +exports.URL_PROPERTIES = [ + { name: 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_ENABLED', type: Type.BOOLEAN }, + { name: 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE', type: Type.BOOLEAN }, + { name: 'WEBGL_VERSION', type: Type.NUMBER }, + { name: 'WEBGL_FLOAT_TEXTURE_ENABLED', type: Type.BOOLEAN }, { + name: 'WEBGL_GET_BUFFER_SUB_DATA_ASYNC_EXTENSION_ENABLED', + type: Type.BOOLEAN + } +]; +function getWebGLRenderingContext(webGLVersion) { + if (webGLVersion === 0) { + throw new Error('Cannot get WebGL rendering context, WebGL is disabled.'); + } + var tempCanvas = document.createElement('canvas'); + if (webGLVersion === 1) { + return (tempCanvas.getContext('webgl') || + tempCanvas.getContext('experimental-webgl')); + } + return tempCanvas.getContext('webgl2'); +} +function loseContext(gl) { + if (gl != null) { + var loseContextExtension = gl.getExtension('WEBGL_lose_context'); + if (loseContextExtension == null) { + throw new Error('Extension WEBGL_lose_context not supported on this browser.'); + } + loseContextExtension.loseContext(); + } +} +function isWebGLVersionEnabled(webGLVersion) { + var gl = getWebGLRenderingContext(webGLVersion); + if (gl != null) { + loseContext(gl); + return true; + } + return false; +} +function isWebGLDisjointQueryTimerEnabled(webGLVersion) { + var gl = getWebGLRenderingContext(webGLVersion); + var extensionName = webGLVersion === 1 ? 'EXT_disjoint_timer_query' : + 'EXT_disjoint_timer_query_webgl2'; + var ext = gl.getExtension(extensionName); + var isExtEnabled = ext != null; + if (gl != null) { + loseContext(gl); + } + return isExtEnabled; +} +function isFloatTextureReadPixelsEnabled(webGLVersion) { + if (webGLVersion === 0) { + return false; + } + var gl = getWebGLRenderingContext(webGLVersion); + if (webGLVersion === 1) { + if (gl.getExtension('OES_texture_float') == null) { + return false; + } + } + else { + if (gl.getExtension('EXT_color_buffer_float') == null) { + return false; + } + } + var frameBuffer = gl.createFramebuffer(); + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + var internalFormat = webGLVersion === 2 ? gl.RGBA32F : gl.RGBA; + gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null); + gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + var frameBufferComplete = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, new Float32Array(4)); + var readPixelsNoError = gl.getError() === gl.NO_ERROR; + loseContext(gl); + return frameBufferComplete && readPixelsNoError; +} +function isWebGLGetBufferSubDataAsyncExtensionEnabled(webGLVersion) { + if (webGLVersion !== 2) { + return false; + } + var gl = getWebGLRenderingContext(webGLVersion); + var ext = gl.getExtension('WEBGL_get_buffer_sub_data_async'); + var isEnabled = ext != null; + loseContext(gl); + return isEnabled; +} +var Environment = (function () { + function Environment(features) { + this.features = {}; + this.globalMath = null; + this.backendRegistry = {}; + this.prevBackendRegistry = this.backendRegistry; + if (features != null) { + this.features = features; + } + } + Environment.prototype.get = function (feature) { + if (feature in this.features) { + return this.features[feature]; + } + this.features[feature] = this.evaluateFeature(feature); + return this.features[feature]; + }; + Environment.prototype.getBestBackend = function () { + var orderedBackends = ['webgl', 'cpu']; + for (var i = 0; i < orderedBackends.length; ++i) { + var backendId = orderedBackends[i]; + if (backendId in this.backendRegistry) { + return this.backendRegistry[backendId]; + } + } + throw new Error('No backend found in registry.'); + }; + Environment.prototype.evaluateFeature = function (feature) { + if (feature === 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_ENABLED') { + var webGLVersion = this.get('WEBGL_VERSION'); + if (webGLVersion === 0) { + return false; + } + return isWebGLDisjointQueryTimerEnabled(webGLVersion); + } + else if (feature === 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE') { + return this.get('WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_ENABLED') && + !device_util.isMobile(); + } + else if (feature === 'WEBGL_VERSION') { + if (isWebGLVersionEnabled(2)) { + return 2; + } + else if (isWebGLVersionEnabled(1)) { + return 1; + } + return 0; + } + else if (feature === 'WEBGL_FLOAT_TEXTURE_ENABLED') { + return isFloatTextureReadPixelsEnabled(this.get('WEBGL_VERSION')); + } + else if (feature === 'WEBGL_GET_BUFFER_SUB_DATA_ASYNC_EXTENSION_ENABLED') { + return isWebGLGetBufferSubDataAsyncExtensionEnabled(this.get('WEBGL_VERSION')); + } + throw new Error("Unknown feature " + feature + "."); + }; + Environment.prototype.setFeatures = function (features) { + this.empty(); + this.features = features; + }; + Environment.prototype.reset = function () { + this.globalMath = null; + this.backendRegistry = this.prevBackendRegistry; + this.features = getFeaturesFromURL(); + }; + Environment.prototype.setMath = function (math) { + this.globalMath = math; + }; + Environment.prototype.getBackend = function (name) { + return this.backendRegistry[name]; + }; + Environment.prototype.registerBackend = function (name, factory) { + if (name in this.backendRegistry) { + throw new Error(name + " backend was already registered"); + } + try { + var backend = factory(); + this.backendRegistry[name] = backend; + return true; + } + catch (err) { + return false; + } + }; + Object.defineProperty(Environment.prototype, "math", { + get: function () { + if (this.globalMath == null) { + var bestBackend = this.getBestBackend(); + var safeMode = false; + this.globalMath = new math_1.NDArrayMath(bestBackend, safeMode); + } + return this.globalMath; + }, + enumerable: true, + configurable: true + }); + Environment.prototype.empty = function () { + this.globalMath = null; + this.prevBackendRegistry = this.backendRegistry; + this.backendRegistry = {}; + this.features = null; + }; + return Environment; +}()); +exports.Environment = Environment; +var DEEPLEARNJS_FLAGS_PREFIX = 'dljsflags'; +function getFeaturesFromURL() { + var features = {}; + if (typeof window === 'undefined') { + return features; + } + var urlParams = util.getQueryParams(window.location.search); + if (DEEPLEARNJS_FLAGS_PREFIX in urlParams) { + var urlFlags_1 = {}; + var keyValues = urlParams[DEEPLEARNJS_FLAGS_PREFIX].split(','); + keyValues.forEach(function (keyValue) { + var _a = keyValue.split(':'), key = _a[0], value = _a[1]; + urlFlags_1[key] = value; + }); + exports.URL_PROPERTIES.forEach(function (urlProperty) { + if (urlProperty.name in urlFlags_1) { + console.log("Setting feature override from URL " + urlProperty.name + ": " + + ("" + urlFlags_1[urlProperty.name])); + if (urlProperty.type === Type.NUMBER) { + features[urlProperty.name] = +urlFlags_1[urlProperty.name]; + } + else if (urlProperty.type === Type.BOOLEAN) { + features[urlProperty.name] = urlFlags_1[urlProperty.name] === 'true'; + } + else { + console.warn("Unknown URL param: " + urlProperty.name + "."); + } + } + }); + } + return features; +} +function getGlobalNamespace() { + var ns; + if (typeof (window) !== 'undefined') { + ns = window; + } + else if (typeof (global) !== 'undefined') { + ns = global; + } + else { + throw new Error('Could not find a global object'); + } + return ns; +} +function getOrMakeEnvironment() { + var ns = getGlobalNamespace(); + ns.ENV = ns.ENV || new Environment(getFeaturesFromURL()); + return ns.ENV; +} +exports.ENV = getOrMakeEnvironment(); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./device_util":14,"./math/math":94,"./util":101}],16:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var initializers_1 = require("../initializers"); +var concat_util = require("../math/concat_util"); +var conv_util = require("../math/conv_util"); +var ndarray_1 = require("../math/ndarray"); +var util = require("../util"); +var GraphLayers = (function () { + function GraphLayers(g) { + this.g = g; + } + GraphLayers.prototype.dense = function (name, x, units, activation, useBias, kernelInitializer, biasInitializer) { + if (activation === void 0) { activation = null; } + if (useBias === void 0) { useBias = true; } + if (kernelInitializer === void 0) { kernelInitializer = new initializers_1.VarianceScalingInitializer(); } + if (biasInitializer === void 0) { biasInitializer = new initializers_1.ZerosInitializer(); } + var weights = this.g.variable(name + '-weights', kernelInitializer.initialize([x.shape[0], units], x.shape[0], units)); + var out = this.g.matmul(x, weights); + if (useBias) { + var bias = this.g.variable(name + '-bias', biasInitializer.initialize([units], x.shape[0], units)); + out = this.g.add(out, bias); + } + if (activation != null) { + out = activation(out); + } + return out; + }; + return GraphLayers; +}()); +exports.GraphLayers = GraphLayers; +var Graph = (function () { + function Graph() { + this.nodes = []; + this.layers = new GraphLayers(this); + } + Graph.prototype.variable = function (name, data) { + return this.addNodeAndReturnOutput(new VariableNode(this, name, data)); + }; + Graph.prototype.placeholder = function (name, shape) { + return this.addNodeAndReturnOutput(new PlaceholderNode(this, name, shape)); + }; + Graph.prototype.constant = function (value) { + var finalValue; + if (typeof value === 'number') { + finalValue = ndarray_1.Scalar.new(value); + } + else if (value instanceof ndarray_1.NDArray) { + finalValue = value; + } + else if (value instanceof Array) { + var flatValues = util.flatten(value); + var vals = new Float32Array(flatValues); + finalValue = ndarray_1.NDArray.make(util.inferShape(value), { values: vals }); + } + else { + throw new Error('unimplemented constant type.'); + } + return this.addNodeAndReturnOutput(new ConstantNode(this, finalValue)); + }; + Graph.prototype.reshape = function (x, shape) { + return this.addNodeAndReturnOutput(new ReshapeNode(this, 'Reshape', x, shape)); + }; + Graph.prototype.fusedLinearCombination = function (x1, x2, c1, c2) { + return this.addNodeAndReturnOutput(new FusedLinearCombinationNode(this, x1, x2, c1, c2)); + }; + Graph.prototype.add = function (x1, x2) { + return this.addNodeAndReturnOutput(new AddNode(this, x1, x2)); + }; + Graph.prototype.subtract = function (x1, x2) { + return this.addNodeAndReturnOutput(new SubtractNode(this, x1, x2)); + }; + Graph.prototype.multiply = function (x1, x2) { + return this.addNodeAndReturnOutput(new MultiplyNode(this, x1, x2)); + }; + Graph.prototype.divide = function (x1, x2) { + return this.addNodeAndReturnOutput(new DivideNode(this, x1, x2)); + }; + Graph.prototype.reduceSum = function (x) { + return this.addNodeAndReturnOutput(new ReduceSumNode(this, x)); + }; + Graph.prototype.concat3d = function (x1, x2, axis) { + return this.addNodeAndReturnOutput(new Concat3DNode(this, x1, x2, axis)); + }; + Graph.prototype.matmul = function (x1, x2) { + return this.addNodeAndReturnOutput(new MatMulNode(this, x1, x2)); + }; + Graph.prototype.conv2d = function (x, w, b, fieldSize, outputDepth, stride, zeroPad) { + if (stride === void 0) { stride = 1; } + return this.addNodeAndReturnOutput(new Convolution2DNode(this, x, w, b, fieldSize, outputDepth, stride, zeroPad)); + }; + Graph.prototype.maxPool = function (x, fieldSize, stride, zeroPad) { + if (stride === void 0) { stride = 1; } + return this.addNodeAndReturnOutput(new MaxPoolNode(this, x, fieldSize, stride, zeroPad)); + }; + Graph.prototype.exp = function (x) { + return this.addNodeAndReturnOutput(new ExpNode(this, x)); + }; + Graph.prototype.log = function (x) { + return this.addNodeAndReturnOutput(new LogNode(this, x)); + }; + Graph.prototype.relu = function (x) { + return this.addNodeAndReturnOutput(new ReLUNode(this, x)); + }; + Graph.prototype.leakyRelu = function (x, alpha) { + return this.addNodeAndReturnOutput(new LeakyReLUNode(this, x, alpha)); + }; + Graph.prototype.prelu = function (x, alpha) { + return this.addNodeAndReturnOutput(new PReLUNode(this, x, alpha)); + }; + Graph.prototype.elu = function (x) { + return this.addNodeAndReturnOutput(new EluNode(this, x)); + }; + Graph.prototype.tanh = function (x) { + return this.addNodeAndReturnOutput(new TanHNode(this, x)); + }; + Graph.prototype.sigmoid = function (x) { + return this.addNodeAndReturnOutput(new SigmoidNode(this, x)); + }; + Graph.prototype.square = function (x) { + return this.addNodeAndReturnOutput(new SquareNode(this, x)); + }; + Graph.prototype.softmax = function (x) { + return this.addNodeAndReturnOutput(new SoftmaxNode(this, x)); + }; + Graph.prototype.softmaxCrossEntropyCost = function (x, target) { + return this.addNodeAndReturnOutput(new SoftmaxCrossEntropyCostNode(this, x, target)); + }; + Graph.prototype.meanSquaredCost = function (label, prediction) { + return this.addNodeAndReturnOutput(new MeanSquaredCostNode(this, label, prediction)); + }; + Graph.prototype.argmax = function (x) { + return this.addNodeAndReturnOutput(new ArgMaxNode(this, x)); + }; + Graph.prototype.argmaxEquals = function (x1, x2) { + return this.addNodeAndReturnOutput(new ArgMaxEqualsNode(this, x1, x2)); + }; + Graph.prototype.addNodeAndReturnOutput = function (node) { + this.nodes.push(node); + node.validate(); + return node.output; + }; + Graph.prototype.getNodes = function () { + return this.nodes; + }; + return Graph; +}()); +exports.Graph = Graph; +var Tensor = (function () { + function Tensor(shape) { + this.shape = shape; + this.id = Tensor.nextID++; + } + Tensor.nextID = 0; + return Tensor; +}()); +exports.Tensor = Tensor; +var Node = (function () { + function Node(graph, name, inputs, output) { + this.graph = graph; + this.name = name; + this.inputs = inputs; + this.output = output; + this.id = Node.nextID++; + output.node = this; + } + Node.nextID = 0; + return Node; +}()); +exports.Node = Node; +var VariableNode = (function (_super) { + __extends(VariableNode, _super); + function VariableNode(graph, name, data) { + var _this = _super.call(this, graph, name, {}, new Tensor(data.shape)) || this; + _this.data = data; + return _this; + } + VariableNode.prototype.validate = function () { + util.assert(this.data != null, 'Error adding variable op: Data for variable \'' + this.name + + '\' is null or undefined'); + }; + return VariableNode; +}(Node)); +exports.VariableNode = VariableNode; +var PlaceholderNode = (function (_super) { + __extends(PlaceholderNode, _super); + function PlaceholderNode(graph, name, shape) { + return _super.call(this, graph, name, {}, new Tensor(shape)) || this; + } + PlaceholderNode.prototype.validate = function () { }; + return PlaceholderNode; +}(Node)); +exports.PlaceholderNode = PlaceholderNode; +var ConstantNode = (function (_super) { + __extends(ConstantNode, _super); + function ConstantNode(graph, data) { + var _this = _super.call(this, graph, 'Constant', {}, new Tensor(data.shape)) || this; + _this.data = data; + return _this; + } + ConstantNode.prototype.validate = function () { + util.assert(this.data != null, 'Error adding constant: data for placeholder \'' + this.name + + '\' is null or undefined'); + }; + return ConstantNode; +}(Node)); +exports.ConstantNode = ConstantNode; +var ReshapeNode = (function (_super) { + __extends(ReshapeNode, _super); + function ReshapeNode(graph, name, x, shape) { + var _this = _super.call(this, graph, name, { x: x }, new Tensor(shape)) || this; + _this.name = name; + _this.x = x; + _this.shape = shape; + return _this; + } + ReshapeNode.prototype.validate = function () { + var xSize = util.sizeFromShape(this.x.shape); + var shapeSize = util.sizeFromShape(this.shape); + util.assert(xSize === shapeSize, "Error making reshape operation: input to reshape '" + this.name + "'" + + (" of shape (" + this.x.shape + ") does not match size of ") + + ("requested shape " + this.shape + ".")); + }; + ReshapeNode.X = 'x'; + return ReshapeNode; +}(Node)); +exports.ReshapeNode = ReshapeNode; +var FusedLinearCombinationNode = (function (_super) { + __extends(FusedLinearCombinationNode, _super); + function FusedLinearCombinationNode(graph, t1, t2, c1, c2) { + var _this = _super.call(this, graph, 'Linear Combination', { t1: t1, t2: t2, c1: c1, c2: c2 }, new Tensor(t1.shape)) || this; + _this.t1 = t1; + _this.t2 = t2; + _this.c1 = c1; + _this.c2 = c2; + return _this; + } + FusedLinearCombinationNode.prototype.validate = function () { + util.assertShapesMatch(this.t1.shape, this.t2.shape); + if (!util.isScalarShape(this.c1.shape)) { + throw new Error('Error adding fusedLinearCombination: c1 is not a scalar, got ' + + ("shape: " + this.c1.shape)); + } + if (!util.isScalarShape(this.c2.shape)) { + throw new Error('Error adding fusedLinearCombination: c2 is not a scalar, got ' + + ("shape: " + this.c2.shape)); + } + }; + FusedLinearCombinationNode.T1 = 't1'; + FusedLinearCombinationNode.T2 = 't2'; + FusedLinearCombinationNode.C1 = 'c1'; + FusedLinearCombinationNode.C2 = 'c2'; + return FusedLinearCombinationNode; +}(Node)); +exports.FusedLinearCombinationNode = FusedLinearCombinationNode; +var AddNode = (function (_super) { + __extends(AddNode, _super); + function AddNode(graph, t1, t2) { + var _this = _super.call(this, graph, 'Add', { t1: t1, t2: t2 }, new Tensor(util.sizeFromShape(t1.shape) === 1 + ? t2.shape + : (t1.shape.length < t2.shape.length ? t2.shape : t1.shape))) || this; + _this.t1 = t1; + _this.t2 = t2; + return _this; + } + AddNode.prototype.validate = function () { + util.assert(util.sizeFromShape(this.t1.shape) === 1 || + util.sizeFromShape(this.t2.shape) === 1 || + util.arraysEqual(this.t1.shape, this.t2.shape) || + (this.t1.shape.length === 2 && this.t2.shape.length === 1 && + this.t1.shape[1] === this.t2.shape[0]) || + (this.t1.shape.length === 1 && this.t2.shape.length === 2 && + this.t1.shape[0] === this.t2.shape[1]), 'Error adding add operation op: one of inputs must be scalar, ' + + ("shapes " + this.t1.shape + " and " + this.t2.shape + " must match,") + + 'or one of them can be broadcasted (2D and 1D).'); + }; + AddNode.T1 = 't1'; + AddNode.T2 = 't2'; + return AddNode; +}(Node)); +exports.AddNode = AddNode; +var SubtractNode = (function (_super) { + __extends(SubtractNode, _super); + function SubtractNode(graph, t1, t2) { + var _this = _super.call(this, graph, 'Subtract', { t1: t1, t2: t2 }, new Tensor(util.sizeFromShape(t1.shape) === 1 ? t2.shape : t1.shape)) || this; + _this.t1 = t1; + _this.t2 = t2; + return _this; + } + SubtractNode.prototype.validate = function () { + util.assert(util.sizeFromShape(this.t1.shape) === 1 || + util.sizeFromShape(this.t2.shape) === 1 || + util.arraysEqual(this.t1.shape, this.t2.shape), 'Error adding subtract op: one of inputs must be scalar or the ' + + ("shapes " + this.t1.shape + " and " + this.t2.shape + " must match.")); + }; + SubtractNode.T1 = 't1'; + SubtractNode.T2 = 't2'; + return SubtractNode; +}(Node)); +exports.SubtractNode = SubtractNode; +var MultiplyNode = (function (_super) { + __extends(MultiplyNode, _super); + function MultiplyNode(graph, t1, t2) { + var _this = _super.call(this, graph, 'Multiply', { t1: t1, t2: t2 }, new Tensor(util.sizeFromShape(t1.shape) === 1 ? t2.shape : t1.shape)) || this; + _this.t1 = t1; + _this.t2 = t2; + return _this; + } + MultiplyNode.prototype.validate = function () { + util.assert(util.sizeFromShape(this.t1.shape) === 1 || + util.sizeFromShape(this.t2.shape) === 1 || + util.arraysEqual(this.t1.shape, this.t2.shape), 'Error adding multiply op: one of inputs must be scalar or the ' + + ("shapes " + this.t1.shape + " and " + this.t2.shape + " must match.")); + }; + MultiplyNode.T1 = 't1'; + MultiplyNode.T2 = 't2'; + return MultiplyNode; +}(Node)); +exports.MultiplyNode = MultiplyNode; +var DivideNode = (function (_super) { + __extends(DivideNode, _super); + function DivideNode(graph, t1, t2) { + var _this = _super.call(this, graph, 'Divide', { t1: t1, t2: t2 }, new Tensor(util.sizeFromShape(t1.shape) === 1 ? t2.shape : t1.shape)) || this; + _this.t1 = t1; + _this.t2 = t2; + return _this; + } + DivideNode.prototype.validate = function () { + util.assert(util.sizeFromShape(this.t1.shape) === 1 || + util.sizeFromShape(this.t2.shape) === 1 || + util.arraysEqual(this.t1.shape, this.t2.shape), 'Error adding divide op: one of inputs must be scalar or the ' + + ("shapes " + this.t1.shape + " and " + this.t2.shape + " must match.")); + }; + DivideNode.T1 = 't1'; + DivideNode.T2 = 't2'; + return DivideNode; +}(Node)); +exports.DivideNode = DivideNode; +var ReduceSumNode = (function (_super) { + __extends(ReduceSumNode, _super); + function ReduceSumNode(graph, x) { + return _super.call(this, graph, 'ReduceSum', { x: x }, new Tensor([])) || this; + } + ReduceSumNode.prototype.validate = function () { }; + ReduceSumNode.X = 'x'; + return ReduceSumNode; +}(Node)); +exports.ReduceSumNode = ReduceSumNode; +var Concat3DNode = (function (_super) { + __extends(Concat3DNode, _super); + function Concat3DNode(graph, x1, x2, axis) { + var _this = _super.call(this, graph, 'Concat3D', { x1: x1, x2: x2 }, new Tensor(concat_util.computeOutShape(x1.shape, x2.shape, axis))) || this; + _this.x1 = x1; + _this.x2 = x2; + _this.axis = axis; + return _this; + } + Concat3DNode.prototype.validate = function () { + concat_util.assertParams(this.x1.shape, this.x2.shape, this.axis); + }; + Concat3DNode.X1 = 'x1'; + Concat3DNode.X2 = 'x2'; + Concat3DNode.AXIS = 'axis'; + return Concat3DNode; +}(Node)); +exports.Concat3DNode = Concat3DNode; +function getMatMulOutputShape(x1Shape, x2Shape) { + if (x1Shape.length === 1 && x2Shape.length === 1) { + return [1]; + } + else if (x1Shape.length === 1 && x2Shape.length === 2) { + return [x2Shape[1]]; + } + else if (x1Shape.length === 2 && x2Shape.length === 1) { + return [x1Shape[0]]; + } + return [x1Shape[0], x2Shape[1]]; +} +var MatMulNode = (function (_super) { + __extends(MatMulNode, _super); + function MatMulNode(graph, x1, x2) { + var _this = _super.call(this, graph, 'MatMul', { x1: x1, x2: x2 }, new Tensor(getMatMulOutputShape(x1.shape, x2.shape))) || this; + _this.x1 = x1; + _this.x2 = x2; + return _this; + } + MatMulNode.prototype.validate = function () { + if (this.x1.shape.length === 2 && this.x2.shape.length === 2) { + util.assert(this.x1.shape[1] === this.x2.shape[0], 'Error adding matmul op: inner shapes of matrices with shapes ' + + (this.x1.shape + " and " + this.x2.shape + " must match.")); + } + else if (this.x1.shape.length === 2 && this.x2.shape.length === 1) { + util.assert(this.x1.shape[1] === this.x2.shape[0], 'Error adding matmul op: second dimension of matrix with shape ' + + this.x1.shape.toString() + + (" must match size of vector with shape " + this.x2.shape + ".")); + } + else if (this.x1.shape.length === 1 && this.x2.shape.length === 2) { + util.assert(this.x1.shape[0] === this.x2.shape[0], "Error adding matmul op: size of vector with shape " + this.x1.shape + + " must match first dimension of matrix with " + + ("shape " + this.x2.shape + ".")); + } + else { + throw new Error('Error adding matmul op: inputs must be vectors or matrices.'); + } + }; + MatMulNode.X1 = 'x1'; + MatMulNode.X2 = 'x2'; + return MatMulNode; +}(Node)); +exports.MatMulNode = MatMulNode; +var Convolution2DNode = (function (_super) { + __extends(Convolution2DNode, _super); + function Convolution2DNode(graph, x, w, b, fieldSize, outputDepth, stride, zeroPad) { + if (stride === void 0) { stride = 1; } + var _this = _super.call(this, graph, 'Convolution 2D', { x: x, w: w, b: b }, new Tensor(conv_util.computeOutputShape3D(x.shape, fieldSize, outputDepth, stride, zeroPad))) || this; + _this.x = x; + _this.w = w; + _this.b = b; + _this.fieldSize = fieldSize; + _this.outputDepth = outputDepth; + _this.stride = stride; + _this.zeroPad = zeroPad; + return _this; + } + Convolution2DNode.prototype.validate = function () { + util.assert(this.x.shape.length === 3, 'Error adding conv2d op: input must be of rank 3, but got shape: ' + + (this.x.shape + ".")); + util.assert(this.w.shape.length === 4, 'Error adding conv2d op: weights must be of rank 4, but got shape: ' + + (this.w.shape + ".")); + util.assert(this.b.shape.length === 1, 'Error adding conv2d op: biases must be of rank 1, but got shape: ' + + (this.b.shape + ".")); + util.assert(this.x.shape[2] === this.w.shape[2], "Error adding conv2d op: depth of input (" + this.x.shape[2] + ") " + + ("must match input depth for weights (" + this.w.shape[2] + ").")); + }; + Convolution2DNode.X = 'x'; + Convolution2DNode.W = 'w'; + Convolution2DNode.B = 'b'; + return Convolution2DNode; +}(Node)); +exports.Convolution2DNode = Convolution2DNode; +var MaxPoolNode = (function (_super) { + __extends(MaxPoolNode, _super); + function MaxPoolNode(graph, x, fieldSize, stride, zeroPad) { + if (stride === void 0) { stride = 1; } + var _this = _super.call(this, graph, 'Max pool', { x: x }, new Tensor(conv_util.computeOutputShape3D(x.shape, fieldSize, x.shape[2], stride, zeroPad))) || this; + _this.x = x; + _this.fieldSize = fieldSize; + _this.stride = stride; + _this.zeroPad = zeroPad; + return _this; + } + MaxPoolNode.prototype.validate = function () { + util.assert(this.x.shape.length === 3, 'Error adding maxPool op: input must be of rank 3, but got shape: ' + + (this.x.shape + ".")); + }; + MaxPoolNode.X = 'x'; + return MaxPoolNode; +}(Node)); +exports.MaxPoolNode = MaxPoolNode; +var ReLUNode = (function (_super) { + __extends(ReLUNode, _super); + function ReLUNode(graph, x) { + return _super.call(this, graph, 'ReLU', { x: x }, new Tensor(x.shape)) || this; + } + ReLUNode.prototype.validate = function () { }; + ReLUNode.X = 'x'; + return ReLUNode; +}(Node)); +exports.ReLUNode = ReLUNode; +var LeakyReLUNode = (function (_super) { + __extends(LeakyReLUNode, _super); + function LeakyReLUNode(graph, x, alpha) { + var _this = _super.call(this, graph, 'LeakyReLU', { x: x }, new Tensor(x.shape)) || this; + _this.alpha = alpha; + return _this; + } + LeakyReLUNode.prototype.validate = function () { }; + LeakyReLUNode.X = 'x'; + return LeakyReLUNode; +}(Node)); +exports.LeakyReLUNode = LeakyReLUNode; +var PReLUNode = (function (_super) { + __extends(PReLUNode, _super); + function PReLUNode(graph, x, alpha) { + var _this = _super.call(this, graph, 'PReLU', { x: x, alpha: alpha }, new Tensor(x.shape)) || this; + _this.x = x; + _this.alpha = alpha; + return _this; + } + PReLUNode.prototype.validate = function () { + util.assert(util.arraysEqual(this.x.shape, this.alpha.shape), 'Error adding pRelu op: the ' + + ("shapes x: " + this.x.shape + " and alpha: " + this.alpha.shape + " must match.")); + }; + PReLUNode.X = 'x'; + PReLUNode.ALPHA = 'alpha'; + return PReLUNode; +}(Node)); +exports.PReLUNode = PReLUNode; +var EluNode = (function (_super) { + __extends(EluNode, _super); + function EluNode(graph, x) { + return _super.call(this, graph, 'Elu', { x: x }, new Tensor(x.shape)) || this; + } + EluNode.prototype.validate = function () { }; + EluNode.X = 'x'; + return EluNode; +}(Node)); +exports.EluNode = EluNode; +var ExpNode = (function (_super) { + __extends(ExpNode, _super); + function ExpNode(graph, x) { + return _super.call(this, graph, 'Exp', { x: x }, new Tensor(x.shape)) || this; + } + ExpNode.prototype.validate = function () { }; + ExpNode.X = 'x'; + return ExpNode; +}(Node)); +exports.ExpNode = ExpNode; +var LogNode = (function (_super) { + __extends(LogNode, _super); + function LogNode(graph, x) { + return _super.call(this, graph, 'Log', { x: x }, new Tensor(x.shape)) || this; + } + LogNode.prototype.validate = function () { }; + LogNode.X = 'x'; + return LogNode; +}(Node)); +exports.LogNode = LogNode; +var TanHNode = (function (_super) { + __extends(TanHNode, _super); + function TanHNode(graph, x) { + return _super.call(this, graph, 'TanH', { x: x }, new Tensor(x.shape)) || this; + } + TanHNode.prototype.validate = function () { }; + TanHNode.X = 'x'; + return TanHNode; +}(Node)); +exports.TanHNode = TanHNode; +var SigmoidNode = (function (_super) { + __extends(SigmoidNode, _super); + function SigmoidNode(graph, x) { + return _super.call(this, graph, 'Sigmoid', { x: x }, new Tensor(x.shape)) || this; + } + SigmoidNode.prototype.validate = function () { }; + SigmoidNode.X = 'x'; + return SigmoidNode; +}(Node)); +exports.SigmoidNode = SigmoidNode; +var SquareNode = (function (_super) { + __extends(SquareNode, _super); + function SquareNode(graph, x) { + return _super.call(this, graph, 'Square', { x: x }, new Tensor(x.shape)) || this; + } + SquareNode.prototype.validate = function () { }; + SquareNode.X = 'x'; + return SquareNode; +}(Node)); +exports.SquareNode = SquareNode; +var SoftmaxCrossEntropyCostNode = (function (_super) { + __extends(SoftmaxCrossEntropyCostNode, _super); + function SoftmaxCrossEntropyCostNode(graph, x, target) { + var _this = _super.call(this, graph, 'SoftmaxCrossEntropyCost', { x: x, target: target }, new Tensor([])) || this; + _this.x = x; + _this.target = target; + return _this; + } + SoftmaxCrossEntropyCostNode.prototype.validate = function () { + util.assert(util.arraysEqual(this.x.shape, this.target.shape), "Error adding softmaxCrossEntropyCost op: x shape (" + this.x.shape + ") " + + ("must match target shape (" + this.target.shape + ").")); + }; + SoftmaxCrossEntropyCostNode.X = 'x'; + SoftmaxCrossEntropyCostNode.TARGET = 'target'; + return SoftmaxCrossEntropyCostNode; +}(Node)); +exports.SoftmaxCrossEntropyCostNode = SoftmaxCrossEntropyCostNode; +var SoftmaxNode = (function (_super) { + __extends(SoftmaxNode, _super); + function SoftmaxNode(graph, x) { + var _this = _super.call(this, graph, 'Softmax', { x: x }, new Tensor(x.shape)) || this; + _this.x = x; + return _this; + } + SoftmaxNode.prototype.validate = function () { + util.assert(this.x.shape.length === 1, 'The input to a softmax must be a 1-D tensor'); + util.assert(this.x.shape[0] >= 2, 'The input to a softmax must have at least 2 values'); + }; + SoftmaxNode.X = 'x'; + return SoftmaxNode; +}(Node)); +exports.SoftmaxNode = SoftmaxNode; +var MeanSquaredCostNode = (function (_super) { + __extends(MeanSquaredCostNode, _super); + function MeanSquaredCostNode(graph, label, prediction) { + var _this = _super.call(this, graph, 'Mean Squared Cost', { label: label, prediction: prediction }, new Tensor([])) || this; + _this.label = label; + _this.prediction = prediction; + return _this; + } + MeanSquaredCostNode.prototype.validate = function () { + util.assert(util.arraysEqual(this.label.shape, this.prediction.shape), "Error adding meanSquaredCost op: label shape (" + this.label.shape + ") " + + ("must match prediction shape (" + this.prediction.shape + ").")); + }; + MeanSquaredCostNode.LABEL = 'label'; + MeanSquaredCostNode.PREDICTION = 'prediction'; + return MeanSquaredCostNode; +}(Node)); +exports.MeanSquaredCostNode = MeanSquaredCostNode; +var ArgMaxNode = (function (_super) { + __extends(ArgMaxNode, _super); + function ArgMaxNode(graph, x) { + var _this = _super.call(this, graph, 'ArgMax', { x: x }, new Tensor([1])) || this; + _this.x = x; + return _this; + } + ArgMaxNode.prototype.validate = function () { + util.assert(util.sizeFromShape(this.x.shape) > 0, 'Error adding argmax op: input tensor must have at least one entry.'); + }; + ArgMaxNode.X = 'x'; + return ArgMaxNode; +}(Node)); +exports.ArgMaxNode = ArgMaxNode; +var ArgMaxEqualsNode = (function (_super) { + __extends(ArgMaxEqualsNode, _super); + function ArgMaxEqualsNode(graph, x1, x2) { + var _this = _super.call(this, graph, 'ArgMaxEquals', { x1: x1, x2: x2 }, new Tensor([1])) || this; + _this.x1 = x1; + _this.x2 = x2; + return _this; + } + ArgMaxEqualsNode.prototype.validate = function () { + util.assert(util.arraysEqual(this.x1.shape, this.x2.shape), "Error adding ArgMaxEquals op: x1 shape (" + this.x1.shape + ") " + + ("must match x2 shape (" + this.x2.shape + ").")); + }; + ArgMaxEqualsNode.X1 = 'x1'; + ArgMaxEqualsNode.X2 = 'x2'; + return ArgMaxEqualsNode; +}(Node)); +exports.ArgMaxEqualsNode = ArgMaxEqualsNode; + +},{"../initializers":52,"../math/concat_util":91,"../math/conv_util":92,"../math/ndarray":95,"../util":101}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var graph_1 = require("./graph"); +var priority_queue = require("./priority_queue"); +var priority_queue_1 = require("./priority_queue"); +function getUnorderedEvaluationSet(nodes, terminatingNodes) { + var terminatingNodeMap = {}; + var seen = {}; + var set = []; + var visit = nodes.slice(); + terminatingNodes.forEach(function (node) { return terminatingNodeMap[node.id] = node; }); + var _loop_1 = function () { + var cur = visit.pop(); + if (seen[cur.id] == null) { + if (terminatingNodeMap[cur.id] == null) { + Object.keys(cur.inputs) + .map(function (inputName) { return cur.inputs[inputName]; }) + .forEach(function (input) { return visit.push(input.node); }); + } + set.push(cur); + seen[cur.id] = cur; + } + }; + while (visit.length !== 0) { + _loop_1(); + } + return set; +} +exports.getUnorderedEvaluationSet = getUnorderedEvaluationSet; +function getOrderedEvaluationSet(unorderedEvaluationSet) { + var set = []; + var nodeIndices = {}; + var pendingDependencies = {}; + var nodeQueue = new priority_queue_1.PriorityQueue(function (a, b) { return priority_queue.defaultCompare(pendingDependencies[a.id], pendingDependencies[b.id]); }, function (node, newIndex) { return nodeIndices[node.id] = newIndex; }); + unorderedEvaluationSet.forEach(function (node) { return pendingDependencies[node.id] = 0; }); + unorderedEvaluationSet.forEach(function (node) { return Object.keys(node.inputs) + .map(function (key) { return node.inputs[key]; }) + .forEach(function (input) { + if (unorderedEvaluationSet.indexOf(input.node) !== -1) { + pendingDependencies[input.node.id]++; + } + }); }); + unorderedEvaluationSet.forEach(function (node) { return nodeQueue.enqueue(node); }); + while (!nodeQueue.empty()) { + set.unshift(nodeQueue.dequeue()); + Object.keys(set[0].inputs).map(function (key) { return set[0].inputs[key]; }).forEach(function (input) { + if (unorderedEvaluationSet.indexOf(input.node) === -1) { + return; + } + pendingDependencies[input.node.id]--; + nodeQueue.update(input.node, nodeIndices[input.node.id]); + }); + } + return set; +} +exports.getOrderedEvaluationSet = getOrderedEvaluationSet; +function isInputNode(node) { + return Object.keys(node.inputs).length === 0; +} +exports.isInputNode = isInputNode; +function shouldBackProp(t) { + return !(t.node instanceof graph_1.ConstantNode); +} +exports.shouldBackProp = shouldBackProp; +function isPassthroughNode(node, map) { + var keys = Object.keys(node.inputs); + for (var i = 0; i < keys.length; i++) { + var input = node.inputs[keys[i]]; + if (map.get(input, true) === map.get(node.output, true)) { + return true; + } + } + return false; +} +exports.isPassthroughNode = isPassthroughNode; + +},{"./graph":16,"./priority_queue":46}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var graph_1 = require("./graph"); +var graph_util = require("./graph_util"); +var add_1 = require("./ops/add"); +var argmax_1 = require("./ops/argmax"); +var argmaxequals_1 = require("./ops/argmaxequals"); +var concat3d_1 = require("./ops/concat3d"); +var convolution_1 = require("./ops/convolution"); +var divide_1 = require("./ops/divide"); +var element_wise_activation_1 = require("./ops/element_wise_activation"); +var element_wise_cost_1 = require("./ops/element_wise_cost"); +var exp_1 = require("./ops/exp"); +var linear_combination_1 = require("./ops/linear_combination"); +var log_1 = require("./ops/log"); +var matmul_1 = require("./ops/matmul"); +var max_pool_1 = require("./ops/max_pool"); +var multiply_1 = require("./ops/multiply"); +var reduce_sum_1 = require("./ops/reduce_sum"); +var reshape_1 = require("./ops/reshape"); +var softmax_1 = require("./ops/softmax"); +var subtract_1 = require("./ops/subtract"); +function emitFromGraphNodes(nodes) { + var ops = []; + nodes.forEach(function (node) { return Array.prototype.push.apply(ops, emitOpFromNode(node)); }); + return ops; +} +exports.emitFromGraphNodes = emitFromGraphNodes; +function emitOpFromNode(node) { + if (node instanceof graph_1.ReshapeNode) { + return [new reshape_1.Reshape(node.inputs[graph_1.ReshapeNode.X], node.output)]; + } + else if (node instanceof graph_1.MatMulNode) { + var x1 = node.inputs[graph_1.MatMulNode.X1]; + var x2 = node.inputs[graph_1.MatMulNode.X2]; + return [new matmul_1.MatMul(x1, x2, node.output)]; + } + else if (node instanceof graph_1.Convolution2DNode) { + var w = node.inputs[graph_1.Convolution2DNode.W]; + var x = node.inputs[graph_1.Convolution2DNode.X]; + var b = node.inputs[graph_1.Convolution2DNode.B]; + return [new convolution_1.Convolution2D(w, x, b, node.output, node.fieldSize, node.outputDepth, node.stride, node.zeroPad)]; + } + else if (node instanceof graph_1.MaxPoolNode) { + var x = node.inputs[graph_1.MaxPoolNode.X]; + return [new max_pool_1.MaxPool(x, node.output, node.fieldSize, node.stride, node.zeroPad)]; + } + else if (node instanceof graph_1.ExpNode) { + return [new exp_1.Exp(node.inputs[graph_1.ExpNode.X], node.output)]; + } + else if (node instanceof graph_1.LogNode) { + return [new log_1.Log(node.inputs[graph_1.LogNode.X], node.output)]; + } + else if (node instanceof graph_1.ReLUNode) { + return [new element_wise_activation_1.ReLU(node.inputs[graph_1.ReLUNode.X], node.output)]; + } + else if (node instanceof graph_1.LeakyReLUNode) { + return [new element_wise_activation_1.LeakyReLU(node.inputs[graph_1.LeakyReLUNode.X], node.output, node.alpha)]; + } + else if (node instanceof graph_1.PReLUNode) { + return [new element_wise_activation_1.PReLU(node.inputs[graph_1.PReLUNode.X], node.inputs[graph_1.PReLUNode.ALPHA], node.output)]; + } + else if (node instanceof graph_1.EluNode) { + return [new element_wise_activation_1.Elu(node.inputs[graph_1.EluNode.X], node.output)]; + } + else if (node instanceof graph_1.TanHNode) { + return [new element_wise_activation_1.TanH(node.inputs[graph_1.TanHNode.X], node.output)]; + } + else if (node instanceof graph_1.SigmoidNode) { + return [new element_wise_activation_1.Sigmoid(node.inputs[graph_1.SigmoidNode.X], node.output)]; + } + else if (node instanceof graph_1.SoftmaxCrossEntropyCostNode) { + var x = node.inputs[graph_1.SoftmaxCrossEntropyCostNode.X]; + var target = node.inputs[graph_1.SoftmaxCrossEntropyCostNode.TARGET]; + return [new softmax_1.SoftmaxCrossEntropyCost(x, target, node.output)]; + } + else if (node instanceof graph_1.SoftmaxNode) { + return [new softmax_1.Softmax(node.inputs[graph_1.SoftmaxNode.X], node.output)]; + } + else if (node instanceof graph_1.MeanSquaredCostNode) { + var label = node.inputs[graph_1.MeanSquaredCostNode.LABEL]; + var prediction = node.inputs[graph_1.MeanSquaredCostNode.PREDICTION]; + return [new element_wise_cost_1.MeanSquaredCost(label, prediction, node.output)]; + } + else if (node instanceof graph_1.ArgMaxEqualsNode) { + return [new argmaxequals_1.ArgMaxEquals(node.inputs[graph_1.ArgMaxEqualsNode.X1], node.inputs[graph_1.ArgMaxEqualsNode.X2], node.output)]; + } + else if (node instanceof graph_1.ArgMaxNode) { + return [new argmax_1.ArgMax(node.x, node.output)]; + } + else if (node instanceof graph_1.FusedLinearCombinationNode) { + return [new linear_combination_1.LinearCombination(node.inputs[graph_1.FusedLinearCombinationNode.T1], node.inputs[graph_1.FusedLinearCombinationNode.T2], node.inputs[graph_1.FusedLinearCombinationNode.C1], node.inputs[graph_1.FusedLinearCombinationNode.C2], node.output)]; + } + else if (node instanceof graph_1.Concat3DNode) { + return [new concat3d_1.Concat3D(node.inputs[graph_1.Concat3DNode.X1], node.inputs[graph_1.Concat3DNode.X2], node.axis, node.output)]; + } + else if (node instanceof graph_1.SquareNode) { + return [new element_wise_activation_1.Square(node.inputs[graph_1.SquareNode.X], node.output)]; + } + else if (node instanceof graph_1.AddNode) { + return [new add_1.Add(node.inputs[graph_1.AddNode.T1], node.inputs[graph_1.AddNode.T2], node.output)]; + } + else if (node instanceof graph_1.SubtractNode) { + return [new subtract_1.Subtract(node.inputs[graph_1.SubtractNode.T1], node.inputs[graph_1.SubtractNode.T2], node.output)]; + } + else if (node instanceof graph_1.MultiplyNode) { + return [new multiply_1.Multiply(node.inputs[graph_1.MultiplyNode.T1], node.inputs[graph_1.MultiplyNode.T2], node.output)]; + } + else if (node instanceof graph_1.DivideNode) { + return [new divide_1.Divide(node.inputs[graph_1.DivideNode.T1], node.inputs[graph_1.DivideNode.T2], node.output)]; + } + else if (node instanceof graph_1.ReduceSumNode) { + return [new reduce_sum_1.ReduceSum(node.inputs[graph_1.ReduceSumNode.X], node.output)]; + } + else if (graph_util.isInputNode(node)) { + return []; + } + else { + throw Error("Unsupported node type: " + node.constructor.name); + } +} + +},{"./graph":16,"./graph_util":17,"./ops/add":19,"./ops/argmax":20,"./ops/argmaxequals":21,"./ops/concat3d":22,"./ops/convolution":23,"./ops/divide":24,"./ops/element_wise_activation":25,"./ops/element_wise_cost":26,"./ops/exp":27,"./ops/linear_combination":28,"./ops/log":29,"./ops/matmul":30,"./ops/max_pool":31,"./ops/multiply":32,"./ops/reduce_sum":34,"./ops/reshape":35,"./ops/softmax":36,"./ops/subtract":37}],19:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../../util"); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var Add = (function (_super) { + __extends(Add, _super); + function Add(x1Tensor, x2Tensor, yTensor) { + var _this = _super.call(this) || this; + _this.x1Tensor = x1Tensor; + _this.x2Tensor = x2Tensor; + _this.yTensor = yTensor; + util.assert(util.sizeFromShape(x1Tensor.shape) === 1 || + util.sizeFromShape(x2Tensor.shape) === 1 || + util.arraysEqual(x1Tensor.shape, x2Tensor.shape) || + (x1Tensor.shape.length === 2 && x2Tensor.shape.length === 1 && + x1Tensor.shape[1] === x2Tensor.shape[0]) || + (x1Tensor.shape.length === 1 && x2Tensor.shape.length === 2 && + x1Tensor.shape[0] === x2Tensor.shape[1]), 'One of t1 or t2 must be a scalar, or t1 and t2 must have ' + + 'the same shape, ' + + 'or one of them can be broadcasted (2D and 1D).'); + return _this; + } + Add.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + math.scope(function (keep) { + var result; + if (util.isScalarShape(x1.shape)) { + result = math.scalarPlusArray(x1, x2); + } + else if (util.isScalarShape(x2.shape)) { + result = math.scalarPlusArray(x2, x1); + } + else { + result = math.add(x1, x2); + } + inferenceArrays.set(_this.yTensor, keep(result)); + }); + }; + Add.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var dy = gradientArrays.get(this.yTensor); + math.scope(function () { + if (graph_util.shouldBackProp(_this.x1Tensor)) { + if (_this.x1Tensor.shape.length === 1 && + _this.x2Tensor.shape.length === 2 && + _this.x1Tensor.shape[0] === _this.x2Tensor.shape[1]) { + var sum = math.sum(dy, 0); + gradientArrays.add(_this.x1Tensor, sum); + } + else if (util.isScalarShape(_this.x1Tensor.shape)) { + var sum = math.sum(dy); + gradientArrays.add(_this.x1Tensor, sum); + } + else { + gradientArrays.add(_this.x1Tensor, math.clone(dy)); + } + } + if (graph_util.shouldBackProp(_this.x2Tensor)) { + if (_this.x1Tensor.shape.length === 2 && + _this.x2Tensor.shape.length === 1 && + _this.x1Tensor.shape[1] === _this.x2Tensor.shape[0]) { + var sum = math.sum(dy, 0); + gradientArrays.add(_this.x2Tensor, sum); + } + else if (util.isScalarShape(_this.x2Tensor.shape)) { + var sum = math.sum(dy); + gradientArrays.add(_this.x2Tensor, sum); + } + else { + gradientArrays.add(_this.x2Tensor, math.clone(dy)); + } + } + }); + }; + Add.prototype.dispose = function () { + if (this.dySizeScalar != null) { + this.dySizeScalar.dispose(); + } + }; + return Add; +}(op_1.Operation)); +exports.Add = Add; + +},{"../../util":101,"../graph_util":17,"./op":33}],20:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var op_1 = require("./op"); +var ArgMax = (function (_super) { + __extends(ArgMax, _super); + function ArgMax(xTensor, yTensor) { + var _this = _super.call(this) || this; + _this.xTensor = xTensor; + _this.yTensor = yTensor; + return _this; + } + ArgMax.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(math.argMax(x))); + }); + }; + ArgMax.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + throw new Error('ArgMax backprop unimplemented'); + }; + return ArgMax; +}(op_1.Operation)); +exports.ArgMax = ArgMax; + +},{"./op":33}],21:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var op_1 = require("./op"); +var ArgMaxEquals = (function (_super) { + __extends(ArgMaxEquals, _super); + function ArgMaxEquals(x1Tensor, x2Tensor, yTensor) { + var _this = _super.call(this) || this; + _this.x1Tensor = x1Tensor; + _this.x2Tensor = x2Tensor; + _this.yTensor = yTensor; + return _this; + } + ArgMaxEquals.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(math.argMaxEquals(x1, x2))); + }); + }; + ArgMaxEquals.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + throw new Error('ArgMaxEquals backprop unimplemented'); + }; + return ArgMaxEquals; +}(op_1.Operation)); +exports.ArgMaxEquals = ArgMaxEquals; + +},{"./op":33}],22:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var concat_util = require("../../math/concat_util"); +var op_1 = require("./op"); +var Concat3D = (function (_super) { + __extends(Concat3D, _super); + function Concat3D(x1Tensor, x2Tensor, axis, yTensor) { + var _this = _super.call(this) || this; + _this.x1Tensor = x1Tensor; + _this.x2Tensor = x2Tensor; + _this.axis = axis; + _this.yTensor = yTensor; + concat_util.assertParams(x1Tensor.shape, x2Tensor.shape, axis); + return _this; + } + Concat3D.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + math.scope(function (keep) { + var concatResult = math.concat3D(x1, x2, _this.axis); + inferenceArrays.set(_this.yTensor, keep(concatResult)); + }); + }; + Concat3D.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + throw new Error('Concat3D backprop not implemented.'); + }; + return Concat3D; +}(op_1.Operation)); +exports.Concat3D = Concat3D; + +},{"../../math/concat_util":91,"./op":33}],23:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var conv_util = require("../../math/conv_util"); +var util = require("../../util"); +var op_1 = require("./op"); +var Convolution2D = (function (_super) { + __extends(Convolution2D, _super); + function Convolution2D(wTensor, xTensor, bTensor, yTensor, fieldSize, outputDepth, stride, zeroPad) { + if (stride === void 0) { stride = 1; } + var _this = _super.call(this) || this; + _this.wTensor = wTensor; + _this.xTensor = xTensor; + _this.bTensor = bTensor; + _this.yTensor = yTensor; + _this.fieldSize = fieldSize; + _this.outputDepth = outputDepth; + _this.stride = stride; + _this.assertWeightsShape(wTensor.shape); + _this.zeroPad = zeroPad != null ? + zeroPad : + conv_util.computeDefaultPad(_this.xTensor.shape, _this.fieldSize, _this.stride); + util.assert(util.isInt(_this.zeroPad), "The zero padding (" + _this.zeroPad + ") must be an integer. Change the " + + "stride and/or zero pad parameters"); + return _this; + } + Convolution2D.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var weights = inferenceArrays.get(this.wTensor); + var biases = inferenceArrays.get(this.bTensor); + var x = inferenceArrays.get(this.xTensor); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(math.conv2d(x, weights, biases, _this.stride, _this.zeroPad))); + }); + }; + Convolution2D.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var filter = inferenceArrays.get(this.wTensor); + var x = inferenceArrays.get(this.xTensor); + var dy = gradientArrays.get(this.yTensor); + math.scope(function () { + var dw = math.conv2dDerFilter(x, dy, filter.shape, _this.stride, _this.zeroPad); + var db = math.conv2dDerBias(dy); + var dx = math.conv2dDerInput(x.shape, dy, filter, _this.stride, _this.zeroPad); + gradientArrays.add(_this.wTensor, dw); + gradientArrays.add(_this.bTensor, db); + gradientArrays.add(_this.xTensor, dx); + }); + }; + Convolution2D.prototype.assertWeightsShape = function (weightsShape) { + util.assert(weightsShape[0] === this.fieldSize && + weightsShape[1] === this.fieldSize && + weightsShape[2] === this.xTensor.shape[2] && + weightsShape[3] === this.outputDepth, "weights must be of shape [" + this.fieldSize + "," + this.fieldSize + "," + + (this.xTensor.shape[2] + "," + this.outputDepth + "] but they are of") + + ("shape [" + weightsShape + "]")); + }; + return Convolution2D; +}(op_1.Operation)); +exports.Convolution2D = Convolution2D; + +},{"../../math/conv_util":92,"../../util":101,"./op":33}],24:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../../util"); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var Divide = (function (_super) { + __extends(Divide, _super); + function Divide(x1Tensor, x2Tensor, yTensor) { + var _this = _super.call(this) || this; + _this.x1Tensor = x1Tensor; + _this.x2Tensor = x2Tensor; + _this.yTensor = yTensor; + util.assert(util.sizeFromShape(x1Tensor.shape) === 1 || + util.sizeFromShape(x2Tensor.shape) === 1 || + util.arraysEqual(x1Tensor.shape, x2Tensor.shape), 'One of t1 or t2 must be a scalar, or t1 and t2 must have ' + + 'the same shape'); + return _this; + } + Divide.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var t1 = inferenceArrays.get(this.x1Tensor); + var t2 = inferenceArrays.get(this.x2Tensor); + math.scope(function (keep) { + var result; + if (util.isScalarShape(t1.shape)) { + result = math.scalarDividedByArray(t1, t2); + } + else if (util.isScalarShape(t2.shape)) { + result = math.arrayDividedByScalar(t1, t2); + } + else { + result = math.divide(t1, t2); + } + inferenceArrays.set(_this.yTensor, keep(result)); + }); + }; + Divide.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + var dy = gradientArrays.get(this.yTensor); + var x1IsScalar = util.isScalarShape(x1.shape); + var x2IsScalar = util.isScalarShape(x2.shape); + math.scope(function () { + if (graph_util.shouldBackProp(_this.x1Tensor)) { + if (x1IsScalar) { + var div = math.divide(dy, x2); + gradientArrays.add(_this.x1Tensor, math.sum(div)); + div.dispose(); + } + else if (x2IsScalar) { + gradientArrays.add(_this.x1Tensor, math.arrayDividedByScalar(dy, x2)); + } + else { + gradientArrays.add(_this.x1Tensor, math.divide(dy, x2)); + } + } + if (graph_util.shouldBackProp(_this.x2Tensor)) { + var x2Squared = math.elementWiseMul(x2, x2); + var x1OverX2Squared = void 0; + if (x2IsScalar) { + x1OverX2Squared = math.arrayDividedByScalar(x1, x2Squared); + } + else if (x1IsScalar) { + x1OverX2Squared = math.scalarDividedByArray(x1, x2Squared); + } + else { + x1OverX2Squared = math.divide(x1, x2Squared); + } + var dx2 = math.neg(x1OverX2Squared); + var dyTimesDerivative = math.elementWiseMul(dy, dx2); + if (x2IsScalar) { + gradientArrays.add(_this.x2Tensor, math.sum(dyTimesDerivative)); + } + else { + gradientArrays.add(_this.x2Tensor, dyTimesDerivative); + } + } + }); + }; + return Divide; +}(op_1.Operation)); +exports.Divide = Divide; + +},{"../../util":101,"../graph_util":17,"./op":33}],25:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var activation_functions_1 = require("../../math/activation_functions"); +var op_1 = require("./op"); +var ElementWiseActivation = (function (_super) { + __extends(ElementWiseActivation, _super); + function ElementWiseActivation(xTensor, yTensor, func) { + var _this = _super.call(this) || this; + _this.xTensor = xTensor; + _this.yTensor = yTensor; + _this.func = func; + return _this; + } + ElementWiseActivation.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(_this.func.output(math, x))); + }); + }; + ElementWiseActivation.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + var y = inferenceArrays.get(this.yTensor); + var dy = gradientArrays.get(this.yTensor); + math.scope(function () { + var dydx = _this.func.der(math, x, y); + gradientArrays.add(_this.xTensor, math.elementWiseMul(dy, dydx)); + dydx.dispose(); + }); + }; + ElementWiseActivation.prototype.dispose = function () { + this.func.dispose(); + }; + return ElementWiseActivation; +}(op_1.Operation)); +exports.ElementWiseActivation = ElementWiseActivation; +var ReLU = (function (_super) { + __extends(ReLU, _super); + function ReLU(xTensor, yTensor) { + return _super.call(this, xTensor, yTensor, new activation_functions_1.ReLUFunc()) || this; + } + return ReLU; +}(ElementWiseActivation)); +exports.ReLU = ReLU; +var LeakyReLU = (function (_super) { + __extends(LeakyReLU, _super); + function LeakyReLU(xTensor, yTensor, alpha) { + return _super.call(this, xTensor, yTensor, new activation_functions_1.LeakyReluFunc(alpha)) || this; + } + return LeakyReLU; +}(ElementWiseActivation)); +exports.LeakyReLU = LeakyReLU; +var TanH = (function (_super) { + __extends(TanH, _super); + function TanH(xTensor, yTensor) { + return _super.call(this, xTensor, yTensor, new activation_functions_1.TanHFunc()) || this; + } + return TanH; +}(ElementWiseActivation)); +exports.TanH = TanH; +var Sigmoid = (function (_super) { + __extends(Sigmoid, _super); + function Sigmoid(xTensor, yTensor) { + return _super.call(this, xTensor, yTensor, new activation_functions_1.SigmoidFunc()) || this; + } + return Sigmoid; +}(ElementWiseActivation)); +exports.Sigmoid = Sigmoid; +var Square = (function (_super) { + __extends(Square, _super); + function Square(xTensor, yTensor) { + return _super.call(this, xTensor, yTensor, new activation_functions_1.SquareFunc()) || this; + } + return Square; +}(ElementWiseActivation)); +exports.Square = Square; +var Elu = (function (_super) { + __extends(Elu, _super); + function Elu(xTensor, yTensor) { + return _super.call(this, xTensor, yTensor, new activation_functions_1.EluFunc()) || this; + } + return Elu; +}(ElementWiseActivation)); +exports.Elu = Elu; +var PReLU = (function (_super) { + __extends(PReLU, _super); + function PReLU(xTensor, alphaTensor, yTensor) { + var _this = _super.call(this) || this; + _this.xTensor = xTensor; + _this.alphaTensor = alphaTensor; + _this.yTensor = yTensor; + return _this; + } + PReLU.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + var alpha = inferenceArrays.get(this.alphaTensor); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(math.prelu(x, alpha))); + }); + }; + PReLU.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + var alpha = inferenceArrays.get(this.alphaTensor); + var dy = gradientArrays.get(this.yTensor); + math.scope(function () { + var dydx = math.preluDer(x, alpha); + gradientArrays.add(_this.xTensor, math.elementWiseMul(dy, dydx)); + }); + }; + return PReLU; +}(op_1.Operation)); +exports.PReLU = PReLU; + +},{"../../math/activation_functions":53,"./op":33}],26:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../environment"); +var cost_functions_1 = require("../../math/cost_functions"); +var ndarray_1 = require("../../math/ndarray"); +var util = require("../../util"); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var ElementWiseCost = (function (_super) { + __extends(ElementWiseCost, _super); + function ElementWiseCost(x1Tensor, x2Tensor, yTensor, func) { + var _this = _super.call(this) || this; + _this.x1Tensor = x1Tensor; + _this.x2Tensor = x2Tensor; + _this.yTensor = yTensor; + _this.func = func; + _this.oneOverNScalar = + environment_1.ENV.math.keep(ndarray_1.Scalar.new(1 / util.sizeFromShape(x1Tensor.shape))); + return _this; + } + ElementWiseCost.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + math.scope(function (keep) { + var elementWiseCost = _this.func.cost(math, x1, x2); + var sum = math.sum(elementWiseCost); + var result = math.scalarTimesArray(_this.oneOverNScalar, sum); + inferenceArrays.set(_this.yTensor, keep(result)); + }); + }; + ElementWiseCost.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + math.scope(function () { + if (graph_util.shouldBackProp(_this.x1Tensor)) { + gradientArrays.add(_this.x1Tensor, _this.func.der(math, x1, x2)); + } + if (graph_util.shouldBackProp(_this.x2Tensor)) { + gradientArrays.add(_this.x2Tensor, _this.func.der(math, x2, x1)); + } + }); + }; + ElementWiseCost.prototype.dispose = function () { + this.func.dispose(); + this.oneOverNScalar.dispose(); + }; + return ElementWiseCost; +}(op_1.Operation)); +exports.ElementWiseCost = ElementWiseCost; +var MeanSquaredCost = (function (_super) { + __extends(MeanSquaredCost, _super); + function MeanSquaredCost(x1Tensor, x2Tensor, yTensor) { + return _super.call(this, x1Tensor, x2Tensor, yTensor, new cost_functions_1.SquareCostFunc()) || this; + } + return MeanSquaredCost; +}(ElementWiseCost)); +exports.MeanSquaredCost = MeanSquaredCost; + +},{"../../environment":15,"../../math/cost_functions":93,"../../math/ndarray":95,"../../util":101,"../graph_util":17,"./op":33}],27:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var Exp = (function (_super) { + __extends(Exp, _super); + function Exp(xTensor, yTensor) { + var _this = _super.call(this) || this; + _this.xTensor = xTensor; + _this.yTensor = yTensor; + return _this; + } + Exp.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(math.exp(x))); + }); + }; + Exp.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var y = inferenceArrays.get(this.yTensor); + var dy = gradientArrays.get(this.yTensor); + math.scope(function () { + if (graph_util.shouldBackProp(_this.xTensor)) { + gradientArrays.add(_this.xTensor, math.elementWiseMul(y, dy)); + } + }); + }; + return Exp; +}(op_1.Operation)); +exports.Exp = Exp; + +},{"../graph_util":17,"./op":33}],28:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var LinearCombination = (function (_super) { + __extends(LinearCombination, _super); + function LinearCombination(x1Tensor, x2Tensor, c1Tensor, c2Tensor, outTensor) { + var _this = _super.call(this) || this; + _this.x1Tensor = x1Tensor; + _this.x2Tensor = x2Tensor; + _this.c1Tensor = c1Tensor; + _this.c2Tensor = c2Tensor; + _this.outTensor = outTensor; + return _this; + } + LinearCombination.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + var c1 = inferenceArrays.get(this.c1Tensor).asScalar(); + var c2 = inferenceArrays.get(this.c2Tensor).asScalar(); + math.scope(function (keep) { + inferenceArrays.set(_this.outTensor, keep(math.scaledArrayAdd(c1, x1, c2, x2))); + }); + }; + LinearCombination.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + var c1 = inferenceArrays.get(this.c1Tensor); + var c2 = inferenceArrays.get(this.c2Tensor); + var dy = gradientArrays.get(this.outTensor); + math.scope(function () { + if (graph_util.shouldBackProp(_this.x1Tensor)) { + gradientArrays.add(_this.x1Tensor, math.scalarTimesArray(c1, dy)); + } + if (graph_util.shouldBackProp(_this.x2Tensor)) { + gradientArrays.add(_this.x2Tensor, math.scalarTimesArray(c2, dy)); + } + if (graph_util.shouldBackProp(_this.c1Tensor)) { + var dotProduct1 = math.elementWiseMul(x1, dy); + gradientArrays.add(_this.c1Tensor, math.sum(dotProduct1)); + } + if (graph_util.shouldBackProp(_this.c2Tensor)) { + var dotProduct2 = math.elementWiseMul(x2, dy); + gradientArrays.add(_this.c2Tensor, math.sum(dotProduct2)); + } + }); + }; + return LinearCombination; +}(op_1.Operation)); +exports.LinearCombination = LinearCombination; + +},{"../graph_util":17,"./op":33}],29:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var Log = (function (_super) { + __extends(Log, _super); + function Log(xTensor, yTensor) { + var _this = _super.call(this) || this; + _this.xTensor = xTensor; + _this.yTensor = yTensor; + return _this; + } + Log.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(math.log(x))); + }); + }; + Log.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + var dy = gradientArrays.get(this.yTensor); + math.scope(function () { + if (graph_util.shouldBackProp(_this.xTensor)) { + gradientArrays.add(_this.xTensor, math.divide(dy, x)); + } + }); + }; + return Log; +}(op_1.Operation)); +exports.Log = Log; + +},{"../graph_util":17,"./op":33}],30:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var matmul_1 = require("../../math/backends/types/matmul"); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var MatMul = (function (_super) { + __extends(MatMul, _super); + function MatMul(x1Tensor, x2Tensor, yTensor) { + var _this = _super.call(this) || this; + _this.x1Tensor = x1Tensor; + _this.x2Tensor = x2Tensor; + _this.yTensor = yTensor; + return _this; + } + MatMul.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + math.scope(function (keep) { + if (x1.shape.length === 2 && x2.shape.length === 2) { + inferenceArrays.set(_this.yTensor, keep(math.matMul(x1, x2))); + } + else if (x1.shape.length === 2 && x2.shape.length === 1) { + inferenceArrays.set(_this.yTensor, keep(math.matrixTimesVector(x1, x2))); + } + else if (x1.shape.length === 1 && x2.shape.length === 2) { + inferenceArrays.set(_this.yTensor, keep(math.vectorTimesMatrix(x1, x2))); + } + }); + }; + MatMul.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + var dy = gradientArrays.get(this.yTensor); + if (x1.shape.length === 1) { + x1 = x1.reshape([1, x1.size]); + dy = dy.reshape([1, dy.size]); + } + if (x2.shape.length === 1) { + x2 = x2.reshape([x2.size, 1]); + dy = dy.reshape([dy.size, 1]); + } + math.scope(function () { + if (graph_util.shouldBackProp(_this.x1Tensor)) { + var dx1 = math.matMul(dy, x2, matmul_1.MatrixOrientation.REGULAR, matmul_1.MatrixOrientation.TRANSPOSED); + gradientArrays.add(_this.x1Tensor, _this.x1Tensor.shape.length === 1 ? dx1.as1D() : dx1); + } + if (graph_util.shouldBackProp(_this.x2Tensor)) { + var dx2 = math.matMul(x1, dy, matmul_1.MatrixOrientation.TRANSPOSED, matmul_1.MatrixOrientation.REGULAR); + gradientArrays.add(_this.x2Tensor, _this.x2Tensor.shape.length === 1 ? dx2.as1D() : dx2); + } + }); + }; + return MatMul; +}(op_1.Operation)); +exports.MatMul = MatMul; + +},{"../../math/backends/types/matmul":61,"../graph_util":17,"./op":33}],31:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var conv_util = require("../../math/conv_util"); +var util = require("../../util"); +var op_1 = require("./op"); +var MaxPool = (function (_super) { + __extends(MaxPool, _super); + function MaxPool(xTensor, yTensor, fieldSize, stride, pad) { + if (stride === void 0) { stride = 1; } + var _this = _super.call(this) || this; + _this.xTensor = xTensor; + _this.yTensor = yTensor; + _this.fieldSize = fieldSize; + _this.stride = stride; + if (pad != null) { + _this.pad = pad; + } + else { + _this.pad = conv_util.computeDefaultPad(xTensor.shape, _this.fieldSize, _this.stride); + } + util.assert(util.isInt(_this.pad), "The zero padding (" + _this.pad + ") must be an integer. Change the " + + "stride and/or zero pad parameters"); + return _this; + } + MaxPool.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(math.maxPool(x, _this.fieldSize, _this.stride, _this.pad))); + }); + }; + MaxPool.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + var dy = gradientArrays.get(this.yTensor); + math.scope(function () { + gradientArrays.add(_this.xTensor, math.maxPoolBackprop(dy, x, _this.fieldSize, _this.stride, _this.pad)); + }); + }; + return MaxPool; +}(op_1.Operation)); +exports.MaxPool = MaxPool; + +},{"../../math/conv_util":92,"../../util":101,"./op":33}],32:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../../util"); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var Multiply = (function (_super) { + __extends(Multiply, _super); + function Multiply(x1Tensor, x2Tensor, yTensor) { + var _this = _super.call(this) || this; + _this.x1Tensor = x1Tensor; + _this.x2Tensor = x2Tensor; + _this.yTensor = yTensor; + util.assert(util.sizeFromShape(x1Tensor.shape) === 1 || + util.sizeFromShape(x2Tensor.shape) === 1 || + util.arraysEqual(x1Tensor.shape, x2Tensor.shape), 'One of t1 or t2 must be a scalar, or t1 and t2 must have ' + + 'the same shape'); + return _this; + } + Multiply.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var t1 = inferenceArrays.get(this.x1Tensor); + var t2 = inferenceArrays.get(this.x2Tensor); + math.scope(function (keep) { + var result; + if (util.isScalarShape(t1.shape)) { + result = math.scalarTimesArray(t1, t2); + } + else if (util.isScalarShape(t2.shape)) { + result = math.scalarTimesArray(t2, t1); + } + else { + result = math.elementWiseMul(t1, t2); + } + inferenceArrays.set(_this.yTensor, keep(result)); + }); + }; + Multiply.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var x1 = inferenceArrays.get(this.x1Tensor); + var x2 = inferenceArrays.get(this.x2Tensor); + var dy = gradientArrays.get(this.yTensor); + math.scope(function () { + if (graph_util.shouldBackProp(_this.x1Tensor)) { + if (util.isScalarShape(_this.x1Tensor.shape)) { + var mul = math.elementWiseMul(dy, x2); + gradientArrays.add(_this.x1Tensor, math.sum(mul)); + } + else if (util.isScalarShape(x2.shape)) { + gradientArrays.add(_this.x1Tensor, math.scalarTimesArray(x2, dy)); + } + else { + gradientArrays.add(_this.x1Tensor, math.elementWiseMul(x2, dy)); + } + } + if (graph_util.shouldBackProp(_this.x2Tensor)) { + if (util.isScalarShape(_this.x2Tensor.shape)) { + var mul = math.elementWiseMul(dy, x1); + gradientArrays.add(_this.x2Tensor, math.sum(mul)); + } + else if (util.isScalarShape(x1.shape)) { + gradientArrays.add(_this.x2Tensor, math.scalarTimesArray(x1, dy)); + } + else { + gradientArrays.add(_this.x2Tensor, math.elementWiseMul(x1, dy)); + } + } + }); + }; + return Multiply; +}(op_1.Operation)); +exports.Multiply = Multiply; + +},{"../../util":101,"../graph_util":17,"./op":33}],33:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Operation = (function () { + function Operation() { + } + Operation.prototype.disposeTransientArrays = function (inferenceArrays, gradientArrays) { }; + Operation.prototype.dispose = function () { }; + return Operation; +}()); +exports.Operation = Operation; + +},{}],34:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../environment"); +var ndarray_1 = require("../../math/ndarray"); +var util = require("../../util"); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var ReduceSum = (function (_super) { + __extends(ReduceSum, _super); + function ReduceSum(x, outTensor) { + var _this = _super.call(this) || this; + _this.x = x; + _this.outTensor = outTensor; + util.assertShapesMatch(outTensor.shape, []); + _this.ones = environment_1.ENV.math.keep(ndarray_1.NDArray.ones(x.shape)); + return _this; + } + ReduceSum.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x = inferenceArrays.get(this.x); + math.scope(function (keep) { + inferenceArrays.set(_this.outTensor, keep(math.sum(x))); + }); + }; + ReduceSum.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + if (!graph_util.shouldBackProp(this.x)) { + return; + } + math.scope(function () { + var dy = gradientArrays.get(_this.outTensor); + gradientArrays.add(_this.x, math.scalarTimesArray(dy, _this.ones)); + }); + }; + ReduceSum.prototype.dispose = function () { + this.ones.dispose(); + }; + return ReduceSum; +}(op_1.Operation)); +exports.ReduceSum = ReduceSum; + +},{"../../environment":15,"../../math/ndarray":95,"../../util":101,"../graph_util":17,"./op":33}],35:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../../util"); +var op_1 = require("./op"); +var Reshape = (function (_super) { + __extends(Reshape, _super); + function Reshape(xTensor, yTensor) { + var _this = _super.call(this) || this; + _this.xTensor = xTensor; + _this.yTensor = yTensor; + var xSize = util.sizeFromShape(xTensor.shape); + var ySize = util.sizeFromShape(yTensor.shape); + util.assert(xSize === ySize, "The input size (" + xSize + ") and output size (" + ySize + ") must match"); + return _this; + } + Reshape.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var x = inferenceArrays.get(this.xTensor); + var clone = math.clone(x); + math.scope(function (keep) { + inferenceArrays.set(_this.yTensor, keep(clone.reshape(_this.yTensor.shape))); + }); + }; + Reshape.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var dy = gradientArrays.get(this.yTensor); + var clone = math.clone(dy); + math.scope(function () { + gradientArrays.add(_this.xTensor, clone.reshape(_this.xTensor.shape)); + }); + }; + return Reshape; +}(op_1.Operation)); +exports.Reshape = Reshape; + +},{"../../util":101,"./op":33}],36:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../environment"); +var ndarray_1 = require("../../math/ndarray"); +var util = require("../../util"); +var graph_1 = require("../graph"); +var op_1 = require("./op"); +var Softmax = (function (_super) { + __extends(Softmax, _super); + function Softmax(logitsTensor, output) { + var _this = _super.call(this) || this; + _this.logitsTensor = logitsTensor; + _this.output = output; + return _this; + } + Softmax.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var logits = inferenceArrays.get(this.logitsTensor); + return math.scope(function (keep) { + inferenceArrays.set(_this.output, keep(math.softmax(logits))); + }); + }; + Softmax.prototype.backProp = function () { + throw Error('Softmax backprop is not yet implemented'); + }; + return Softmax; +}(op_1.Operation)); +exports.Softmax = Softmax; +var SoftmaxCrossEntropyCost = (function (_super) { + __extends(SoftmaxCrossEntropyCost, _super); + function SoftmaxCrossEntropyCost(logitsTensor, labelTensor, yTensor) { + var _this = _super.call(this) || this; + _this.logitsTensor = logitsTensor; + _this.labelTensor = labelTensor; + _this.yTensor = yTensor; + _this.softmaxTensor = new graph_1.Tensor(logitsTensor.shape); + _this.epsilon = environment_1.ENV.math.keep(ndarray_1.Scalar.new(1e-5)); + return _this; + } + SoftmaxCrossEntropyCost.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var logits = inferenceArrays.get(this.logitsTensor); + var label = inferenceArrays.get(this.labelTensor); + math.scope(function (keep) { + var softmaxResult = math.softmax(logits); + inferenceArrays.set(_this.softmaxTensor, keep(softmaxResult)); + inferenceArrays.set(_this.yTensor, keep(crossEntropyCost(math, softmaxResult, label, _this.epsilon))); + }); + }; + SoftmaxCrossEntropyCost.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var softmax = inferenceArrays.get(this.softmaxTensor); + var label = inferenceArrays.get(this.labelTensor); + math.scope(function () { + gradientArrays.add(_this.logitsTensor, math.subtract(softmax, label)); + }); + }; + SoftmaxCrossEntropyCost.prototype.disposeTransientArrays = function (inferenceArrays, gradientArrays) { + inferenceArrays.disposeArray(this.softmaxTensor); + }; + SoftmaxCrossEntropyCost.prototype.dispose = function () { + this.epsilon.dispose(); + }; + return SoftmaxCrossEntropyCost; +}(op_1.Operation)); +exports.SoftmaxCrossEntropyCost = SoftmaxCrossEntropyCost; +function crossEntropyCost(math, y, target, epsilon) { + util.assert(y.size === target.size, 'The output and target must be the same size'); + return math.scope(function () { + var yPlusEps = math.scalarPlusArray(epsilon, y); + var logOutput = math.log(yPlusEps); + var tarLogOutput = math.elementWiseMul(target, logOutput); + var costVector = math.neg(tarLogOutput); + return math.sum(costVector); + }); +} +exports.crossEntropyCost = crossEntropyCost; + +},{"../../environment":15,"../../math/ndarray":95,"../../util":101,"../graph":16,"./op":33}],37:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../../util"); +var graph_util = require("../graph_util"); +var op_1 = require("./op"); +var Subtract = (function (_super) { + __extends(Subtract, _super); + function Subtract(t1, t2, outTensor) { + var _this = _super.call(this) || this; + _this.t1 = t1; + _this.t2 = t2; + _this.outTensor = outTensor; + util.assert(util.sizeFromShape(t1.shape) === 1 || + util.sizeFromShape(t2.shape) === 1 || + util.arraysEqual(t1.shape, t2.shape), 'One of t1 or t2 must be a scalar, or t1 and t2 must have ' + + 'the same shape'); + return _this; + } + Subtract.prototype.feedForward = function (math, inferenceArrays) { + var _this = this; + var t1 = inferenceArrays.get(this.t1); + var t2 = inferenceArrays.get(this.t2); + math.scope(function (keep) { + var result; + if (util.isScalarShape(t1.shape)) { + result = math.scalarMinusArray(t1, t2); + } + else if (util.isScalarShape(t2.shape)) { + result = math.arrayMinusScalar(t1, t2); + } + else { + result = math.subtract(t1, t2); + } + inferenceArrays.set(_this.outTensor, keep(result)); + }); + }; + Subtract.prototype.backProp = function (math, inferenceArrays, gradientArrays) { + var _this = this; + var dy = gradientArrays.get(this.outTensor); + math.scope(function () { + if (graph_util.shouldBackProp(_this.t1)) { + if (util.isScalarShape(_this.t1.shape)) { + var sum = math.sum(dy); + gradientArrays.add(_this.t1, sum); + } + else { + gradientArrays.add(_this.t1, math.clone(dy)); + } + } + if (graph_util.shouldBackProp(_this.t2)) { + if (util.isScalarShape(_this.t2.shape)) { + var sum = math.sum(dy); + var negSum = math.neg(sum); + gradientArrays.add(_this.t2, negSum); + } + else { + gradientArrays.add(_this.t2, math.neg(dy)); + } + } + }); + }; + Subtract.prototype.dispose = function () { + if (this.dySizeScalar != null) { + this.dySizeScalar.dispose(); + } + }; + return Subtract; +}(op_1.Operation)); +exports.Subtract = Subtract; + +},{"../../util":101,"../graph_util":17,"./op":33}],38:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../../math/ndarray"); +var tensor_array_map_1 = require("../tensor_array_map"); +var optimizer_1 = require("./optimizer"); +var AdadeltaOptimizer = (function (_super) { + __extends(AdadeltaOptimizer, _super); + function AdadeltaOptimizer(learningRate, gamma, specifiedVariableList) { + var _this = _super.call(this, learningRate, specifiedVariableList) || this; + _this.learningRate = learningRate; + _this.gamma = gamma; + _this.accumulatedSquaredGradients = new tensor_array_map_1.TensorArrayMap(); + _this.accumulatedUpdates = new tensor_array_map_1.TensorArrayMap(); + _this.eps = ndarray_1.Scalar.new(1e-6); + _this.g = ndarray_1.Scalar.new(_this.gamma); + return _this; + } + AdadeltaOptimizer.prototype.beforeBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + _super.prototype.beforeBatch.call(this, math, batchSize, runtime, activationArrayMap, gradientArrayMap); + if (this.accumulatedSquaredGradients.size() === 0) { + this.variableNodes.forEach(function (node) { + _this.accumulatedSquaredGradients.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + _this.accumulatedUpdates.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + }); + } + }; + AdadeltaOptimizer.prototype.afterBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + math.scope(function (keep) { + _this.variableNodes.forEach(function (node) { + var oldVariable = activationArrayMap.get(node.output); + var gradient = _this.variableGradients.get(node.output); + var oldCache = _this.accumulatedSquaredGradients.get(node.output); + var oldUpdates = _this.accumulatedUpdates.get(node.output); + var gradientSquare = math.multiply(gradient, gradient); + var cache = math.scaledArrayAdd(_this.g, oldCache, math.subtract(_this.one, _this.g), gradientSquare); + var updates = math.multiply(math.divide(math.sqrt(math.add(oldUpdates, _this.eps)), math.sqrt(math.add(oldCache, _this.eps))), gradient); + var variable = math.scaledArrayAdd(_this.c, updates, _this.one, oldVariable); + var updateSquare = math.multiply(updates, updates); + var newUpdates = math.scaledArrayAdd(_this.g, oldUpdates, math.subtract(_this.one, _this.g), updateSquare); + _this.accumulatedSquaredGradients.set(node.output, keep(cache)); + _this.accumulatedUpdates.set(node.output, keep(newUpdates)); + activationArrayMap.set(node.output, keep(variable)); + node.data = variable; + oldVariable.dispose(); + oldCache.dispose(); + oldUpdates.dispose(); + }); + }); + this.variableGradients.dispose(); + this.variableGradients = new tensor_array_map_1.TensorArrayMap(); + }; + AdadeltaOptimizer.prototype.dispose = function () { + _super.prototype.dispose.call(this); + this.eps.dispose(); + this.g.dispose(); + this.accumulatedSquaredGradients.dispose(); + this.accumulatedUpdates.dispose(); + }; + return AdadeltaOptimizer; +}(optimizer_1.Optimizer)); +exports.AdadeltaOptimizer = AdadeltaOptimizer; + +},{"../../math/ndarray":95,"../tensor_array_map":49,"./optimizer":43}],39:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../../math/ndarray"); +var tensor_array_map_1 = require("../tensor_array_map"); +var optimizer_1 = require("./optimizer"); +var AdagradOptimizer = (function (_super) { + __extends(AdagradOptimizer, _super); + function AdagradOptimizer(learningRate, specifiedVariableList) { + var _this = _super.call(this, learningRate, specifiedVariableList) || this; + _this.learningRate = learningRate; + _this.accumulatedSquaredGradients = new tensor_array_map_1.TensorArrayMap(); + _this.eps = ndarray_1.Scalar.new(1e-6); + return _this; + } + AdagradOptimizer.prototype.beforeBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + _super.prototype.beforeBatch.call(this, math, batchSize, runtime, activationArrayMap, gradientArrayMap); + if (this.accumulatedSquaredGradients.size() === 0) { + this.variableNodes.forEach(function (node) { + _this.accumulatedSquaredGradients.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + }); + } + }; + AdagradOptimizer.prototype.afterBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + math.scope(function (keep) { + _this.variableNodes.forEach(function (node) { + var oldVariable = activationArrayMap.get(node.output); + var gradient = _this.variableGradients.get(node.output); + var oldCache = _this.accumulatedSquaredGradients.get(node.output); + var gradientSquare = math.multiply(gradient, gradient); + var cache = math.add(oldCache, gradientSquare); + var variable = math.scaledArrayAdd(_this.c, math.divide(gradient, math.add(math.sqrt(cache), _this.eps)), _this.one, oldVariable); + _this.accumulatedSquaredGradients.set(node.output, keep(cache)); + activationArrayMap.set(node.output, keep(variable)); + node.data = variable; + oldVariable.dispose(); + oldCache.dispose(); + }); + }); + this.variableGradients.dispose(); + this.variableGradients = new tensor_array_map_1.TensorArrayMap(); + }; + AdagradOptimizer.prototype.dispose = function () { + _super.prototype.dispose.call(this); + this.eps.dispose(); + this.accumulatedSquaredGradients.dispose(); + }; + return AdagradOptimizer; +}(optimizer_1.Optimizer)); +exports.AdagradOptimizer = AdagradOptimizer; + +},{"../../math/ndarray":95,"../tensor_array_map":49,"./optimizer":43}],40:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../../math/ndarray"); +var tensor_array_map_1 = require("../tensor_array_map"); +var optimizer_1 = require("./optimizer"); +var AdamOptimizer = (function (_super) { + __extends(AdamOptimizer, _super); + function AdamOptimizer(learningRate, beta1, beta2, specifiedVariableList) { + var _this = _super.call(this, learningRate, specifiedVariableList) || this; + _this.learningRate = learningRate; + _this.beta1 = beta1; + _this.beta2 = beta2; + _this.firstMoment = new tensor_array_map_1.TensorArrayMap(); + _this.secondMoment = new tensor_array_map_1.TensorArrayMap(); + _this.eps = ndarray_1.Scalar.new(1e-8); + _this.b1 = ndarray_1.Scalar.new(_this.beta1); + _this.b2 = ndarray_1.Scalar.new(_this.beta2); + _this.accB1 = ndarray_1.Scalar.new(_this.beta1); + _this.accB2 = ndarray_1.Scalar.new(_this.beta2); + return _this; + } + AdamOptimizer.prototype.beforeBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + _super.prototype.beforeBatch.call(this, math, batchSize, runtime, activationArrayMap, gradientArrayMap); + if (this.firstMoment.size() === 0) { + this.variableNodes.forEach(function (node) { + _this.firstMoment.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + }); + } + if (this.secondMoment.size() === 0) { + this.variableNodes.forEach(function (node) { + _this.secondMoment.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + }); + } + }; + AdamOptimizer.prototype.afterBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + math.scope(function (keep) { + _this.variableNodes.forEach(function (node) { + var oldVariable = activationArrayMap.get(node.output); + var gradient = _this.variableGradients.get(node.output); + var oldFirstMoment = _this.firstMoment.get(node.output); + var oldSecondMoment = _this.secondMoment.get(node.output); + var newFirstMoment = math.scaledArrayAdd(_this.b1, oldFirstMoment, math.subtract(_this.one, _this.b1), gradient); + var gradientSquare = math.multiply(gradient, gradient); + var newSecondMoment = math.scaledArrayAdd(_this.b2, oldSecondMoment, math.subtract(_this.one, _this.b2), gradientSquare); + var biasCorrectedFirstMoment = math.divide(newFirstMoment, math.subtract(_this.one, _this.accB1)); + var biasCorrectedSecondMoment = math.divide(newSecondMoment, math.subtract(_this.one, _this.accB2)); + var variable = math.scaledArrayAdd(_this.c, math.divide(biasCorrectedFirstMoment, math.add(math.sqrt(biasCorrectedSecondMoment), _this.eps)), _this.one, oldVariable); + activationArrayMap.set(node.output, keep(variable)); + node.data = variable; + _this.firstMoment.set(node.output, keep(newFirstMoment)); + _this.secondMoment.set(node.output, keep(newSecondMoment)); + oldVariable.dispose(); + gradient.dispose(); + oldFirstMoment.dispose(); + oldSecondMoment.dispose(); + }); + var oldAccB1 = _this.accB1; + var oldAccB2 = _this.accB2; + _this.accB1 = keep(math.multiply(_this.accB1, _this.b1)); + _this.accB2 = keep(math.multiply(_this.accB2, _this.b2)); + oldAccB1.dispose(); + oldAccB2.dispose(); + }); + this.variableGradients.dispose(); + this.variableGradients = new tensor_array_map_1.TensorArrayMap(); + }; + AdamOptimizer.prototype.dispose = function () { + _super.prototype.dispose.call(this); + this.firstMoment.dispose(); + this.secondMoment.dispose(); + this.eps.dispose(); + this.b1.dispose(); + this.b2.dispose(); + this.accB1.dispose(); + this.accB2.dispose(); + }; + return AdamOptimizer; +}(optimizer_1.Optimizer)); +exports.AdamOptimizer = AdamOptimizer; + +},{"../../math/ndarray":95,"../tensor_array_map":49,"./optimizer":43}],41:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../../math/ndarray"); +var tensor_array_map_1 = require("../tensor_array_map"); +var optimizer_1 = require("./optimizer"); +var AdamaxOptimizer = (function (_super) { + __extends(AdamaxOptimizer, _super); + function AdamaxOptimizer(learningRate, beta1, beta2, specifiedVariableList) { + var _this = _super.call(this, learningRate, specifiedVariableList) || this; + _this.learningRate = learningRate; + _this.beta1 = beta1; + _this.beta2 = beta2; + _this.firstMoment = new tensor_array_map_1.TensorArrayMap(); + _this.weightedInfNorm = new tensor_array_map_1.TensorArrayMap(); + _this.eps = ndarray_1.Scalar.new(1e-8); + _this.b1 = ndarray_1.Scalar.new(_this.beta1); + _this.b2 = ndarray_1.Scalar.new(_this.beta2); + _this.accB1 = ndarray_1.Scalar.new(_this.beta1); + return _this; + } + AdamaxOptimizer.prototype.beforeBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + _super.prototype.beforeBatch.call(this, math, batchSize, runtime, activationArrayMap, gradientArrayMap); + if (this.firstMoment.size() === 0) { + this.variableNodes.forEach(function (node) { + _this.firstMoment.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + }); + } + if (this.weightedInfNorm.size() === 0) { + this.variableNodes.forEach(function (node) { + _this.weightedInfNorm.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + }); + } + }; + AdamaxOptimizer.prototype.afterBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + math.scope(function (keep) { + _this.variableNodes.forEach(function (node) { + var oldVariable = activationArrayMap.get(node.output); + var gradient = _this.variableGradients.get(node.output); + var oldFirstMoment = _this.firstMoment.get(node.output); + var oldWeightedInfNorm = _this.weightedInfNorm.get(node.output); + var newFirstMoment = math.scaledArrayAdd(_this.b1, oldFirstMoment, math.subtract(_this.one, _this.b1), gradient); + var ut0 = math.multiply(_this.b2, oldWeightedInfNorm); + var ut1 = math.abs(gradient); + var newWeightedInfNorm = math.add(math.relu(math.subtract(ut0, ut1)), ut1); + var variable = math.scaledArrayAdd(_this.one, oldVariable, math.divide(_this.c, math.subtract(_this.one, _this.accB1)), math.divide(newFirstMoment, math.add(_this.eps, newWeightedInfNorm))); + activationArrayMap.set(node.output, keep(variable)); + node.data = variable; + _this.firstMoment.set(node.output, keep(newFirstMoment)); + _this.weightedInfNorm.set(node.output, keep(newWeightedInfNorm)); + oldVariable.dispose(); + gradient.dispose(); + oldFirstMoment.dispose(); + oldWeightedInfNorm.dispose(); + }); + var oldAccB1 = _this.accB1; + _this.accB1 = keep(math.multiply(_this.accB1, _this.b1)); + oldAccB1.dispose(); + }); + this.variableGradients.dispose(); + this.variableGradients = new tensor_array_map_1.TensorArrayMap(); + }; + AdamaxOptimizer.prototype.dispose = function () { + _super.prototype.dispose.call(this); + this.firstMoment.dispose(); + this.weightedInfNorm.dispose(); + this.eps.dispose(); + this.accB1.dispose(); + this.b1.dispose(); + this.b2.dispose(); + }; + return AdamaxOptimizer; +}(optimizer_1.Optimizer)); +exports.AdamaxOptimizer = AdamaxOptimizer; + +},{"../../math/ndarray":95,"../tensor_array_map":49,"./optimizer":43}],42:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../../math/ndarray"); +var tensor_array_map_1 = require("../tensor_array_map"); +var sgd_optimizer_1 = require("./sgd_optimizer"); +var MomentumOptimizer = (function (_super) { + __extends(MomentumOptimizer, _super); + function MomentumOptimizer(learningRate, momentum, specifiedVariableList) { + var _this = _super.call(this, learningRate, specifiedVariableList) || this; + _this.learningRate = learningRate; + _this.momentum = momentum; + _this.variableVelocities = new tensor_array_map_1.TensorArrayMap(); + _this.m = ndarray_1.Scalar.new(_this.momentum); + return _this; + } + MomentumOptimizer.prototype.beforeBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + _super.prototype.beforeBatch.call(this, math, batchSize, runtime, activationArrayMap, gradientArrayMap); + if (this.variableVelocities.size() === 0) { + this.variableNodes.forEach(function (node) { + _this.variableVelocities.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + }); + } + }; + MomentumOptimizer.prototype.afterBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + math.scope(function (keep) { + _this.variableNodes.forEach(function (node) { + var oldVariable = activationArrayMap.get(node.output); + var gradient = _this.variableGradients.get(node.output); + var oldVelocity = _this.variableVelocities.get(node.output); + var velocity = math.scaledArrayAdd(_this.m, oldVelocity, _this.one, gradient); + var variable = math.scaledArrayAdd(_this.c, velocity, _this.one, oldVariable); + _this.variableVelocities.set(node.output, keep(velocity)); + activationArrayMap.set(node.output, keep(variable)); + node.data = variable; + oldVariable.dispose(); + oldVelocity.dispose(); + }); + }); + this.variableGradients.dispose(); + this.variableGradients = new tensor_array_map_1.TensorArrayMap(); + }; + MomentumOptimizer.prototype.dispose = function () { + _super.prototype.dispose.call(this); + this.m.dispose(); + this.variableVelocities.dispose(); + }; + MomentumOptimizer.prototype.setMomentum = function (momentum) { + this.momentum = momentum; + }; + return MomentumOptimizer; +}(sgd_optimizer_1.SGDOptimizer)); +exports.MomentumOptimizer = MomentumOptimizer; + +},{"../../math/ndarray":95,"../tensor_array_map":49,"./sgd_optimizer":45}],43:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../environment"); +var ndarray_1 = require("../../math/ndarray"); +var session_util = require("../session_util"); +var tensor_array_map_1 = require("../tensor_array_map"); +var Optimizer = (function () { + function Optimizer(learningRate, specifiedVariableList) { + this.learningRate = learningRate; + this.variableGradients = new tensor_array_map_1.TensorArrayMap(); + if (specifiedVariableList != null) { + this.specifiedVariableNodes = specifiedVariableList; + } + this.one = environment_1.ENV.math.keep(ndarray_1.Scalar.new(1)); + } + Optimizer.prototype.beforeBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + this.variableNodes = this.specifiedVariableNodes == null ? + session_util.getVariableNodesFromEvaluationSet(runtime.nodes) : + this.specifiedVariableNodes; + if (batchSize !== this.prevBatchSize) { + if (this.c != null) { + this.c.dispose(); + } + this.prevBatchSize = batchSize; + this.c = math.keep(ndarray_1.Scalar.new(-this.learningRate / batchSize)); + } + this.variableNodes.forEach(function (node) { return _this.variableGradients.set(node.output, math.keep(ndarray_1.NDArray.zeros(node.output.shape))); }); + }; + Optimizer.prototype.afterExample = function (math, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + math.scope(function (keep) { + _this.variableNodes.forEach(function (node) { + var gradient = gradientArrayMap.get(node.output); + var accumulatedGradient = _this.variableGradients.get(node.output); + _this.variableGradients.set(node.output, keep(math.add(gradient, accumulatedGradient))); + accumulatedGradient.dispose(); + }); + }); + }; + Optimizer.prototype.dispose = function () { + if (this.c != null) { + this.c.dispose(); + } + this.one.dispose(); + this.variableNodes.forEach(function (node) { + node.data.dispose(); + }); + this.specifiedVariableNodes.forEach(function (node) { + node.data.dispose(); + }); + }; + return Optimizer; +}()); +exports.Optimizer = Optimizer; + +},{"../../environment":15,"../../math/ndarray":95,"../session_util":48,"../tensor_array_map":49}],44:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../../math/ndarray"); +var tensor_array_map_1 = require("../tensor_array_map"); +var optimizer_1 = require("./optimizer"); +var RMSPropOptimizer = (function (_super) { + __extends(RMSPropOptimizer, _super); + function RMSPropOptimizer(learningRate, gamma, specifiedVariableList) { + var _this = _super.call(this, learningRate, specifiedVariableList) || this; + _this.learningRate = learningRate; + _this.gamma = gamma; + _this.accumulatedSquaredGradients = new tensor_array_map_1.TensorArrayMap(); + _this.eps = ndarray_1.Scalar.new(1e-6); + _this.g = ndarray_1.Scalar.new(_this.gamma); + return _this; + } + RMSPropOptimizer.prototype.beforeBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + _super.prototype.beforeBatch.call(this, math, batchSize, runtime, activationArrayMap, gradientArrayMap); + if (this.accumulatedSquaredGradients.size() === 0) { + this.variableNodes.forEach(function (node) { + _this.accumulatedSquaredGradients.set(node.output, ndarray_1.NDArray.zeros(node.output.shape)); + }); + } + }; + RMSPropOptimizer.prototype.afterBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + math.scope(function (keep) { + _this.variableNodes.forEach(function (node) { + var oldVariable = activationArrayMap.get(node.output); + var gradient = _this.variableGradients.get(node.output); + var oldCache = _this.accumulatedSquaredGradients.get(node.output); + var gradientSquare = math.multiply(gradient, gradient); + var cache = math.scaledArrayAdd(_this.g, oldCache, math.subtract(_this.one, _this.g), gradientSquare); + var variable = math.scaledArrayAdd(_this.c, math.divide(gradient, math.add(math.sqrt(cache), _this.eps)), _this.one, oldVariable); + _this.accumulatedSquaredGradients.set(node.output, keep(cache)); + activationArrayMap.set(node.output, keep(variable)); + node.data = variable; + oldVariable.dispose(); + oldCache.dispose(); + }); + }); + this.variableGradients.dispose(); + this.variableGradients = new tensor_array_map_1.TensorArrayMap(); + }; + RMSPropOptimizer.prototype.dispose = function () { + _super.prototype.dispose.call(this); + this.eps.dispose(); + this.g.dispose(); + this.accumulatedSquaredGradients.dispose(); + }; + return RMSPropOptimizer; +}(optimizer_1.Optimizer)); +exports.RMSPropOptimizer = RMSPropOptimizer; + +},{"../../math/ndarray":95,"../tensor_array_map":49,"./optimizer":43}],45:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var tensor_array_map_1 = require("../tensor_array_map"); +var optimizer_1 = require("./optimizer"); +var SGDOptimizer = (function (_super) { + __extends(SGDOptimizer, _super); + function SGDOptimizer(learningRate, specifiedVariableList) { + var _this = _super.call(this, learningRate, specifiedVariableList) || this; + _this.learningRate = learningRate; + return _this; + } + SGDOptimizer.prototype.afterBatch = function (math, batchSize, runtime, activationArrayMap, gradientArrayMap) { + var _this = this; + math.scope(function (keep) { + _this.variableNodes.forEach(function (node) { + var oldVariable = activationArrayMap.get(node.output); + var gradient = _this.variableGradients.get(node.output); + var variable = math.scaledArrayAdd(_this.c, gradient, _this.one, oldVariable); + activationArrayMap.set(node.output, keep(variable)); + node.data = variable; + oldVariable.dispose(); + }); + }); + this.variableGradients.dispose(); + this.variableGradients = new tensor_array_map_1.TensorArrayMap(); + }; + SGDOptimizer.prototype.dispose = function () { + _super.prototype.dispose.call(this); + }; + SGDOptimizer.prototype.setLearningRate = function (learningRate) { + this.learningRate = learningRate; + }; + return SGDOptimizer; +}(optimizer_1.Optimizer)); +exports.SGDOptimizer = SGDOptimizer; + +},{"../tensor_array_map":49,"./optimizer":43}],46:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function defaultCompare(a, b) { + if (a === b) { + return 0; + } + else if (a < b) { + return -1; + } + else { + return 1; + } +} +exports.defaultCompare = defaultCompare; +var PriorityQueue = (function () { + function PriorityQueue(comparator, indexObserver) { + this.comparator = comparator; + this.indexObserver = indexObserver; + this.heap = []; + } + PriorityQueue.prototype.enqueue = function (t) { + this.heap.push(t); + this.onIndexChanged(t, this.heap.length - 1); + this.siftUp(this.heap.length - 1); + }; + PriorityQueue.prototype.dequeue = function () { + if (this.empty()) { + throw new Error('dequeue called on empty priority queue.'); + } + var t = this.heap[0]; + this.swap(0, this.heap.length - 1); + this.heap.pop(); + this.siftDown(0); + return t; + }; + PriorityQueue.prototype.update = function (newT, index) { + var last = (index === this.heap.length - 1); + if (!last) { + this.swap(index, this.heap.length - 1); + } + this.heap.pop(); + if (!last) { + if (this.siftUpIndex(index) !== -1) { + this.siftUp(index); + } + else if (this.siftDownIndex(index) !== -1) { + this.siftDown(index); + } + } + this.enqueue(newT); + }; + PriorityQueue.prototype.empty = function () { + return this.heap.length === 0; + }; + PriorityQueue.prototype.onIndexChanged = function (t, newIndex) { + if (this.indexObserver) { + this.indexObserver(t, newIndex); + } + }; + PriorityQueue.prototype.getParentIndex = function (index) { + if (index === 0) { + return -1; + } + return Math.floor((index - 1) / 2); + }; + PriorityQueue.prototype.getLeftChildIndex = function (index) { + var candidate = index * 2 + 1; + return candidate < this.heap.length ? candidate : -1; + }; + PriorityQueue.prototype.getRightChildIndex = function (index) { + var candidate = index * 2 + 2; + return candidate < this.heap.length ? candidate : -1; + }; + PriorityQueue.prototype.siftUpIndex = function (index) { + var parentIndex = this.getParentIndex(index); + if (parentIndex === -1) { + return -1; + } + if (this.compare(parentIndex, index) > 0) { + return parentIndex; + } + return -1; + }; + PriorityQueue.prototype.siftUp = function (index) { + var siftIndex = this.siftUpIndex(index); + while (siftIndex !== -1) { + this.swap(index, siftIndex); + index = siftIndex; + siftIndex = this.siftUpIndex(index); + } + }; + PriorityQueue.prototype.siftDownIndex = function (index) { + if (index >= this.heap.length) { + return -1; + } + var largestChildIndex = index; + var leftChildIndex = this.getLeftChildIndex(index); + if ((leftChildIndex !== -1) && + (this.compare(leftChildIndex, largestChildIndex) < 0)) { + largestChildIndex = leftChildIndex; + } + var rightChildIndex = this.getRightChildIndex(index); + if ((rightChildIndex !== -1) && + (this.compare(rightChildIndex, largestChildIndex) < 0)) { + largestChildIndex = rightChildIndex; + } + return (largestChildIndex === index) ? -1 : largestChildIndex; + }; + PriorityQueue.prototype.siftDown = function (index) { + var siftIndex = this.siftDownIndex(index); + while (siftIndex !== -1) { + this.swap(index, siftIndex); + index = siftIndex; + siftIndex = this.siftDownIndex(index); + } + }; + PriorityQueue.prototype.compare = function (aIndex, bIndex) { + return this.comparator(this.heap[aIndex], this.heap[bIndex]); + }; + PriorityQueue.prototype.swap = function (a, b) { + var temp = this.heap[a]; + this.heap[a] = this.heap[b]; + this.heap[b] = temp; + this.onIndexChanged(this.heap[a], a); + this.onIndexChanged(this.heap[b], b); + }; + return PriorityQueue; +}()); +exports.PriorityQueue = PriorityQueue; + +},{}],47:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../math/ndarray"); +var util = require("../util"); +var operation_emitter = require("./operation_emitter"); +var session_util = require("./session_util"); +var tensor_array_map_1 = require("./tensor_array_map"); +var FeedDictionary = (function () { + function FeedDictionary(feedEntries) { + var _this = this; + this.dict = {}; + if (feedEntries) { + feedEntries.forEach(function (entry) { return _this.dict[entry.tensor.id] = entry; }); + } + } + return FeedDictionary; +}()); +exports.FeedDictionary = FeedDictionary; +var CostReduction; +(function (CostReduction) { + CostReduction[CostReduction["NONE"] = 0] = "NONE"; + CostReduction[CostReduction["SUM"] = 1] = "SUM"; + CostReduction[CostReduction["MEAN"] = 2] = "MEAN"; +})(CostReduction = exports.CostReduction || (exports.CostReduction = {})); +var Session = (function () { + function Session(graph, math) { + this.math = math; + this.activationArrayMap = new tensor_array_map_1.TensorArrayMap(); + this.runtimeCache = {}; + this.oneScalar = ndarray_1.Scalar.new(1); + this.gradientArrayMap = new tensor_array_map_1.SummedTensorArrayMap(this.math); + } + Session.prototype.dispose = function () { + var _this = this; + this.activationArrayMap.dispose(); + Object.keys(this.runtimeCache).forEach(function (key) { + var runtime = _this.runtimeCache[key]; + if (runtime.operations) { + runtime.operations.forEach(function (op) { return op.dispose(); }); + } + }); + this.runtimeCache = {}; + if (this.batchSizeScalar != null) { + this.batchSizeScalar.dispose(); + } + this.oneScalar.dispose(); + }; + Session.prototype.evalAll = function (tensors, feedEntries) { + var _this = this; + return this.math.scope(function () { + var feed = new FeedDictionary(feedEntries); + var runtime = _this.getOrCreateRuntime(tensors, feed); + var activations = _this.activationArrayMap; + session_util.disposeAndInitializeOperationOutputs(runtime.nodes, activations); + session_util.disposeTransientOperationArrays(runtime.operations, _this.activationArrayMap, _this.gradientArrayMap); + session_util.addPersistentArraysToTensorArrayMap(runtime.nodes, activations); + session_util.loadInputsFromFeedDictionaryToTensorArrayMap(feed, activations, _this.math); + runtime.operations.forEach(function (op) { return op.feedForward(_this.math, activations); }); + var results = tensors.map(function (x) { return activations.get(x); }); + tensors.forEach(function (x) { return activations.delete(x); }); + session_util.releaseFeedDictionaryInputsFromTensorArrayMap(feed, activations, _this.math); + return results; + }); + }; + Session.prototype.eval = function (tensor, feedEntries) { + return this.evalAll([tensor], feedEntries)[0]; + }; + Session.prototype.train = function (costTensor, feedEntries, batchSize, optimizer, costReduction) { + var _this = this; + if (costReduction === void 0) { costReduction = CostReduction.NONE; } + util.assert(util.isScalarShape(costTensor.shape), 'Cost tensor for training must be a scalar value.'); + if (this.prevBatchSize !== batchSize) { + this.prevBatchSize = batchSize; + if (this.batchSizeScalar != null) { + this.batchSizeScalar.dispose(); + } + this.batchSizeScalar = this.math.keep(ndarray_1.Scalar.new(batchSize)); + } + var feed = new FeedDictionary(feedEntries); + session_util.throwIfFeedDictionaryContainsNDArrays(feed); + var runtime = this.getOrCreateRuntime([costTensor], feed); + var inferenceOperations = runtime.operations; + var backPropOperations = runtime.operations.slice().reverse(); + var activations = this.activationArrayMap; + var gradients = this.gradientArrayMap; + gradients.nullify(costTensor); + gradients.add(costTensor, this.oneScalar); + session_util.addPersistentArraysToTensorArrayMap(runtime.nodes, activations); + optimizer.beforeBatch(this.math, batchSize, runtime, activations, gradients); + return this.math.scope(function () { + var cost = ndarray_1.Scalar.new(0); + for (var i = 0; i < batchSize; ++i) { + session_util.disposeAndInitializeOperationOutputs(runtime.nodes, activations); + session_util.disposeAndInitializeOperationInputGradients(runtime.nodes, gradients); + session_util.disposeTransientOperationArrays(runtime.operations, activations, gradients); + session_util.loadInputsFromFeedDictionaryToTensorArrayMap(feed, activations, _this.math); + inferenceOperations.forEach(function (op) { return op.feedForward(_this.math, activations); }); + backPropOperations.forEach(function (op) { return op.backProp(_this.math, activations, gradients); }); + optimizer.afterExample(_this.math, runtime, activations, gradients); + session_util.releaseFeedDictionaryInputsFromTensorArrayMap(feed, activations, _this.math); + cost = _this.updateCostForExample(cost, activations.get(costTensor), costReduction); + } + optimizer.afterBatch(_this.math, batchSize, runtime, activations, gradients); + return _this.updateCostForBatch(cost, costReduction); + }); + }; + Session.prototype.updateCostForExample = function (totalCost, currCost, costReduction) { + if (costReduction === CostReduction.MEAN || + costReduction === CostReduction.SUM) { + return this.math.add(totalCost, currCost); + } + return totalCost; + }; + Session.prototype.updateCostForBatch = function (totalCost, costReduction) { + if (costReduction === CostReduction.MEAN) { + return this.math.divide(totalCost, this.batchSizeScalar); + } + return totalCost; + }; + Session.prototype.getOrCreateRuntime = function (tensors, feed) { + var key = this.makeRuntimeCacheKey(tensors, feed); + var runtime = this.runtimeCache[key]; + if (runtime === undefined) { + var nodes = session_util.getOrderedEvaluationSetFromEvalTensor(tensors, feed); + session_util.removeFeedDictionaryNodesFromEvaluationSet(feed, nodes); + session_util.throwErrorIfEvaluationSetContainsPlaceholderNodes(nodes); + var operations = operation_emitter.emitFromGraphNodes(nodes); + runtime = { nodes: nodes, operations: operations }; + this.runtimeCache[key] = runtime; + } + return runtime; + }; + Session.prototype.makeRuntimeCacheKey = function (tensors, feed) { + return tensors.map(function (x) { return x.id; }).sort().join('_') + '__' + + Object.keys(feed.dict).sort().join('_'); + }; + return Session; +}()); +exports.Session = Session; + +},{"../math/ndarray":95,"../util":101,"./operation_emitter":18,"./session_util":48,"./tensor_array_map":49}],48:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../math/ndarray"); +var util = require("../util"); +var graph_1 = require("./graph"); +var graph_util = require("./graph_util"); +function getTerminatingNodesFromFeedDictionary(feedDictionary) { + return Object.keys(feedDictionary.dict) + .map(function (tensorID) { return feedDictionary.dict[+tensorID].tensor.node; }); +} +exports.getTerminatingNodesFromFeedDictionary = getTerminatingNodesFromFeedDictionary; +function getOrderedEvaluationSetFromEvalTensor(evalTensors, feedDictionary) { + var terminatingNodes = getTerminatingNodesFromFeedDictionary(feedDictionary); + var evalNodes = evalTensors.map(function (x) { return x.node; }); + var unorderedEvaluationSet = graph_util.getUnorderedEvaluationSet(evalNodes, terminatingNodes); + var orderedEvaluationSet = graph_util.getOrderedEvaluationSet(unorderedEvaluationSet); + return orderedEvaluationSet; +} +exports.getOrderedEvaluationSetFromEvalTensor = getOrderedEvaluationSetFromEvalTensor; +function addPersistentArraysToTensorArrayMap(evaluationSet, tensorArrayMap) { + evaluationSet.forEach(function (node) { + if (node instanceof graph_1.VariableNode || node instanceof graph_1.ConstantNode) { + tensorArrayMap.set(node.output, node.data); + } + }); +} +exports.addPersistentArraysToTensorArrayMap = addPersistentArraysToTensorArrayMap; +function getVariableNodesFromEvaluationSet(evaluationSet) { + var nodes = []; + evaluationSet.forEach(function (node) { + if (node instanceof graph_1.VariableNode) { + nodes.push(node); + } + }); + return nodes; +} +exports.getVariableNodesFromEvaluationSet = getVariableNodesFromEvaluationSet; +function throwIfFeedDictionaryContainsNDArrays(feedDictionary) { + Object.keys(feedDictionary.dict).forEach(function (tensorID) { + if (feedDictionary.dict[+tensorID].data instanceof ndarray_1.NDArray) { + throw new Error('training requires FeedDictionary entries to be InputProviders' + + 'and not NDArrays.'); + } + }); +} +exports.throwIfFeedDictionaryContainsNDArrays = throwIfFeedDictionaryContainsNDArrays; +function loadInputsFromFeedDictionaryToTensorArrayMap(batchFeed, activations, math) { + Object.keys(batchFeed.dict).forEach(function (tensorID) { + var feedEntry = batchFeed.dict[+tensorID]; + var data; + if (feedEntry.data instanceof ndarray_1.NDArray) { + data = feedEntry.data; + } + else { + var provider = feedEntry.data; + data = provider.getNextCopy(math); + } + util.assert(util.arraysEqual(feedEntry.tensor.shape, data.shape), "Error loading FeedEntry: feeding NDArray of shape " + data.shape + " " + + ("does not match Tensor (id: " + feedEntry.tensor.id + ") shape: ") + + (feedEntry.tensor.shape + ".")); + activations.set(feedEntry.tensor, data); + }); +} +exports.loadInputsFromFeedDictionaryToTensorArrayMap = loadInputsFromFeedDictionaryToTensorArrayMap; +function releaseFeedDictionaryInputsFromTensorArrayMap(batchFeed, activations, math) { + Object.keys(batchFeed.dict).forEach(function (tensorID) { + var feedEntry = batchFeed.dict[+tensorID]; + if (!(feedEntry.data instanceof ndarray_1.NDArray)) { + var provider = feedEntry.data; + var feedEntryArray = activations.get(feedEntry.tensor); + provider.disposeCopy(math, feedEntryArray); + } + activations.delete(feedEntry.tensor); + }); +} +exports.releaseFeedDictionaryInputsFromTensorArrayMap = releaseFeedDictionaryInputsFromTensorArrayMap; +function removeFeedDictionaryNodesFromEvaluationSet(feedDictionary, evaluationSet) { + var i = 0; + while (i < evaluationSet.length) { + var node = evaluationSet[i]; + if (feedDictionary.dict[node.output.id] != null) { + evaluationSet.splice(i, 1); + } + else { + ++i; + } + } +} +exports.removeFeedDictionaryNodesFromEvaluationSet = removeFeedDictionaryNodesFromEvaluationSet; +function disposeAndInitializeOperationOutputs(evaluationSet, tensorArrayMap) { + evaluationSet.forEach(function (node) { + if (!graph_util.isInputNode(node)) { + if (!graph_util.isPassthroughNode(node, tensorArrayMap)) { + tensorArrayMap.disposeArray(node.output); + } + tensorArrayMap.set(node.output, null); + } + }); +} +exports.disposeAndInitializeOperationOutputs = disposeAndInitializeOperationOutputs; +function disposeAndInitializeOperationInputGradients(evaluationSet, gradients) { + evaluationSet.forEach(function (node) { + Object.keys(node.inputs).forEach(function (inputName) { + var input = node.inputs[inputName]; + if (gradients.get(input, true) !== gradients.get(node.output, true)) { + gradients.disposeArray(input); + } + gradients.nullify(input); + }); + }); +} +exports.disposeAndInitializeOperationInputGradients = disposeAndInitializeOperationInputGradients; +function disposeTransientOperationArrays(operations, activations, gradients) { + operations.forEach(function (op) { return op.disposeTransientArrays(activations, gradients); }); +} +exports.disposeTransientOperationArrays = disposeTransientOperationArrays; +function throwErrorIfEvaluationSetContainsPlaceholderNodes(evaluationSet) { + evaluationSet.forEach(function (node) { + if (node instanceof graph_1.PlaceholderNode) { + var shape = '[' + node.output.shape.join(', ') + ']'; + throw new Error('Placeholder node "' + node.name + '" ' + shape + + ' not present in feed dictionary.'); + } + }); +} +exports.throwErrorIfEvaluationSetContainsPlaceholderNodes = throwErrorIfEvaluationSetContainsPlaceholderNodes; + +},{"../math/ndarray":95,"../util":101,"./graph":16,"./graph_util":17}],49:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var TensorArrayMapBase = (function () { + function TensorArrayMapBase() { + this.dict = {}; + } + TensorArrayMapBase.prototype.get = function (tensor, skipChecks) { + if (skipChecks === void 0) { skipChecks = false; } + if (!skipChecks && this.dict[tensor.id] === undefined) { + throw new Error("tensor " + tensor.id + " not in array map."); + } + var nda = this.dict[tensor.id]; + if (!skipChecks && nda === null) { + throw new Error("tensor " + tensor.id + " has null array."); + } + return nda; + }; + TensorArrayMapBase.prototype.delete = function (tensor) { + delete this.dict[tensor.id]; + }; + TensorArrayMapBase.prototype.nullify = function (tensor) { + this.dict[tensor.id] = null; + }; + TensorArrayMapBase.prototype.disposeArray = function (tensor) { + if (this.dict[tensor.id] === undefined) { + return; + } + var nda = this.dict[tensor.id]; + if (nda === null) { + return; + } + nda.dispose(); + this.dict[tensor.id] = null; + }; + TensorArrayMapBase.prototype.size = function () { + return Object.keys(this.dict).length; + }; + TensorArrayMapBase.prototype.dispose = function () { + var _this = this; + Object.keys(this.dict).forEach(function (tensorID) { + var nda = _this.dict[+tensorID]; + if (nda) { + nda.dispose(); + } + }); + this.dict = {}; + }; + TensorArrayMapBase.prototype.hasNullArray = function (tensor) { + if (this.dict[tensor.id] === undefined) { + throw new Error("tensor " + tensor.id + " not in array map."); + } + return this.dict[tensor.id] === null; + }; + return TensorArrayMapBase; +}()); +exports.TensorArrayMapBase = TensorArrayMapBase; +var TensorArrayMap = (function (_super) { + __extends(TensorArrayMap, _super); + function TensorArrayMap() { + return _super !== null && _super.apply(this, arguments) || this; + } + TensorArrayMap.prototype.set = function (tensor, array) { + this.dict[tensor.id] = array; + }; + return TensorArrayMap; +}(TensorArrayMapBase)); +exports.TensorArrayMap = TensorArrayMap; +var SummedTensorArrayMap = (function (_super) { + __extends(SummedTensorArrayMap, _super); + function SummedTensorArrayMap(math) { + var _this = _super.call(this) || this; + _this.math = math; + return _this; + } + SummedTensorArrayMap.prototype.add = function (tensor, array) { + if (this.dict[tensor.id] == null) { + this.dict[tensor.id] = this.math.keep(array); + } + else { + var oldValue = this.get(tensor); + var newValue = this.math.keep(this.math.addStrict(oldValue, array)); + this.dict[tensor.id] = newValue; + oldValue.dispose(); + } + }; + return SummedTensorArrayMap; +}(TensorArrayMapBase)); +exports.SummedTensorArrayMap = SummedTensorArrayMap; + +},{}],50:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var session_1 = require("./graph/session"); +var ndarray_1 = require("./math/ndarray"); +var DEFAULT_EVAL_INTERVAL_MS = 1500; +var DEFAULT_COST_INTERVAL_MS = 500; +var DEFAULT_INFERENCE_EXAMPLE_INTERVAL_MS = 3000; +var MetricReduction; +(function (MetricReduction) { + MetricReduction[MetricReduction["SUM"] = 0] = "SUM"; + MetricReduction[MetricReduction["MEAN"] = 1] = "MEAN"; +})(MetricReduction = exports.MetricReduction || (exports.MetricReduction = {})); +var GraphRunner = (function () { + function GraphRunner(math, session, eventObserver) { + this.math = math; + this.session = session; + this.eventObserver = eventObserver; + this.lastCostTimestamp = 0; + this.lastEvalTimestamp = 0; + this.resetStatistics(); + this.zeroScalar = ndarray_1.Scalar.new(0); + } + GraphRunner.prototype.resetStatistics = function () { + this.totalBatchesTrained = 0; + }; + GraphRunner.prototype.train = function (costTensor, trainFeedEntries, batchSize, optimizer, numBatches, metricTensor, metricFeedEntries, metricBatchSize, metricReduction, evalIntervalMs, costIntervalMs) { + if (metricReduction === void 0) { metricReduction = MetricReduction.MEAN; } + if (evalIntervalMs === void 0) { evalIntervalMs = DEFAULT_EVAL_INTERVAL_MS; } + if (costIntervalMs === void 0) { costIntervalMs = DEFAULT_COST_INTERVAL_MS; } + this.costTensor = costTensor; + this.trainFeedEntries = trainFeedEntries; + this.metricTensor = metricTensor; + this.metricFeedEntries = metricFeedEntries; + if (metricBatchSize != null && this.metricBatchSize !== metricBatchSize) { + if (this.metricBatchSizeScalar != null) { + this.metricBatchSizeScalar.dispose(); + } + this.metricBatchSizeScalar = ndarray_1.Scalar.new(metricBatchSize); + } + this.metricBatchSize = metricBatchSize; + this.metricReduction = metricReduction; + this.batchSize = batchSize; + this.optimizer = optimizer; + this.metricIntervalMs = evalIntervalMs; + this.costIntervalMs = costIntervalMs; + this.currentTrainLoopNumBatches = numBatches; + this.batchesTrainedThisRun = 0; + this.isTraining = true; + this.trainStartTimestamp = performance.now(); + this.trainNetwork(); + }; + GraphRunner.prototype.stopTraining = function () { + this.isTraining = false; + }; + GraphRunner.prototype.resumeTraining = function () { + this.isTraining = true; + this.trainNetwork(); + }; + GraphRunner.prototype.trainNetwork = function () { + var _this = this; + if (this.batchesTrainedThisRun === this.currentTrainLoopNumBatches) { + this.stopTraining(); + } + if (!this.isTraining) { + if (this.eventObserver.doneTrainingCallback != null) { + this.eventObserver.doneTrainingCallback(); + } + return; + } + var start = performance.now(); + var shouldComputeCost = this.eventObserver.avgCostCallback != null && + (start - this.lastCostTimestamp > this.costIntervalMs); + if (shouldComputeCost) { + this.lastCostTimestamp = start; + } + var costReduction = shouldComputeCost ? session_1.CostReduction.MEAN : session_1.CostReduction.NONE; + this.math.scope(function (keep) { + var avgCost = _this.session.train(_this.costTensor, _this.trainFeedEntries, _this.batchSize, _this.optimizer, costReduction); + if (shouldComputeCost) { + var trainTime = performance.now() - start; + _this.eventObserver.avgCostCallback(avgCost); + if (_this.eventObserver.trainExamplesPerSecCallback != null) { + var examplesPerSec = (_this.batchSize * 1000 / trainTime); + _this.eventObserver.trainExamplesPerSecCallback(examplesPerSec); + } + } + if (_this.eventObserver.metricCallback != null && + _this.metricFeedEntries != null && + start - _this.lastEvalTimestamp > _this.metricIntervalMs) { + _this.lastEvalTimestamp = start; + if (_this.lastComputedMetric != null) { + _this.lastComputedMetric.dispose(); + } + _this.lastComputedMetric = _this.computeMetric(); + _this.eventObserver.metricCallback(_this.lastComputedMetric); + } + if (_this.eventObserver.totalTimeCallback != null) { + _this.eventObserver.totalTimeCallback((start - _this.trainStartTimestamp) / 1000); + } + _this.batchesTrainedThisRun++; + _this.totalBatchesTrained++; + if (_this.eventObserver.batchesTrainedCallback != null) { + _this.eventObserver.batchesTrainedCallback(_this.totalBatchesTrained); + } + }); + requestAnimationFrame(function () { return _this.trainNetwork(); }); + }; + GraphRunner.prototype.infer = function (inferenceTensor, inferenceFeedEntries, inferenceExampleIntervalMs, inferenceExampleCount, numPasses) { + var _this = this; + if (inferenceExampleIntervalMs === void 0) { inferenceExampleIntervalMs = DEFAULT_INFERENCE_EXAMPLE_INTERVAL_MS; } + if (inferenceExampleCount === void 0) { inferenceExampleCount = 5; } + if (this.eventObserver.inferenceExamplesCallback == null && + this.eventObserver.inferenceExamplesPerSecCallback == null) { + throw new Error('Cannot start inference loop, no inference example or ' + + 'examples/sec observer provided.'); + } + for (var i = 0; i < inferenceFeedEntries.length; i++) { + var feedEntry = inferenceFeedEntries[i]; + if (feedEntry.data instanceof ndarray_1.NDArray) { + throw new Error('Cannot start inference on the model runner with feed entries of ' + + 'type NDArray. Please use InputProviders.'); + } + } + this.inferenceExampleIntervalMs = inferenceExampleIntervalMs; + this.inferenceTensor = inferenceTensor; + this.inferenceFeedEntries = inferenceFeedEntries; + this.inferenceExampleCount = inferenceExampleCount; + this.currentInferenceLoopNumPasses = numPasses; + if (!this.isInferring) { + this.inferencePassesThisRun = 0; + requestAnimationFrame(function () { return _this.inferNetwork(); }); + } + this.isInferring = true; + }; + GraphRunner.prototype.inferNetwork = function () { + var _this = this; + if (!this.isInferring || + this.inferencePassesThisRun === this.currentInferenceLoopNumPasses) { + return; + } + this.math.scope(function (keep) { + var feeds = []; + var inferenceValues = []; + var start = performance.now(); + for (var i = 0; i < _this.inferenceExampleCount; i++) { + var ndarrayFeedEntries = []; + for (var j = 0; j < _this.inferenceFeedEntries.length; j++) { + var feedEntry = _this.inferenceFeedEntries[j]; + var nextCopy = feedEntry.data.getNextCopy(_this.math); + ndarrayFeedEntries.push({ tensor: feedEntry.tensor, data: nextCopy }); + } + feeds.push(ndarrayFeedEntries); + inferenceValues.push(_this.session.eval(_this.inferenceTensor, ndarrayFeedEntries)); + } + if (_this.eventObserver.inferenceExamplesPerSecCallback != null) { + inferenceValues[inferenceValues.length - 1].getValues(); + var inferenceExamplesPerSecTime = performance.now() - start; + var examplesPerSec = (_this.inferenceExampleCount * 1000 / inferenceExamplesPerSecTime); + _this.eventObserver.inferenceExamplesPerSecCallback(examplesPerSec); + } + if (_this.eventObserver.inferenceExamplesCallback != null) { + _this.eventObserver.inferenceExamplesCallback(feeds, inferenceValues); + } + _this.inferencePassesThisRun++; + }); + this.lastInferTimeoutID = window.setTimeout(function () { return _this.inferNetwork(); }, this.inferenceExampleIntervalMs); + }; + GraphRunner.prototype.stopInferring = function () { + this.isInferring = false; + window.clearTimeout(this.lastInferTimeoutID); + }; + GraphRunner.prototype.isInferenceRunning = function () { + return this.isInferring; + }; + GraphRunner.prototype.computeMetric = function () { + var _this = this; + if (this.metricFeedEntries == null) { + throw new Error('Cannot compute metric, no metric FeedEntries provided.'); + } + var metric = this.zeroScalar; + return this.math.scope(function (keep) { + for (var i = 0; i < _this.metricBatchSize; i++) { + var metricValue = _this.session.eval(_this.metricTensor, _this.metricFeedEntries); + metric = _this.math.add(metric, metricValue); + } + if (_this.metricReduction === MetricReduction.MEAN) { + metric = _this.math.divide(metric, _this.metricBatchSizeScalar); + } + return metric; + }); + }; + GraphRunner.prototype.getTotalBatchesTrained = function () { + return this.totalBatchesTrained; + }; + GraphRunner.prototype.getLastComputedMetric = function () { + return this.lastComputedMetric; + }; + GraphRunner.prototype.setMath = function (math) { + this.math = math; + }; + GraphRunner.prototype.setSession = function (session) { + this.session = session; + }; + GraphRunner.prototype.setInferenceTensor = function (inferenceTensor) { + this.inferenceTensor = inferenceTensor; + }; + GraphRunner.prototype.setInferenceExampleCount = function (inferenceExampleCount) { + this.inferenceExampleCount = inferenceExampleCount; + }; + return GraphRunner; +}()); +exports.GraphRunner = GraphRunner; + +},{"./graph/session":47,"./math/ndarray":95}],51:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var xhr_dataset = require("./data/xhr-dataset"); +exports.xhr_dataset = xhr_dataset; +var environment = require("./environment"); +exports.environment = environment; +var gpgpu_util = require("./math/backends/webgl/gpgpu_util"); +exports.gpgpu_util = gpgpu_util; +var render_ndarray_gpu_util = require("./math/backends/webgl/render_ndarray_gpu_util"); +exports.render_ndarray_gpu_util = render_ndarray_gpu_util; +var webgl_util = require("./math/backends/webgl/webgl_util"); +exports.webgl_util = webgl_util; +var conv_util = require("./math/conv_util"); +exports.conv_util = conv_util; +var test_util = require("./test_util"); +exports.test_util = test_util; +var util = require("./util"); +exports.util = util; +var version_1 = require("./version"); +exports.version = version_1.version; +var checkpoint_loader_1 = require("./data/checkpoint_loader"); +exports.CheckpointLoader = checkpoint_loader_1.CheckpointLoader; +var dataset_1 = require("./data/dataset"); +exports.InMemoryDataset = dataset_1.InMemoryDataset; +var input_provider_1 = require("./data/input_provider"); +exports.InCPUMemoryShuffledInputProviderBuilder = input_provider_1.InCPUMemoryShuffledInputProviderBuilder; +exports.InGPUMemoryShuffledInputProviderBuilder = input_provider_1.InGPUMemoryShuffledInputProviderBuilder; +var xhr_dataset_1 = require("./data/xhr-dataset"); +exports.XhrDataset = xhr_dataset_1.XhrDataset; +var environment_1 = require("./environment"); +exports.ENV = environment_1.ENV; +exports.Environment = environment_1.Environment; +var graph_1 = require("./graph/graph"); +exports.Graph = graph_1.Graph; +exports.Tensor = graph_1.Tensor; +var adadelta_optimizer_1 = require("./graph/optimizers/adadelta_optimizer"); +exports.AdadeltaOptimizer = adadelta_optimizer_1.AdadeltaOptimizer; +var adagrad_optimizer_1 = require("./graph/optimizers/adagrad_optimizer"); +exports.AdagradOptimizer = adagrad_optimizer_1.AdagradOptimizer; +var adam_optimizer_1 = require("./graph/optimizers/adam_optimizer"); +exports.AdamOptimizer = adam_optimizer_1.AdamOptimizer; +var adamax_optimizer_1 = require("./graph/optimizers/adamax_optimizer"); +exports.AdamaxOptimizer = adamax_optimizer_1.AdamaxOptimizer; +var momentum_optimizer_1 = require("./graph/optimizers/momentum_optimizer"); +exports.MomentumOptimizer = momentum_optimizer_1.MomentumOptimizer; +var optimizer_1 = require("./graph/optimizers/optimizer"); +exports.Optimizer = optimizer_1.Optimizer; +var rmsprop_optimizer_1 = require("./graph/optimizers/rmsprop_optimizer"); +exports.RMSPropOptimizer = rmsprop_optimizer_1.RMSPropOptimizer; +var sgd_optimizer_1 = require("./graph/optimizers/sgd_optimizer"); +exports.SGDOptimizer = sgd_optimizer_1.SGDOptimizer; +var session_1 = require("./graph/session"); +exports.CostReduction = session_1.CostReduction; +exports.Session = session_1.Session; +var graph_runner_1 = require("./graph_runner"); +exports.GraphRunner = graph_runner_1.GraphRunner; +exports.MetricReduction = graph_runner_1.MetricReduction; +var initializers_1 = require("./initializers"); +exports.ConstantInitializer = initializers_1.ConstantInitializer; +exports.NDArrayInitializer = initializers_1.NDArrayInitializer; +exports.OnesInitializer = initializers_1.OnesInitializer; +exports.RandomNormalInitializer = initializers_1.RandomNormalInitializer; +exports.RandomTruncatedNormalInitializer = initializers_1.RandomTruncatedNormalInitializer; +exports.RandomUniformInitializer = initializers_1.RandomUniformInitializer; +exports.VarianceScalingInitializer = initializers_1.VarianceScalingInitializer; +exports.ZerosInitializer = initializers_1.ZerosInitializer; +var backend_cpu_1 = require("./math/backends/backend_cpu"); +exports.MathBackendCPU = backend_cpu_1.MathBackendCPU; +exports.NDArrayMathCPU = backend_cpu_1.NDArrayMathCPU; +var backend_webgl_1 = require("./math/backends/backend_webgl"); +exports.MathBackendWebGL = backend_webgl_1.MathBackendWebGL; +exports.NDArrayMathGPU = backend_webgl_1.NDArrayMathGPU; +var matmul_1 = require("./math/backends/types/matmul"); +exports.MatrixOrientation = matmul_1.MatrixOrientation; +var gpgpu_context_1 = require("./math/backends/webgl/gpgpu_context"); +exports.GPGPUContext = gpgpu_context_1.GPGPUContext; +var math_1 = require("./math/math"); +exports.NDArrayMath = math_1.NDArrayMath; +var ndarray_1 = require("./math/ndarray"); +exports.Array1D = ndarray_1.Array1D; +exports.Array2D = ndarray_1.Array2D; +exports.Array3D = ndarray_1.Array3D; +exports.Array4D = ndarray_1.Array4D; +exports.NDArray = ndarray_1.NDArray; +exports.Scalar = ndarray_1.Scalar; + +},{"./data/checkpoint_loader":10,"./data/dataset":11,"./data/input_provider":12,"./data/xhr-dataset":13,"./environment":15,"./graph/graph":16,"./graph/optimizers/adadelta_optimizer":38,"./graph/optimizers/adagrad_optimizer":39,"./graph/optimizers/adam_optimizer":40,"./graph/optimizers/adamax_optimizer":41,"./graph/optimizers/momentum_optimizer":42,"./graph/optimizers/optimizer":43,"./graph/optimizers/rmsprop_optimizer":44,"./graph/optimizers/sgd_optimizer":45,"./graph/session":47,"./graph_runner":50,"./initializers":52,"./math/backends/backend_cpu":55,"./math/backends/backend_webgl":57,"./math/backends/types/matmul":61,"./math/backends/webgl/gpgpu_context":71,"./math/backends/webgl/gpgpu_util":73,"./math/backends/webgl/render_ndarray_gpu_util":80,"./math/backends/webgl/webgl_util":89,"./math/conv_util":92,"./math/math":94,"./math/ndarray":95,"./test_util":100,"./util":101,"./version":102}],52:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("./math/ndarray"); +var VarianceScalingInitializer = (function () { + function VarianceScalingInitializer(scale, mode, distribution) { + if (scale === void 0) { scale = 1.0; } + if (mode === void 0) { mode = 'fan_in'; } + if (distribution === void 0) { distribution = 'normal'; } + this.scale = scale; + this.mode = mode; + this.distribution = distribution; + } + VarianceScalingInitializer.prototype.initialize = function (weightsShape, inputUnits, outputUnits) { + var n = 0; + if (this.mode === 'fan_in') { + n = inputUnits; + } + else if (this.mode === 'fan_out') { + n = outputUnits; + } + else if (this.mode === 'fan_avg') { + n = (inputUnits + outputUnits) / 2; + } + else { + throw new Error("Unexpected mode for variance scaling initializer: " + this.mode); + } + if (this.distribution === 'normal') { + return ndarray_1.NDArray.randTruncatedNormal(weightsShape, 0.0, Math.sqrt(this.scale / n)); + } + else if (this.distribution === 'uniform') { + return ndarray_1.NDArray.randUniform(weightsShape, 0.0, Math.sqrt(3 * this.scale / n)); + } + else { + throw new Error("Unexpected distribution for variance scaling initializer: " + + ("" + this.distribution)); + } + }; + return VarianceScalingInitializer; +}()); +exports.VarianceScalingInitializer = VarianceScalingInitializer; +var ZerosInitializer = (function () { + function ZerosInitializer() { + } + ZerosInitializer.prototype.initialize = function (weightsShape, inputUnits, outputUnits) { + return ndarray_1.NDArray.zeros(weightsShape); + }; + return ZerosInitializer; +}()); +exports.ZerosInitializer = ZerosInitializer; +var OnesInitializer = (function () { + function OnesInitializer() { + } + OnesInitializer.prototype.initialize = function (weightsShape, inputUnits, outputUnits) { + var values = ndarray_1.NDArray.zeros(weightsShape); + values.fill(1); + return values; + }; + return OnesInitializer; +}()); +exports.OnesInitializer = OnesInitializer; +var ConstantInitializer = (function () { + function ConstantInitializer(value) { + if (value === void 0) { value = 0; } + this.value = value; + } + ConstantInitializer.prototype.initialize = function (weightsShape, inputUnits, outputUnits) { + var values = ndarray_1.NDArray.zeros(weightsShape); + values.fill(this.value); + return values; + }; + return ConstantInitializer; +}()); +exports.ConstantInitializer = ConstantInitializer; +var NDArrayInitializer = (function () { + function NDArrayInitializer(ndarray) { + this.ndarray = ndarray; + } + NDArrayInitializer.prototype.initialize = function (weightsShape, inputUnits, outputUnits) { + return this.ndarray; + }; + return NDArrayInitializer; +}()); +exports.NDArrayInitializer = NDArrayInitializer; +var RandomNormalInitializer = (function () { + function RandomNormalInitializer(mean, stdev) { + if (mean === void 0) { mean = 0; } + if (stdev === void 0) { stdev = .05; } + this.mean = mean; + this.stdev = stdev; + } + RandomNormalInitializer.prototype.initialize = function (weightsShape, inputUnits, outputUnits) { + return ndarray_1.NDArray.randNormal(weightsShape, this.mean, this.stdev); + }; + return RandomNormalInitializer; +}()); +exports.RandomNormalInitializer = RandomNormalInitializer; +var RandomTruncatedNormalInitializer = (function () { + function RandomTruncatedNormalInitializer(mean, stdev) { + if (mean === void 0) { mean = 0; } + if (stdev === void 0) { stdev = .05; } + this.mean = mean; + this.stdev = stdev; + } + RandomTruncatedNormalInitializer.prototype.initialize = function (weightsShape, inputUnits, outputUnits) { + return ndarray_1.NDArray.randTruncatedNormal(weightsShape, this.mean, this.stdev); + }; + return RandomTruncatedNormalInitializer; +}()); +exports.RandomTruncatedNormalInitializer = RandomTruncatedNormalInitializer; +var RandomUniformInitializer = (function () { + function RandomUniformInitializer(minval, maxval) { + if (minval === void 0) { minval = -.05; } + if (maxval === void 0) { maxval = .05; } + this.minval = minval; + this.maxval = maxval; + } + RandomUniformInitializer.prototype.initialize = function (weightsShape, inputUnits, outputUnits) { + return ndarray_1.NDArray.randUniform(weightsShape, this.minval, this.maxval); + }; + return RandomUniformInitializer; +}()); +exports.RandomUniformInitializer = RandomUniformInitializer; + +},{"./math/ndarray":95}],53:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("./ndarray"); +var TanHFunc = (function () { + function TanHFunc() { + this.one = ndarray_1.Scalar.new(1); + } + TanHFunc.prototype.output = function (math, x) { + return math.tanh(x); + }; + TanHFunc.prototype.der = function (math, x, y) { + var _this = this; + return math.scope(function () { + var ySquared = math.elementWiseMul(y, y); + return math.scalarMinusArray(_this.one, ySquared); + }); + }; + TanHFunc.prototype.dispose = function () { + this.one.dispose(); + }; + return TanHFunc; +}()); +exports.TanHFunc = TanHFunc; +var ReLUFunc = (function () { + function ReLUFunc() { + } + ReLUFunc.prototype.output = function (math, x) { + return math.relu(x); + }; + ReLUFunc.prototype.der = function (math, x, y) { + return math.step(x); + }; + ReLUFunc.prototype.dispose = function () { }; + return ReLUFunc; +}()); +exports.ReLUFunc = ReLUFunc; +var LeakyReluFunc = (function () { + function LeakyReluFunc(alpha) { + this.alpha = alpha; + } + LeakyReluFunc.prototype.output = function (math, x) { + return math.leakyRelu(x, this.alpha); + }; + LeakyReluFunc.prototype.der = function (math, x, y) { + return math.step(x, this.alpha); + }; + LeakyReluFunc.prototype.dispose = function () { }; + return LeakyReluFunc; +}()); +exports.LeakyReluFunc = LeakyReluFunc; +var SigmoidFunc = (function () { + function SigmoidFunc() { + } + SigmoidFunc.prototype.output = function (math, x) { + return math.sigmoid(x); + }; + SigmoidFunc.prototype.der = function (math, x, y) { + return math.scope(function () { + var ySquared = math.elementWiseMul(y, y); + return math.subStrict(y, ySquared); + }); + }; + SigmoidFunc.prototype.dispose = function () { }; + return SigmoidFunc; +}()); +exports.SigmoidFunc = SigmoidFunc; +var SquareFunc = (function () { + function SquareFunc() { + this.two = ndarray_1.Scalar.new(2); + } + SquareFunc.prototype.output = function (math, x) { + return math.elementWiseMul(x, x); + }; + SquareFunc.prototype.der = function (math, x, y) { + return math.scalarTimesArray(this.two, x); + }; + SquareFunc.prototype.dispose = function () { + this.two.dispose(); + }; + return SquareFunc; +}()); +exports.SquareFunc = SquareFunc; +var EluFunc = (function () { + function EluFunc() { + } + EluFunc.prototype.output = function (math, x) { + return math.elu(x); + }; + EluFunc.prototype.der = function (math, x, y) { + return math.eluDer(x); + }; + EluFunc.prototype.dispose = function () { }; + return EluFunc; +}()); +exports.EluFunc = EluFunc; + +},{"./ndarray":95}],54:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function axesAreInnerMostDims(axes, rank) { + for (var i = 0; i < axes.length; ++i) { + if (axes[axes.length - i - 1] !== rank - 1 - i) { + return false; + } + } + return true; +} +exports.axesAreInnerMostDims = axesAreInnerMostDims; +function combineLocations(outputLoc, reduceLoc, axes) { + var rank = outputLoc.length + reduceLoc.length; + var loc = []; + var outIdx = 0; + var reduceIdx = 0; + for (var dim = 0; dim < rank; dim++) { + if (axes.indexOf(dim) === -1) { + loc.push(outputLoc[outIdx++]); + } + else { + loc.push(reduceLoc[reduceIdx++]); + } + } + return loc; +} +exports.combineLocations = combineLocations; +function computeOutAndReduceShapes(aShape, axes) { + var outShape = []; + var rank = aShape.length; + for (var dim = 0; dim < rank; dim++) { + if (axes.indexOf(dim) === -1) { + outShape.push(aShape[dim]); + } + } + var reduceShape = axes.map(function (dim) { return aShape[dim]; }); + return [outShape, reduceShape]; +} +exports.computeOutAndReduceShapes = computeOutAndReduceShapes; +function expandShapeToKeepDim(shape, axes) { + var reduceSubShape = axes.map(function (x) { return 1; }); + return combineLocations(shape, reduceSubShape, axes); +} +exports.expandShapeToKeepDim = expandShapeToKeepDim; +function parseAxisParam(axis, shape) { + if (axis == null) { + axis = shape.map(function (s, i) { return i; }); + } + else if (typeof (axis) === 'number') { + axis = [axis]; + } + return axis; +} +exports.parseAxisParam = parseAxisParam; +function assertAxesAreInnerMostDims(msg, axes, rank) { + if (!axesAreInnerMostDims(axes, rank)) { + throw new Error(msg + " supports only inner-most axes for now. " + + ("Got axes " + axes + " and rank-" + rank + " input.")); + } +} +exports.assertAxesAreInnerMostDims = assertAxesAreInnerMostDims; +function getPermutedAxes(axes, rank) { + if (axesAreInnerMostDims(axes, rank)) { + return null; + } + var result = []; + for (var i = 0; i < rank; ++i) { + if (axes.indexOf(i) === -1) { + result.push(i); + } + } + axes.forEach(function (axis) { return result.push(axis); }); + return result; +} +exports.getPermutedAxes = getPermutedAxes; +function getInnerMostAxes(numAxes, rank) { + var res = []; + for (var i = rank - numAxes; i < rank; ++i) { + res.push(i); + } + return res; +} +exports.getInnerMostAxes = getInnerMostAxes; + +},{}],55:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var seedrandom = require("seedrandom"); +var environment_1 = require("../../environment"); +var util = require("../../util"); +var broadcast_util = require("../broadcast_util"); +var concat_util = require("../concat_util"); +var math_1 = require("../math"); +var ndarray_1 = require("../ndarray"); +var types = require("../types"); +var types_1 = require("../types"); +var axis_util = require("./../axis_util"); +var matmul_1 = require("./types/matmul"); +var MathBackendCPU = (function () { + function MathBackendCPU() { + this.data = {}; + } + MathBackendCPU.prototype.dispose = function () { }; + MathBackendCPU.prototype.write = function (id, values, dtype, shape) { + this.data[id] = values; + }; + MathBackendCPU.prototype.writePixels = function (id, pixels, numChannels) { + var vals; + if (pixels instanceof ImageData) { + vals = pixels.data; + } + else if (pixels instanceof HTMLCanvasElement) { + vals = pixels.getContext('2d') + .getImageData(0, 0, pixels.width, pixels.height) + .data; + } + else if (pixels instanceof HTMLImageElement || + pixels instanceof HTMLVideoElement) { + var canvas = document.createElement('canvas'); + canvas.width = pixels.width; + canvas.height = pixels.height; + canvas.getContext('2d').drawImage(pixels, 0, 0, canvas.width, canvas.height); + vals = canvas.getContext('2d') + .getImageData(0, 0, canvas.width, canvas.height) + .data; + } + else { + throw new Error("pixels is of unknown type: " + pixels.constructor.name); + } + var values; + if (numChannels === 4) { + values = new Int32Array(vals); + } + else { + var numPixels = pixels.width * pixels.height; + values = new Int32Array(numPixels * numChannels); + for (var i = 0; i < numPixels; i++) { + for (var channel = 0; channel < numChannels; ++channel) { + values[i * numChannels + channel] = vals[i * 4 + channel]; + } + } + } + this.data[id] = values; + }; + MathBackendCPU.prototype.read = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + this.throwIfNoData(id); + return [2, this.data[id]]; + }); + }); + }; + MathBackendCPU.prototype.readSync = function (id) { + this.throwIfNoData(id); + return this.data[id]; + }; + MathBackendCPU.prototype.disposeData = function (id) { + delete this.data[id]; + }; + MathBackendCPU.prototype.time = function (query) { + return __awaiter(this, void 0, void 0, function () { + var start; + return __generator(this, function (_a) { + start = performance.now(); + query(); + return [2, performance.now() - start]; + }); + }); + }; + MathBackendCPU.prototype.throwIfNoData = function (id) { + if (!(id in this.data)) { + throw new Error("No data found for NDArray with id " + id + ". " + + "Use dl.ENV.math instead of constructing your own NDArrayMath. " + + "If you need to construct your own math, make sure this array is " + + "allocated after the math construction"); + } + }; + MathBackendCPU.prototype.clone = function (x) { + return ndarray_1.NDArray.make(x.shape, { values: new Float32Array(x.getValues()) }); + }; + MathBackendCPU.prototype.slice1D = function (x, begin, size) { + var newVals = x.getValues().slice(begin, begin + size); + return ndarray_1.Array1D.new(newVals); + }; + MathBackendCPU.prototype.slice2D = function (x, begin, size) { + var result = ndarray_1.Array2D.zeros(size); + var startI = begin[0], startJ = begin[1]; + for (var i = 0; i < size[0]; ++i) { + for (var j = 0; j < size[1]; ++j) { + var val = x.get(i + startI, j + startJ); + result.set(val, i, j); + } + } + return result; + }; + MathBackendCPU.prototype.slice3D = function (x, begin, size) { + var result = ndarray_1.Array3D.zeros(size); + var startI = begin[0], startJ = begin[1], startK = begin[2]; + for (var i = 0; i < size[0]; ++i) { + for (var j = 0; j < size[1]; ++j) { + for (var k = 0; k < size[2]; ++k) { + var val = x.get(i + startI, j + startJ, k + startK); + result.set(val, i, j, k); + } + } + } + return result; + }; + MathBackendCPU.prototype.slice4D = function (x, begin, size) { + var result = ndarray_1.Array4D.zeros(size); + var startI = begin[0], startJ = begin[1], startK = begin[2], startL = begin[3]; + for (var i = 0; i < size[0]; ++i) { + for (var j = 0; j < size[1]; ++j) { + for (var k = 0; k < size[2]; ++k) { + for (var l = 0; l < size[3]; ++l) { + var val = x.get(i + startI, j + startJ, k + startK, l + startL); + result.set(val, i, j, k, l); + } + } + } + } + return result; + }; + MathBackendCPU.prototype.concat1D = function (a, b) { + var outShape = concat_util.computeOutShape(a.shape, b.shape, 0); + var result = ndarray_1.Array1D.zeros(outShape); + var aVals = a.getValues(); + var bVals = b.getValues(); + var vals = result.getValues(); + vals.set(aVals, 0); + vals.set(bVals, a.size); + return result; + }; + MathBackendCPU.prototype.concat2D = function (a, b, axis) { + var outShape = concat_util.computeOutShape(a.shape, b.shape, axis); + var result = ndarray_1.Array2D.zeros(outShape); + if (axis === 0) { + var aVals = a.getValues(); + var bVals = b.getValues(); + var vals = result.getValues(); + vals.set(aVals, 0); + vals.set(bVals, a.size); + return result; + } + for (var i = 0; i < outShape[0]; ++i) { + for (var j = 0; j < outShape[1]; ++j) { + var index = [i, j]; + var value = void 0; + if (index[axis] < a.shape[axis]) { + value = a.get(i, j); + } + else { + index[axis] -= a.shape[axis]; + var i2 = index[0], j2 = index[1]; + value = b.get(i2, j2); + } + result.set(value, i, j); + } + } + return result; + }; + MathBackendCPU.prototype.concat3D = function (a, b, axis) { + var outShape = concat_util.computeOutShape(a.shape, b.shape, axis); + var result = ndarray_1.Array3D.zeros(outShape); + if (axis === 0) { + var aVals = a.getValues(); + var bVals = b.getValues(); + var vals = result.getValues(); + vals.set(aVals, 0); + vals.set(bVals, a.size); + return result; + } + for (var i = 0; i < outShape[0]; ++i) { + for (var j = 0; j < outShape[1]; ++j) { + for (var k = 0; k < outShape[2]; ++k) { + var index = [i, j, k]; + var value = void 0; + if (index[axis] < a.shape[axis]) { + value = a.get(i, j, k); + } + else { + index[axis] -= a.shape[axis]; + var i2 = index[0], j2 = index[1], k2 = index[2]; + value = b.get(i2, j2, k2); + } + result.set(value, i, j, k); + } + } + } + return result; + }; + MathBackendCPU.prototype.concat4D = function (a, b, axis) { + var outShape = concat_util.computeOutShape(a.shape, b.shape, axis); + var result = ndarray_1.Array4D.zeros(outShape); + if (axis === 0) { + var aVals = a.getValues(); + var bVals = b.getValues(); + var vals = result.getValues(); + vals.set(aVals, 0); + vals.set(bVals, a.size); + return result; + } + for (var i = 0; i < outShape[0]; ++i) { + for (var j = 0; j < outShape[1]; ++j) { + for (var k = 0; k < outShape[2]; ++k) { + for (var l = 0; l < outShape[3]; ++l) { + var index = [i, j, k, l]; + var value = void 0; + if (index[axis] < a.shape[axis]) { + value = a.get(i, j, k, l); + } + else { + index[axis] -= a.shape[axis]; + var i2 = index[0], j2 = index[1], k2 = index[2], l2 = index[3]; + value = b.get(i2, j2, k2, l2); + } + result.set(value, i, j, k, l); + } + } + } + } + return result; + }; + MathBackendCPU.prototype.neg = function (x) { + return this.multiply(ndarray_1.Scalar.new(-1), x); + }; + MathBackendCPU.prototype.add = function (a, b) { + return this.broadcastedBinaryOp(a, b, types.upcastType(a.dtype, b.dtype), function (aValue, bValue) { return aValue + bValue; }); + }; + MathBackendCPU.prototype.subtract = function (a, b) { + return this.broadcastedBinaryOp(a, b, types.upcastType(a.dtype, b.dtype), function (aValue, bValue) { return aValue - bValue; }); + }; + MathBackendCPU.prototype.pow = function (a, b) { + return this.broadcastedBinaryOp(a, b, a.dtype, function (aValue, bValue) { return Math.pow(aValue, bValue); }); + }; + MathBackendCPU.prototype.matMul = function (a, b, aOrientation, bOrientation) { + if (aOrientation === void 0) { aOrientation = matmul_1.MatrixOrientation.REGULAR; } + if (bOrientation === void 0) { bOrientation = matmul_1.MatrixOrientation.REGULAR; } + var sharedDim = (aOrientation === matmul_1.MatrixOrientation.REGULAR) ? a.shape[1] : a.shape[0]; + var leftDim = (aOrientation === matmul_1.MatrixOrientation.REGULAR) ? a.shape[0] : a.shape[1]; + var rightDim = (bOrientation === matmul_1.MatrixOrientation.REGULAR) ? b.shape[1] : b.shape[0]; + var normalGetter = function (matrix, i, j) { + return matrix.get(i, j); + }; + var transposedGetter = function (matrix, i, j) { + return matrix.get(j, i); + }; + var aGetter = (aOrientation === matmul_1.MatrixOrientation.REGULAR) ? + normalGetter : + transposedGetter; + var bGetter = (bOrientation === matmul_1.MatrixOrientation.REGULAR) ? + normalGetter : + transposedGetter; + var values = new Float32Array(leftDim * rightDim); + var index = 0; + for (var i = 0; i < leftDim; ++i) { + for (var j = 0; j < rightDim; ++j) { + var sum = 0; + for (var k = 0; k < sharedDim; ++k) { + sum += aGetter(a, i, k) * bGetter(b, k, j); + } + values[index++] = sum; + } + } + return ndarray_1.Array2D.new([leftDim, rightDim], values); + }; + MathBackendCPU.prototype.multiply = function (a, b) { + return this.broadcastedBinaryOp(a, b, a.dtype, function (aValue, bValue) { return aValue * bValue; }); + }; + MathBackendCPU.prototype.divide = function (a, b) { + return this.broadcastedBinaryOp(a, b, 'float32', function (aValue, bValue) { return aValue / bValue; }); + }; + MathBackendCPU.prototype.sum = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('sum', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var resultDtype = types_1.SumTypesMap[x.dtype]; + var result = ndarray_1.NDArray.zeros(outShape, resultDtype); + var reduceSize = util.sizeFromShape(reduceShape); + var vals = result.getValues(); + var aVals = x.getValues(); + for (var i = 0; i < vals.length; ++i) { + var offset = i * reduceSize; + var sum = 0; + for (var j = 0; j < reduceSize; ++j) { + sum += aVals[offset + j]; + } + vals[i] = sum; + } + return result; + }; + MathBackendCPU.prototype.argMin = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('argMin', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var result = ndarray_1.NDArray.zeros(outShape, 'int32'); + var reduceSize = util.sizeFromShape(reduceShape); + var vals = result.getValues(); + var aVals = x.getValues(); + for (var i = 0; i < vals.length; ++i) { + var offset = i * reduceSize; + var min = aVals[offset]; + var minIndex = 0; + for (var j = 0; j < reduceSize; ++j) { + var value = aVals[offset + j]; + if (isNaN(value)) { + minIndex = util.NAN_INT32; + break; + } + if (value < min) { + min = value; + minIndex = j; + } + } + vals[i] = minIndex; + } + return result; + }; + MathBackendCPU.prototype.argMax = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('argMax', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var result = ndarray_1.NDArray.zeros(outShape, 'int32'); + var reduceSize = util.sizeFromShape(reduceShape); + var vals = result.getValues(); + var aVals = x.getValues(); + for (var i = 0; i < vals.length; ++i) { + var offset = i * reduceSize; + var max = aVals[offset]; + var maxIndex = 0; + for (var j = 0; j < reduceSize; ++j) { + var value = aVals[offset + j]; + if (isNaN(value)) { + maxIndex = util.NAN_INT32; + break; + } + if (value > max) { + max = value; + maxIndex = j; + } + } + vals[i] = maxIndex; + } + return result; + }; + MathBackendCPU.prototype.equal = function (a, b) { + return this.broadcastedBinaryOp(a, b, 'bool', function (aVal, bVal) { + if (util.isValNaN(aVal, a.dtype) || util.isValNaN(bVal, b.dtype)) { + return util.getNaN('bool'); + } + else { + return (aVal === bVal) ? 1 : 0; + } + }); + }; + MathBackendCPU.prototype.topKValues = function (x, k) { + return this.topK(x, k).values; + }; + MathBackendCPU.prototype.topKIndices = function (x, k) { + return this.topK(x, k).indices; + }; + MathBackendCPU.prototype.topK = function (x, k) { + var values = x.getValues(); + var valuesAndIndices = []; + for (var i = 0; i < values.length; i++) { + valuesAndIndices.push({ value: values[i], index: i }); + } + valuesAndIndices.sort(function (a, b) { + return b.value - a.value; + }); + var topkValues = util.getTypedArrayFromDType(x.dtype, k); + var topkIndices = new Int32Array(k); + for (var i = 0; i < k; i++) { + topkValues[i] = valuesAndIndices[i].value; + topkIndices[i] = valuesAndIndices[i].index; + } + return { + values: ndarray_1.Array1D.new(topkValues), + indices: ndarray_1.Array1D.new(topkIndices) + }; + }; + MathBackendCPU.prototype.min = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('min', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var result = ndarray_1.NDArray.zeros(outShape, x.dtype); + var reduceSize = util.sizeFromShape(reduceShape); + var vals = result.getValues(); + var aVals = x.getValues(); + for (var i = 0; i < vals.length; ++i) { + var offset = i * reduceSize; + var min = aVals[0]; + for (var j = 0; j < reduceSize; ++j) { + var value = aVals[offset + j]; + if (isNaN(value)) { + min = Number.NaN; + break; + } + if (value < min) { + min = value; + } + } + vals[i] = min; + } + return result; + }; + MathBackendCPU.prototype.max = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('max', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var result = ndarray_1.NDArray.zeros(outShape, x.dtype); + var reduceSize = util.sizeFromShape(reduceShape); + var vals = result.getValues(); + var aVals = x.getValues(); + for (var i = 0; i < vals.length; ++i) { + var offset = i * reduceSize; + var max = aVals[offset]; + for (var j = 0; j < reduceSize; ++j) { + var value = aVals[offset + j]; + if (isNaN(value)) { + max = Number.NaN; + break; + } + if (value > max) { + max = value; + } + } + vals[i] = max; + } + return result; + }; + MathBackendCPU.prototype.ceil = function (x) { + var values = x.getValues(); + var newValues = new Float32Array(values.length); + for (var i = 0; i < values.length; ++i) { + newValues[i] = Math.ceil(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: newValues }); + }; + MathBackendCPU.prototype.floor = function (x) { + var values = x.getValues(); + var newValues = new Float32Array(values.length); + for (var i = 0; i < values.length; ++i) { + newValues[i] = Math.floor(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: newValues }); + }; + MathBackendCPU.prototype.exp = function (x) { + var values = x.getValues(); + var newValues = new Float32Array(values.length); + for (var i = 0; i < values.length; ++i) { + newValues[i] = Math.exp(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: newValues }); + }; + MathBackendCPU.prototype.log = function (x) { + var values = x.getValues(); + var newValues = new Float32Array(values.length); + for (var i = 0; i < values.length; ++i) { + var value = values[i]; + newValues[i] = Math.log(value); + } + return ndarray_1.NDArray.make(x.shape, { values: newValues }); + }; + MathBackendCPU.prototype.sqrt = function (x) { + var values = x.getValues(); + var newValues = new Float32Array(values.length); + for (var i = 0; i < values.length; ++i) { + var value = values[i]; + newValues[i] = Math.sqrt(value); + } + return ndarray_1.NDArray.make(x.shape, { values: newValues }); + }; + MathBackendCPU.prototype.square = function (x) { + var values = x.getValues(); + var newValues = new Float32Array(values.length); + for (var i = 0; i < values.length; ++i) { + var value = values[i]; + newValues[i] = value * value; + } + return ndarray_1.NDArray.make(x.shape, { values: newValues }); + }; + MathBackendCPU.prototype.relu = function (x) { + var res = ndarray_1.NDArray.zeros(x.shape, x.dtype); + var resVals = res.getValues(); + var inVals = x.getValues(); + for (var i = 0; i < inVals.length; ++i) { + var val = inVals[i]; + if (util.isValNaN(val, x.dtype)) { + resVals[i] = util.getNaN(res.dtype); + } + else { + resVals[i] = Math.max(0, inVals[i]); + } + } + return res; + }; + MathBackendCPU.prototype.elu = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.dataSync(); + for (var i = 0; i < values.length; ++i) { + var v = values[i]; + if (v >= 0) { + resultValues[i] = v; + } + else { + resultValues[i] = (Math.exp(v) - 1); + } + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.eluDer = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.dataSync(); + for (var i = 0; i < values.length; ++i) { + var v = values[i]; + if (v >= 0) { + resultValues[i] = 1; + } + else { + resultValues[i] = Math.exp(v); + } + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.selu = function (x) { + var scaleAlpha = 1.7580993408473768599402175208123; + var scale = 1.0507009873554804934193349852946; + var resultValues = new Float32Array(x.size); + var values = x.dataSync(); + for (var i = 0; i < values.length; ++i) { + var v = values[i]; + if (v >= 0) { + resultValues[i] = scale * v; + } + else { + resultValues[i] = scaleAlpha * (Math.exp(v) - 1); + } + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.leakyRelu = function (x, alpha) { + var resultValues = new Float32Array(x.size); + var values = x.dataSync(); + for (var i = 0; i < values.length; i++) { + var v = values[i]; + if (v >= 0) { + resultValues[i] = v; + } + else { + resultValues[i] = alpha * v; + } + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.prelu = function (x, alpha) { + var resultValues = new Float32Array(x.size); + var values = x.dataSync(); + var alphas = alpha.dataSync(); + for (var i = 0; i < values.length; i++) { + var v = values[i]; + if (v >= 0) { + resultValues[i] = v; + } + else { + resultValues[i] = alphas[i] * v; + } + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.preluDer = function (x, alpha) { + var resultValues = new Float32Array(x.size); + var values = x.dataSync(); + var alphas = alpha.dataSync(); + for (var i = 0; i < values.length; i++) { + var v = values[i]; + if (v > 0) { + resultValues[i] = 1; + } + else if (v < 0) { + resultValues[i] = alphas[i]; + } + else { + resultValues[i] = v; + } + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.clip = function (x, min, max) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.min(max, Math.max(min, values[i])); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.abs = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.abs(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.sigmoid = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = 1 / (1 + Math.exp(-values[i])); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.sin = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.sin(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.cos = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.cos(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.tan = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.tan(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.asin = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.asin(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.acos = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.acos(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.atan = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.atan(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.sinh = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.sinh(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.cosh = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = Math.cosh(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.tanh = function (x) { + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + resultValues[i] = util.tanh(values[i]); + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.step = function (x, alpha) { + if (alpha === void 0) { alpha = 0; } + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + for (var i = 0; i < values.length; ++i) { + var value = values[i]; + if (util.isValNaN(value, x.dtype)) { + resultValues[i] = util.getNaN(x.dtype); + } + else { + resultValues[i] = value > 0 ? 1 : alpha; + } + } + return ndarray_1.NDArray.make(x.shape, { values: resultValues }); + }; + MathBackendCPU.prototype.conv2d = function (x, filter, bias, convInfo) { + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var padLeft = convInfo.padInfo.left; + var padTop = convInfo.padInfo.top; + var y = ndarray_1.Array4D.zeros(convInfo.outShape); + for (var b = 0; b < convInfo.batchSize; ++b) { + for (var d2 = 0; d2 < convInfo.outChannels; ++d2) { + for (var yR = 0; yR < convInfo.outHeight; ++yR) { + var xRCorner = yR * convInfo.strideHeight - padLeft; + var xRMin = Math.max(0, xRCorner); + var xRMax = Math.min(convInfo.inHeight, filterHeight + xRCorner); + for (var yC = 0; yC < convInfo.outWidth; ++yC) { + var xCCorner = yC * convInfo.strideWidth - padTop; + var xCMin = Math.max(0, xCCorner); + var xCMax = Math.min(convInfo.inWidth, filterWidth + xCCorner); + var dotProd = 0; + for (var xR = xRMin; xR < xRMax; ++xR) { + var wR = xR - xRCorner; + for (var xC = xCMin; xC < xCMax; ++xC) { + var wC = xC - xCCorner; + for (var d1 = 0; d1 < convInfo.inChannels; ++d1) { + var pixel = x.get(b, xR, xC, d1); + var weight = filter.get(wR, wC, d1, d2); + dotProd += pixel * weight; + } + } + } + var biasVal = (bias != null) ? bias.get(d2) : 0; + y.set(dotProd + biasVal, b, yR, yC, d2); + } + } + } + } + return y; + }; + MathBackendCPU.prototype.conv2dDerInput = function (dy, filter, convInfo) { + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var topPad = filterHeight - 1 - convInfo.padInfo.top; + var leftPad = filterWidth - 1 - convInfo.padInfo.left; + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var dx = ndarray_1.Array4D.zeros(convInfo.inShape); + for (var b = 0; b < convInfo.batchSize; ++b) { + for (var d1 = 0; d1 < convInfo.inChannels; ++d1) { + for (var xR = 0; xR < convInfo.inHeight; ++xR) { + var xRCorner = xR - leftPad; + var xRMin = Math.max(0, Math.ceil(xRCorner / strideHeight)); + var yRMax = Math.min(convInfo.outHeight, (filterHeight + xRCorner) / strideHeight); + for (var xC = 0; xC < convInfo.inWidth; ++xC) { + var xCCorner = xC - topPad; + var xCMin = Math.max(0, Math.ceil(xCCorner / strideWidth)); + var yCMax = Math.min(convInfo.outWidth, (filterWidth + xCCorner) / strideWidth); + var dotProd = 0; + for (var yR = xRMin; yR < yRMax; ++yR) { + var wR = yR * strideHeight - xRCorner; + for (var yC = xCMin; yC < yCMax; ++yC) { + var wC = yC * strideWidth - xCCorner; + for (var d2 = 0; d2 < convInfo.outChannels; ++d2) { + var pixel = dy.get(b, yR, yC, d2); + var weight = filter.get(filterHeight - 1 - wR, filterWidth - 1 - wC, d1, d2); + dotProd += pixel * weight; + } + } + } + dx.set(dotProd, b, xR, xC, d1); + } + } + } + } + return dx; + }; + MathBackendCPU.prototype.conv2dDerFilter = function (x, dy, convInfo) { + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var dW = ndarray_1.Array4D.zeros(convInfo.filterShape); + var leftPad = convInfo.padInfo.left; + var topPad = convInfo.padInfo.top; + for (var wR = 0; wR < filterHeight; ++wR) { + var yRMin = Math.max(0, Math.ceil((topPad - wR) / strideHeight)); + var yRMax = Math.min(convInfo.outHeight, (convInfo.inHeight + topPad - wR) / strideHeight); + for (var wC = 0; wC < filterWidth; ++wC) { + var yCMin = Math.max(0, Math.ceil((leftPad - wC) / strideWidth)); + var yCMax = Math.min(convInfo.outWidth, (convInfo.inWidth + leftPad - wC) / strideWidth); + for (var d1 = 0; d1 < convInfo.inChannels; ++d1) { + for (var d2 = 0; d2 < convInfo.outChannels; ++d2) { + var dotProd = 0; + for (var b = 0; b < convInfo.batchSize; ++b) { + for (var yR = yRMin; yR < yRMax; ++yR) { + var xR = wR + yR * strideHeight - topPad; + for (var yC = yCMin; yC < yCMax; ++yC) { + var xC = wC + yC * strideWidth - leftPad; + dotProd += x.get(b, xR, xC, d1) * dy.get(b, yR, yC, d2); + } + } + } + dW.set(dotProd, wR, wC, d1, d2); + } + } + } + } + return dW; + }; + MathBackendCPU.prototype.conv2dDerBias = function (dy) { + var _a = dy.shape, batchSize = _a[0], numRows = _a[1], numCols = _a[2], outDepth = _a[3]; + var values = new Float32Array(outDepth); + for (var d2 = 0; d2 < outDepth; ++d2) { + var sum = 0; + for (var b = 0; b < batchSize; ++b) { + for (var r = 0; r < numRows; ++r) { + for (var c = 0; c < numCols; ++c) { + sum += dy.get(b, r, c, d2); + } + } + } + values[d2] = sum; + } + return ndarray_1.Array1D.new(values); + }; + MathBackendCPU.prototype.depthwiseConv2D = function (x, filter, convInfo) { + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var padLeft = convInfo.padInfo.left; + var padTop = convInfo.padInfo.top; + var chMul = convInfo.outChannels / convInfo.inChannels; + var y = ndarray_1.Array4D.zeros(convInfo.outShape); + for (var b = 0; b < convInfo.batchSize; ++b) { + for (var d1 = 0; d1 < convInfo.inChannels; ++d1) { + for (var yR = 0; yR < convInfo.outHeight; ++yR) { + var xRCorner = yR * convInfo.strideHeight - padLeft; + var xRMin = Math.max(0, xRCorner); + var xRMax = Math.min(convInfo.inHeight, filterHeight + xRCorner); + for (var yC = 0; yC < convInfo.outWidth; ++yC) { + var xCCorner = yC * convInfo.strideWidth - padTop; + var xCMin = Math.max(0, xCCorner); + var xCMax = Math.min(convInfo.inWidth, filterWidth + xCCorner); + for (var q = 0; q < chMul; ++q) { + var dotProd = 0; + for (var xR = xRMin; xR < xRMax; ++xR) { + var wR = xR - xRCorner; + for (var xC = xCMin; xC < xCMax; ++xC) { + var wC = xC - xCCorner; + var pixel = x.get(b, xR, xC, d1); + var weight = filter.get(wR, wC, d1, q); + dotProd += pixel * weight; + } + } + y.set(dotProd, b, yR, yC, d1 * chMul + q); + } + } + } + } + } + return y; + }; + MathBackendCPU.prototype.tile = function (x, reps) { + var newShape = new Array(x.rank); + for (var i = 0; i < newShape.length; i++) { + newShape[i] = x.shape[i] * reps[i]; + } + var dtype; + if (x.dtype === 'float32') { + dtype = Float32Array; + } + else if (x.dtype === 'int32') { + dtype = Int32Array; + } + else if (x.dtype === 'bool') { + dtype = Uint8Array; + } + else { + throw new Error("Dtype " + x.dtype + " not supported for tile"); + } + var resultValues = new dtype(util.sizeFromShape(newShape)); + var result = ndarray_1.NDArray.make(newShape, { values: resultValues }, x.dtype); + var values = x.getValues(); + for (var i = 0; i < result.size; ++i) { + var newLoc = result.indexToLoc(i); + var originalLoc = new Array(x.rank); + for (var i_1 = 0; i_1 < originalLoc.length; i_1++) { + originalLoc[i_1] = newLoc[i_1] % x.shape[i_1]; + } + var originalIndex = x.locToIndex(originalLoc); + resultValues[i] = values[originalIndex]; + } + return result; + }; + MathBackendCPU.prototype.transpose = function (x, perm) { + var newShape = new Array(x.rank); + for (var i = 0; i < newShape.length; i++) { + newShape[i] = x.shape[perm[i]]; + } + var resultValues = new Float32Array(x.size); + var values = x.getValues(); + var result = ndarray_1.NDArray.make(newShape, { values: resultValues }); + for (var i = 0; i < x.size; ++i) { + var loc = x.indexToLoc(i); + var newLoc = new Array(loc.length); + for (var i_2 = 0; i_2 < newLoc.length; i_2++) { + newLoc[i_2] = loc[perm[i_2]]; + } + var newIndex = result.locToIndex(newLoc); + resultValues[newIndex] = values[i]; + } + return result; + }; + MathBackendCPU.prototype.pool = function (x, convInfo, poolType) { + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var y = ndarray_1.Array4D.zeros(convInfo.outShape); + var padTop = convInfo.padInfo.top; + var padLeft = convInfo.padInfo.left; + for (var b = 0; b < convInfo.batchSize; ++b) { + for (var d = 0; d < convInfo.inChannels; ++d) { + for (var yR = 0; yR < convInfo.outHeight; ++yR) { + var xRCorner = yR * strideHeight - padTop; + var xRMin = Math.max(0, xRCorner); + var xRMax = Math.min(convInfo.inHeight, filterHeight + xRCorner); + for (var yC = 0; yC < convInfo.outWidth; ++yC) { + var xCCorner = yC * strideWidth - padLeft; + var xCMin = Math.max(0, xCCorner); + var xCMax = Math.min(convInfo.inWidth, filterWidth + xCCorner); + var minMaxValue = (poolType === 'max' ? Number.NEGATIVE_INFINITY : + Number.POSITIVE_INFINITY); + var avgValue = 0; + for (var xR = xRMin; xR < xRMax; ++xR) { + for (var xC = xCMin; xC < xCMax; ++xC) { + var pixel = x.get(b, xR, xC, d); + if (isNaN(pixel)) { + minMaxValue = NaN; + avgValue = NaN; + break; + } + if ((poolType === 'max' && pixel > minMaxValue) || + (poolType === 'min' && pixel < minMaxValue)) { + minMaxValue = pixel; + } + else if (poolType === 'avg') { + avgValue += pixel / (filterHeight * filterWidth); + } + } + if (isNaN(minMaxValue)) { + break; + } + } + y.set(poolType === 'avg' ? avgValue : minMaxValue, b, yR, yC, d); + } + } + } + } + return y; + }; + MathBackendCPU.prototype.maxPool = function (x, convInfo) { + return this.pool(x, convInfo, 'max'); + }; + MathBackendCPU.prototype.maxPoolPositions = function (x, convInfo) { + var maxPositions = ndarray_1.Array4D.zeros(convInfo.outShape); + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var padTop = convInfo.padInfo.top; + var padLeft = convInfo.padInfo.left; + for (var b = 0; b < convInfo.batchSize; ++b) { + for (var d = 0; d < convInfo.inChannels; ++d) { + for (var yR = 0; yR < convInfo.outHeight; ++yR) { + var xRCorner = yR * strideHeight - padTop; + var xRMin = Math.max(0, xRCorner); + var xRMax = Math.min(convInfo.inHeight, filterHeight + xRCorner); + for (var yC = 0; yC < convInfo.outWidth; ++yC) { + var xCCorner = yC * strideWidth - padLeft; + var xCMin = Math.max(0, xCCorner); + var xCMax = Math.min(convInfo.inWidth, filterWidth + xCCorner); + var maxValue = Number.NEGATIVE_INFINITY; + var maxPosition = -1; + for (var xR = xRMin; xR < xRMax; ++xR) { + var wR = xR - xRCorner; + for (var xC = xCMin; xC < xCMax; ++xC) { + var wC = xC - xCCorner; + var pixel = x.get(b, xR, xC, d); + if (pixel > maxValue) { + maxValue = pixel; + maxPosition = wR * filterWidth + wC; + } + } + } + maxPositions.set(maxPosition, b, yR, yC, d); + } + } + } + } + return maxPositions; + }; + MathBackendCPU.prototype.maxPoolBackprop = function (dy, x, convInfo) { + var maxPositions = this.maxPoolPositions(x, convInfo); + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var padLeft = filterWidth - 1 - convInfo.padInfo.left; + var padTop = filterHeight - 1 - convInfo.padInfo.top; + var dx = ndarray_1.Array4D.zeros(x.shape); + for (var b = 0; b < convInfo.batchSize; ++b) { + for (var d = 0; d < convInfo.inChannels; ++d) { + for (var dxR = 0; dxR < convInfo.inHeight; ++dxR) { + for (var dxC = 0; dxC < convInfo.inWidth; ++dxC) { + var dyRCorner = dxR - padTop; + var dyCCorner = dxC - padLeft; + var dotProd = 0; + for (var wR = 0; wR < filterHeight; ++wR) { + var dyR = (dyRCorner + wR) / strideHeight; + if (dyR < 0 || dyR >= convInfo.outHeight || + Math.floor(dyR) !== dyR) { + continue; + } + for (var wC = 0; wC < filterWidth; ++wC) { + var dyC = (dyCCorner + wC) / strideWidth; + if (dyC < 0 || dyC >= convInfo.outWidth || + Math.floor(dyC) !== dyC) { + continue; + } + var maxPos = filterHeight * filterWidth - 1 - + maxPositions.get(b, dyR, dyC, d); + var curPos = wR * filterWidth + wC; + var mask = maxPos === curPos ? 1 : 0; + if (mask === 0) { + continue; + } + var pixel = dy.get(b, dyR, dyC, d); + dotProd += pixel * mask; + } + } + dx.set(dotProd, b, dxR, dxC, d); + } + } + } + } + return dx; + }; + MathBackendCPU.prototype.minPool = function (x, convInfo) { + return this.pool(x, convInfo, 'min'); + }; + MathBackendCPU.prototype.avgPool = function (x, convInfo) { + return this.pool(x, convInfo, 'avg'); + }; + MathBackendCPU.prototype.resizeBilinear3D = function (x, newShape2D, alignCorners) { + var output = ndarray_1.Array3D.zeros([newShape2D[0], newShape2D[1], x.shape[2]]); + var effectiveInputSize = alignCorners ? [x.shape[0] - 1, x.shape[1] - 1, x.shape[2]] : x.shape; + var effectiveOutputSize = alignCorners ? + [output.shape[0] - 1, output.shape[1] - 1, output.shape[2]] : + output.shape; + for (var r = 0; r < output.shape[0]; r++) { + for (var c = 0; c < output.shape[1]; c++) { + for (var d = 0; d < output.shape[2]; d++) { + var sourceFracRow = (effectiveInputSize[0]) * r / (effectiveOutputSize[0]); + var sourceFracCol = (effectiveInputSize[1]) * c / (effectiveOutputSize[1]); + var sourceRowFloor = Math.floor(sourceFracRow); + var sourceRowCeil = Math.min(x.shape[0] - 1, Math.ceil(sourceFracRow)); + var sourceColFloor = Math.floor(sourceFracCol); + var sourceColCeil = Math.min(x.shape[1] - 1, Math.ceil(sourceFracCol)); + var topLeft = x.get(sourceRowFloor, sourceColFloor, d); + var bottomLeft = x.get(sourceRowCeil, sourceColFloor, d); + var topRight = x.get(sourceRowFloor, sourceColCeil, d); + var bottomRight = x.get(sourceRowCeil, sourceColCeil, d); + var rowFrac = sourceFracRow - sourceRowFloor; + var colFrac = sourceFracCol - sourceColFloor; + var top_1 = topLeft + (topRight - topLeft) * colFrac; + var bottom = bottomLeft + (bottomRight - bottomLeft) * colFrac; + var newValue = top_1 + (bottom - top_1) * rowFrac; + output.set(newValue, r, c, d); + } + } + } + return output; + }; + MathBackendCPU.prototype.batchNormalization2D = function (x, mean, variance, varianceEpsilon, scale, offset) { + var xValues = x.getValues(); + var meanValues = mean.getValues(); + var varianceValues = variance.getValues(); + var scaleValues = scale ? scale.getValues() : new Float32Array([1]); + var offsetValues = offset ? offset.getValues() : new Float32Array([0]); + var outValues = new Float32Array(xValues.length); + for (var i = 0; i < xValues.length; i++) { + outValues[i] = offsetValues[i % offsetValues.length] + + (xValues[i] - meanValues[i % meanValues.length]) * + scaleValues[i % scaleValues.length] / + Math.sqrt(varianceValues[i % varianceValues.length] + varianceEpsilon); + } + return ndarray_1.Array2D.new(x.shape, outValues); + }; + MathBackendCPU.prototype.batchNormalization3D = function (x, mean, variance, varianceEpsilon, scale, offset) { + var xValues = x.getValues(); + var meanValues = mean.getValues(); + var varianceValues = variance.getValues(); + var scaleValues = scale ? scale.getValues() : new Float32Array([1]); + var offsetValues = offset ? offset.getValues() : new Float32Array([0]); + var outValues = new Float32Array(xValues.length); + for (var i = 0; i < xValues.length; i++) { + outValues[i] = offsetValues[i % offsetValues.length] + + (xValues[i] - meanValues[i % meanValues.length]) * + scaleValues[i % scaleValues.length] / + Math.sqrt(varianceValues[i % varianceValues.length] + varianceEpsilon); + } + return ndarray_1.Array3D.new(x.shape, outValues); + }; + MathBackendCPU.prototype.multinomial = function (probabilities, numSamples, seed) { + var batchSize = probabilities.shape[0]; + var numEvents = probabilities.shape[1]; + var res = ndarray_1.Array2D.zeros([batchSize, numSamples], 'int32'); + var resVals = res.getValues(); + var probVals = probabilities.getValues(); + for (var b = 0; b < batchSize; ++b) { + var offset = b * numEvents; + var cdf = new Float32Array(numEvents - 1); + cdf[0] = probVals[offset]; + for (var event_1 = 1; event_1 < cdf.length; ++event_1) { + cdf[event_1] = cdf[event_1 - 1] + probVals[offset + event_1]; + } + var random = seedrandom.alea(seed.toString()); + var outOffset = b * numSamples; + for (var sampleId = 0; sampleId < numSamples; ++sampleId) { + var r = random(); + resVals[outOffset + sampleId] = cdf.length; + for (var event_2 = 0; event_2 < cdf.length; event_2++) { + if (r < cdf[event_2]) { + resVals[outOffset + sampleId] = event_2; + break; + } + } + } + } + return res; + }; + MathBackendCPU.prototype.oneHot = function (indices, depth, onValue, offValue) { + var res = new Float32Array(indices.size * depth); + res.fill(offValue); + for (var event_3 = 0; event_3 < indices.size; ++event_3) { + res[event_3 * depth + indices.get(event_3)] = onValue; + } + return ndarray_1.Array2D.new([indices.size, depth], res); + }; + MathBackendCPU.prototype.broadcastedBinaryOp = function (a, b, dtype, op) { + var newShape = broadcast_util.assertAndGetBroadcastShape(a.shape, b.shape); + var result = ndarray_1.NDArray.zeros(newShape, dtype); + var newValues = result.getValues(); + var aValues = a.getValues(); + var bValues = b.getValues(); + var aBroadcastDims = broadcast_util.getBroadcastDims(a.shape, newShape); + var bBroadcastDims = broadcast_util.getBroadcastDims(b.shape, newShape); + var _loop_1 = function (i) { + var loc = result.indexToLoc(i); + var aLoc = loc.slice(-a.rank); + aBroadcastDims.forEach(function (d) { return aLoc[d] = 0; }); + var aIndex = a.locToIndex(aLoc); + var bLoc = loc.slice(-b.rank); + bBroadcastDims.forEach(function (d) { return bLoc[d] = 0; }); + var bIndex = b.locToIndex(bLoc); + newValues[i] = op(aValues[aIndex], bValues[bIndex]); + }; + for (var i = 0; i < newValues.length; ++i) { + _loop_1(i); + } + return result; + }; + return MathBackendCPU; +}()); +exports.MathBackendCPU = MathBackendCPU; +environment_1.ENV.registerBackend('cpu', function () { return new MathBackendCPU(); }); +var NDArrayMathCPU = (function (_super) { + __extends(NDArrayMathCPU, _super); + function NDArrayMathCPU(safeMode) { + if (safeMode === void 0) { safeMode = false; } + var _this = this; + console.warn('new NDArrayMathCPU() is deprecated. Please use the global ' + + 'dl.ENV.math. In rare cases, to construct your own NDArrayMath ' + + 'that runs on CPU, use math = new NDArrayMath(\'cpu\', safeMode); ' + + 'and make sure to set it as global: dl.ENV.setMath(math);'); + _this = _super.call(this, 'cpu', safeMode) || this; + environment_1.ENV.setMath(_this); + return _this; + } + return NDArrayMathCPU; +}(math_1.NDArrayMath)); +exports.NDArrayMathCPU = NDArrayMathCPU; + +},{"../../environment":15,"../../util":101,"../broadcast_util":90,"../concat_util":91,"../math":94,"../ndarray":95,"../types":99,"./../axis_util":54,"./types/matmul":61,"seedrandom":2}],56:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../../util"); +var kernel_registry = require("./kernel_registry"); +var tape_1 = require("./tape"); +var BackendEngine = (function () { + function BackendEngine(backend) { + this.backend = backend; + this.debugMode = false; + this.masterTape = new tape_1.Tape(backend); + } + BackendEngine.prototype.enableDebugMode = function () { + this.debugMode = true; + }; + BackendEngine.prototype.executeKernel = function (kernelName, config, grad) { + var _this = this; + var kernelFn = function () { + return kernel_registry.executeKernel(_this.backend, kernelName, config); + }; + var start; + if (this.debugMode) { + start = performance.now(); + } + var result = kernelFn(); + if (this.debugMode) { + var vals = result.getValues(); + var time = util.rightPad(performance.now() - start + "ms", 9); + var paddedName = util.rightPad(name, 25); + var rank = result.rank; + var size = result.size; + var shape = util.rightPad(result.shape.toString(), 14); + console.log("%c" + paddedName + "\t%c" + time + "\t%c" + rank + "D " + shape + "\t%c" + size, 'font-weight:bold', 'color:red', 'color:blue', 'color: orange'); + this.checkForNaN(vals, result.dtype, name); + } + var evaluatedNode = { + name: "kernel: " + kernelName, + kernel: kernelName, + inputAndArgs: config, + output: result, + gradient: grad + }; + this.masterTape.addEvaluatedKernelNode(evaluatedNode); + return result; + }; + BackendEngine.prototype.gradientWrt = function (y, xs) { + return this.masterTape.gradientWrt(y, xs); + }; + BackendEngine.prototype.checkForNaN = function (vals, dtype, name) { + for (var i = 0; i < vals.length; i++) { + if (util.isValNaN(vals[i], dtype)) { + throw Error("The result of the last math." + name + " has NaNs."); + } + } + }; + BackendEngine.prototype.getBackend = function () { + return this.backend; + }; + return BackendEngine; +}()); +exports.BackendEngine = BackendEngine; + +},{"../../util":101,"./kernel_registry":58,"./tape":59}],57:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../environment"); +var util = require("../../util"); +var axis_util = require("../axis_util"); +var math_1 = require("../math"); +var ndarray_1 = require("../ndarray"); +var reduce_util = require("../reduce_util"); +var types_1 = require("../types"); +var argminmax_gpu_1 = require("./webgl/argminmax_gpu"); +var batchnorm_gpu_1 = require("./webgl/batchnorm_gpu"); +var binaryop_gpu = require("./webgl/binaryop_gpu"); +var binaryop_gpu_1 = require("./webgl/binaryop_gpu"); +var clip_gpu_1 = require("./webgl/clip_gpu"); +var concat_gpu_1 = require("./webgl/concat_gpu"); +var conv_backprop_gpu_1 = require("./webgl/conv_backprop_gpu"); +var conv_gpu_1 = require("./webgl/conv_gpu"); +var conv_gpu_depthwise_1 = require("./webgl/conv_gpu_depthwise"); +var copy_gpu_1 = require("./webgl/copy_gpu"); +var gpgpu_context_1 = require("./webgl/gpgpu_context"); +var gpgpu_math = require("./webgl/gpgpu_math"); +var gpgpu_util = require("./webgl/gpgpu_util"); +var max_pool_backprop_gpu_1 = require("./webgl/max_pool_backprop_gpu"); +var mulmat_gpu_1 = require("./webgl/mulmat_gpu"); +var multinomial_gpu_1 = require("./webgl/multinomial_gpu"); +var onehot_gpu_1 = require("./webgl/onehot_gpu"); +var pool_gpu_1 = require("./webgl/pool_gpu"); +var reduce_gpu_1 = require("./webgl/reduce_gpu"); +var resize_bilinear_gpu_1 = require("./webgl/resize_bilinear_gpu"); +var slice_gpu_1 = require("./webgl/slice_gpu"); +var tex_util_1 = require("./webgl/tex_util"); +var texture_manager_1 = require("./webgl/texture_manager"); +var tile_gpu_1 = require("./webgl/tile_gpu"); +var transpose_gpu_1 = require("./webgl/transpose_gpu"); +var unary_op = require("./webgl/unaryop_gpu"); +var unaryop_gpu_1 = require("./webgl/unaryop_gpu"); +var webgl_util = require("./webgl/webgl_util"); +var MathBackendWebGL = (function () { + function MathBackendWebGL(gpgpu) { + this.texData = {}; + this.binaryCache = {}; + if (environment_1.ENV.get('WEBGL_VERSION') < 1) { + throw new Error('WebGL is not supported on this device'); + } + if (gpgpu == null) { + var gl = gpgpu_util.createWebGLContext(); + this.gpgpu = new gpgpu_context_1.GPGPUContext(gl); + this.gpgpuCreatedLocally = true; + } + else { + this.gpgpu = gpgpu; + this.gpgpuCreatedLocally = false; + } + this.textureManager = new texture_manager_1.TextureManager(this.gpgpu); + } + MathBackendWebGL.prototype.writePixels = function (id, pixels, numChannels) { + var shape = [pixels.height, pixels.width, numChannels]; + var texShape = [shape[0], shape[1]]; + var texture = this.textureManager.acquireTexture(texShape); + this.gpgpu.uploadPixelDataToTexture(texture, pixels); + this.texData[id] = { + texture: texture, + textureType: tex_util_1.TextureType.RGBA_COLOR, + texShape: texShape, + numChannels: numChannels, + dtype: 'int32' + }; + }; + MathBackendWebGL.prototype.write = function (id, values, dtype, shape) { + var texShape = webgl_util.getTextureShapeFromLogicalShape(this.gpgpu.gl, shape); + var texture = this.textureManager.acquireTexture(texShape); + var textureType = tex_util_1.TextureType.DEFAULT; + this.texData[id] = { texture: texture, textureType: textureType, texShape: texShape, dtype: dtype }; + if (values != null) { + this.gpgpu.uploadMatrixToTexture(texture, texShape[0], texShape[1], typedArrayToFloat32(values, dtype)); + } + }; + MathBackendWebGL.prototype.readSync = function (id) { + this.throwIfNoData(id); + var values; + var _a = this.texData[id], texture = _a.texture, textureType = _a.textureType, texShape = _a.texShape, numChannels = _a.numChannels, dtype = _a.dtype; + if (textureType === tex_util_1.TextureType.DEFAULT) { + values = this.gpgpu.downloadMatrixFromTexture(texture, texShape[0], texShape[1]); + } + else { + values = this.gpgpu.downloadMatrixFromRGBAColorTexture(texture, texShape[0], texShape[1], numChannels); + } + return float32ToTypedArray(values, dtype); + }; + MathBackendWebGL.prototype.read = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _a, texture, textureType, texShape; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + this.throwIfNoData(id); + _a = this.texData[id], texture = _a.texture, textureType = _a.textureType, texShape = _a.texShape; + if (environment_1.ENV.get('WEBGL_GET_BUFFER_SUB_DATA_ASYNC_EXTENSION_ENABLED') && + textureType === tex_util_1.TextureType.DEFAULT) { + return [2, this.gpgpu.downloadMatrixFromTextureAsync(texture, texShape[0], texShape[1])]; + } + if (!environment_1.ENV.get('WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_ENABLED')) { + return [2, this.readSync(id)]; + } + return [4, this.gpgpu.runQuery(function () { })]; + case 1: + _b.sent(); + return [2, this.readSync(id)]; + } + }); + }); + }; + MathBackendWebGL.prototype.time = function (query) { + return __awaiter(this, void 0, void 0, function () { + var start, a; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!!environment_1.ENV.get('WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_ENABLED')) return [3, 2]; + start = performance.now(); + a = query(); + return [4, a.data()]; + case 1: + _a.sent(); + return [2, performance.now() - start]; + case 2: return [2, this.gpgpu.runQuery(query)]; + } + }); + }); + }; + MathBackendWebGL.prototype.disposeData = function (id) { + if (id in this.texData) { + var _a = this.texData[id], texture = _a.texture, texShape = _a.texShape; + this.textureManager.releaseTexture(texture, texShape); + delete this.texData[id]; + } + }; + MathBackendWebGL.prototype.getTexture = function (id) { + this.throwIfNoData(id); + return this.texData[id].texture; + }; + MathBackendWebGL.prototype.getTextureData = function (id) { + this.throwIfNoData(id); + return this.texData[id]; + }; + MathBackendWebGL.prototype.getGPGPUContext = function () { + return this.gpgpu; + }; + MathBackendWebGL.prototype.clone = function (x) { + this.throwIfNoData(x.id); + var texShape = this.texData[x.id].texShape; + var source = x.as2D(texShape[0], texShape[1]); + var output = this.makeOutputArray(texShape, x.dtype); + this.copy2D(source, [0, 0], texShape, output, [0, 0], texShape); + return output.reshape(x.shape); + }; + MathBackendWebGL.prototype.slice1D = function (x, begin, size) { + var program = new slice_gpu_1.SliceProgram([size]); + var customSetup = program.getCustomSetupFunc([begin]); + return this.compileAndRun(program, [x], null, customSetup); + }; + MathBackendWebGL.prototype.slice2D = function (x, begin, size) { + var program = new slice_gpu_1.SliceProgram(size); + var customSetup = program.getCustomSetupFunc(begin); + return this.compileAndRun(program, [x], null, customSetup); + }; + MathBackendWebGL.prototype.slice3D = function (x, begin, size) { + var program = new slice_gpu_1.SliceProgram(size); + var customSetup = program.getCustomSetupFunc(begin); + return this.compileAndRun(program, [x], null, customSetup); + }; + MathBackendWebGL.prototype.slice4D = function (x, begin, size) { + var program = new slice_gpu_1.SliceProgram(size); + var customSetup = program.getCustomSetupFunc(begin); + return this.compileAndRun(program, [x], null, customSetup); + }; + MathBackendWebGL.prototype.copy2D = function (source, sourceBeginRowCol, sourceSizeRowCol, dest, destBeginRowCol, destSizeRowCol) { + var program = new copy_gpu_1.Copy2DProgram(sourceSizeRowCol[1], destSizeRowCol[1]); + var customSetup = program.getCustomSetupFunc(sourceBeginRowCol, destBeginRowCol, destSizeRowCol); + this.compileAndRun(program, [source], dest, customSetup); + }; + MathBackendWebGL.prototype.concat1D = function (a, b) { + var program = new concat_gpu_1.ConcatProgram(a.shape, b.shape, 0); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.concat2D = function (a, b, axis) { + var program = new concat_gpu_1.ConcatProgram(a.shape, b.shape, axis); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.concat3D = function (a, b, axis) { + var program = new concat_gpu_1.ConcatProgram(a.shape, b.shape, axis); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.concat4D = function (a, b, axis) { + var program = new concat_gpu_1.ConcatProgram(a.shape, b.shape, axis); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.neg = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.NEG); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.matMul = function (a, b, aOrientation, bOrientation) { + var program = new mulmat_gpu_1.MatMulProgram(a.shape, b.shape, aOrientation, bOrientation); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.multiply = function (a, b) { + var program = new binaryop_gpu_1.BinaryOpProgram(binaryop_gpu.MUL, a.shape, b.shape); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.batchNormalization2D = function (x, mean, variance, varianceEpsilon, scale, offset) { + var inputs = [x, mean, variance]; + var offsetShape = null; + if (offset != null) { + offsetShape = offset.shape; + inputs.push(offset); + } + var scaleShape = null; + if (scale != null) { + scaleShape = scale.shape; + inputs.push(scale); + } + var program = new batchnorm_gpu_1.BatchNormProgram(x.shape, mean.shape, variance.shape, offsetShape, scaleShape, varianceEpsilon); + return this.compileAndRun(program, inputs); + }; + MathBackendWebGL.prototype.batchNormalization3D = function (x, mean, variance, varianceEpsilon, scale, offset) { + var inputs = [x, mean, variance]; + var offsetShape = null; + if (offset != null) { + offsetShape = offset.shape; + inputs.push(offset); + } + var scaleShape = null; + if (scale != null) { + scaleShape = scale.shape; + inputs.push(scale); + } + var program = new batchnorm_gpu_1.BatchNormProgram(x.shape, mean.shape, variance.shape, offsetShape, scaleShape, varianceEpsilon); + return this.compileAndRun(program, inputs); + }; + MathBackendWebGL.prototype.tile = function (x, reps) { + var program = new tile_gpu_1.TileProgram(x.shape, reps); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.transpose = function (x, perm) { + var program = new transpose_gpu_1.TransposeProgram(x.shape, perm); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.reduce = function (x, reduceType, dtype) { + var batchSize = x.shape[0]; + var inSize = x.shape[1]; + var windowSize = reduce_util.computeOptimalWindowSize(inSize); + var reduceInfo = { windowSize: windowSize, inSize: inSize, batchSize: batchSize }; + var program = new reduce_gpu_1.ReduceProgram(reduceInfo, reduceType); + var _a = program.outputShape, rows = _a[0], cols = _a[1]; + var output = this.makeOutputArray(program.outputShape, dtype).as2D(rows, cols); + this.compileAndRun(program, [x], output); + if (output.shape[1] === 1) { + return output; + } + return this.reduce(output, reduceType, dtype); + }; + MathBackendWebGL.prototype.argReduce = function (x, reduceType, bestIndicesA) { + if (bestIndicesA === void 0) { bestIndicesA = null; } + var batchSize = x.shape[0]; + var inSize = x.shape[1]; + if (bestIndicesA != null) { + batchSize = bestIndicesA.shape[0]; + inSize = bestIndicesA.shape[1]; + } + var windowSize = reduce_util.computeOptimalWindowSize(inSize); + var reduceInfo = { windowSize: windowSize, inSize: inSize, batchSize: batchSize }; + var program = new argminmax_gpu_1.ArgMinMaxProgram(reduceInfo, reduceType, bestIndicesA == null); + var _a = program.outputShape, rows = _a[0], cols = _a[1]; + var output = this.makeOutputArray(program.outputShape, 'int32').as2D(rows, cols); + var inputs = [x]; + if (bestIndicesA != null) { + inputs.push(bestIndicesA); + } + this.compileAndRun(program, inputs, output); + if (output.shape[1] === 1) { + return output; + } + return this.argReduce(x, reduceType, output); + }; + MathBackendWebGL.prototype.sum = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('sum', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var inSize = util.sizeFromShape(reduceShape); + var a2D = x.as2D(-1, inSize); + var outputDType = types_1.SumTypesMap[x.dtype]; + return this.reduce(a2D, 'sum', outputDType).reshape(outShape); + }; + MathBackendWebGL.prototype.argMin = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('argMin', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var inSize = util.sizeFromShape(reduceShape); + var a2D = x.as2D(-1, inSize); + return this.argReduce(a2D, 'min').reshape(outShape); + }; + MathBackendWebGL.prototype.argMax = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('argMax', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var inSize = util.sizeFromShape(reduceShape); + var a2D = x.as2D(-1, inSize); + return this.argReduce(a2D, 'max').reshape(outShape); + }; + MathBackendWebGL.prototype.equal = function (a, b) { + var program = new binaryop_gpu_1.BinaryOpProgram(binaryop_gpu.EQUAL, a.shape, b.shape); + var output = this.makeOutputArray(program.outputShape, 'bool'); + return this.compileAndRun(program, [a, b], output); + }; + MathBackendWebGL.prototype.topKValues = function (x, k) { + throw new Error('topKValues GPU not yet implemented!'); + }; + MathBackendWebGL.prototype.topKIndices = function (x, k) { + throw new Error('topKIndices GPU not yet implemented!'); + }; + MathBackendWebGL.prototype.min = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('min', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var inSize = util.sizeFromShape(reduceShape); + var a2D = x.as2D(-1, inSize); + return this.reduce(a2D, 'min', a2D.dtype).reshape(outShape); + }; + MathBackendWebGL.prototype.max = function (x, axes) { + axis_util.assertAxesAreInnerMostDims('max', axes, x.rank); + var _a = axis_util.computeOutAndReduceShapes(x.shape, axes), outShape = _a[0], reduceShape = _a[1]; + var inSize = util.sizeFromShape(reduceShape); + var a2D = x.as2D(-1, inSize); + return this.reduce(a2D, 'max', a2D.dtype).reshape(outShape); + }; + MathBackendWebGL.prototype.divide = function (a, b) { + var program = new binaryop_gpu_1.BinaryOpProgram(binaryop_gpu.DIV, a.shape, b.shape); + var output = this.makeOutputArray(program.outputShape, 'float32'); + return this.compileAndRun(program, [a, b], output); + }; + MathBackendWebGL.prototype.add = function (a, b) { + var program = new binaryop_gpu_1.BinaryOpProgram(binaryop_gpu.ADD, a.shape, b.shape); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.subtract = function (a, b) { + var program = new binaryop_gpu_1.BinaryOpProgram(binaryop_gpu.SUB, a.shape, b.shape); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.pow = function (a, b) { + var program = new binaryop_gpu_1.BinaryOpProgram(binaryop_gpu.POW, a.shape, b.shape); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.ceil = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.CEIL); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.floor = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.FLOOR); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.exp = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.EXP); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.log = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.LOG); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.sqrt = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.SQRT); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.square = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.SQUARE); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.relu = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.RELU); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.elu = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.ELU); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.eluDer = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.ELU_DER); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.selu = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.SELU); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.leakyRelu = function (x, alpha) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.LEAKY_RELU(alpha)); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.prelu = function (a, b) { + var program = new binaryop_gpu_1.BinaryOpProgram(binaryop_gpu.PRELU, a.shape, b.shape); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.preluDer = function (a, b) { + var program = new binaryop_gpu_1.BinaryOpProgram(binaryop_gpu.PRELU_DER, a.shape, b.shape); + return this.compileAndRun(program, [a, b]); + }; + MathBackendWebGL.prototype.clip = function (x, min, max) { + var program = new clip_gpu_1.ClipProgram(x.shape, min, max); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.abs = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.ABS); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.sigmoid = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.SIGMOID); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.sin = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.SIN); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.cos = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.COS); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.tan = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.TAN); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.asin = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.ASIN); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.acos = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.ACOS); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.atan = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.ATAN); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.sinh = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.SINH); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.cosh = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.COSH); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.tanh = function (x) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.TANH); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.step = function (x, alpha) { + var program = new unaryop_gpu_1.UnaryOpProgram(x.shape, unary_op.STEP(alpha)); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.conv2d = function (x, filter, bias, convInfo) { + var program = new conv_gpu_1.Conv2DProgram(convInfo, bias != null); + var inputs = bias != null ? [x, filter, bias] : [x, filter]; + return this.compileAndRun(program, inputs); + }; + MathBackendWebGL.prototype.conv2dDerInput = function (dy, filter, convInfo) { + var program = new conv_backprop_gpu_1.Conv2DDerInputProgram(convInfo); + return this.compileAndRun(program, [dy, filter]); + }; + MathBackendWebGL.prototype.conv2dDerFilter = function (x, dy, convInfo) { + var program = new conv_backprop_gpu_1.Conv2DDerFilterProgram(convInfo); + return this.compileAndRun(program, [x, dy]); + }; + MathBackendWebGL.prototype.conv2dDerBias = function (dy) { + var program = new conv_backprop_gpu_1.Conv2DDerBiasProgram(dy.shape); + return this.compileAndRun(program, [dy]); + }; + MathBackendWebGL.prototype.depthwiseConv2D = function (x, filter, convInfo) { + var program = new conv_gpu_depthwise_1.DepthwiseConv2DProgram(convInfo); + return this.compileAndRun(program, [x, filter]); + }; + MathBackendWebGL.prototype.maxPool = function (x, convInfo) { + var program = new pool_gpu_1.Pool2DProgram(convInfo, 'max', false); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.minPool = function (x, convInfo) { + var program = new pool_gpu_1.Pool2DProgram(convInfo, 'min', false); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.avgPool = function (x, convInfo) { + var program = new pool_gpu_1.Pool2DProgram(convInfo, 'avg', false); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.maxPoolBackprop = function (dy, x, convInfo) { + var getPositions = true; + var maxPoolPositionsProgram = new pool_gpu_1.Pool2DProgram(convInfo, 'max', getPositions); + var maxPoolPositions = this.compileAndRun(maxPoolPositionsProgram, [x]); + var maxPoolBackPropProgram = new max_pool_backprop_gpu_1.MaxPool2DBackpropProgram(convInfo); + var result = this.compileAndRun(maxPoolBackPropProgram, [dy, maxPoolPositions]); + maxPoolPositions.dispose(); + return result; + }; + MathBackendWebGL.prototype.resizeBilinear3D = function (x, newShape2D, alignCorners) { + var program = new resize_bilinear_gpu_1.ResizeBilinear3DProgram(x.shape, newShape2D, alignCorners); + return this.compileAndRun(program, [x]); + }; + MathBackendWebGL.prototype.multinomial = function (probs, numSamples, seed) { + var batchSize = probs.shape[0]; + var numOutcomes = probs.shape[1]; + var program = new multinomial_gpu_1.MultinomialProgram(batchSize, numOutcomes, numSamples); + var output = this.makeOutputArray(program.outputShape, 'int32'); + var customSetup = program.getCustomSetupFunc(seed); + return this.compileAndRun(program, [probs], output, customSetup); + }; + MathBackendWebGL.prototype.oneHot = function (indices, depth, onValue, offValue) { + var program = new onehot_gpu_1.OneHotProgram(indices.size, depth, onValue, offValue); + return this.compileAndRun(program, [indices]); + }; + MathBackendWebGL.prototype.makeOutputArray = function (shape, dtype) { + return ndarray_1.NDArray.make(shape, {}, dtype); + }; + MathBackendWebGL.prototype.compileAndRun = function (program, inputs, output, customSetup) { + var _this = this; + if (output == null) { + output = this.makeOutputArray(program.outputShape, inputs[0].dtype); + } + var inputsData = inputs.map(function (input) { + _this.throwIfNoData(input.id); + return { array: input, texData: _this.texData[input.id] }; + }); + this.throwIfNoData(output.id); + var outputData = { array: output, texData: this.texData[output.id] }; + var key = gpgpu_math.makeShaderKey(program, inputsData, outputData); + var binary = this.getAndSaveBinary(key, function () { + return gpgpu_math.compileProgram(_this.gpgpu, program, inputsData, outputData); + }); + gpgpu_math.runProgram(binary, inputsData, outputData, customSetup); + return output; + }; + MathBackendWebGL.prototype.getAndSaveBinary = function (key, getBinary) { + if (!(key in this.binaryCache)) { + this.binaryCache[key] = getBinary(); + } + return this.binaryCache[key]; + }; + MathBackendWebGL.prototype.getTextureManager = function () { + return this.textureManager; + }; + MathBackendWebGL.prototype.dispose = function () { + for (var key in this.binaryCache) { + this.gpgpu.deleteProgram(this.binaryCache[key].webGLProgram); + } + this.textureManager.dispose(); + if (this.gpgpuCreatedLocally) { + this.gpgpu.dispose(); + } + }; + MathBackendWebGL.prototype.throwIfNoData = function (id) { + if (!(id in this.texData)) { + throw new Error("No data found for NDArray with id " + id + ". " + + "Use dl.ENV.math instead of constructing your own NDArrayMath. " + + "If you need to construct your own math, make sure this array is " + + "allocated after the math construction"); + } + }; + return MathBackendWebGL; +}()); +exports.MathBackendWebGL = MathBackendWebGL; +environment_1.ENV.registerBackend('webgl', function () { return new MathBackendWebGL(); }); +var NDArrayMathGPU = (function (_super) { + __extends(NDArrayMathGPU, _super); + function NDArrayMathGPU(gpgpu, safeMode) { + if (safeMode === void 0) { safeMode = false; } + var _this = this; + console.warn('new NDArrayMathGPU() is deprecated. Please use the global ' + + 'dl.ENV.math. In rare cases, to construct your own NDArrayMath ' + + 'that runs on GPU, use math = new NDArrayMath(\'webgl\', safeMode); ' + + 'and make sure to set it as global: dl.ENV.setMath(math);'); + _this = _super.call(this, new MathBackendWebGL(gpgpu), safeMode) || this; + environment_1.ENV.setMath(_this); + return _this; + } + NDArrayMathGPU.prototype.getGPGPUContext = function () { + return this.backendEngine.getBackend() + .getGPGPUContext(); + }; + NDArrayMathGPU.prototype.getTextureManager = function () { + return this.backendEngine.getBackend() + .getTextureManager(); + }; + return NDArrayMathGPU; +}(math_1.NDArrayMath)); +exports.NDArrayMathGPU = NDArrayMathGPU; +function float32ToTypedArray(a, dtype) { + if (dtype === 'float32') { + return a; + } + else if (dtype === 'int32' || dtype === 'bool') { + var result = (dtype === 'int32') ? new Int32Array(a.length) : + new Uint8Array(a.length); + for (var i = 0; i < result.length; ++i) { + var val = a[i]; + val = isNaN(val) ? util.getNaN(dtype) : Math.round(val); + result[i] = val; + } + return result; + } + else { + throw new Error("Unknown dtype " + dtype); + } +} +function typedArrayToFloat32(a, dtype) { + if (a instanceof Float32Array) { + return a; + } + else { + var res = new Float32Array(a.length); + for (var i = 0; i < res.length; i++) { + var val = a[i]; + res[i] = util.isValNaN(val, dtype) ? NaN : val; + } + return res; + } +} + +},{"../../environment":15,"../../util":101,"../axis_util":54,"../math":94,"../ndarray":95,"../reduce_util":97,"../types":99,"./webgl/argminmax_gpu":62,"./webgl/batchnorm_gpu":63,"./webgl/binaryop_gpu":64,"./webgl/clip_gpu":65,"./webgl/concat_gpu":66,"./webgl/conv_backprop_gpu":67,"./webgl/conv_gpu":68,"./webgl/conv_gpu_depthwise":69,"./webgl/copy_gpu":70,"./webgl/gpgpu_context":71,"./webgl/gpgpu_math":72,"./webgl/gpgpu_util":73,"./webgl/max_pool_backprop_gpu":74,"./webgl/mulmat_gpu":75,"./webgl/multinomial_gpu":76,"./webgl/onehot_gpu":77,"./webgl/pool_gpu":78,"./webgl/reduce_gpu":79,"./webgl/resize_bilinear_gpu":81,"./webgl/slice_gpu":83,"./webgl/tex_util":84,"./webgl/texture_manager":85,"./webgl/tile_gpu":86,"./webgl/transpose_gpu":87,"./webgl/unaryop_gpu":88,"./webgl/webgl_util":89}],58:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var KERNEL_METHODS = { + MatMul: function (backend, config) { + return backend.matMul(config.inputs.a, config.inputs.b, config.args.aOrientation, config.args.bOrientation); + }, + Clone: function (backend, config) { + return backend.clone(config.inputs.x); + }, + Slice1D: function (backend, config) { + return backend.slice1D(config.inputs.x, config.args.begin, config.args.size); + }, + Slice2D: function (backend, config) { + return backend.slice2D(config.inputs.x, config.args.begin, config.args.size); + }, + Slice3D: function (backend, config) { + return backend.slice3D(config.inputs.x, config.args.begin, config.args.size); + }, + Slice4D: function (backend, config) { + return backend.slice4D(config.inputs.x, config.args.begin, config.args.size); + }, + Concat1D: function (backend, config) { + return backend.concat1D(config.inputs.a, config.inputs.b); + }, + Concat2D: function (backend, config) { + return backend.concat2D(config.inputs.a, config.inputs.b, config.args.axis); + }, + Concat3D: function (backend, config) { + return backend.concat3D(config.inputs.a, config.inputs.b, config.args.axis); + }, + Concat4D: function (backend, config) { + return backend.concat4D(config.inputs.a, config.inputs.b, config.args.axis); + }, + Neg: function (backend, config) { + return backend.neg(config.inputs.x); + }, + Add: function (backend, config) { + return backend.add(config.inputs.a, config.inputs.b); + }, + Sub: function (backend, config) { + return backend.subtract(config.inputs.a, config.inputs.b); + }, + Mul: function (backend, config) { + return backend.multiply(config.inputs.a, config.inputs.b); + }, + Div: function (backend, config) { + return backend.divide(config.inputs.a, config.inputs.b); + }, + Sum: function (backend, config) { + return backend.sum(config.inputs.x, config.args.axes); + }, + ArgMax: function (backend, config) { + return backend.argMax(config.inputs.x, config.args.axes); + }, + ArgMin: function (backend, config) { + return backend.argMin(config.inputs.x, config.args.axes); + }, + Equal: function (backend, config) { + return backend.equal(config.inputs.a, config.inputs.b); + }, + TopKValues: function (backend, config) { + return backend.topKValues(config.inputs.x, config.args.k); + }, + TopKIndices: function (backend, config) { + return backend.topKIndices(config.inputs.x, config.args.k); + }, + Min: function (backend, config) { + return backend.min(config.inputs.x, config.args.axes); + }, + Max: function (backend, config) { + return backend.max(config.inputs.x, config.args.axes); + }, + Ceil: function (backend, config) { + return backend.ceil(config.inputs.x); + }, + Floor: function (backend, config) { + return backend.floor(config.inputs.x); + }, + Pow: function (backend, config) { + return backend.pow(config.inputs.a, config.inputs.b); + }, + Exp: function (backend, config) { + return backend.exp(config.inputs.x); + }, + Log: function (backend, config) { + return backend.log(config.inputs.x); + }, + Sqrt: function (backend, config) { + return backend.sqrt(config.inputs.x); + }, + Square: function (backend, config) { + return backend.square(config.inputs.x); + }, + Relu: function (backend, config) { + return backend.relu(config.inputs.x); + }, + LeakyRelu: function (backend, config) { + return backend.leakyRelu(config.inputs.x, config.args.alpha); + }, + PReLU: function (backend, config) { + return backend.prelu(config.inputs.x, config.inputs.alpha); + }, + PReLUDer: function (backend, config) { + return backend.preluDer(config.inputs.x, config.inputs.alpha); + }, + Elu: function (backend, config) { + return backend.elu(config.inputs.x); + }, + EluDer: function (backend, config) { + return backend.eluDer(config.inputs.x); + }, + Selu: function (backend, config) { + return backend.selu(config.inputs.x); + }, + Abs: function (backend, config) { + return backend.abs(config.inputs.x); + }, + Sigmoid: function (backend, config) { + return backend.sigmoid(config.inputs.x); + }, + Step: function (backend, config) { + return backend.step(config.inputs.x, config.args.alpha); + }, + Sin: function (backend, config) { + return backend.sin(config.inputs.x); + }, + Cos: function (backend, config) { + return backend.cos(config.inputs.x); + }, + Tan: function (backend, config) { + return backend.tan(config.inputs.x); + }, + Asin: function (backend, config) { + return backend.asin(config.inputs.x); + }, + Acos: function (backend, config) { + return backend.acos(config.inputs.x); + }, + Atan: function (backend, config) { + return backend.atan(config.inputs.x); + }, + Sinh: function (backend, config) { + return backend.sinh(config.inputs.x); + }, + Cosh: function (backend, config) { + return backend.cosh(config.inputs.x); + }, + Tanh: function (backend, config) { + return backend.tanh(config.inputs.x); + }, + Clip: function (backend, config) { + return backend.clip(config.inputs.x, config.args.min, config.args.max); + }, + Transpose: function (backend, config) { + return backend.transpose(config.inputs.x, config.args.perm); + }, + Tile: function (backend, config) { + return backend.tile(config.inputs.x, config.args.reps); + }, + Conv2D: function (backend, config) { + return backend.conv2d(config.inputs.x, config.inputs.filter, config.inputs.bias, config.args.convInfo); + }, + Conv2DDerInput: function (backend, config) { + return backend.conv2dDerInput(config.inputs.dy, config.inputs.filter, config.args.convInfo); + }, + Conv2DDerFilter: function (backend, config) { + return backend.conv2dDerFilter(config.inputs.x, config.inputs.dy, config.args.convInfo); + }, + Conv2DDerBias: function (backend, config) { + return backend.conv2dDerBias(config.inputs.dy); + }, + DepthwiseConv2D: function (backend, config) { + return backend.depthwiseConv2D(config.inputs.x, config.inputs.filter, config.args.convInfo); + }, + MaxPool: function (backend, config) { + return backend.maxPool(config.inputs.x, config.args.convInfo); + }, + MaxPoolBackprop: function (backend, config) { + return backend.maxPoolBackprop(config.inputs.dy, config.inputs.x, config.args.convInfo); + }, + AvgPool: function (backend, config) { + return backend.avgPool(config.inputs.x, config.args.convInfo); + }, + MinPool: function (backend, config) { + return backend.minPool(config.inputs.x, config.args.convInfo); + }, + ResizeBilinear3D: function (backend, config) { + return backend.resizeBilinear3D(config.inputs.x, config.args.newShape2D, config.args.alignCorners); + }, + BatchNorm3D: function (backend, config) { + return backend.batchNormalization3D(config.inputs.x, config.inputs.mean, config.inputs.variance, config.args.varianceEpsilon, config.inputs.scale, config.inputs.offset); + }, + BatchNorm2D: function (backend, config) { + return backend.batchNormalization2D(config.inputs.x, config.inputs.mean, config.inputs.variance, config.args.varianceEpsilon, config.inputs.scale, config.inputs.offset); + }, + Multinomial: function (backend, config) { + return backend.multinomial(config.inputs.probs, config.args.numSamples, config.args.seed); + }, + OneHot: function (backend, config) { + return backend.oneHot(config.inputs.indices, config.args.depth, config.args.onValue, config.args.offValue); + } +}; +function executeKernel(backend, kernelName, config) { + return KERNEL_METHODS[kernelName](backend, config); +} +exports.executeKernel = executeKernel; + +},{}],59:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ndarray_1 = require("../ndarray"); +var tape_util = require("./tape_util"); +var Tape = (function () { + function Tape(backend) { + this.backend = backend; + this.evaluatedTapeNodes = []; + this.outputNodeMap = {}; + } + Tape.prototype.addEvaluatedKernelNode = function (node) { + this.outputNodeMap[node.output.id] = node; + this.evaluatedTapeNodes.push(node); + }; + Tape.prototype.gradientWrt = function (y, xs) { + if (this.outputNodeMap[y.id] == null) { + throw new Error("Cannot compute gradient: y is not part of this tape."); + } + var filteredNodes = tape_util.getFilteredNodesXToY(this.evaluatedTapeNodes, xs, y); + var arrayAccumulatedGradientMap = {}; + arrayAccumulatedGradientMap[y.id] = ndarray_1.Scalar.new(1); + tape_util.backpropagateGradients(this.backend, arrayAccumulatedGradientMap, filteredNodes); + var gradients = []; + for (var i = 0; i < xs.length; i++) { + gradients.push(arrayAccumulatedGradientMap[xs[i].id]); + } + return gradients; + }; + return Tape; +}()); +exports.Tape = Tape; + +},{"../ndarray":95,"./tape_util":60}],60:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function getFilteredNodesXToY(tapeNodes, xs, y) { + var arraysFromX = {}; + for (var i = 0; i < xs.length; i++) { + arraysFromX[xs[i].id] = true; + } + for (var i = 0; i < tapeNodes.length; i++) { + var node = tapeNodes[i]; + var nodeInputs = node.inputAndArgs.inputs; + for (var inputName in nodeInputs) { + var input = nodeInputs[inputName]; + for (var j = 0; j < xs.length; j++) { + if (arraysFromX[input.id]) { + arraysFromX[node.output.id] = true; + break; + } + } + if (arraysFromX[node.output.id]) { + break; + } + } + } + var arraysLeadToY = {}; + arraysLeadToY[y.id] = true; + for (var i = tapeNodes.length - 1; i >= 0; i--) { + var node = tapeNodes[i]; + var nodeInputs = node.inputAndArgs.inputs; + if (arraysLeadToY[node.output.id]) { + for (var inputName in nodeInputs) { + arraysLeadToY[nodeInputs[inputName].id] = true; + } + } + } + var filteredTapeNodes = []; + for (var i = 0; i < tapeNodes.length; i++) { + var node = tapeNodes[i]; + if (arraysFromX[node.output.id] && arraysLeadToY[node.output.id]) { + var prunedInputs = {}; + for (var inputName in node.inputAndArgs.inputs) { + var nodeInput = node.inputAndArgs.inputs[inputName]; + if (arraysFromX[nodeInput.id]) { + prunedInputs[inputName] = nodeInput; + } + } + var prunedNode = Object.assign({}, node); + prunedNode.inputAndArgs = { inputs: prunedInputs }; + filteredTapeNodes.push(prunedNode); + } + } + return filteredTapeNodes; +} +exports.getFilteredNodesXToY = getFilteredNodesXToY; +function backpropagateGradients(backend, arrayAccumulatedGradientMap, filteredNodes) { + for (var i = filteredNodes.length - 1; i >= 0; i--) { + var node = filteredNodes[i]; + var dy = arrayAccumulatedGradientMap[node.output.id]; + if (node.gradient == null) { + throw new Error("Cannot compute gradient: gradient function not found for\n " + node.name + "."); + } + var inputGradients = node.gradient(dy, node.output); + for (var inputName in node.inputAndArgs.inputs) { + if (!(inputName in inputGradients)) { + throw new Error("Cannot backprop through input " + + (node.name + "." + inputName + ". Gradients found: ") + + (Object.keys(inputGradients) + ".")); + } + var grad = inputGradients[inputName](); + var activation = node.inputAndArgs.inputs[inputName]; + if (arrayAccumulatedGradientMap[activation.id] == null) { + arrayAccumulatedGradientMap[activation.id] = grad; + } + else { + var curGradient = arrayAccumulatedGradientMap[activation.id]; + arrayAccumulatedGradientMap[activation.id] = + backend.add(curGradient, grad); + curGradient.dispose(); + } + } + } +} +exports.backpropagateGradients = backpropagateGradients; + +},{}],61:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var MatrixOrientation; +(function (MatrixOrientation) { + MatrixOrientation[MatrixOrientation["REGULAR"] = 0] = "REGULAR"; + MatrixOrientation[MatrixOrientation["TRANSPOSED"] = 1] = "TRANSPOSED"; +})(MatrixOrientation = exports.MatrixOrientation || (exports.MatrixOrientation = {})); + +},{}],62:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ArgMinMaxProgram = (function () { + function ArgMinMaxProgram(reduceInfo, op, firstPass) { + this.variableNames = ['A']; + var windowSize = reduceInfo.windowSize; + var batchSize = reduceInfo.batchSize; + var inSize = reduceInfo.inSize; + var outSize = Math.ceil(inSize / windowSize); + if (!firstPass) { + this.variableNames.push('bestIndicesA'); + } + this.outputShape = [batchSize, outSize]; + var compOp = (op === 'max') ? '>' : '<'; + var indexSnippet = firstPass ? + 'inOffset + i;' : + 'round(getBestIndicesA(batch, inOffset + i));'; + this.userCode = "\n void main() {\n ivec2 coords = getOutputCoords();\n int batch = coords[0];\n int outIdx = coords[1];\n int inOffset = outIdx * " + windowSize + ";\n\n int bestIndex = 0;\n float bestValue = getA(batch, inOffset);\n\n for (int i = 0; i < " + windowSize + "; i++) {\n int inIdx = " + indexSnippet + ";\n float candidate = getA(batch, inIdx);\n if (isNaN(candidate)) {\n setOutput(candidate);\n return;\n }\n if (candidate " + compOp + " bestValue) {\n bestValue = candidate;\n bestIndex = inIdx;\n }\n }\n setOutput(float(bestIndex));\n }\n "; + } + return ArgMinMaxProgram; +}()); +exports.ArgMinMaxProgram = ArgMinMaxProgram; + +},{}],63:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var broadcast_util = require("../../broadcast_util"); +var BatchNormProgram = (function () { + function BatchNormProgram(xShape, meanShape, varianceShape, offsetShape, scaleShape, varianceEpsilon) { + this.outputShape = []; + this.supportsBroadcasting = true; + this.variableNames = ['x', 'mean', 'variance']; + broadcast_util.assertAndGetBroadcastShape(xShape, meanShape); + broadcast_util.assertAndGetBroadcastShape(xShape, varianceShape); + var offsetSnippet = '0.0'; + if (offsetShape != null) { + broadcast_util.assertAndGetBroadcastShape(xShape, offsetShape); + this.variableNames.push('offset'); + offsetSnippet = 'getOffsetAtOutCoords()'; + } + var scaleSnippet = '1.0'; + if (scaleShape != null) { + broadcast_util.assertAndGetBroadcastShape(xShape, scaleShape); + this.variableNames.push('scale'); + scaleSnippet = 'getScaleAtOutCoords()'; + } + this.outputShape = xShape; + this.userCode = "\n void main() {\n float x = getXAtOutCoords();\n float mean = getMeanAtOutCoords();\n float variance = getVarianceAtOutCoords();\n float offset = " + offsetSnippet + ";\n float scale = " + scaleSnippet + ";\n float inv = scale / sqrt(variance + float(" + varianceEpsilon + "));\n setOutput((x - mean) * inv + offset);\n }\n "; + } + return BatchNormProgram; +}()); +exports.BatchNormProgram = BatchNormProgram; + +},{"../../broadcast_util":90}],64:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var broadcast_util = require("../../broadcast_util"); +exports.ADD = 'return a + b;'; +exports.SUB = 'return a - b;'; +exports.MUL = 'return a * b;'; +exports.DIV = 'return a / b;'; +exports.POW = "\n return (round(mod(b, 2.0)) == 0 || round(mod(b, 2.0)) == 2) ?\n pow(abs(a), b) : sign(a) * pow(abs(a), b);\n"; +exports.EQUAL = "\n if (isNaN(a)) return a;\n if (isNaN(b)) return b;\n return float(a == b);\n"; +exports.PRELU = "\n return (a >= 0.0) ? a : b * a;\n"; +exports.PRELU_DER = "\n return (a > 0.0) ? 1.0 : ((a < 0.0) ? b : a);\n"; +var BinaryOpProgram = (function () { + function BinaryOpProgram(op, aShape, bShape) { + this.variableNames = ['A', 'B']; + this.supportsBroadcasting = true; + this.outputShape = + broadcast_util.assertAndGetBroadcastShape(aShape, bShape); + this.userCode = "\n float binaryOperation(float a, float b) {\n " + op + "\n }\n\n void main() {\n float a = getAAtOutCoords();\n float b = getBAtOutCoords();\n setOutput(binaryOperation(a, b));\n }\n "; + } + return BinaryOpProgram; +}()); +exports.BinaryOpProgram = BinaryOpProgram; + +},{"../../broadcast_util":90}],65:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ClipProgram = (function () { + function ClipProgram(aShape, min, max) { + this.variableNames = ['A']; + this.outputShape = aShape; + var minFixed = min.toFixed(20); + var maxFixed = max.toFixed(20); + this.userCode = "\n void main() {\n float value = getAAtOutCoords();\n if (isNaN(value)) {\n setOutput(value);\n return;\n }\n\n setOutput(clamp(value, " + minFixed + ", " + maxFixed + "));\n }\n "; + } + return ClipProgram; +}()); +exports.ClipProgram = ClipProgram; + +},{}],66:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var concat_util = require("../../concat_util"); +var shader_compiler_1 = require("./shader_compiler"); +var ConcatProgram = (function () { + function ConcatProgram(aShape, bShape, axis) { + this.variableNames = ['A', 'B']; + this.outputShape = []; + var yAxes = ['yR', 'yC', 'yD', 'yW']; + var concatAxis = yAxes[axis]; + this.outputShape = concat_util.computeOutShape(aShape, bShape, axis); + var dType = shader_compiler_1.getCoordsDataType(aShape.length); + var unpackSnippet = getUnpack(aShape.length); + var sampleCoords = getSampleCoords(aShape.length); + this.userCode = "\n void main() {\n " + dType + " coords = getOutputCoords();\n " + unpackSnippet + "\n\n float value = 0.0;\n if (" + concatAxis + " < " + aShape[axis] + ") {\n value = getA(" + sampleCoords + ");\n } else {\n " + concatAxis + " -= " + aShape[axis] + ";\n value = getB(" + sampleCoords + ");\n }\n\n setOutput(value);\n }\n "; + } + return ConcatProgram; +}()); +exports.ConcatProgram = ConcatProgram; +function getSampleCoords(rank) { + if (rank === 1) { + return 'yR'; + } + else if (rank === 2) { + return 'yR, yC'; + } + else if (rank === 3) { + return 'yR, yC, yD'; + } + else if (rank === 4) { + return 'yR, yC, yD, yW'; + } + else { + throw Error("Concat for rank " + rank + " is not yet supported"); + } +} +function getUnpack(rank) { + var res = rank === 1 ? 'int yR = coords;' : 'int yR = coords.x;'; + if (rank > 1) { + res += '\nint yC = coords.y;'; + } + if (rank > 2) { + res += '\nint yD = coords.z;'; + } + if (rank > 3) { + res += '\nint yW = coords.w;'; + } + if (rank > 4) { + throw Error("Concat for rank " + rank + " is not yet supported"); + } + return res; +} + +},{"../../concat_util":91,"./shader_compiler":82}],67:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Conv2DDerFilterProgram = (function () { + function Conv2DDerFilterProgram(convInfo) { + this.variableNames = ['x', 'dy']; + this.outputShape = convInfo.filterShape; + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var padTop = convInfo.padInfo.top; + var padLeft = convInfo.padInfo.left; + this.userCode = "\n void main() {\n ivec4 coords = getOutputCoords();\n int wR = coords.x;\n int wC = coords.y;\n int d1 = coords.z;\n int d2 = coords.w;\n\n // Convolve x(?, ?, d1) with dy(:, :, d2) to get dw(wR, wC, d1, d2).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n\n for (int b = 0; b < " + convInfo.batchSize + "; b++) {\n for (int yR = 0; yR < " + convInfo.outHeight + "; yR++) {\n int xR = wR + yR * " + strideHeight + " - " + padTop + ";\n\n if (xR < 0 || xR >= " + convInfo.inHeight + ") {\n continue;\n }\n\n for (int yC = 0; yC < " + convInfo.outWidth + "; yC++) {\n int xC = wC + yC * " + strideWidth + " - " + padLeft + ";\n\n if (xC < 0 || xC >= " + convInfo.inWidth + ") {\n continue;\n }\n\n float dyValue = getDy(b, yR, yC, d2);\n float xValue = getX(b, xR, xC, d1);\n dotProd += (xValue * dyValue);\n }\n }\n }\n setOutput(dotProd);\n }\n "; + } + return Conv2DDerFilterProgram; +}()); +exports.Conv2DDerFilterProgram = Conv2DDerFilterProgram; +var Conv2DDerInputProgram = (function () { + function Conv2DDerInputProgram(convInfo) { + this.variableNames = ['dy', 'W']; + this.outputShape = convInfo.inShape; + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var padTop = filterHeight - 1 - convInfo.padInfo.top; + var padLeft = filterWidth - 1 - convInfo.padInfo.left; + this.userCode = "\n const ivec2 pads = ivec2(" + padTop + ", " + padLeft + ");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d1 = coords[3];\n\n ivec2 dyCorner = coords.yz - pads;\n int dyRCorner = dyCorner.x;\n int dyCCorner = dyCorner.y;\n\n // Convolve dy(?, ?, d2) with w(:, :, d1, d2) to compute dx(xR, xC, d1).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n for (int wR = 0; wR < " + filterHeight + "; wR++) {\n float dyR = float(dyRCorner + wR) / " + strideHeight + ".0;\n\n if (dyR < 0.0 || dyR >= " + convInfo.outHeight + ".0 || fract(dyR) > 0.0) {\n continue;\n }\n int idyR = int(dyR);\n\n int wRPerm = " + filterHeight + " - 1 - wR;\n\n for (int wC = 0; wC < " + filterWidth + "; wC++) {\n float dyC = float(dyCCorner + wC) / " + strideWidth + ".0;\n\n if (dyC < 0.0 || dyC >= " + convInfo.outWidth + ".0 ||\n fract(dyC) > 0.0) {\n continue;\n }\n int idyC = int(dyC);\n\n int wCPerm = " + filterWidth + " - 1 - wC;\n\n for (int d2 = 0; d2 < " + convInfo.outChannels + "; d2++) {\n float xValue = getDy(batch, idyR, idyC, d2);\n float wValue = getW(wRPerm, wCPerm, d1, d2);\n dotProd += xValue * wValue;\n }\n }\n }\n setOutput(dotProd);\n }\n "; + } + return Conv2DDerInputProgram; +}()); +exports.Conv2DDerInputProgram = Conv2DDerInputProgram; +var Conv2DDerBiasProgram = (function () { + function Conv2DDerBiasProgram(yShape) { + this.variableNames = ['dy']; + var batchSize = yShape[0], yNumRows = yShape[1], yNumCols = yShape[2], outputDepth = yShape[3]; + this.outputShape = [outputDepth]; + this.userCode = "\n void main() {\n int d2 = getOutputCoords();\n\n float derBias = 0.0;\n for (int b = 0; b < " + batchSize + "; b++) {\n for (int yR = 0; yR < " + yNumRows + "; yR++) {\n for (int yC = 0; yC < " + yNumCols + "; yC++) {\n derBias += getDy(b, yR, yC, d2);\n }\n }\n }\n setOutput(derBias);\n }\n "; + } + return Conv2DDerBiasProgram; +}()); +exports.Conv2DDerBiasProgram = Conv2DDerBiasProgram; + +},{}],68:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Conv2DProgram = (function () { + function Conv2DProgram(convInfo, hasBias) { + this.variableNames = ['x', 'W']; + if (hasBias) { + this.variableNames.push('bias'); + } + this.outputShape = convInfo.outShape; + var biasSnippet = hasBias ? 'dotProd += getBias(d2);' : ''; + var padTop = convInfo.padInfo.top; + var padLeft = convInfo.padInfo.left; + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var inputDepthNearestVec4 = Math.floor(convInfo.inChannels / 4) * 4; + var inputDepthVec4Remainder = convInfo.inChannels % 4; + this.userCode = "\n const ivec2 strides = ivec2(" + strideHeight + ", " + strideWidth + ");\n const ivec2 pads = ivec2(" + padTop + ", " + padLeft + ");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d2 = coords[3];\n\n ivec2 xRCCorner = coords.yz * strides - pads;\n int xRCorner = xRCCorner.x;\n int xCCorner = xRCCorner.y;\n\n // Convolve x(?, ?, d1) with w(:, :, d1, d2) to get y(yR, yC, d2).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n for (int wR = 0; wR < " + filterHeight + "; wR++) {\n int xR = xRCorner + wR;\n\n if (xR < 0 || xR >= " + convInfo.inHeight + ") {\n continue;\n }\n\n for (int wC = 0; wC < " + filterWidth + "; wC++) {\n int xC = xCCorner + wC;\n\n if (xC < 0 || xC >= " + convInfo.inWidth + ") {\n continue;\n }\n\n for (int d1 = 0; d1 < " + inputDepthNearestVec4 + "; d1 += 4) {\n vec4 xValues = vec4(\n getX(batch, xR, xC, d1),\n getX(batch, xR, xC, d1 + 1),\n getX(batch, xR, xC, d1 + 2),\n getX(batch, xR, xC, d1 + 3)\n );\n vec4 wValues = vec4(\n getW(wR, wC, d1, d2),\n getW(wR, wC, d1 + 1, d2),\n getW(wR, wC, d1 + 2, d2),\n getW(wR, wC, d1 + 3, d2)\n );\n\n dotProd += dot(xValues, wValues);\n }\n\n if (" + (inputDepthVec4Remainder === 1) + ") {\n dotProd +=\n getX(batch, xR, xC, " + inputDepthNearestVec4 + ") *\n getW(wR, wC, " + inputDepthNearestVec4 + ", d2);\n } else if (" + (inputDepthVec4Remainder === 2) + ") {\n vec2 xValues = vec2(\n getX(batch, xR, xC, " + inputDepthNearestVec4 + "),\n getX(batch, xR, xC, " + inputDepthNearestVec4 + " + 1)\n );\n vec2 wValues = vec2(\n getW(wR, wC, " + inputDepthNearestVec4 + ", d2),\n getW(wR, wC, " + inputDepthNearestVec4 + " + 1, d2)\n );\n dotProd += dot(xValues, wValues);\n } else if (" + (inputDepthVec4Remainder === 3) + ") {\n vec3 xValues = vec3(\n getX(batch, xR, xC, " + inputDepthNearestVec4 + "),\n getX(batch, xR, xC, " + inputDepthNearestVec4 + " + 1),\n getX(batch, xR, xC, " + inputDepthNearestVec4 + " + 2)\n );\n vec3 wValues = vec3(\n getW(wR, wC, " + inputDepthNearestVec4 + ", d2),\n getW(wR, wC, " + inputDepthNearestVec4 + " + 1, d2),\n getW(wR, wC, " + inputDepthNearestVec4 + " + 2, d2)\n );\n dotProd += dot(xValues, wValues);\n }\n }\n }\n " + biasSnippet + "\n setOutput(dotProd);\n }\n "; + } + return Conv2DProgram; +}()); +exports.Conv2DProgram = Conv2DProgram; + +},{}],69:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var DepthwiseConv2DProgram = (function () { + function DepthwiseConv2DProgram(convInfo) { + this.variableNames = ['x', 'W']; + this.outputShape = convInfo.outShape; + var xNumRows = convInfo.inHeight; + var xNumCols = convInfo.inWidth; + var padTop = convInfo.padInfo.top; + var padLeft = convInfo.padInfo.left; + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var channelMul = convInfo.outChannels / convInfo.inChannels; + this.userCode = "\n const ivec2 strides = ivec2(" + strideHeight + ", " + strideWidth + ");\n const ivec2 pads = ivec2(" + padTop + ", " + padLeft + ");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords.x;\n ivec2 xRCCorner = coords.yz * strides - pads;\n int d2 = coords.w;\n int d1 = d2 / " + channelMul + ";\n int q = d2 - d1 * " + channelMul + ";\n\n int xRCorner = xRCCorner.x;\n int xCCorner = xRCCorner.y;\n\n // Convolve x(?, ?, d1) with w(:, :, d1, q) to get y(yR, yC, d2).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n // TODO(dsmilkov): Flatten the two for loops and vec4 the operations.\n for (int wR = 0; wR < " + filterHeight + "; wR++) {\n int xR = xRCorner + wR;\n\n if (xR < 0 || xR >= " + xNumRows + ") {\n continue;\n }\n\n for (int wC = 0; wC < " + filterWidth + "; wC++) {\n int xC = xCCorner + wC;\n\n if (xC < 0 || xC >= " + xNumCols + ") {\n continue;\n }\n\n float xVal = getX(batch, xR, xC, d1);\n float wVal = getW(wR, wC, d1, q);\n dotProd += xVal * wVal;\n }\n }\n setOutput(dotProd);\n }\n "; + } + return DepthwiseConv2DProgram; +}()); +exports.DepthwiseConv2DProgram = DepthwiseConv2DProgram; + +},{}],70:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Copy2DProgram = (function () { + function Copy2DProgram(srcNumCols, destNumCols) { + this.variableNames = ['source']; + this.outputShape = null; + this.userCode = "\n uniform ivec2 sourceStart;\n uniform ivec2 destStart;\n\n void main() {\n ivec2 destCoords = getOutputCoords() - destStart;\n int index = destCoords.x * " + destNumCols + " + destCoords.y;\n int r = index / " + srcNumCols + ";\n ivec2 sourceCoords = sourceStart + ivec2(r, index - r * " + srcNumCols + ");\n setOutput(getSource(sourceCoords.x, sourceCoords.y));\n }\n "; + } + Copy2DProgram.prototype.getCustomSetupFunc = function (sourceStart, destStart, destSize) { + return function (gpgpu, webGLProgram) { + gpgpu.setOutputMatrixWriteRegion(destStart[0], destSize[0], destStart[1], destSize[1]); + var sourceStartCRLoc = gpgpu.getUniformLocation(webGLProgram, 'sourceStart'); + gpgpu.gl.uniform2i(sourceStartCRLoc, sourceStart[0], sourceStart[1]); + var destStartCRLoc = gpgpu.getUniformLocation(webGLProgram, 'destStart'); + gpgpu.gl.uniform2i(destStartCRLoc, destStart[0], destStart[1]); + }; + }; + return Copy2DProgram; +}()); +exports.Copy2DProgram = Copy2DProgram; + +},{}],71:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../../environment"); +var util = require("../../../util"); +var gpgpu_util = require("./gpgpu_util"); +var tex_util = require("./tex_util"); +var webgl_util = require("./webgl_util"); +var GPGPUContext = (function () { + function GPGPUContext(gl) { + this.outputTexture = null; + this.program = null; + this.disposed = false; + this.autoDebugValidate = false; + if (gl != null) { + this.gl = gl; + } + else { + this.gl = gpgpu_util.createWebGLContext(); + } + if (environment_1.ENV.get('WEBGL_VERSION') === 1) { + this.textureFloatExtension = + webgl_util.getExtensionOrThrow(this.gl, 'OES_texture_float'); + this.colorBufferFloatExtension = + this.gl.getExtension('WEBGL_color_buffer_float'); + } + else { + this.colorBufferFloatExtension = + webgl_util.getExtensionOrThrow(this.gl, 'EXT_color_buffer_float'); + } + this.loseContextExtension = + webgl_util.getExtensionOrThrow(this.gl, 'WEBGL_lose_context'); + if (environment_1.ENV.get('WEBGL_GET_BUFFER_SUB_DATA_ASYNC_EXTENSION_ENABLED')) { + this.getBufferSubDataAsyncExtension = + this.gl.getExtension('WEBGL_get_buffer_sub_data_async'); + } + this.vertexBuffer = gpgpu_util.createVertexBuffer(this.gl); + this.indexBuffer = gpgpu_util.createIndexBuffer(this.gl); + this.framebuffer = webgl_util.createFramebuffer(this.gl); + } + GPGPUContext.prototype.dispose = function () { + var _this = this; + this.throwIfDisposed(); + if (this.program != null) { + console.warn('Disposing a GPGPUContext that still has a bound WebGLProgram.' + + ' This is probably a resource leak, delete the program with ' + + 'GPGPUContext.deleteProgram before disposing.'); + } + if (this.outputTexture != null) { + console.warn('Disposing a GPGPUContext that still has a bound output matrix ' + + 'texture. This is probably a resource leak, delete the output ' + + 'matrix texture with GPGPUContext.deleteMatrixTexture before ' + + 'disposing.'); + } + var gl = this.gl; + webgl_util.callAndCheck(gl, function () { return gl.finish(); }); + webgl_util.callAndCheck(gl, function () { return gl.bindFramebuffer(gl.FRAMEBUFFER, null); }); + webgl_util.callAndCheck(gl, function () { return gl.deleteFramebuffer(_this.framebuffer); }); + webgl_util.callAndCheck(gl, function () { return gl.bindBuffer(gl.ARRAY_BUFFER, null); }); + webgl_util.callAndCheck(gl, function () { return gl.deleteBuffer(_this.vertexBuffer); }); + webgl_util.callAndCheck(gl, function () { return gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); }); + webgl_util.callAndCheck(gl, function () { return gl.deleteBuffer(_this.indexBuffer); }); + this.loseContextExtension.loseContext(); + this.disposed = true; + }; + GPGPUContext.prototype.enableAutomaticDebugValidation = function (enabled) { + this.autoDebugValidate = enabled; + webgl_util.enableDebugWebGLErrorChecking(enabled); + }; + GPGPUContext.prototype.createMatrixTexture = function (rows, columns) { + this.throwIfDisposed(); + return gpgpu_util.createMatrixTexture(this.gl, rows, columns); + }; + GPGPUContext.prototype.uploadPixelDataToTexture = function (texture, pixels) { + this.throwIfDisposed(); + gpgpu_util.uploadPixelDataToTexture(this.gl, texture, pixels); + }; + GPGPUContext.prototype.createPackedMatrixTexture = function (rows, columns) { + this.throwIfDisposed(); + return gpgpu_util.createPackedMatrixTexture(this.gl, rows, columns); + }; + GPGPUContext.prototype.deleteMatrixTexture = function (texture) { + var _this = this; + this.throwIfDisposed(); + if (this.outputTexture === texture) { + webgl_util.unbindColorTextureFromFramebuffer(this.gl, this.framebuffer); + this.outputTexture = null; + } + webgl_util.callAndCheck(this.gl, function () { return _this.gl.deleteTexture(texture); }); + }; + GPGPUContext.prototype.uploadMatrixToTexture = function (texture, rows, columns, matrix) { + this.throwIfDisposed(); + var numChannels = 1; + return gpgpu_util.uploadMatrixToTexture(this.gl, texture, rows, columns, matrix, numChannels); + }; + GPGPUContext.prototype.uploadMatrixToPackedTexture = function (texture, rows, columns, matrix) { + this.throwIfDisposed(); + return gpgpu_util.uploadMatrixToPackedTexture(this.gl, texture, rows, columns, matrix); + }; + GPGPUContext.prototype.downloadMatrixFromTexture = function (texture, rows, columns) { + var _this = this; + return this.downloadMatrixDriver(texture, function () { + return gpgpu_util.downloadMatrixFromOutputTexture(_this.gl, rows, columns); + }); + }; + GPGPUContext.prototype.downloadMatrixFromTextureAsync = function (texture, rows, columns) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + if (this.getBufferSubDataAsyncExtension == null) { + throw new Error("Cannot download matrix from output texture asynchronously, " + + "WEBGL_get_buffer_sub_data_async is not enabled."); + } + return [2, this.downloadMatrixDriverAsync(texture, function () { return gpgpu_util.downloadMatrixFromOutputTextureAsync(_this.gl, _this.getBufferSubDataAsyncExtension, rows, columns); })]; + }); + }); + }; + GPGPUContext.prototype.downloadMatrixFromRGBAColorTexture = function (texture, rows, columns, channels) { + var _this = this; + return this.downloadMatrixDriver(texture, function () { return gpgpu_util.downloadMatrixFromRGBAColorTexture(_this.gl, rows, columns, channels); }); + }; + GPGPUContext.prototype.downloadMatrixFromPackedTexture = function (texture, rows, columns) { + var _this = this; + return this.downloadMatrixDriver(texture, function () { return gpgpu_util.downloadMatrixFromPackedOutputTexture(_this.gl, rows, columns); }); + }; + GPGPUContext.prototype.createProgram = function (fragmentShaderSource) { + this.throwIfDisposed(); + var gl = this.gl; + var fragmentShader = webgl_util.createFragmentShader(gl, fragmentShaderSource); + var vertexShader = gpgpu_util.createVertexShader(gl); + var program = webgl_util.createProgram(gl); + webgl_util.callAndCheck(gl, function () { return gl.attachShader(program, vertexShader); }); + webgl_util.callAndCheck(gl, function () { return gl.attachShader(program, fragmentShader); }); + webgl_util.linkProgram(gl, program); + if (this.autoDebugValidate) { + webgl_util.validateProgram(gl, program); + } + return program; + }; + GPGPUContext.prototype.deleteProgram = function (program) { + var _this = this; + this.throwIfDisposed(); + if (program === this.program) { + this.program = null; + } + if (program != null) { + webgl_util.callAndCheck(this.gl, function () { return _this.gl.deleteProgram(program); }); + } + }; + GPGPUContext.prototype.setProgram = function (program) { + var _this = this; + this.throwIfDisposed(); + this.program = program; + if ((this.program != null) && this.autoDebugValidate) { + webgl_util.validateProgram(this.gl, this.program); + } + webgl_util.callAndCheck(this.gl, function () { return _this.gl.useProgram(program); }); + }; + GPGPUContext.prototype.getUniformLocation = function (program, uniformName) { + this.throwIfDisposed(); + return webgl_util.getProgramUniformLocationOrThrow(this.gl, program, uniformName); + }; + GPGPUContext.prototype.getAttributeLocation = function (program, attribute) { + var _this = this; + this.throwIfDisposed(); + return webgl_util.callAndCheck(this.gl, function () { return _this.gl.getAttribLocation(program, attribute); }); + }; + GPGPUContext.prototype.getUniformLocationNoThrow = function (program, uniformName) { + this.throwIfDisposed(); + return this.gl.getUniformLocation(program, uniformName); + }; + GPGPUContext.prototype.setInputMatrixTexture = function (inputMatrixTexture, uniformLocation, textureUnit) { + this.throwIfDisposed(); + this.throwIfNoProgram(); + webgl_util.bindTextureToProgramUniformSampler(this.gl, this.program, inputMatrixTexture, uniformLocation, textureUnit); + }; + GPGPUContext.prototype.setOutputMatrixTexture = function (outputMatrixTexture, rows, columns) { + this.setOutputMatrixTextureDriver(outputMatrixTexture, columns, rows); + }; + GPGPUContext.prototype.setOutputPackedMatrixTexture = function (outputPackedMatrixTexture, rows, columns) { + this.throwIfDisposed(); + var _a = tex_util.getPackedMatrixTextureShapeWidthHeight(rows, columns), width = _a[0], height = _a[1]; + this.setOutputMatrixTextureDriver(outputPackedMatrixTexture, width, height); + }; + GPGPUContext.prototype.setOutputMatrixWriteRegion = function (startRow, numRows, startColumn, numColumns) { + this.setOutputMatrixWriteRegionDriver(startColumn, startRow, numColumns, numRows); + }; + GPGPUContext.prototype.setOutputPackedMatrixWriteRegion = function (startRow, numRows, startColumn, numColumns) { + throw new Error('setOutputPackedMatrixWriteRegion not implemented.'); + }; + GPGPUContext.prototype.debugValidate = function () { + if (this.program != null) { + webgl_util.validateProgram(this.gl, this.program); + } + webgl_util.validateFramebuffer(this.gl); + }; + GPGPUContext.prototype.executeProgram = function (attribLocations) { + this.throwIfDisposed(); + this.throwIfNoProgram(); + var gl = this.gl; + gpgpu_util.bindVertexProgramAttributeStreams(gl, this.program, this.vertexBuffer, attribLocations); + if (this.autoDebugValidate) { + this.debugValidate(); + } + webgl_util.callAndCheck(gl, function () { return gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); }); + }; + GPGPUContext.prototype.blockUntilAllProgramsCompleted = function () { + var _this = this; + this.throwIfDisposed(); + webgl_util.callAndCheck(this.gl, function () { return _this.gl.finish(); }); + }; + GPGPUContext.prototype.runQuery = function (queryFn) { + if (environment_1.ENV.get('WEBGL_VERSION') === 2) { + return this.runQueryWebGL2(queryFn); + } + return this.runQueryWebGL1(queryFn); + }; + GPGPUContext.prototype.runQueryWebGL2 = function (benchmark) { + var _this = this; + var ext = webgl_util.getExtensionOrThrow(this.gl, 'EXT_disjoint_timer_query_webgl2'); + var query = this.gl.createQuery(); + this.gl.beginQuery(ext.TIME_ELAPSED_EXT, query); + benchmark(); + this.gl.endQuery(ext.TIME_ELAPSED_EXT); + return new Promise(function (resolve, reject) { + var queryGPU = function () { + var available = _this.gl + .getQueryParameter(query, _this.gl.QUERY_RESULT_AVAILABLE); + var disjoint = _this.gl.getParameter(ext.GPU_DISJOINT_EXT); + return available && !disjoint; + }; + var getTimeElapsed = function () { + var timeElapsedNanos = _this.gl + .getQueryParameter(query, _this.gl.QUERY_RESULT); + resolve(timeElapsedNanos / 1000000); + }; + var resolveWithWarning = function () { + console.warn('Disjoint query timer never available.'); + resolve(-1); + }; + util.repeatedTry(queryGPU).then(getTimeElapsed).catch(resolveWithWarning); + }); + }; + GPGPUContext.prototype.runQueryWebGL1 = function (benchmark) { + var _this = this; + var ext = webgl_util.getExtensionOrThrow(this.gl, 'EXT_disjoint_timer_query'); + var query = ext.createQueryEXT(); + ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query); + benchmark(); + ext.endQueryEXT(ext.TIME_ELAPSED_EXT); + return new Promise(function (resolve, reject) { + var queryGPU = function () { + var available = ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT); + var disjoint = _this.gl.getParameter(ext.GPU_DISJOINT_EXT); + return available && !disjoint; + }; + var getTimeElapsed = function () { + var timeElapsedNanos = ext.getQueryObjectEXT(query, ext.QUERY_RESULT_EXT); + resolve(timeElapsedNanos / 1000000); + }; + var resolveWithWarning = function () { + console.warn('Disjoint query timer never available.'); + resolve(-1); + }; + util.repeatedTry(queryGPU).then(getTimeElapsed).catch(resolveWithWarning); + }); + }; + GPGPUContext.prototype.downloadMatrixDriverSetup = function (texture) { + this.throwIfDisposed(); + webgl_util.bindColorTextureToFramebuffer(this.gl, texture, this.framebuffer); + if (this.autoDebugValidate) { + webgl_util.validateFramebuffer(this.gl); + } + }; + GPGPUContext.prototype.downloadMatrixDriverTeardown = function () { + if (this.outputTexture != null) { + webgl_util.bindColorTextureToFramebuffer(this.gl, this.outputTexture, this.framebuffer); + if (this.autoDebugValidate) { + webgl_util.validateFramebuffer(this.gl); + } + } + else { + webgl_util.unbindColorTextureFromFramebuffer(this.gl, this.framebuffer); + } + }; + GPGPUContext.prototype.downloadMatrixDriver = function (texture, downloadAndDecode) { + this.downloadMatrixDriverSetup(texture); + var result = downloadAndDecode(); + this.downloadMatrixDriverTeardown(); + return result; + }; + GPGPUContext.prototype.downloadMatrixDriverAsync = function (texture, downloadAndDecode) { + return __awaiter(this, void 0, void 0, function () { + var result; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.downloadMatrixDriverSetup(texture); + return [4, downloadAndDecode()]; + case 1: + result = _a.sent(); + this.downloadMatrixDriverTeardown(); + return [2, result]; + } + }); + }); + }; + GPGPUContext.prototype.setOutputMatrixTextureDriver = function (outputMatrixTextureMaybePacked, width, height) { + this.throwIfDisposed(); + var gl = this.gl; + webgl_util.bindColorTextureToFramebuffer(gl, outputMatrixTextureMaybePacked, this.framebuffer); + if (this.autoDebugValidate) { + webgl_util.validateFramebuffer(gl); + } + this.outputTexture = outputMatrixTextureMaybePacked; + webgl_util.callAndCheck(gl, function () { return gl.viewport(0, 0, width, height); }); + webgl_util.callAndCheck(gl, function () { return gl.scissor(0, 0, width, height); }); + }; + GPGPUContext.prototype.setOutputMatrixWriteRegionDriver = function (x, y, width, height) { + var _this = this; + this.throwIfDisposed(); + webgl_util.callAndCheck(this.gl, function () { return _this.gl.scissor(x, y, width, height); }); + }; + GPGPUContext.prototype.throwIfDisposed = function () { + if (this.disposed) { + throw new Error('Attempted to use disposed GPGPUContext.'); + } + }; + GPGPUContext.prototype.throwIfNoProgram = function () { + if (this.program == null) { + throw new Error('No GPU program is currently set.'); + } + }; + return GPGPUContext; +}()); +exports.GPGPUContext = GPGPUContext; + +},{"../../../environment":15,"../../../util":101,"./gpgpu_util":73,"./tex_util":84,"./webgl_util":89}],72:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../../environment"); +var util = require("../../../util"); +var shader_compiler = require("./shader_compiler"); +var ATTRIBUTE_NAMES = ['uv', 'clipSpacePos']; +var NAN_UNIFORM_NAME = 'NaN'; +function shouldUploadNaNUniform() { + return !environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED'); +} +function compileProgram(gpgpu, program, inputs, output) { + var userCode = program.userCode; + var inputInfos = inputs.map(function (input, i) { + var shapeInfo = { + logicalShape: input.array.shape, + texShape: input.texData.texShape, + textureType: input.texData.textureType + }; + return { name: program.variableNames[i], shapeInfo: shapeInfo }; + }); + var inShapeInfos = inputInfos.map(function (x) { return x.shapeInfo; }); + var outShapeInfo = { + logicalShape: output.array.shape, + texShape: output.texData.texShape, + textureType: output.texData.textureType + }; + var source = shader_compiler.makeShader(inputInfos, outShapeInfo, userCode, program.supportsBroadcasting === true); + var webGLProgram = gpgpu.createProgram(source); + var uniformLocations = {}; + for (var i = 0; i < program.variableNames.length; i++) { + var uniformName = program.variableNames[i]; + uniformLocations[uniformName] = + gpgpu.getUniformLocation(webGLProgram, uniformName); + } + var attributeLocations = {}; + ATTRIBUTE_NAMES.forEach(function (attribute) { + attributeLocations[attribute] = + gpgpu.getAttributeLocation(webGLProgram, attribute); + }); + if (shouldUploadNaNUniform()) { + uniformLocations[NAN_UNIFORM_NAME] = + gpgpu.getUniformLocation(webGLProgram, NAN_UNIFORM_NAME); + } + return { + program: program, + source: source, + webGLProgram: webGLProgram, + uniformLocations: uniformLocations, + attributeLocations: attributeLocations, + gpgpu: gpgpu, + inShapeInfos: inShapeInfos, + outShapeInfo: outShapeInfo + }; +} +exports.compileProgram = compileProgram; +function validateBinaryAndProgram(shapeInfos, inputs) { + if (shapeInfos.length !== inputs.length) { + throw Error("Binary was compiled with " + shapeInfos.length + " inputs, but " + + ("was executed with " + inputs.length + " inputs")); + } + shapeInfos.forEach(function (s, i) { + var shapeA = s.logicalShape; + var texShapeA = s.texShape; + var shapeB = inputs[i].array.shape; + var texShapeB = inputs[i].texData.texShape; + if (!util.arraysEqual(shapeA, shapeB)) { + throw Error("Binary was compiled with different shapes than " + + ("the current args. Shapes " + shapeA + " and " + shapeB + " must match")); + } + if (!util.arraysEqual(texShapeA, texShapeB)) { + throw Error("Binary was compiled with different texture shapes than the" + + (" current args. Shape " + texShapeA + " and " + texShapeB + " must match")); + } + }); +} +function runProgram(binary, inputs, output, customSetup) { + validateBinaryAndProgram(binary.inShapeInfos, inputs); + validateBinaryAndProgram([binary.outShapeInfo], [output]); + var outTex = output.texData.texture; + var outTexShape = output.texData.texShape; + var gpgpu = binary.gpgpu; + gpgpu.setOutputMatrixTexture(outTex, outTexShape[0], outTexShape[1]); + gpgpu.setProgram(binary.webGLProgram); + inputs.forEach(function (input, i) { + var tex = input.texData.texture; + var variableName = binary.program.variableNames[i]; + var variableUniformLocation = binary.uniformLocations[variableName]; + gpgpu.setInputMatrixTexture(tex, variableUniformLocation, i); + }); + if (shouldUploadNaNUniform()) { + gpgpu.gl.uniform1f(binary.uniformLocations[NAN_UNIFORM_NAME], NaN); + } + if (customSetup != null) { + customSetup(gpgpu, binary.webGLProgram); + } + gpgpu.executeProgram(binary.attributeLocations); +} +exports.runProgram = runProgram; +function makeShaderKey(program, inputs, output) { + var keyInputs = ''; + inputs.concat(output).forEach(function (x) { + keyInputs += x.array.shape + "_" + x.texData.texShape; + }); + var keyUserCode = program.userCode; + var keyBroadcast = (program.supportsBroadcasting === true).toString(); + var key = program.constructor.name; + key += '_' + keyBroadcast + '_' + keyInputs + '_' + keyUserCode; + return key; +} +exports.makeShaderKey = makeShaderKey; + +},{"../../../environment":15,"../../../util":101,"./shader_compiler":82}],73:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../../environment"); +var tex_util = require("./tex_util"); +var webgl_util = require("./webgl_util"); +function getWebGLContextAttributes() { + return { + alpha: false, + antialias: false, + premultipliedAlpha: false, + preserveDrawingBuffer: false, + depth: false, + stencil: false, + failIfMajorPerformanceCaveat: true + }; +} +exports.getWebGLContextAttributes = getWebGLContextAttributes; +function createWebGLContext(canvas) { + var attributes = getWebGLContextAttributes(); + var gl; + if (canvas != null) { + gl = webgl_util.createWebGLRenderingContextFromCanvas(canvas, attributes); + } + else { + gl = webgl_util.createWebGLRenderingContext(attributes); + } + webgl_util.callAndCheck(gl, function () { return gl.disable(gl.DEPTH_TEST); }); + webgl_util.callAndCheck(gl, function () { return gl.disable(gl.STENCIL_TEST); }); + webgl_util.callAndCheck(gl, function () { return gl.disable(gl.BLEND); }); + webgl_util.callAndCheck(gl, function () { return gl.disable(gl.DITHER); }); + webgl_util.callAndCheck(gl, function () { return gl.disable(gl.POLYGON_OFFSET_FILL); }); + webgl_util.callAndCheck(gl, function () { return gl.disable(gl.SAMPLE_COVERAGE); }); + webgl_util.callAndCheck(gl, function () { return gl.enable(gl.SCISSOR_TEST); }); + webgl_util.callAndCheck(gl, function () { return gl.enable(gl.CULL_FACE); }); + webgl_util.callAndCheck(gl, function () { return gl.cullFace(gl.BACK); }); + return gl; +} +exports.createWebGLContext = createWebGLContext; +function createVertexShader(gl) { + var vertexShaderSource = "\n precision highp float;\n attribute vec3 clipSpacePos;\n attribute vec2 uv;\n varying vec2 resultUV;\n\n void main() {\n gl_Position = vec4(clipSpacePos, 1);\n resultUV = uv;\n }"; + return webgl_util.createVertexShader(gl, vertexShaderSource); +} +exports.createVertexShader = createVertexShader; +function createVertexBuffer(gl) { + var vertexArray = new Float32Array([-1, 1, 0, 0, 1, -1, -1, 0, 0, 0, 1, 1, 0, 1, 1, 1, -1, 0, 1, 0]); + return webgl_util.createStaticVertexBuffer(gl, vertexArray); +} +exports.createVertexBuffer = createVertexBuffer; +function createIndexBuffer(gl) { + var triangleVertexIndices = new Uint16Array([0, 1, 2, 2, 1, 3]); + return webgl_util.createStaticIndexBuffer(gl, triangleVertexIndices); +} +exports.createIndexBuffer = createIndexBuffer; +function getTextureInternalFormat(gl, numChannels) { + if (!environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { + return gl.RGBA; + } + if (environment_1.ENV.get('WEBGL_VERSION') === 2) { + if (numChannels === 4) { + return gl.RGBA32F; + } + return gl.R32F; + } + return gl.RGBA; +} +function getTextureFormat(gl, numChannels) { + if (!environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { + return gl.RGBA; + } + if (environment_1.ENV.get('WEBGL_VERSION') === 2) { + if (numChannels === 4) { + return gl.RGBA; + } + return gl.RED; + } + return gl.RGBA; +} +function getTextureType(gl) { + if (!environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { + return gl.UNSIGNED_BYTE; + } + return gl.FLOAT; +} +function createAndConfigureTexture(gl, width, height, numChannels) { + webgl_util.validateTextureSize(gl, width, height); + var texture = webgl_util.createTexture(gl); + var tex2d = gl.TEXTURE_2D; + var internalFormat = getTextureInternalFormat(gl, numChannels); + var format = getTextureFormat(gl, numChannels); + webgl_util.callAndCheck(gl, function () { return gl.bindTexture(tex2d, texture); }); + webgl_util.callAndCheck(gl, function () { return gl.texParameteri(tex2d, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); }); + webgl_util.callAndCheck(gl, function () { return gl.texParameteri(tex2d, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); }); + webgl_util.callAndCheck(gl, function () { return gl.texParameteri(tex2d, gl.TEXTURE_MIN_FILTER, gl.NEAREST); }); + webgl_util.callAndCheck(gl, function () { return gl.texParameteri(tex2d, gl.TEXTURE_MAG_FILTER, gl.NEAREST); }); + webgl_util.callAndCheck(gl, function () { return gl.texImage2D(tex2d, 0, internalFormat, width, height, 0, format, getTextureType(gl), null); }); + webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, null); }); + return texture; +} +function createMatrixTexture(gl, rows, columns) { + var _a = tex_util.getUnpackedMatrixTextureShapeWidthHeight(rows, columns), width = _a[0], height = _a[1]; + var numChannels = 1; + return createAndConfigureTexture(gl, width, height, numChannels); +} +exports.createMatrixTexture = createMatrixTexture; +function createColorMatrixTexture(gl, rows, columns) { + var _a = tex_util.getColorMatrixTextureShapeWidthHeight(rows, columns), width = _a[0], height = _a[1]; + var numChannels = 4; + return createAndConfigureTexture(gl, width, height, numChannels); +} +exports.createColorMatrixTexture = createColorMatrixTexture; +function createPackedMatrixTexture(gl, rows, columns) { + var _a = tex_util.getPackedMatrixTextureShapeWidthHeight(rows, columns), width = _a[0], height = _a[1]; + var numChannels = 4; + return createAndConfigureTexture(gl, width, height, numChannels); +} +exports.createPackedMatrixTexture = createPackedMatrixTexture; +function bindVertexProgramAttributeStreams(gl, program, vertexBuffer, attribLocations) { + var posOffset = 0; + var uvOffset = 3 * 4; + var stride = (3 * 4) + (2 * 4); + webgl_util.callAndCheck(gl, function () { return gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); }); + webgl_util.bindVertexBufferToProgramAttribute(gl, program, 'clipSpacePos', vertexBuffer, 3, stride, posOffset, attribLocations); + webgl_util.bindVertexBufferToProgramAttribute(gl, program, 'uv', vertexBuffer, 2, stride, uvOffset, attribLocations); +} +exports.bindVertexProgramAttributeStreams = bindVertexProgramAttributeStreams; +function uploadPixelDataToTexture(gl, texture, pixels) { + webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, texture); }); + webgl_util.callAndCheck(gl, function () { return gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, pixels); }); + webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, null); }); +} +exports.uploadPixelDataToTexture = uploadPixelDataToTexture; +function uploadDataToTexture(gl, texture, width, height, data, numChannels) { + var textureFormat = getTextureFormat(gl, numChannels); + webgl_util.validateTextureSize(gl, width, height); + webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, texture); }); + webgl_util.callAndCheck(gl, function () { return gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, textureFormat, getTextureType(gl), data); }); + webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, null); }); +} +function uploadMatrixToTexture(gl, texture, rows, columns, matrix, numChannels) { + var _a = tex_util.getUnpackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; + var unpackedArray; + if (environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { + var channelsPerTexture = numChannels === 1 ? webgl_util.getChannelsPerTexture() : numChannels; + if (channelsPerTexture === 1) { + unpackedArray = matrix; + } + else { + unpackedArray = + new Float32Array(tex_util.getUnpackedArraySizeFromMatrixSize(matrix.length, channelsPerTexture)); + tex_util.encodeMatrixToUnpackedArray(matrix, unpackedArray, channelsPerTexture); + } + } + else { + unpackedArray = tex_util.encodeFloatArray(matrix); + } + uploadDataToTexture(gl, texture, w, h, unpackedArray, numChannels); +} +exports.uploadMatrixToTexture = uploadMatrixToTexture; +function uploadMatrixToPackedTexture(gl, texture, rows, columns, matrix) { + var _a = tex_util.getPackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; + var packedRGBA = new Float32Array(tex_util.getPackedRGBAArraySizeFromMatrixShape(rows, columns)); + tex_util.encodeMatrixToPackedRGBA(matrix, rows, columns, packedRGBA); + var numChannels = 4; + uploadDataToTexture(gl, texture, w, h, packedRGBA, numChannels); +} +exports.uploadMatrixToPackedTexture = uploadMatrixToPackedTexture; +function getDownloadTargetArrayBuffer(rows, columns, channelsPerTexture) { + var isFloatTexture = environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED'); + var downloadTarget; + if (isFloatTexture) { + downloadTarget = + new Float32Array(tex_util.getUnpackedArraySizeFromMatrixSize(rows * columns, channelsPerTexture)); + } + else { + downloadTarget = new Uint8Array(rows * columns * channelsPerTexture); + } + return downloadTarget; +} +function decodeDownloadTargetArrayBuffer(downloadTarget, rows, columns, channelsPerPixel) { + var isFloatTexture = environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED'); + if (isFloatTexture) { + var matrix = new Float32Array(rows * columns); + tex_util.decodeMatrixFromUnpackedArray(downloadTarget, matrix, channelsPerPixel); + return matrix; + } + else { + return tex_util.decodeToFloatArray(downloadTarget); + } +} +function downloadMatrixFromOutputTextureAsync(gl, getBufferSubDataAsyncExtension, rows, columns) { + return __awaiter(this, void 0, void 0, function () { + var gl2, channelsPerPixel, downloadTarget, bufferSizeBytes, buffer; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + gl2 = gl; + channelsPerPixel = 4; + downloadTarget = getDownloadTargetArrayBuffer(rows, columns, channelsPerPixel); + bufferSizeBytes = downloadTarget instanceof Float32Array ? + downloadTarget.length * 4 : + downloadTarget; + buffer = gl.createBuffer(); + webgl_util.callAndCheck(gl, function () { return gl.bindBuffer(gl2.PIXEL_PACK_BUFFER, buffer); }); + webgl_util.callAndCheck(gl, function () { return gl.bufferData(gl2.PIXEL_PACK_BUFFER, bufferSizeBytes, gl.STATIC_DRAW); }); + webgl_util.callAndCheck(gl, function () { + return gl2.readPixels(0, 0, columns, rows, gl.RGBA, getTextureType(gl), 0); + }); + return [4, getBufferSubDataAsyncExtension.getBufferSubDataAsync(gl2.PIXEL_PACK_BUFFER, 0, downloadTarget)]; + case 1: + _a.sent(); + return [2, decodeDownloadTargetArrayBuffer(downloadTarget, rows, columns, channelsPerPixel)]; + } + }); + }); +} +exports.downloadMatrixFromOutputTextureAsync = downloadMatrixFromOutputTextureAsync; +function downloadMatrixFromOutputTexture(gl, rows, columns) { + var _a = tex_util.getUnpackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; + var channelsPerPixel = 4; + var downloadTarget = getDownloadTargetArrayBuffer(rows, columns, channelsPerPixel); + webgl_util.callAndCheck(gl, function () { return gl.readPixels(0, 0, w, h, gl.RGBA, getTextureType(gl), downloadTarget); }); + return decodeDownloadTargetArrayBuffer(downloadTarget, rows, columns, channelsPerPixel); +} +exports.downloadMatrixFromOutputTexture = downloadMatrixFromOutputTexture; +function downloadMatrixFromRGBAColorTexture(gl, rows, columns, channels) { + var size = rows * columns * 4; + var downloadTarget = new Uint8Array(size); + webgl_util.callAndCheck(gl, function () { return gl.readPixels(0, 0, columns, rows, gl.RGBA, gl.UNSIGNED_BYTE, downloadTarget); }); + var packedRGBA = new Float32Array(size); + for (var i = 0; i < downloadTarget.length; i++) { + packedRGBA[i] = downloadTarget[i]; + } + var matrix = new Float32Array(rows * columns * channels); + tex_util.decodeMatrixFromUnpackedColorRGBAArray(packedRGBA, matrix, channels); + return matrix; +} +exports.downloadMatrixFromRGBAColorTexture = downloadMatrixFromRGBAColorTexture; +function downloadMatrixFromPackedOutputTexture(gl, rows, columns) { + var _a = tex_util.getPackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; + var packedRGBA = new Float32Array(tex_util.getPackedRGBAArraySizeFromMatrixShape(rows, columns)); + webgl_util.callAndCheck(gl, function () { return gl.readPixels(0, 0, w, h, gl.RGBA, getTextureType(gl), packedRGBA); }); + var matrix = new Float32Array(rows * columns); + return tex_util.decodeMatrixFromPackedRGBA(packedRGBA, rows, columns, matrix); +} +exports.downloadMatrixFromPackedOutputTexture = downloadMatrixFromPackedOutputTexture; + +},{"../../../environment":15,"./tex_util":84,"./webgl_util":89}],74:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var MaxPool2DBackpropProgram = (function () { + function MaxPool2DBackpropProgram(convInfo) { + this.variableNames = ['dy', 'maxPos']; + this.outputShape = convInfo.inShape; + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var padTop = filterHeight - 1 - convInfo.padInfo.top; + var padLeft = filterWidth - 1 - convInfo.padInfo.left; + var lastIndex = filterHeight * filterWidth - 1; + this.userCode = "\n const ivec2 pads = ivec2(" + padTop + ", " + padLeft + ");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int b = coords[0];\n int d = coords[3];\n\n ivec2 dyRCCorner = coords.yz - pads;\n int dyRCorner = dyRCCorner.x;\n int dyCCorner = dyRCCorner.y;\n\n // Convolve dy(?, ?, d) with pos mask(:, :, d) to get dx(xR, xC, d).\n // ? = to be determined. : = across all values in that axis.\n float dotProd = 0.0;\n for (int wR = 0; wR < " + filterHeight + "; wR++) {\n float dyR = float(dyRCorner + wR) / " + strideHeight + ".0;\n\n if (dyR < 0.0 || dyR >= " + convInfo.outHeight + ".0 || fract(dyR) > 0.0) {\n continue;\n }\n int idyR = int(dyR);\n\n for (int wC = 0; wC < " + filterWidth + "; wC++) {\n float dyC = float(dyCCorner + wC) / " + strideWidth + ".0;\n\n if (dyC < 0.0 || dyC >= " + convInfo.outWidth + ".0 ||\n fract(dyC) > 0.0) {\n continue;\n }\n int idyC = int(dyC);\n\n float dyValue = getDy(b, idyR, idyC, d);\n int maxPosValue = " + lastIndex + " - int(getMaxPos(b, idyR, idyC, d));\n\n // Get the current value, check it against the value from the\n // position matrix.\n int curPosValue = wR * " + filterWidth + " + wC;\n float mask = float(maxPosValue == curPosValue ? 1.0 : 0.0);\n\n dotProd += dyValue * mask;\n }\n }\n setOutput(dotProd);\n }\n "; + } + return MaxPool2DBackpropProgram; +}()); +exports.MaxPool2DBackpropProgram = MaxPool2DBackpropProgram; + +},{}],75:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var matmul_1 = require("../types/matmul"); +var MatMulProgram = (function () { + function MatMulProgram(aShape, bShape, aOrient, bOrient) { + if (aOrient === void 0) { aOrient = matmul_1.MatrixOrientation.REGULAR; } + if (bOrient === void 0) { bOrient = matmul_1.MatrixOrientation.REGULAR; } + this.variableNames = ['matrixA', 'matrixB']; + var outerShapeA = (aOrient === matmul_1.MatrixOrientation.REGULAR) ? aShape[0] : aShape[1]; + var outerShapeB = (bOrient === matmul_1.MatrixOrientation.REGULAR) ? bShape[1] : bShape[0]; + this.outputShape = [outerShapeA, outerShapeB]; + var sharedDim = (aOrient === matmul_1.MatrixOrientation.REGULAR ? aShape[1] : aShape[0]); + var aSnippetFromOffset = function (vec4Offset, indexVar) { + return (aOrient === matmul_1.MatrixOrientation.REGULAR) ? + "aRow, " + indexVar + " + " + vec4Offset : + indexVar + " + " + vec4Offset + ", aRow"; + }; + var bSnippetFromOffset = function (vec4Offset, indexVar) { + return (bOrient === matmul_1.MatrixOrientation.REGULAR) ? + indexVar + " + " + vec4Offset + ", bCol" : + "bCol, " + indexVar + " + " + vec4Offset; + }; + var sharedDimNearestVec4 = Math.floor(sharedDim / 4) * 4; + var sharedDimVec4Remainder = sharedDim % 4; + this.userCode = " float dotARowBCol(int aRow, int bCol) {\n float result = 0.0;\n for (int i = 0; i < " + sharedDimNearestVec4 + "; i += 4) {\n vec4 a = vec4(\n getMatrixA(" + aSnippetFromOffset(0, 'i') + "),\n getMatrixA(" + aSnippetFromOffset(1, 'i') + "),\n getMatrixA(" + aSnippetFromOffset(2, 'i') + "),\n getMatrixA(" + aSnippetFromOffset(3, 'i') + ")\n );\n vec4 b = vec4(\n getMatrixB(" + bSnippetFromOffset(0, 'i') + "),\n getMatrixB(" + bSnippetFromOffset(1, 'i') + "),\n getMatrixB(" + bSnippetFromOffset(2, 'i') + "),\n getMatrixB(" + bSnippetFromOffset(3, 'i') + ")\n );\n\n result += dot(a, b);\n }\n\n if (" + (sharedDimVec4Remainder === 1) + ") {\n result += getMatrixA(" + aSnippetFromOffset(0, sharedDimNearestVec4) + ") *\n getMatrixB(" + bSnippetFromOffset(0, sharedDimNearestVec4) + ");\n } else if (" + (sharedDimVec4Remainder === 2) + ") {\n vec2 a = vec2(\n getMatrixA(" + aSnippetFromOffset(0, sharedDimNearestVec4) + "),\n getMatrixA(" + aSnippetFromOffset(1, sharedDimNearestVec4) + ")\n );\n vec2 b = vec2(\n getMatrixB(" + bSnippetFromOffset(0, sharedDimNearestVec4) + "),\n getMatrixB(" + bSnippetFromOffset(1, sharedDimNearestVec4) + ")\n );\n result += dot(a, b);\n } else if (" + (sharedDimVec4Remainder === 3) + ") {\n vec3 a = vec3(\n getMatrixA(" + aSnippetFromOffset(0, sharedDimNearestVec4) + "),\n getMatrixA(" + aSnippetFromOffset(1, sharedDimNearestVec4) + "),\n getMatrixA(" + aSnippetFromOffset(2, sharedDimNearestVec4) + ")\n );\n vec3 b = vec3(\n getMatrixB(" + bSnippetFromOffset(0, sharedDimNearestVec4) + "),\n getMatrixB(" + bSnippetFromOffset(1, sharedDimNearestVec4) + "),\n getMatrixB(" + bSnippetFromOffset(2, sharedDimNearestVec4) + ")\n );\n result += dot(a, b);\n }\n\n return result;\n }\n\n void main() {\n ivec2 resRC = getOutputCoords();\n setOutput(dotARowBCol(resRC.x, resRC.y));\n }\n "; + } + return MatMulProgram; +}()); +exports.MatMulProgram = MatMulProgram; + +},{"../types/matmul":61}],76:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var MultinomialProgram = (function () { + function MultinomialProgram(batchSize, numOutcomes, numSamples) { + this.variableNames = ['probs']; + this.outputShape = [batchSize, numSamples]; + this.userCode = "\n uniform float seed;\n\n void main() {\n ivec2 coords = getOutputCoords();\n int batch = coords[0];\n\n float r = random(seed);\n float cdf = 0.0;\n\n for (int i = 0; i < " + (numOutcomes - 1) + "; i++) {\n cdf += getProbs(batch, i);\n\n if (r < cdf) {\n setOutput(float(i));\n return;\n }\n }\n\n // If no other event happened, last event happened.\n setOutput(float(" + (numOutcomes - 1) + "));\n }\n "; + } + MultinomialProgram.prototype.getCustomSetupFunc = function (seed) { + var _this = this; + return function (gpgpu, webGLProgram) { + if (_this.seedLoc == null) { + _this.seedLoc = gpgpu.getUniformLocation(webGLProgram, 'seed'); + } + gpgpu.gl.uniform1f(_this.seedLoc, seed); + }; + }; + return MultinomialProgram; +}()); +exports.MultinomialProgram = MultinomialProgram; + +},{}],77:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OneHotProgram = (function () { + function OneHotProgram(numIndices, depth, onValue, offValue) { + this.variableNames = ['indices']; + this.outputShape = [numIndices, depth]; + this.userCode = "\n void main() {\n ivec2 coords = getOutputCoords();\n int index = round(getIndices(coords.x));\n setOutput(mix(float(" + offValue + "), float(" + onValue + "),\n float(index == coords.y)));\n }\n "; + } + OneHotProgram.prototype.getCustomSetupFunc = function (seed) { + var _this = this; + return function (gpgpu, webGLProgram) { + if (_this.seedLoc == null) { + _this.seedLoc = gpgpu.getUniformLocation(webGLProgram, 'seed'); + } + gpgpu.gl.uniform1f(_this.seedLoc, seed); + }; + }; + return OneHotProgram; +}()); +exports.OneHotProgram = OneHotProgram; + +},{}],78:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Pool2DProgram = (function () { + function Pool2DProgram(convInfo, poolType, computePositions) { + this.variableNames = ['x']; + if (poolType === 'avg' && computePositions) { + throw new Error('Cannot compute positions for average pool.'); + } + var filterHeight = convInfo.filterHeight; + var filterWidth = convInfo.filterWidth; + var strideHeight = convInfo.strideHeight; + var strideWidth = convInfo.strideWidth; + var padTop = convInfo.padInfo.top; + var padLeft = convInfo.padInfo.left; + this.outputShape = convInfo.outShape; + var isAvgPool = poolType === 'avg'; + var initializationValue = '0.0'; + if (!isAvgPool) { + if (poolType === 'min') { + initializationValue = '1.0 / 0.0'; + } + else { + initializationValue = '-1.0 / 0.0'; + } + } + if (computePositions) { + var compareOp_1 = poolType === 'min' ? '<=' : '>='; + this.userCode = "\n const ivec2 strides = ivec2(" + strideHeight + ", " + strideWidth + ");\n const ivec2 pads = ivec2(" + padTop + ", " + padLeft + ");\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d = coords[3];\n\n ivec2 xRCCorner = coords.yz * strides - pads;\n int xRCorner = xRCCorner.x;\n int xCCorner = xRCCorner.y;\n\n // max/min x(?, ?, d) to get y(yR, yC, d).\n // ? = to be determined\n float minMaxValue = 0.0;\n float minMaxValueFound = 0.0;\n int minMaxPosition = 0;\n float avgValue = 0.0;\n\n for (int wR = 0; wR < " + filterHeight + "; wR++) {\n int xR = xRCorner + wR;\n\n if (xR < 0 || xR >= " + convInfo.inHeight + ") {\n continue;\n }\n\n for (int wC = 0; wC < " + filterWidth + "; wC++) {\n int xC = xCCorner + wC;\n\n if (xC < 0 || xC >= " + convInfo.inWidth + ") {\n continue;\n }\n\n float value = getX(batch, xR, xC, d);\n\n if (isNaN(value)) {\n setOutput(value);\n return;\n }\n\n // If a min / max value has already been found, use it. If not,\n // use the current value.\n float currMinMaxValue = mix(\n value, minMaxValue, minMaxValueFound);\n if (value " + compareOp_1 + " currMinMaxValue) {\n minMaxValue = value;\n minMaxValueFound = 1.0;\n minMaxPosition = wR * " + filterWidth + " + wC;\n }\n }\n }\n setOutput(float(minMaxPosition));\n }\n "; + return; + } + var compareOp = poolType === 'min' ? 'min' : 'max'; + var returnValue = poolType + "(" + poolType + "(" + poolType + "(" + + 'minMaxValue[0], minMaxValue[1]), minMaxValue[2]), minMaxValue[3])'; + if (poolType === 'avg') { + returnValue = "avgValue / " + filterHeight * filterWidth + ".0"; + } + var filterWidthNearestVec4 = Math.floor(filterWidth / 4) * 4; + var filterWidthVec4Remainder = filterWidth % 4; + var updateSnippet = "\n if (hasNaN(values)) {\n setOutput(getNaN(values));\n return;\n }\n if (" + isAvgPool + ") {\n avgValue += dot(values, ones);\n } else {\n minMaxValue = " + compareOp + "(values, minMaxValue);\n }\n "; + this.userCode = "\n const ivec2 strides = ivec2(" + strideHeight + ", " + strideWidth + ");\n const ivec2 pads = ivec2(" + padTop + ", " + padLeft + ");\n const float initializationValue = " + initializationValue + ";\n const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n float getValue(int batch, int xR, int xC, int d) {\n if (xC < 0 || xC >= " + convInfo.inWidth + ") {\n return initializationValue;\n }\n return getX(batch, xR, xC, d);\n }\n\n void main() {\n ivec4 coords = getOutputCoords();\n int batch = coords[0];\n int d = coords[3];\n\n ivec2 xRCCorner = coords.yz * strides - pads;\n int xRCorner = xRCCorner.x;\n int xCCorner = xRCCorner.y;\n\n // max/min x(?, ?, d) to get y(yR, yC, d).\n // ? = to be determined\n vec4 minMaxValue = vec4(" + initializationValue + ");\n float avgValue = 0.0;\n\n for (int wR = 0; wR < " + filterHeight + "; wR++) {\n int xR = xRCorner + wR;\n\n if (xR < 0 || xR >= " + convInfo.inHeight + ") {\n continue;\n }\n\n for (int wC = 0; wC < " + filterWidthNearestVec4 + "; wC += 4) {\n int xC = xCCorner + wC;\n\n vec4 values = vec4(\n getValue(batch, xR, xC, d),\n getValue(batch, xR, xC + 1, d),\n getValue(batch, xR, xC + 2, d),\n getValue(batch, xR, xC + 3, d)\n );\n\n " + updateSnippet + "\n }\n\n int xC = xCCorner + " + filterWidthNearestVec4 + ";\n if (" + (filterWidthVec4Remainder === 1) + ") {\n vec4 values = vec4(\n getValue(batch, xR, xC, d),\n initializationValue,\n initializationValue,\n initializationValue\n );\n " + updateSnippet + "\n } else if (" + (filterWidthVec4Remainder === 2) + ") {\n vec4 values = vec4(\n getValue(batch, xR, xC, d),\n getValue(batch, xR, xC + 1, d),\n initializationValue,\n initializationValue\n );\n\n " + updateSnippet + "\n } else if (" + (filterWidthVec4Remainder === 3) + ") {\n vec4 values = vec4(\n getValue(batch, xR, xC, d),\n getValue(batch, xR, xC + 1, d),\n getValue(batch, xR, xC + 2, d),\n initializationValue\n );\n\n " + updateSnippet + "\n }\n }\n setOutput(" + returnValue + ");\n }\n "; + } + return Pool2DProgram; +}()); +exports.Pool2DProgram = Pool2DProgram; + +},{}],79:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ReduceProgram = (function () { + function ReduceProgram(reduceInfo, reduceType) { + this.variableNames = ['x']; + var windowSize = reduceInfo.windowSize; + var batchSize = reduceInfo.batchSize; + var inSize = reduceInfo.inSize; + var outSize = Math.ceil(inSize / windowSize); + this.outputShape = [batchSize, outSize]; + var isReduceSum = reduceType === 'sum'; + var initializationValue = '0.0'; + if (!isReduceSum) { + if (reduceType === 'min') { + initializationValue = '1.0 / 0.0'; + } + else { + initializationValue = '-1.0 / 0.0'; + } + } + var compareOp = reduceType === 'min' ? 'min' : 'max'; + var returnValue = reduceType + "(" + reduceType + "(" + reduceType + "(" + + 'minMaxValue[0], minMaxValue[1]), minMaxValue[2]), minMaxValue[3])'; + if (reduceType === 'sum') { + returnValue = "sumValue"; + } + var windowSizeNearestVec4 = Math.floor(windowSize / 4) * 4; + var windowSizeVec4Remainder = windowSize % 4; + var updateSnippet = "\n if (" + isReduceSum + ") {\n sumValue += dot(values, ones);\n } else {\n if (hasNaN(values)) {\n setOutput(getNaN(values));\n return;\n }\n minMaxValue = " + compareOp + "(values, minMaxValue);\n }\n "; + var checkOutOfBounds = ''; + if (inSize % windowSize > 0) { + checkOutOfBounds = "\n if (inIdx < 0 || inIdx >= " + inSize + ") {\n return initializationValue;\n }\n "; + } + this.userCode = "\n const float initializationValue = " + initializationValue + ";\n const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n float getValue(int batch, int inIdx) {\n " + checkOutOfBounds + "\n return getX(batch, inIdx);\n }\n\n void main() {\n ivec2 coords = getOutputCoords();\n int batch = coords[0];\n int outIdx = coords[1];\n int inOffset = outIdx * " + windowSize + ";\n\n vec4 minMaxValue = vec4(" + initializationValue + ");\n float sumValue = 0.0;\n\n for (int i = 0; i < " + windowSizeNearestVec4 + "; i += 4) {\n int inIdx = inOffset + i;\n vec4 values = vec4(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n getValue(batch, inIdx + 2),\n getValue(batch, inIdx + 3)\n );\n\n " + updateSnippet + "\n }\n\n int inIdx = inOffset + " + windowSizeNearestVec4 + ";\n if (" + (windowSizeVec4Remainder === 1) + ") {\n vec4 values = vec4(\n getValue(batch, inIdx),\n initializationValue,\n initializationValue,\n initializationValue\n );\n " + updateSnippet + "\n } else if (" + (windowSizeVec4Remainder === 2) + ") {\n vec4 values = vec4(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n initializationValue,\n initializationValue\n );\n " + updateSnippet + "\n } else if (" + (windowSizeVec4Remainder === 3) + ") {\n vec4 values = vec4(\n getValue(batch, inIdx),\n getValue(batch, inIdx + 1),\n getValue(batch, inIdx + 2),\n initializationValue\n );\n " + updateSnippet + "\n }\n setOutput(" + returnValue + ");\n }\n "; + } + return ReduceProgram; +}()); +exports.ReduceProgram = ReduceProgram; + +},{}],80:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var webgl_util = require("./webgl_util"); +function getRenderRGBShader(gpgpu, destinationWidth) { + var fragmentShaderSource = "\n precision highp float;\n uniform sampler2D source;\n varying vec2 resultUV;\n\n const float destinationWidth = " + destinationWidth + ".0;\n const float a = 1.0;\n\n void main() {\n float xr = floor(resultUV.s * destinationWidth) * 3.0;\n vec3 x = xr + vec3(0, 1, 2);\n\n float sourceWidth = destinationWidth * 3.0;\n vec3 u = (x + 0.5) / sourceWidth;\n float v = 1.0 - resultUV.t;\n\n float r = texture2D(source, vec2(u[0], v)).r;\n float g = texture2D(source, vec2(u[1], v)).r;\n float b = texture2D(source, vec2(u[2], v)).r;\n\n gl_FragColor = vec4(r, g, b, a);\n }"; + return gpgpu.createProgram(fragmentShaderSource); +} +exports.getRenderRGBShader = getRenderRGBShader; +function renderToCanvas(gpgpu, renderShader, sourceTex) { + webgl_util.bindCanvasToFramebuffer(gpgpu.gl); + renderToFramebuffer(gpgpu, renderShader, sourceTex); +} +exports.renderToCanvas = renderToCanvas; +function renderToFramebuffer(gpgpu, renderShader, sourceTex) { + gpgpu.setProgram(renderShader); + var sourceSamplerLocation = webgl_util.getProgramUniformLocationOrThrow(gpgpu.gl, renderShader, 'source'); + gpgpu.setInputMatrixTexture(sourceTex, sourceSamplerLocation, 0); + gpgpu.executeProgram(); +} +exports.renderToFramebuffer = renderToFramebuffer; + +},{"./webgl_util":89}],81:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ResizeBilinear3DProgram = (function () { + function ResizeBilinear3DProgram(inputShape, outputDimensionsRowCol, alignCorners) { + this.variableNames = ['A']; + this.outputShape = []; + var depth = inputShape[2]; + this.outputShape = + [outputDimensionsRowCol[0], outputDimensionsRowCol[1], depth]; + var effectiveInputShape = alignCorners ? + [inputShape[0] - 1, inputShape[1] - 1, depth] : + inputShape; + var effectiveOutputShape = alignCorners ? + [this.outputShape[0] - 1, this.outputShape[1] - 1, depth] : + this.outputShape; + this.userCode = "\n const vec2 effectiveInputOverOutputRatioRC = vec2(\n " + effectiveInputShape[0] / effectiveOutputShape[0] + ",\n " + effectiveInputShape[1] / effectiveOutputShape[1] + ");\n const vec2 inputShapeRC = vec2(" + inputShape[0] + ".0, " + inputShape[1] + ".0);\n\n void main() {\n ivec3 coords = getOutputCoords();\n ivec2 yRC = coords.xy;\n int d = coords.z;\n\n // Fractional source index.\n vec2 sourceFracIndexRC = vec2(yRC) * effectiveInputOverOutputRatioRC;\n\n // Compute the four integer indices.\n ivec2 sourceFloorRC = ivec2(sourceFracIndexRC);\n ivec2 sourceCeilRC = ivec2(\n min(inputShapeRC - 1.0, ceil(sourceFracIndexRC)));\n\n float topLeft = getA(sourceFloorRC.x, sourceFloorRC.y, d);\n float bottomLeft = getA(sourceCeilRC.x, sourceFloorRC.y, d);\n float topRight = getA(sourceFloorRC.x, sourceCeilRC.y, d);\n float bottomRight = getA(sourceCeilRC.x, sourceCeilRC.y, d);\n\n vec2 fracRC = sourceFracIndexRC - vec2(sourceFloorRC);\n\n float top = topLeft + (topRight - topLeft) * fracRC.y;\n float bottom = bottomLeft + (bottomRight - bottomLeft) * fracRC.y;\n float newValue = top + (bottom - top) * fracRC.x;\n\n setOutput(newValue);\n }\n "; + } + return ResizeBilinear3DProgram; +}()); +exports.ResizeBilinear3DProgram = ResizeBilinear3DProgram; + +},{}],82:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../../../environment"); +var util = require("../../../util"); +var broadcast_util = require("../../broadcast_util"); +var tex_util = require("./tex_util"); +var tex_util_1 = require("./tex_util"); +function makeShader(inputsInfo, outputShape, userCode, broadcast) { + var sampleSnippet = getSampleSnippet(); + var setOutputSnippet = getSetOutputSnippet(); + var inputPrefixSnippet = inputsInfo.map(function (x) { return "uniform sampler2D " + x.name + ";"; }).join('\n'); + var inputSamplingSnippet = inputsInfo.map(function (x) { return getInputSamplingSnippet(x, outputShape, broadcast); }) + .join('\n'); + var outTexShape = outputShape.texShape; + var outputSamplingSnippet = getOutputSamplingSnippet(outputShape.logicalShape, outTexShape); + var source = [ + SHADER_PREFIX, sampleSnippet, setOutputSnippet, inputPrefixSnippet, + outputSamplingSnippet, inputSamplingSnippet, userCode + ].join('\n'); + return source; +} +exports.makeShader = makeShader; +function getSampleSnippet() { + return environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED') ? + FLOAT_TEXTURE_SAMPLE_SNIPPET : + UNSIGNED_BYTE_TEXTURE_SAMPLE_SNIPPET; +} +function getSetOutputSnippet() { + return environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED') ? + FLOAT_TEXTURE_SETOUTPUT_SNIPPET : + UNSIGNED_BYTE_TEXTURE_SETOUTPUT_SNIPPET; +} +function getSamplerFromInInfo(inInfo) { + var shape = inInfo.shapeInfo.logicalShape; + switch (shape.length) { + case 0: + return getSamplerScalar(inInfo); + case 1: + return getSampler1D(inInfo); + case 2: + return getSampler2D(inInfo); + case 3: + return getSampler3D(inInfo); + case 4: + return getSampler4D(inInfo); + default: + throw new Error(shape.length + "-D input sampling" + + " is not yet supported"); + } +} +function getInputSamplingSnippet(inInfo, outShapeInfo, broadcast) { + var res = getSamplerFlat(inInfo); + res += getSamplerFromInInfo(inInfo); + if (broadcast || + util.arraysEqual(inInfo.shapeInfo.logicalShape, outShapeInfo.logicalShape)) { + res += getSamplerAtOutputCoords(inInfo, outShapeInfo, broadcast); + } + return res; +} +function getOutputSamplingSnippet(outShape, outTexShape) { + switch (outShape.length) { + case 0: + return getOutputScalarCoords(); + case 1: + return getOutput1DCoords(outShape, outTexShape); + case 2: + return getOutput2DCoords(outShape, outTexShape); + case 3: + return getOutput3DCoords(outShape, outTexShape); + case 4: + return getOutput4DCoords(outShape, outTexShape); + default: + throw new Error(outShape.length + "-D output sampling is not yet supported"); + } +} +var SAMPLE_1D_SNIPPET = "\nvec2 UVfrom1D(int texNumR, int texNumC, int index) {\n int texR = index / texNumC;\n int texC = index - texR * texNumC;\n return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n"; +var SAMPLE_2D_SNIPPET = "\nvec2 UVfrom2D(int texNumR, int texNumC, int numC, int row, int col) {\n int index = row * numC + col;\n int texR = index / texNumC;\n int texC = index - texR * texNumC;\n return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n"; +var SAMPLE_3D_SNIPPET = "\nvec2 UVfrom3D(int texNumR, int texNumC, int stride0,\n int stride1, int row, int col, int depth) {\n // Explicitly use integer operations as dot() only works on floats.\n int index = row * stride0 + col * stride1 + depth;\n int texR = index / texNumC;\n int texC = index - texR * texNumC;\n return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n"; +var SAMPLE_4D_SNIPPET = "\nvec2 UVfrom4D(int texNumR, int texNumC, int stride0,\n int stride1, int stride2, int row, int col, int depth,\n int depth2) {\n // Explicitly use integer operations as dot() only works on floats.\n int index = row * stride0 + col * stride1 + depth * stride2 + depth2;\n int texR = index / texNumC;\n int texC = index - texR * texNumC;\n return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n"; +var UNSIGNED_BYTE_TEXTURE_SAMPLE_SNIPPET = "\n uniform float NaN;\n\n const vec4 floatDeltas = vec4(\n 1.0,\n 1.0 / 255.0,\n 1.0 / (255.0 * 255.0),\n 1.0 / (255.0 * 255.0 * 255.0)\n );\n const float minValue = " + tex_util.FLOAT_MIN + ".0;\n const float maxValue = " + tex_util.FLOAT_MAX + ".0;\n const float range = (maxValue - minValue) / 255.0;\n const vec2 dotRange = vec2(1.0, range);\n\n float sample(sampler2D texture, vec2 uv) {\n vec4 sampleValue = texture2D(texture, uv);\n if (all(equal(sampleValue, vec4(" + tex_util.BYTE_NAN_VALUE + ")))) {\n return NaN;\n }\n\n vec4 encValue = floor(sampleValue * 255.0 + 0.5);\n float decodedValue = dot(encValue, floatDeltas);\n return dot(vec2(minValue, decodedValue), dotRange);\n }\n"; +var UNSIGNED_BYTE_TEXTURE_SETOUTPUT_SNIPPET = "\n const vec4 floatPowers = vec4(\n 1.0,\n 255.0,\n 255.0 * 255.0,\n 255.0 * 255.0 * 255.0\n );\n const vec2 recipRange = vec2(1.0/range);\n const vec2 recipRange255 = vec2(1.0/(maxValue - minValue));\n\n void setOutput(float decodedValue) {\n if (isNaN(decodedValue)) {\n gl_FragColor = vec4(" + tex_util.BYTE_NAN_VALUE + ");\n return;\n }\n\n float a = dot(vec2(decodedValue, -minValue), recipRange);\n float b = fract(a) * 255.0;\n float c = fract(b) * 255.0;\n float d = fract(c) * 255.0;\n gl_FragColor = floor(vec4(a, b, c, d)) / 255.0;\n\n // TODO(dsmilkov): Version above gets better accuracy but probably slower\n // than the version below. Benchmark to determine if the accuracy is worth\n // the cost.\n\n // float normValue = dot(vec2(decodedValue, -minValue), recipRange255);\n // vec4 f = normValue * floatPowers;\n // gl_FragColor = floor(fract(f) * 255.0) / 255.0;\n }\n"; +var FLOAT_TEXTURE_SAMPLE_SNIPPET = "\n float sample(sampler2D texture, vec2 uv) {\n return texture2D(texture, uv).r;\n }\n"; +var FLOAT_TEXTURE_SETOUTPUT_SNIPPET = "\n void setOutput(float val) {\n gl_FragColor = vec4(val, 0, 0, 0);\n }\n"; +var SHADER_PREFIX = "\n precision highp float;\n precision highp int;\n varying vec2 resultUV;\n const vec2 halfCR = vec2(0.5, 0.5);\n\n bool isNaN(float val) {\n float v1 = val * val;\n float v2 = val * val;\n return v1 == v2 ? false : true;\n }\n\n bool hasNaN(vec4 values) {\n vec4 v1 = values * values;\n vec4 v2 = values * values;\n return any(notEqual(v1, v2));\n }\n\n float getNaN(vec4 values) {\n return dot(vec4(1), values);\n }\n\n int round(float value) {\n return int(floor(value + 0.5));\n }\n\n int imod(int x, int y) {\n return x - y * (x / y);\n }\n\n const vec2 randomConst = vec2(\n 23.14069263277926, // e^pi (Gelfond's constant)\n 2.665144142690225 // 2^sqrt(2) (Gelfond\u2013Schneider constant)\n );\n\n float random(float seed) {\n return fract(cos(dot(resultUV * seed, randomConst)) * 12345.6789);\n }\n\n float sampleUVAndDepth(sampler2D texture, vec2 uv, int depth) {\n float value;\n if (depth == 0) {\n value = texture2D(texture, uv).r;\n } else if (depth == 1) {\n value = texture2D(texture, uv).g;\n } else if (depth == 2) {\n value = texture2D(texture, uv).b;\n } else if (depth == 3) {\n value = texture2D(texture, uv).a;\n }\n return floor(value * 255.0 + 0.5);\n }\n\n " + SAMPLE_1D_SNIPPET + "\n " + SAMPLE_2D_SNIPPET + "\n " + SAMPLE_3D_SNIPPET + "\n " + SAMPLE_4D_SNIPPET + "\n"; +function getOutputScalarCoords() { + return "\n int getOutputCoords() {\n return 0;\n }\n "; +} +function getOutput1DCoords(shape, texShape) { + if (texShape[0] === 1) { + return "\n int getOutputCoords() {\n return int(resultUV.x * " + texShape[1] + ".0);\n }\n "; + } + if (texShape[1] === 1) { + return "\n int getOutputCoords() {\n return int(resultUV.y * " + texShape[0] + ".0);\n }\n "; + } + return "\n int getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2(" + texShape[0] + ", " + texShape[1] + "));\n return resTexRC.x * " + texShape[1] + " + resTexRC.y;\n }\n "; +} +function getOutput3DCoords(shape, texShape) { + var stride0 = shape[1] * shape[2]; + var stride1 = shape[2]; + return "\n ivec3 getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2(" + texShape[0] + ", " + texShape[1] + "));\n int index = resTexRC.x * " + texShape[1] + " + resTexRC.y;\n int r = index / " + stride0 + ";\n index -= r * " + stride0 + ";\n int c = index / " + stride1 + ";\n int d = index - c * " + stride1 + ";\n return ivec3(r, c, d);\n }\n "; +} +function getOutput4DCoords(shape, texShape) { + var stride2 = shape[3]; + var stride1 = shape[2] * stride2; + var stride0 = shape[1] * stride1; + return "\n ivec4 getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2(" + texShape[0] + ", " + texShape[1] + "));\n int index = resTexRC.x * " + texShape[1] + " + resTexRC.y;\n\n int r = index / " + stride0 + ";\n index -= r * " + stride0 + ";\n\n int c = index / " + stride1 + ";\n index -= c * " + stride1 + ";\n\n int d = index / " + stride2 + ";\n int d2 = index - d * " + stride2 + ";\n\n return ivec4(r, c, d, d2);\n }\n "; +} +function getOutput2DCoords(shape, texShape) { + if (util.arraysEqual(shape, texShape)) { + return "\n ivec2 getOutputCoords() {\n return ivec2(resultUV.yx * vec2(" + texShape[0] + ", " + texShape[1] + "));\n }\n "; + } + if (shape[1] === 1) { + return "\n ivec2 getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2(" + texShape[0] + ", " + texShape[1] + "));\n int index = resTexRC.x * " + texShape[1] + " + resTexRC.y;\n return ivec2(index, 0);\n }\n "; + } + if (shape[0] === 1) { + return "\n ivec2 getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2(" + texShape[0] + ", " + texShape[1] + "));\n int index = resTexRC.x * " + texShape[1] + " + resTexRC.y;\n return ivec2(0, index);\n }\n "; + } + return "\n ivec2 getOutputCoords() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2(" + texShape[0] + ", " + texShape[1] + "));\n int index = resTexRC.x * " + texShape[1] + " + resTexRC.y;\n int r = index / " + shape[1] + ";\n int c = index - r * " + shape[1] + ";\n return ivec2(r, c);\n }\n "; +} +function getSamplerScalar(inputInfo) { + var texName = inputInfo.name; + var funcName = 'get' + texName.charAt(0).toUpperCase() + texName.slice(1); + return "\n float " + funcName + "() {\n return sample(" + texName + ", halfCR);\n }\n "; +} +function getSampler1D(inputInfo) { + var texName = inputInfo.name; + var funcName = 'get' + texName.charAt(0).toUpperCase() + texName.slice(1); + return "\n float " + funcName + "(int index) {\n return " + funcName + "Flat(index);\n }\n "; +} +function getSampler2D(inputInfo) { + var shape = inputInfo.shapeInfo.logicalShape; + var texShape = inputInfo.shapeInfo.texShape; + var texName = inputInfo.name; + var funcName = 'get' + texName.charAt(0).toUpperCase() + texName.slice(1); + var texNumR = texShape[0]; + var texNumC = texShape[1]; + if (util.arraysEqual(shape, texShape)) { + return "\n float " + funcName + "(int row, int col) {\n vec2 uv = (vec2(col, row) + halfCR) / vec2(" + texNumC + ".0, " + texNumR + ".0);\n return sample(" + texName + ", uv);\n }\n "; + } + var _a = util.squeezeShape(shape), newShape = _a.newShape, keptDims = _a.keptDims; + var squeezedShape = newShape; + if (squeezedShape.length < shape.length) { + var newInputInfo = squeezeInputInfo(inputInfo, squeezedShape); + var params = ['row', 'col']; + return "\n " + getSamplerFromInInfo(newInputInfo) + "\n float " + funcName + "(int row, int col) {\n return " + funcName + "(" + getSqueezedParams(params, keptDims) + ");\n }\n "; + } + if (texNumC === 1) { + return "\n float " + funcName + "(int row, int col) {\n int index = row * " + shape[1] + " + col;\n vec2 uv = vec2(0.5, (float(index) + 0.5) / " + texNumR + ".0);\n return sample(" + texName + ", uv);\n }\n "; + } + if (texNumR === 1) { + return "\n float " + funcName + "(int row, int col) {\n int index = row * " + shape[1] + " + col;\n vec2 uv = vec2((float(index) + 0.5) / " + texNumC + ".0, 0.5);\n return sample(" + texName + ", uv);\n }\n "; + } + return "\n float " + funcName + "(int row, int col) {\n vec2 uv = UVfrom2D(" + texNumR + ", " + texNumC + ", " + shape[1] + ", row, col);\n return sample(" + texName + ", uv);\n }\n"; +} +function getSampler3D(inputInfo) { + var texShape = inputInfo.shapeInfo.texShape; + var shape = inputInfo.shapeInfo.logicalShape; + var texName = inputInfo.name; + var funcName = 'get' + texName.charAt(0).toUpperCase() + texName.slice(1); + var texNumR = texShape[0]; + var texNumC = texShape[1]; + var stride0 = shape[1] * shape[2]; + var stride1 = shape[2]; + var texType = inputInfo.shapeInfo.textureType; + if (texType === tex_util_1.TextureType.DEFAULT) { + var _a = util.squeezeShape(shape), newShape = _a.newShape, keptDims = _a.keptDims; + var squeezedShape = newShape; + if (squeezedShape.length < shape.length) { + var newInputInfo = squeezeInputInfo(inputInfo, squeezedShape); + var params = ['row', 'col', 'depth']; + return "\n " + getSamplerFromInInfo(newInputInfo) + "\n float " + funcName + "(int row, int col, int depth) {\n return " + funcName + "(" + getSqueezedParams(params, keptDims) + ");\n }\n "; + } + } + if (texNumC === stride0) { + if (texType === tex_util_1.TextureType.DEFAULT) { + return "\n float " + funcName + "(int row, int col, int depth) {\n int texR = row;\n int texC = col * " + stride1 + " + depth;\n vec2 uv = (vec2(texC, texR) + halfCR) /\n vec2(" + texNumC + ".0, " + texNumR + ".0);\n return sample(" + texName + ", uv);\n }\n "; + } + else if (texType === tex_util_1.TextureType.RGBA_COLOR) { + return "\n float " + funcName + "(int row, int col, int depth) {\n vec2 uv = (vec2(col, row) + halfCR) /\n vec2(" + texNumC + ".0, " + texNumR + ".0);\n return sampleUVAndDepth(" + texName + ", uv, depth);\n }\n "; + } + else { + throw new Error("Unknown TextureType " + texType + "."); + } + } + if (texNumC === stride1 && texType === tex_util_1.TextureType.DEFAULT) { + return "\n float " + funcName + "(int row, int col, int depth) {\n int texR = row * " + shape[1] + " + col;\n int texC = depth;\n vec2 uv = (vec2(texC, texR) + halfCR) / vec2(" + texNumC + ".0, " + texNumR + ".0);\n return sample(" + texName + ", uv);\n }\n "; + } + if (texType === tex_util_1.TextureType.DEFAULT) { + return "\n float " + funcName + "(int row, int col, int depth) {\n vec2 uv = UVfrom3D(\n " + texNumR + ", " + texNumC + ", " + stride0 + ", " + stride1 + ", row, col, depth);\n return sample(" + texName + ", uv);\n }\n "; + } + else if (texType === tex_util_1.TextureType.RGBA_COLOR) { + return "\n float " + funcName + "(int row, int col, int depth) {\n vec2 uv = UVfrom2D(" + texNumR + ", " + texNumC + ", " + shape[1] + ", row, col);\n return sampleUVAndDepth(" + texName + ", uv, depth);\n }\n "; + } + else { + throw new Error("Unknown TextureType " + texType + "."); + } +} +function getSampler4D(inputInfo) { + var shape = inputInfo.shapeInfo.logicalShape; + var texShape = inputInfo.shapeInfo.texShape; + var texName = inputInfo.name; + var funcName = 'get' + texName.charAt(0).toUpperCase() + texName.slice(1); + var texNumR = texShape[0]; + var texNumC = texShape[1]; + var stride2 = shape[3]; + var stride1 = shape[2] * stride2; + var stride0 = shape[1] * stride1; + var _a = util.squeezeShape(shape), newShape = _a.newShape, keptDims = _a.keptDims; + if (newShape.length < shape.length) { + var newInputInfo = squeezeInputInfo(inputInfo, newShape); + var params = ['row', 'col', 'depth', 'depth2']; + return "\n " + getSamplerFromInInfo(newInputInfo) + "\n float " + funcName + "(int row, int col, int depth, int depth2) {\n return " + funcName + "(" + getSqueezedParams(params, keptDims) + ");\n }\n "; + } + if (texNumC === stride0) { + return "\n float " + funcName + "(int row, int col, int depth, int depth2) {\n int texR = row;\n int texC = col * " + stride1 + " + depth * " + stride2 + " + depth2;\n vec2 uv = (vec2(texC, texR) + halfCR) /\n vec2(" + texNumC + ".0, " + texNumR + ".0);\n return sample(" + texName + ", uv);\n }\n "; + } + if (texNumC === stride2) { + return "\n float " + funcName + "(int row, int col, int depth, int depth2) {\n int texR = row * " + shape[1] * shape[2] + " + col * " + shape[2] + " + depth;\n int texC = depth2;\n vec2 uv = (vec2(texC, texR) + halfCR) /\n vec2(" + texNumC + ".0, " + texNumR + ".0);\n return sample(" + texName + ", uv);\n }\n "; + } + return "\n float " + funcName + "(int row, int col, int depth, int depth2) {\n vec2 uv = UVfrom4D(" + texNumR + ", " + texNumC + ", " + stride0 + ", " + stride1 + ",\n " + stride2 + ", row, col, depth, depth2);\n return sample(" + texName + ", uv);\n }\n "; +} +function getSamplerFlat(inputInfo) { + var texName = inputInfo.name; + var texShape = inputInfo.shapeInfo.texShape; + var funcName = 'get' + texName.charAt(0).toUpperCase() + texName.slice(1) + 'Flat'; + var tNumR = texShape[0]; + var tNumC = texShape[1]; + if (tNumC === 1 && tNumR === 1) { + return "\n float " + funcName + "(int index) {\n return sample(" + texName + ", halfCR);\n }\n "; + } + if (tNumC === 1) { + return "\n float " + funcName + "(int index) {\n vec2 uv = vec2(0.5, (float(index) + 0.5) / " + tNumR + ".0);\n return sample(" + texName + ", uv);\n }\n "; + } + if (tNumR === 1) { + return "\n float " + funcName + "(int index) {\n vec2 uv = vec2((float(index) + 0.5) / " + tNumC + ".0, 0.5);\n return sample(" + texName + ", uv);\n }\n "; + } + return "\n float " + funcName + "(int index) {\n vec2 uv = UVfrom1D(" + tNumR + ", " + tNumC + ", index);\n return sample(" + texName + ", uv);\n }\n "; +} +function getBroadcastOutputCoordsSampler(inputInfo, outShapeInfo, texFuncSnippet, funcName) { + var inRank = inputInfo.shapeInfo.logicalShape.length; + var outRank = outShapeInfo.logicalShape.length; + var type = 'int'; + if (outRank === 2) { + type = 'ivec2'; + } + else if (outRank === 3) { + type = 'ivec3'; + } + else if (outRank === 4) { + type = 'ivec4'; + } + var broadcastDims = broadcast_util.getBroadcastDims(inputInfo.shapeInfo.logicalShape, outShapeInfo.logicalShape); + var rankDiff = outRank - inRank; + var coordsSnippet; + if (inRank === 0) { + coordsSnippet = ''; + } + else if (outRank < 2 && broadcastDims.length >= 1) { + coordsSnippet = 'coords = 0;'; + } + else { + coordsSnippet = + broadcastDims.map(function (d) { return "coords[" + (d + rankDiff) + "] = 0;"; }).join('\n'); + } + var unpackedCoordsSnippet = ''; + if (outRank < 2 && inRank > 0) { + unpackedCoordsSnippet = 'coords'; + } + else { + unpackedCoordsSnippet = inputInfo.shapeInfo.logicalShape + .map(function (s, i) { return "coords[" + (i + rankDiff) + "]"; }) + .join(', '); + } + return "\n float " + funcName + "() {\n " + type + " coords = getOutputCoords();\n " + coordsSnippet + "\n return get" + texFuncSnippet + "(" + unpackedCoordsSnippet + ");\n }\n "; +} +function getSamplerAtOutputCoords(inputInfo, outShapeInfo, supportsBroadcasting) { + var inTexShape = inputInfo.shapeInfo.texShape; + var texName = inputInfo.name; + var isRGBAColorTexture = inputInfo.shapeInfo.textureType === tex_util_1.TextureType.RGBA_COLOR; + var texFuncSnippet = texName.charAt(0).toUpperCase() + texName.slice(1); + var funcName = 'get' + texFuncSnippet + 'AtOutCoords'; + var broadcastDims = broadcast_util.getBroadcastDims(inputInfo.shapeInfo.logicalShape, outShapeInfo.logicalShape); + var inRank = inputInfo.shapeInfo.logicalShape.length; + var outRank = outShapeInfo.logicalShape.length; + var doBroadcast = supportsBroadcasting && ((outRank > inRank) || broadcastDims.length > 0); + var broadcastOverOuter = broadcast_util.broadcastDimsAreOuter(broadcastDims); + if (doBroadcast && !broadcastOverOuter) { + return getBroadcastOutputCoordsSampler(inputInfo, outShapeInfo, texFuncSnippet, funcName); + } + var outTexShape = outShapeInfo.texShape; + if (util.arraysEqual(inTexShape, outTexShape) && !isRGBAColorTexture) { + return "\n float " + funcName + "() {\n return sample(" + texName + ", resultUV);\n }\n "; + } + var inTexExpandedShape = isRGBAColorTexture ? + [inTexShape[0], inTexShape[1] * inputInfo.shapeInfo.logicalShape[2]] : + inTexShape; + var sampleSnippet = "return sample(" + texName + ", uv);"; + var rgbaColorSnippet = ''; + if (isRGBAColorTexture) { + rgbaColorSnippet = "\n int col = texC / " + inputInfo.shapeInfo.logicalShape[2] + ";\n int texD = texC - col * " + inputInfo.shapeInfo.logicalShape[2] + ";\n texC = col;\n "; + sampleSnippet = "return sampleUVAndDepth(" + texName + ", uv, texD);"; + } + var inSize = util.sizeFromShape(inTexExpandedShape); + var broadcastSnippet = ''; + if (doBroadcast && broadcastOverOuter) { + broadcastSnippet = "\n int mainPart = index / " + inSize + ";\n index -= mainPart * " + inSize + ";\n "; + } + return "\n float " + funcName + "() {\n ivec2 resTexRC = ivec2(resultUV.yx *\n vec2(" + outTexShape[0] + ", " + outTexShape[1] + "));\n int index = resTexRC.x * " + outTexShape[1] + " + resTexRC.y;\n " + broadcastSnippet + "\n int texR = index / " + inTexExpandedShape[1] + ";\n int texC = index - texR * " + inTexExpandedShape[1] + ";\n\n " + rgbaColorSnippet + "\n\n vec2 uv = (vec2(texC, texR) + halfCR) /\n vec2(" + inTexShape[1] + ".0, " + inTexShape[0] + ".0);\n\n " + sampleSnippet + "\n }\n "; +} +function getCoordsDataType(rank) { + if (rank === 1) { + return 'int'; + } + else if (rank === 2) { + return 'ivec2'; + } + else if (rank === 3) { + return 'ivec3'; + } + else if (rank === 4) { + return 'ivec4'; + } + else { + throw Error("GPU for rank " + rank + " is not yet supported"); + } +} +exports.getCoordsDataType = getCoordsDataType; +function squeezeInputInfo(inInfo, squeezedShape) { + var newInputInfo = JSON.parse(JSON.stringify(inInfo)); + newInputInfo.shapeInfo.logicalShape = squeezedShape; + return newInputInfo; +} +function getSqueezedParams(params, keptDims) { + return keptDims.map(function (d) { return params[d]; }).join(', '); +} + +},{"../../../environment":15,"../../../util":101,"../../broadcast_util":90,"./tex_util":84}],83:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var shader_compiler_1 = require("./shader_compiler"); +var SliceProgram = (function () { + function SliceProgram(destSize) { + this.variableNames = ['source']; + this.outputShape = destSize; + this.rank = destSize.length; + var dtype = shader_compiler_1.getCoordsDataType(this.rank); + var sourceCoords = getCoords(this.rank); + this.userCode = "\n uniform " + dtype + " start;\n\n void main() {\n " + dtype + " sourceLoc = start + getOutputCoords();\n setOutput(getSource(" + sourceCoords + "));\n }\n "; + } + SliceProgram.prototype.getCustomSetupFunc = function (start) { + var _this = this; + if (start.length !== this.rank) { + throw Error("The rank (" + this.rank + ") of the program must match the " + + ("length of start (" + start.length + ")")); + } + return function (gpgpu, webGLProgram) { + if (_this.startLoc == null) { + _this.startLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'start'); + if (_this.startLoc == null) { + return; + } + } + if (_this.rank === 1) { + gpgpu.gl.uniform1i(_this.startLoc, start[0]); + } + else if (_this.rank === 2) { + gpgpu.gl.uniform2i(_this.startLoc, start[0], start[1]); + } + else if (_this.rank === 3) { + gpgpu.gl.uniform3i(_this.startLoc, start[0], start[1], start[2]); + } + else if (_this.rank === 4) { + gpgpu.gl.uniform4i(_this.startLoc, start[0], start[1], start[2], start[3]); + } + else { + throw Error("Slicing for rank " + _this.rank + " is not yet supported"); + } + }; + }; + return SliceProgram; +}()); +exports.SliceProgram = SliceProgram; +function getCoords(rank) { + if (rank === 1) { + return 'sourceLoc'; + } + else if (rank === 2) { + return 'sourceLoc.x, sourceLoc.y'; + } + else if (rank === 3) { + return 'sourceLoc.x, sourceLoc.y, sourceLoc.z'; + } + else if (rank === 4) { + return 'sourceLoc.x, sourceLoc.y, sourceLoc.z, sourceLoc.w'; + } + else { + throw Error("Slicing for rank " + rank + " is not yet supported"); + } +} + +},{"./shader_compiler":82}],84:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var TextureType; +(function (TextureType) { + TextureType[TextureType["DEFAULT"] = 0] = "DEFAULT"; + TextureType[TextureType["RGBA_COLOR"] = 1] = "RGBA_COLOR"; +})(TextureType = exports.TextureType || (exports.TextureType = {})); +function getUnpackedMatrixTextureShapeWidthHeight(rows, columns) { + return [columns, rows]; +} +exports.getUnpackedMatrixTextureShapeWidthHeight = getUnpackedMatrixTextureShapeWidthHeight; +function getUnpackedArraySizeFromMatrixSize(matrixSize, channelsPerTexture) { + return matrixSize * channelsPerTexture; +} +exports.getUnpackedArraySizeFromMatrixSize = getUnpackedArraySizeFromMatrixSize; +function getColorMatrixTextureShapeWidthHeight(rows, columns) { + return [columns * 4, rows]; +} +exports.getColorMatrixTextureShapeWidthHeight = getColorMatrixTextureShapeWidthHeight; +function getMatrixSizeFromUnpackedArraySize(unpackedSize, channelsPerTexture) { + if (unpackedSize % channelsPerTexture !== 0) { + throw new Error("unpackedSize (" + unpackedSize + ") must be a multiple of " + + ("" + channelsPerTexture)); + } + return unpackedSize / channelsPerTexture; +} +exports.getMatrixSizeFromUnpackedArraySize = getMatrixSizeFromUnpackedArraySize; +function encodeMatrixToUnpackedArray(matrix, unpackedArray, channelsPerTexture) { + var requiredSize = getUnpackedArraySizeFromMatrixSize(matrix.length, channelsPerTexture); + if (unpackedArray.length < requiredSize) { + throw new Error("unpackedArray length (" + unpackedArray.length + ") must be >= " + + ("" + requiredSize)); + } + var dst = 0; + for (var src = 0; src < matrix.length; ++src) { + unpackedArray[dst] = matrix[src]; + dst += channelsPerTexture; + } +} +exports.encodeMatrixToUnpackedArray = encodeMatrixToUnpackedArray; +exports.FLOAT_MAX = 20000; +exports.FLOAT_MIN = -exports.FLOAT_MAX; +var FLOAT_RANGE = (exports.FLOAT_MAX - exports.FLOAT_MIN) / 255; +var FLOAT_DELTAS = [1, 1 / 255, 1 / (255 * 255), 1 / (255 * 255 * 255)]; +var FLOAT_POWERS = [1, 255, 255 * 255]; +exports.BYTE_NAN_VALUE = 0; +function encodeFloatArray(floatArray) { + var uintArray = new Uint8Array(floatArray.length * 4); + var _loop_1 = function (i) { + var value = floatArray[i / 4]; + if (isNaN(value)) { + uintArray[i] = exports.BYTE_NAN_VALUE; + uintArray[i + 1] = exports.BYTE_NAN_VALUE; + uintArray[i + 2] = exports.BYTE_NAN_VALUE; + uintArray[i + 3] = exports.BYTE_NAN_VALUE; + return "continue"; + } + var normalizedValue = (value - exports.FLOAT_MIN) / FLOAT_RANGE; + var enc = FLOAT_POWERS.map(function (pow) { return pow * normalizedValue; }); + var buckets = enc.map(function (value) { return Math.floor((value % 1) * 255); }); + uintArray[i] = Math.floor(normalizedValue); + uintArray[i + 1] = buckets[0]; + uintArray[i + 2] = buckets[1]; + uintArray[i + 3] = buckets[2]; + }; + for (var i = 0; i < uintArray.length; i += 4) { + _loop_1(i); + } + return uintArray; +} +exports.encodeFloatArray = encodeFloatArray; +function decodeToFloatArray(uintArray) { + var floatArray = new Float32Array(uintArray.length / 4); + var _loop_2 = function (i) { + if (uintArray[i] === exports.BYTE_NAN_VALUE && + uintArray[i + 1] === exports.BYTE_NAN_VALUE && + uintArray[i + 2] === exports.BYTE_NAN_VALUE && + uintArray[i + 3] === exports.BYTE_NAN_VALUE) { + floatArray[i / 4] = NaN; + return "continue"; + } + var dot = 0; + FLOAT_DELTAS.forEach(function (delta, j) { + dot += delta * uintArray[i + j]; + }); + var value = dot * FLOAT_RANGE + exports.FLOAT_MIN; + floatArray[i / 4] = value; + }; + for (var i = 0; i < uintArray.length; i += 4) { + _loop_2(i); + } + return floatArray; +} +exports.decodeToFloatArray = decodeToFloatArray; +function decodeMatrixFromUnpackedArray(unpackedArray, matrix, channelsPerTexture) { + var requiredSize = getMatrixSizeFromUnpackedArraySize(unpackedArray.length, channelsPerTexture); + if (matrix.length < requiredSize) { + throw new Error("matrix length (" + matrix.length + ") must be >= " + requiredSize); + } + var dst = 0; + for (var src = 0; src < unpackedArray.length; src += channelsPerTexture) { + matrix[dst++] = unpackedArray[src]; + } +} +exports.decodeMatrixFromUnpackedArray = decodeMatrixFromUnpackedArray; +function decodeMatrixFromUnpackedColorRGBAArray(unpackedArray, matrix, channels) { + var requiredSize = unpackedArray.length * channels / 4; + if (matrix.length < requiredSize) { + throw new Error("matrix length (" + matrix.length + ") must be >= " + requiredSize); + } + var dst = 0; + for (var src = 0; src < unpackedArray.length; src += 4) { + for (var c = 0; c < channels; c++) { + matrix[dst++] = unpackedArray[src + c]; + } + } +} +exports.decodeMatrixFromUnpackedColorRGBAArray = decodeMatrixFromUnpackedColorRGBAArray; +function getPackedMatrixTextureShapeWidthHeight(rows, columns) { + return [Math.ceil(columns / 2), Math.ceil(rows / 2)]; +} +exports.getPackedMatrixTextureShapeWidthHeight = getPackedMatrixTextureShapeWidthHeight; +function getPackedRGBAArraySizeFromMatrixShape(rows, columns) { + var _a = getPackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; + return w * h * 4; +} +exports.getPackedRGBAArraySizeFromMatrixShape = getPackedRGBAArraySizeFromMatrixShape; +function encodeMatrixToPackedRGBA(matrix, rows, columns, packedRGBA) { + var requiredSize = getPackedRGBAArraySizeFromMatrixShape(rows, columns); + if (packedRGBA.length < requiredSize) { + throw new Error("packedRGBA length (" + packedRGBA.length + ") must be >= " + requiredSize); + } + var _a = getPackedMatrixTextureShapeWidthHeight(rows, columns), textureWidth = _a[0], textureHeight = _a[1]; + var oddWidth = (columns % 2) === 1; + var oddHeight = (rows % 2) === 1; + var widthInFullBlocks = Math.floor(columns / 2); + var heightInFullBlocks = Math.floor(rows / 2); + { + var dstStride = (oddWidth ? 4 : 0); + var oneRow = columns; + var dst = 0; + for (var blockY = 0; blockY < heightInFullBlocks; ++blockY) { + var matrixSrcRow = (blockY * 2 * columns); + for (var blockX = 0; blockX < widthInFullBlocks; ++blockX) { + var matrixSrcCol = blockX * 2; + var src = matrixSrcRow + matrixSrcCol; + packedRGBA[dst] = matrix[src]; + packedRGBA[dst + 1] = matrix[src + 1]; + packedRGBA[dst + 2] = matrix[src + oneRow]; + packedRGBA[dst + 3] = matrix[src + oneRow + 1]; + dst += 4; + } + dst += dstStride; + } + } + if (oddWidth) { + var src = columns - 1; + var dst = (textureWidth - 1) * 4; + var srcStride = 2 * columns; + var dstStride = textureWidth * 4; + for (var blockY = 0; blockY < heightInFullBlocks; ++blockY) { + packedRGBA[dst] = matrix[src]; + packedRGBA[dst + 2] = matrix[src + columns]; + src += srcStride; + dst += dstStride; + } + } + if (oddHeight) { + var src = (rows - 1) * columns; + var dst = (textureHeight - 1) * textureWidth * 4; + for (var blockX = 0; blockX < widthInFullBlocks; ++blockX) { + packedRGBA[dst++] = matrix[src++]; + packedRGBA[dst++] = matrix[src++]; + dst += 2; + } + } + if (oddWidth && oddHeight) { + packedRGBA[packedRGBA.length - 4] = matrix[matrix.length - 1]; + } + return packedRGBA; +} +exports.encodeMatrixToPackedRGBA = encodeMatrixToPackedRGBA; +function decodeMatrixFromPackedRGBA(packedRGBA, rows, columns, matrix) { + var requiredSize = rows * columns; + if (requiredSize < matrix.length) { + throw new Error("matrix length (" + matrix.length + ") must be >= " + requiredSize); + } + var oddWidth = (columns % 2) === 1; + var oddHeight = (rows % 2) === 1; + var widthInFullBlocks = Math.floor(columns / 2); + var heightInFullBlocks = Math.floor(rows / 2); + var _a = getPackedMatrixTextureShapeWidthHeight(rows, columns), textureWidth = _a[0], textureHeight = _a[1]; + { + var srcStride = oddWidth ? 4 : 0; + var dstStride = columns + (oddWidth ? 1 : 0); + var src = 0; + var dstRow1 = 0; + var dstRow2 = columns; + for (var blockY = 0; blockY < heightInFullBlocks; ++blockY) { + for (var blockX = 0; blockX < widthInFullBlocks; ++blockX) { + matrix[dstRow1++] = packedRGBA[src++]; + matrix[dstRow1++] = packedRGBA[src++]; + matrix[dstRow2++] = packedRGBA[src++]; + matrix[dstRow2++] = packedRGBA[src++]; + } + src += srcStride; + dstRow1 += dstStride; + dstRow2 += dstStride; + } + } + if (oddWidth) { + var src = (textureWidth - 1) * 4; + var dst = columns - 1; + var srcStride = textureWidth * 4; + var dstStride = 2 * columns; + for (var blockY = 0; blockY < heightInFullBlocks; ++blockY) { + matrix[dst] = packedRGBA[src]; + matrix[dst + columns] = packedRGBA[src + 2]; + src += srcStride; + dst += dstStride; + } + } + if (oddHeight) { + var src = (textureHeight - 1) * textureWidth * 4; + var dst = (rows - 1) * columns; + for (var blockX = 0; blockX < widthInFullBlocks; ++blockX) { + matrix[dst++] = packedRGBA[src++]; + matrix[dst++] = packedRGBA[src++]; + src += 2; + } + } + if (oddWidth && oddHeight) { + matrix[matrix.length - 1] = packedRGBA[packedRGBA.length - 4]; + } + return matrix; +} +exports.decodeMatrixFromPackedRGBA = decodeMatrixFromPackedRGBA; + +},{}],85:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var TextureManager = (function () { + function TextureManager(gpgpu) { + this.gpgpu = gpgpu; + this.numUsedTextures = 0; + this.numFreeTextures = 0; + this.freeTextures = {}; + this.logEnabled = false; + this.usedTextureCount = {}; + } + TextureManager.prototype.acquireTexture = function (shapeRC) { + var shapeKey = getKeyFromTextureShape(shapeRC); + if (!(shapeKey in this.freeTextures)) { + this.freeTextures[shapeKey] = []; + } + if (!(shapeKey in this.usedTextureCount)) { + this.usedTextureCount[shapeKey] = 0; + } + this.usedTextureCount[shapeKey]++; + if (this.freeTextures[shapeKey].length > 0) { + this.numFreeTextures--; + this.numUsedTextures++; + this.log(); + return this.freeTextures[shapeKey].shift(); + } + this.numUsedTextures++; + this.log(); + return this.gpgpu.createMatrixTexture(shapeRC[0], shapeRC[1]); + }; + TextureManager.prototype.releaseTexture = function (texture, shape) { + var shapeKey = getKeyFromTextureShape(shape); + if (!(shapeKey in this.freeTextures)) { + this.freeTextures[shapeKey] = []; + } + this.freeTextures[shapeKey].push(texture); + this.numFreeTextures++; + this.numUsedTextures--; + this.usedTextureCount[shapeKey]--; + this.log(); + }; + TextureManager.prototype.log = function () { + if (!this.logEnabled) { + return; + } + var total = this.numFreeTextures + this.numUsedTextures; + console.log('Free/Used', this.numFreeTextures + " / " + this.numUsedTextures, "(" + total + ")"); + }; + TextureManager.prototype.getNumUsedTextures = function () { + return this.numUsedTextures; + }; + TextureManager.prototype.getNumFreeTextures = function () { + return this.numFreeTextures; + }; + TextureManager.prototype.dispose = function () { + for (var shape in this.freeTextures) { + if (this.freeTextures.hasOwnProperty(shape)) { + for (var i = 0; i < this.freeTextures[shape].length; i++) { + this.gpgpu.deleteMatrixTexture(this.freeTextures[shape][i]); + } + } + } + }; + return TextureManager; +}()); +exports.TextureManager = TextureManager; +function getKeyFromTextureShape(shapeRowsCol) { + return shapeRowsCol[0] + "_" + shapeRowsCol[1]; +} + +},{}],86:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var shader_compiler_1 = require("./shader_compiler"); +var TileProgram = (function () { + function TileProgram(aShape, reps) { + this.variableNames = ['A']; + var outputShape = new Array(aShape.length); + for (var i = 0; i < outputShape.length; i++) { + outputShape[i] = aShape[i] * reps[i]; + } + this.outputShape = outputShape; + this.rank = outputShape.length; + var dtype = shader_compiler_1.getCoordsDataType(this.rank); + var sourceCoords = getSourceCoords(aShape); + this.userCode = "\n void main() {\n " + dtype + " resRC = getOutputCoords();\n setOutput(getA(" + sourceCoords + "));\n }\n "; + } + return TileProgram; +}()); +exports.TileProgram = TileProgram; +function getSourceCoords(aShape) { + var rank = aShape.length; + if (rank > 4) { + throw Error("Tile for rank " + rank + " is not yet supported"); + } + if (rank === 1) { + return "imod(resRC, " + aShape[0] + ")"; + } + var currentCoords = ['resRC.x', 'resRC.y', 'resRC.z', 'resRC.w']; + var sourceCoords = []; + for (var i = 0; i < aShape.length; i++) { + sourceCoords.push("imod(" + currentCoords[i] + ", " + aShape[i] + ")"); + } + return sourceCoords.join(); +} + +},{"./shader_compiler":82}],87:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var shader_compiler_1 = require("./shader_compiler"); +var TransposeProgram = (function () { + function TransposeProgram(aShape, newDim) { + this.variableNames = ['A']; + var outputShape = new Array(aShape.length); + for (var i = 0; i < outputShape.length; i++) { + outputShape[i] = aShape[newDim[i]]; + } + this.outputShape = outputShape; + this.rank = outputShape.length; + var dtype = shader_compiler_1.getCoordsDataType(this.rank); + var switched = getSwitchedCoords(newDim); + this.userCode = "\n void main() {\n " + dtype + " resRC = getOutputCoords();\n setOutput(getA(" + switched + "));\n }\n "; + } + return TransposeProgram; +}()); +exports.TransposeProgram = TransposeProgram; +function getSwitchedCoords(newDim) { + var rank = newDim.length; + if (rank > 4) { + throw Error("Transpose for rank " + rank + " is not yet supported"); + } + var originalOrder = ['resRC.x', 'resRC.y', 'resRC.z', 'resRC.w']; + var switchedCoords = new Array(rank); + for (var i = 0; i < newDim.length; i++) { + switchedCoords[newDim[i]] = originalOrder[i]; + } + return switchedCoords.join(); +} + +},{"./shader_compiler":82}],88:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var UnaryOpProgram = (function () { + function UnaryOpProgram(aShape, opSnippet) { + this.variableNames = ['A']; + this.outputShape = aShape; + this.userCode = "\n float unaryOperation(float x) {\n " + opSnippet + "\n }\n\n void main() {\n float x = getAAtOutCoords();\n float y = unaryOperation(x);\n\n setOutput(y);\n }\n "; + } + return UnaryOpProgram; +}()); +exports.UnaryOpProgram = UnaryOpProgram; +exports.CHECK_NAN_SNIPPET = "\n if (isNaN(x)) {\n return x;\n }\n"; +exports.ABS = "\n return abs(x);\n"; +exports.RELU = exports.CHECK_NAN_SNIPPET + "\n return (x < 0.0) ? 0.0 : x;\n"; +exports.ELU = "\n return (x >= 0.0) ? x : (exp(x) - 1.0);\n"; +exports.ELU_DER = "\n return (x >= 0.0) ? 1.0 : exp(x);\n"; +exports.SELU = "\n // Stable and Attracting Fixed Point (0, 1) for Normalized Weights.\n // see: https://arxiv.org/abs/1706.02515\n float scaleAlpha = 1.7580993408473768599402175208123;\n float scale = 1.0507009873554804934193349852946;\n return (x >= 0.0) ? scale * x : scaleAlpha * (exp(x) - 1.0);\n"; +function LEAKY_RELU(alpha) { + return "\n return (x >= 0.0) ? x : " + alpha + " * x;\n "; +} +exports.LEAKY_RELU = LEAKY_RELU; +function STEP(alpha) { + if (alpha === void 0) { alpha = 0.0; } + return exports.CHECK_NAN_SNIPPET + ("\n return x > 0.0 ? 1.0 : float(" + alpha + ");\n "); +} +exports.STEP = STEP; +exports.NEG = "\n return -x;\n"; +exports.CEIL = "\n return ceil(x);\n"; +exports.FLOOR = "\n return floor(x);\n"; +exports.EXP = "\n return exp(x);\n"; +exports.LOG = "\n return log(x);\n"; +exports.SQRT = exports.CHECK_NAN_SNIPPET + "\n return sqrt(x);\n"; +exports.SIGMOID = "\n return 1.0 / (1.0 + exp(-1.0 * x));\n"; +exports.SIN = exports.CHECK_NAN_SNIPPET + "\n return sin(x);\n"; +exports.COS = exports.CHECK_NAN_SNIPPET + "\n return cos(x);\n"; +exports.TAN = "\n return tan(x);\n"; +exports.ASIN = exports.CHECK_NAN_SNIPPET + "\n return asin(x);\n"; +exports.ACOS = exports.CHECK_NAN_SNIPPET + "\n return acos(x);\n"; +exports.ATAN = exports.CHECK_NAN_SNIPPET + "\n return atan(x);\n"; +exports.SINH = "\n float e2x = exp(x);\n return (e2x - 1.0 / e2x) / 2.0;\n"; +exports.COSH = "\n float e2x = exp(-x);\n return (e2x + 1.0 / e2x) / 2.0;\n"; +exports.TANH = "\n float e2x = exp(-2.0 * abs(x));\n return sign(x) * (1.0 - e2x) / (1.0 + e2x);\n"; +exports.SQUARE = "\n return x * x;\n"; + +},{}],89:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var MAX_TEXTURE_SIZE = null; +var util = require("../../../util"); +var environment_1 = require("../../../environment"); +function createWebGLRenderingContext(attributes) { + var canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + return createWebGLRenderingContextFromCanvas(canvas, attributes); +} +exports.createWebGLRenderingContext = createWebGLRenderingContext; +function createWebGLRenderingContextFromCanvas(canvas, attributes) { + var gl; + var webglVersion = environment_1.ENV.get('WEBGL_VERSION'); + if (webglVersion === 2) { + gl = canvas.getContext('webgl2', attributes); + } + else if (webglVersion === 1) { + gl = (canvas.getContext('webgl', attributes) || + canvas.getContext('experimental-webgl', attributes)); + } + if (webglVersion === 0 || gl == null) { + throw new Error('This browser does not support WebGL.'); + } + return gl; +} +exports.createWebGLRenderingContextFromCanvas = createWebGLRenderingContextFromCanvas; +function callAndCheck(gl, func) { + var returnValue = func(); + checkWebGLError(gl); + return returnValue; +} +exports.callAndCheck = callAndCheck; +var webGLDebugErrorCheckingEnabled = false; +function enableDebugWebGLErrorChecking(enabled) { + webGLDebugErrorCheckingEnabled = enabled; +} +exports.enableDebugWebGLErrorChecking = enableDebugWebGLErrorChecking; +function checkWebGLError(gl) { + if (webGLDebugErrorCheckingEnabled) { + var error = gl.getError(); + if (error !== gl.NO_ERROR) { + throw new Error('WebGL Error: ' + getWebGLErrorMessage(gl, error)); + } + } +} +exports.checkWebGLError = checkWebGLError; +function getWebGLErrorMessage(gl, status) { + switch (status) { + case gl.NO_ERROR: + return 'NO_ERROR'; + case gl.INVALID_ENUM: + return 'INVALID_ENUM'; + case gl.INVALID_VALUE: + return 'INVALID_VALUE'; + case gl.INVALID_OPERATION: + return 'INVALID_OPERATION'; + case gl.INVALID_FRAMEBUFFER_OPERATION: + return 'INVALID_FRAMEBUFFER_OPERATION'; + case gl.OUT_OF_MEMORY: + return 'OUT_OF_MEMORY'; + case gl.CONTEXT_LOST_WEBGL: + return 'CONTEXT_LOST_WEBGL'; + default: + return "Unknown error code " + status; + } +} +exports.getWebGLErrorMessage = getWebGLErrorMessage; +function getExtensionOrThrow(gl, extensionName) { + return throwIfNull(gl, function () { return gl.getExtension(extensionName); }, 'Extension "' + extensionName + '" not supported on this browser.'); +} +exports.getExtensionOrThrow = getExtensionOrThrow; +function createVertexShader(gl, vertexShaderSource) { + var vertexShader = throwIfNull(gl, function () { return gl.createShader(gl.VERTEX_SHADER); }, 'Unable to create vertex WebGLShader.'); + callAndCheck(gl, function () { return gl.shaderSource(vertexShader, vertexShaderSource); }); + callAndCheck(gl, function () { return gl.compileShader(vertexShader); }); + if (gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS) === false) { + console.log(gl.getShaderInfoLog(vertexShader)); + throw new Error('Failed to compile vertex shader.'); + } + return vertexShader; +} +exports.createVertexShader = createVertexShader; +function createFragmentShader(gl, fragmentShaderSource) { + var fragmentShader = throwIfNull(gl, function () { return gl.createShader(gl.FRAGMENT_SHADER); }, 'Unable to create fragment WebGLShader.'); + callAndCheck(gl, function () { return gl.shaderSource(fragmentShader, fragmentShaderSource); }); + callAndCheck(gl, function () { return gl.compileShader(fragmentShader); }); + if (gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS) === false) { + logShaderSourceAndInfoLog(fragmentShaderSource, gl.getShaderInfoLog(fragmentShader)); + throw new Error('Failed to compile fragment shader.'); + } + return fragmentShader; +} +exports.createFragmentShader = createFragmentShader; +var lineNumberRegex = /ERROR: [0-9]+:([0-9]+):/g; +function logShaderSourceAndInfoLog(shaderSource, shaderInfoLog) { + var lineNumberRegexResult = lineNumberRegex.exec(shaderInfoLog); + if (lineNumberRegexResult == null) { + console.log("Couldn't parse line number in error: " + shaderInfoLog); + console.log(shaderSource); + return; + } + var lineNumber = +lineNumberRegexResult[1]; + var shaderLines = shaderSource.split('\n'); + var pad = shaderLines.length.toString().length + 2; + var linesWithLineNumbers = shaderLines.map(function (line, lineNumber) { + return util.rightPad((lineNumber + 1).toString(), pad) + line; + }); + var maxLineLength = 0; + for (var i = 0; i < linesWithLineNumbers.length; i++) { + maxLineLength = Math.max(linesWithLineNumbers[i].length, maxLineLength); + } + var beforeErrorLines = linesWithLineNumbers.slice(0, lineNumber - 1); + var errorLine = linesWithLineNumbers.slice(lineNumber - 1, lineNumber); + var afterErrorLines = linesWithLineNumbers.slice(lineNumber); + console.log(beforeErrorLines.join('\n')); + console.log(shaderInfoLog.split('\n')[0]); + console.log("%c " + util.rightPad(errorLine[0], maxLineLength), 'border:1px solid red; background-color:#e3d2d2; color:#a61717'); + console.log(afterErrorLines.join('\n')); +} +function createProgram(gl) { + return throwIfNull(gl, function () { return gl.createProgram(); }, 'Unable to create WebGLProgram.'); +} +exports.createProgram = createProgram; +function linkProgram(gl, program) { + callAndCheck(gl, function () { return gl.linkProgram(program); }); + if (gl.getProgramParameter(program, gl.LINK_STATUS) === false) { + console.log(gl.getProgramInfoLog(program)); + throw new Error('Failed to link vertex and fragment shaders.'); + } +} +exports.linkProgram = linkProgram; +function validateProgram(gl, program) { + callAndCheck(gl, function () { return gl.validateProgram(program); }); + if (gl.getProgramParameter(program, gl.VALIDATE_STATUS) === false) { + console.log(gl.getProgramInfoLog(program)); + throw new Error('Shader program validation failed.'); + } +} +exports.validateProgram = validateProgram; +function createStaticVertexBuffer(gl, data) { + var buffer = throwIfNull(gl, function () { return gl.createBuffer(); }, 'Unable to create WebGLBuffer'); + callAndCheck(gl, function () { return gl.bindBuffer(gl.ARRAY_BUFFER, buffer); }); + callAndCheck(gl, function () { return gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW); }); + return buffer; +} +exports.createStaticVertexBuffer = createStaticVertexBuffer; +function createStaticIndexBuffer(gl, data) { + var buffer = throwIfNull(gl, function () { return gl.createBuffer(); }, 'Unable to create WebGLBuffer'); + callAndCheck(gl, function () { return gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer); }); + callAndCheck(gl, function () { return gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW); }); + return buffer; +} +exports.createStaticIndexBuffer = createStaticIndexBuffer; +function queryMaxTextureSize(gl) { + if (MAX_TEXTURE_SIZE != null) { + return MAX_TEXTURE_SIZE; + } + MAX_TEXTURE_SIZE = + callAndCheck(gl, function () { return gl.getParameter(gl.MAX_TEXTURE_SIZE); }); + return MAX_TEXTURE_SIZE; +} +exports.queryMaxTextureSize = queryMaxTextureSize; +function getChannelsPerTexture() { + if (!environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { + return 4; + } + if (environment_1.ENV.get('WEBGL_VERSION') === 2) { + return 1; + } + return 4; +} +exports.getChannelsPerTexture = getChannelsPerTexture; +function createTexture(gl) { + return throwIfNull(gl, function () { return gl.createTexture(); }, 'Unable to create WebGLTexture.'); +} +exports.createTexture = createTexture; +function validateTextureSize(gl, width, height) { + var maxTextureSize = queryMaxTextureSize(gl); + if ((width <= 0) || (height <= 0)) { + var requested = "[" + width + "x" + height + "]"; + throw new Error('Requested texture size ' + requested + ' is invalid.'); + } + if ((width > maxTextureSize) || (height > maxTextureSize)) { + var requested = "[" + width + "x" + height + "]"; + var max = "[" + maxTextureSize + "x" + maxTextureSize + "]"; + throw new Error('Requested texture size ' + requested + + ' greater than WebGL maximum on this browser / GPU ' + max + '.'); + } +} +exports.validateTextureSize = validateTextureSize; +function createFramebuffer(gl) { + return throwIfNull(gl, function () { return gl.createFramebuffer(); }, 'Unable to create WebGLFramebuffer.'); +} +exports.createFramebuffer = createFramebuffer; +function bindVertexBufferToProgramAttribute(gl, program, attribute, buffer, arrayEntriesPerItem, itemStrideInBytes, itemOffsetInBytes, attribLocations) { + var loc = -1; + if ((attribLocations != null) && (attribute in attribLocations)) { + loc = attribLocations[attribute]; + } + else { + loc = gl.getAttribLocation(program, attribute); + } + if (loc === -1) { + return; + } + callAndCheck(gl, function () { return gl.bindBuffer(gl.ARRAY_BUFFER, buffer); }); + callAndCheck(gl, function () { return gl.vertexAttribPointer(loc, arrayEntriesPerItem, gl.FLOAT, false, itemStrideInBytes, itemOffsetInBytes); }); + callAndCheck(gl, function () { return gl.enableVertexAttribArray(loc); }); +} +exports.bindVertexBufferToProgramAttribute = bindVertexBufferToProgramAttribute; +function bindTextureUnit(gl, texture, textureUnit) { + validateTextureUnit(gl, textureUnit); + callAndCheck(gl, function () { return gl.activeTexture(gl.TEXTURE0 + textureUnit); }); + callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, texture); }); +} +exports.bindTextureUnit = bindTextureUnit; +function unbindTextureUnit(gl, textureUnit) { + validateTextureUnit(gl, textureUnit); + callAndCheck(gl, function () { return gl.activeTexture(gl.TEXTURE0 + textureUnit); }); + callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, null); }); +} +exports.unbindTextureUnit = unbindTextureUnit; +function getProgramUniformLocationOrThrow(gl, program, uniformName) { + return throwIfNull(gl, function () { return gl.getUniformLocation(program, uniformName); }, 'uniform "' + uniformName + '" not present in program.'); +} +exports.getProgramUniformLocationOrThrow = getProgramUniformLocationOrThrow; +function bindTextureToProgramUniformSampler(gl, program, texture, uniformSamplerLocation, textureUnit) { + callAndCheck(gl, function () { return bindTextureUnit(gl, texture, textureUnit); }); + callAndCheck(gl, function () { return gl.uniform1i(uniformSamplerLocation, textureUnit); }); +} +exports.bindTextureToProgramUniformSampler = bindTextureToProgramUniformSampler; +function bindCanvasToFramebuffer(gl) { + callAndCheck(gl, function () { return gl.bindFramebuffer(gl.FRAMEBUFFER, null); }); + callAndCheck(gl, function () { return gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); }); + callAndCheck(gl, function () { return gl.scissor(0, 0, gl.canvas.width, gl.canvas.height); }); +} +exports.bindCanvasToFramebuffer = bindCanvasToFramebuffer; +function bindColorTextureToFramebuffer(gl, texture, framebuffer) { + callAndCheck(gl, function () { return gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); }); + callAndCheck(gl, function () { return gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); }); +} +exports.bindColorTextureToFramebuffer = bindColorTextureToFramebuffer; +function unbindColorTextureFromFramebuffer(gl, framebuffer) { + callAndCheck(gl, function () { return gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); }); + callAndCheck(gl, function () { return gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); }); +} +exports.unbindColorTextureFromFramebuffer = unbindColorTextureFromFramebuffer; +function validateFramebuffer(gl) { + var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (status !== gl.FRAMEBUFFER_COMPLETE) { + throw new Error('Error binding framebuffer: ' + getFramebufferErrorMessage(gl, status)); + } +} +exports.validateFramebuffer = validateFramebuffer; +function getFramebufferErrorMessage(gl, status) { + switch (status) { + case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + return 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT'; + case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + return 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT'; + case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + return 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS'; + case gl.FRAMEBUFFER_UNSUPPORTED: + return 'FRAMEBUFFER_UNSUPPORTED'; + default: + return "unknown error " + status; + } +} +exports.getFramebufferErrorMessage = getFramebufferErrorMessage; +function throwIfNull(gl, returnTOrNull, failureMessage) { + var tOrNull = callAndCheck(gl, function () { return returnTOrNull(); }); + if (tOrNull == null) { + throw new Error(failureMessage); + } + return tOrNull; +} +function validateTextureUnit(gl, textureUnit) { + var maxTextureUnit = gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1; + var glTextureUnit = textureUnit + gl.TEXTURE0; + if (glTextureUnit < gl.TEXTURE0 || glTextureUnit > maxTextureUnit) { + var textureUnitRange = "[gl.TEXTURE0, gl.TEXTURE" + maxTextureUnit + "]"; + throw new Error("textureUnit must be in " + textureUnitRange + "."); + } +} +function getTextureShapeFromLogicalShape(gl, logShape) { + if (logShape.length !== 2) { + var squeezeResult = util.squeezeShape(logShape); + logShape = squeezeResult.newShape; + } + var maxTexSize = queryMaxTextureSize(gl); + var size = util.sizeFromShape(logShape); + if (logShape.length <= 1 && size <= maxTexSize) { + return [size, 1]; + } + else if (logShape.length === 2 && logShape[0] <= maxTexSize && + logShape[1] <= maxTexSize) { + return logShape; + } + else if (logShape.length === 3 && logShape[0] <= maxTexSize && + logShape[1] * logShape[2] <= maxTexSize) { + return [logShape[0], logShape[1] * logShape[2]]; + } + else if (logShape.length === 4 && logShape[0] <= maxTexSize && + logShape[1] * logShape[2] * logShape[3] <= maxTexSize) { + return [logShape[0], logShape[1] * logShape[2] * logShape[3]]; + } + else { + return util.sizeToSquarishShape(size); + } +} +exports.getTextureShapeFromLogicalShape = getTextureShapeFromLogicalShape; + +},{"../../../environment":15,"../../../util":101}],90:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function getBroadcastDims(inShape, outShape) { + var inRank = inShape.length; + var dims = []; + for (var i = 0; i < inRank; i++) { + var dim = inRank - 1 - i; + var a = inShape[dim] || 1; + var b = outShape[outShape.length - 1 - i] || 1; + if (b > 1 && a === 1) { + dims.unshift(dim); + } + } + return dims; +} +exports.getBroadcastDims = getBroadcastDims; +function broadcastDimsAreOuter(dims) { + for (var i = 0; i < dims.length; i++) { + if (dims[i] !== i) { + return false; + } + } + return true; +} +exports.broadcastDimsAreOuter = broadcastDimsAreOuter; +function assertAndGetBroadcastShape(shapeA, shapeB) { + var result = []; + var errMsg = "Operands could not be broadcast together with shapes " + + (shapeA + " and " + shapeB + "."); + var l = Math.max(shapeA.length, shapeB.length); + for (var i = 0; i < l; i++) { + var a = shapeA[shapeA.length - i - 1] || 1; + var b = shapeB[shapeB.length - i - 1] || 1; + if (a > 1 && b > 1 && a !== b) { + throw Error(errMsg); + } + result.unshift(Math.max(a, b)); + } + return result; +} +exports.assertAndGetBroadcastShape = assertAndGetBroadcastShape; + +},{}],91:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../util"); +function assertParams(aShape, bShape, axis) { + var aRank = aShape.length; + var bRank = bShape.length; + util.assert(aShape.length === bShape.length, "Error in concat" + aRank + "D: rank of x1 (" + aRank + ") and x2 (" + bRank + ") " + + "must be the same."); + util.assert(axis >= 0 && axis < aRank, "Error in concat" + aRank + "D: axis must be " + + ("between 0 and " + (aRank - 1) + ".")); + for (var i = 0; i < aRank; i++) { + util.assert((i === axis) || (aShape[i] === bShape[i]), "Error in concat" + aRank + "D: Shape (" + aShape + ") does not match " + + ("(" + bShape + ") along the non-concatenated axis " + i + ".")); + } +} +exports.assertParams = assertParams; +function computeOutShape(x1Shape, x2Shape, axis) { + util.assert(x1Shape.length === x2Shape.length, 'x1 and x2 should have the same rank.'); + var outputShape = x1Shape.slice(); + outputShape[axis] += x2Shape[axis]; + return outputShape; +} +exports.computeOutShape = computeOutShape; + +},{"../util":101}],92:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../util"); +function computePool2DInfo(inShape, filterSize, strides, pad, dataFormat) { + if (dataFormat === void 0) { dataFormat = 'channelsLast'; } + var _a = parseTupleParam(filterSize), filterHeight = _a[0], filterWidth = _a[1]; + var filterShape; + if (dataFormat === 'channelsLast') { + filterShape = [filterHeight, filterWidth, inShape[3], inShape[3]]; + } + else if (dataFormat === 'channelsFirst') { + filterShape = [filterHeight, filterWidth, inShape[1], inShape[1]]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + return computeConv2DInfo(inShape, filterShape, strides, pad, false, dataFormat); +} +exports.computePool2DInfo = computePool2DInfo; +function computeConv2DInfo(inShape, filterShape, strides, pad, depthwise, dataFormat) { + if (depthwise === void 0) { depthwise = false; } + if (dataFormat === void 0) { dataFormat = 'channelsLast'; } + var _a = [-1, -1, -1, -1], batchSize = _a[0], inHeight = _a[1], inWidth = _a[2], inChannels = _a[3]; + if (dataFormat === 'channelsLast') { + batchSize = inShape[0], inHeight = inShape[1], inWidth = inShape[2], inChannels = inShape[3]; + } + else if (dataFormat === 'channelsFirst') { + batchSize = inShape[0], inChannels = inShape[1], inHeight = inShape[2], inWidth = inShape[3]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + var filterHeight = filterShape[0], filterWidth = filterShape[1], filterChannels = filterShape[3]; + var _b = parseTupleParam(strides), strideHeight = _b[0], strideWidth = _b[1]; + var _c = getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, filterHeight, filterWidth), padInfo = _c.padInfo, outHeight = _c.outHeight, outWidth = _c.outWidth; + var outChannels = depthwise ? filterChannels * inChannels : filterChannels; + var outShape; + if (dataFormat === 'channelsFirst') { + outShape = [batchSize, outChannels, outHeight, outWidth]; + } + else if (dataFormat === 'channelsLast') { + outShape = [batchSize, outHeight, outWidth, outChannels]; + } + return { + batchSize: batchSize, + dataFormat: dataFormat, + inHeight: inHeight, + inWidth: inWidth, + inChannels: inChannels, + outHeight: outHeight, + outWidth: outWidth, + outChannels: outChannels, + padInfo: padInfo, + strideHeight: strideHeight, + strideWidth: strideWidth, + filterHeight: filterHeight, + filterWidth: filterWidth, + inShape: inShape, + outShape: outShape, + filterShape: filterShape + }; +} +exports.computeConv2DInfo = computeConv2DInfo; +function computeOutputShape3D(inShape, fieldSize, outDepth, stride, zeroPad) { + if (zeroPad == null) { + zeroPad = computeDefaultPad(inShape, fieldSize, stride); + } + var inputRows = inShape[0]; + var inputCols = inShape[1]; + var outputRows = (inputRows - fieldSize + 2 * zeroPad) / stride + 1; + util.assert(util.isInt(outputRows), "The output # of rows (" + outputRows + ") must be an integer. Change the " + + "stride and/or zero pad parameters"); + var outputCols = (inputCols - fieldSize + 2 * zeroPad) / stride + 1; + util.assert(util.isInt(outputCols), "The output # of columns (" + outputCols + ") must be an integer. Change " + + "the stride and/or zero pad parameters"); + return [outputRows, outputCols, outDepth]; +} +exports.computeOutputShape3D = computeOutputShape3D; +function computeDefaultPad(inputShape, fieldSize, stride) { + return Math.floor((inputShape[0] * (stride - 1) - stride + fieldSize) / 2); +} +exports.computeDefaultPad = computeDefaultPad; +function computeWeightsShape4D(inputDepth, outputDepth, filterHeight, filterWidth) { + return [filterHeight, filterWidth, inputDepth, outputDepth]; +} +exports.computeWeightsShape4D = computeWeightsShape4D; +function computeDilatedRC(rc, origStride) { + var rowsDilated = (rc[0] - 1) * origStride + 1; + var colsDilated = (rc[1] - 1) * origStride + 1; + return [rowsDilated, colsDilated]; +} +exports.computeDilatedRC = computeDilatedRC; +function parseTupleParam(param) { + return typeof param === 'number' ? [param, param] : param; +} +function getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, filterHeight, filterWidth) { + var padInfo; + var outHeight; + var outWidth; + if (typeof pad === 'number') { + padInfo = { top: pad, bottom: pad, left: pad, right: pad }; + var outShape = computeOutputShape3D([inHeight, inWidth, 1], filterHeight, 1, strideHeight, pad); + outHeight = outShape[0]; + outWidth = outShape[1]; + } + else if (pad === 'same') { + outHeight = Math.ceil(inHeight / strideHeight); + outWidth = Math.ceil(inWidth / strideWidth); + var padAlongHeight = (outHeight - 1) * strideHeight + filterHeight - inHeight; + var padAlongWidth = (outWidth - 1) * strideWidth + filterWidth - inWidth; + var top_1 = Math.floor(padAlongHeight / 2); + var bottom = padAlongHeight - top_1; + var left = Math.floor(padAlongWidth / 2); + var right = padAlongWidth - left; + padInfo = { top: top_1, bottom: bottom, left: left, right: right }; + } + else if (pad === 'valid') { + padInfo = { top: 0, bottom: 0, left: 0, right: 0 }; + outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); + outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); + } + else { + throw Error("Unknown padding parameter: " + pad); + } + return { padInfo: padInfo, outHeight: outHeight, outWidth: outWidth }; +} + +},{"../util":101}],93:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../environment"); +var ndarray_1 = require("./ndarray"); +var SquareCostFunc = (function () { + function SquareCostFunc() { + this.halfOne = environment_1.ENV.math.keep(ndarray_1.Scalar.new(0.5)); + } + SquareCostFunc.prototype.cost = function (math, x1, x2) { + var diff = math.subStrict(x1, x2); + var diffSquared = math.elementWiseMul(diff, diff); + var result = math.scalarTimesArray(this.halfOne, diffSquared); + diff.dispose(); + diffSquared.dispose(); + return result; + }; + SquareCostFunc.prototype.der = function (math, x1, x2) { + return math.subStrict(x1, x2); + }; + SquareCostFunc.prototype.dispose = function () { + this.halfOne.dispose(); + }; + return SquareCostFunc; +}()); +exports.SquareCostFunc = SquareCostFunc; + +},{"../environment":15,"./ndarray":95}],94:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../environment"); +var util = require("../util"); +var axis_util = require("./axis_util"); +var backend_engine_1 = require("./backends/backend_engine"); +var matmul_1 = require("./backends/types/matmul"); +var broadcast_util = require("./broadcast_util"); +var concat_util = require("./concat_util"); +var conv_util = require("./conv_util"); +var ndarray_1 = require("./ndarray"); +var slice_util = require("./slice_util"); +var NDArrayMath = (function () { + function NDArrayMath(backend, safeMode) { + this.safeMode = safeMode; + this.numArrays = 0; + this.customBackend = false; + this.ndarrayScopes = []; + this.ndarraysToKeep = []; + this.activeScopeNDArraysToKeep = []; + if (typeof backend === 'string') { + this.backend = environment_1.ENV.getBackend(backend); + } + else { + this.customBackend = true; + this.backend = backend; + } + this.backendEngine = new backend_engine_1.BackendEngine(this.backend); + } + NDArrayMath.prototype.time = function (query) { + return this.backend.time(query); + }; + NDArrayMath.prototype.getNumArrays = function () { + return this.numArrays; + }; + NDArrayMath.prototype.register = function (a) { + this.track(a); + this.numArrays++; + }; + NDArrayMath.prototype.writePixels = function (id, pixels, numChannels) { + this.backend.writePixels(id, pixels, numChannels); + }; + NDArrayMath.prototype.write = function (id, values, dtype, shape) { + this.backend.write(id, values, dtype, shape); + }; + NDArrayMath.prototype.readSync = function (id) { + return this.backend.readSync(id); + }; + NDArrayMath.prototype.read = function (id) { + return this.backend.read(id); + }; + NDArrayMath.prototype.scope = function (scopeFn) { + var _this = this; + this.startScope(); + var keepFn = function (ndarray) { return _this.keep(ndarray); }; + var trackFn = function (ndarray) { return ndarray; }; + var result = scopeFn(keepFn, trackFn); + if (result instanceof Promise) { + result.then(function (r) { return _this.endScope(r); }); + return result; + } + else { + this.endScope(result); + return result; + } + }; + NDArrayMath.prototype.enableDebugMode = function () { + this.backendEngine.enableDebugMode(); + console.warn('Debugging mode is ON. The output of every math call will ' + + 'be downloaded to CPU and checked for NaNs. ' + + 'This significantly impacts performance.'); + }; + NDArrayMath.prototype.startScope = function () { + var newScope = []; + this.ndarrayScopes.push(newScope); + this.activeScope = newScope; + var newNDArraysToKeep = []; + this.ndarraysToKeep.push(newNDArraysToKeep); + this.activeScopeNDArraysToKeep = newNDArraysToKeep; + }; + NDArrayMath.prototype.extractNDArraysFromScopeResult = function (result) { + if (result == null) { + return []; + } + if (result instanceof ndarray_1.NDArray) { + return [result]; + } + var list = []; + var resultObj = result; + for (var k in resultObj) { + var val = resultObj[k]; + if (val instanceof ndarray_1.NDArray) { + list.push(val); + } + } + return list; + }; + NDArrayMath.prototype.endScope = function (result) { + var _this = this; + var arraysToKeep = this.activeScopeNDArraysToKeep; + var resultArrays = this.extractNDArraysFromScopeResult(result); + arraysToKeep = arraysToKeep.concat(resultArrays); + for (var i = 0; i < this.activeScope.length; i++) { + var ndarray = this.activeScope[i]; + if (this.isNDArrayDataInList(ndarray, arraysToKeep)) { + continue; + } + ndarray.dispose(); + } + this.ndarrayScopes.pop(); + this.activeScope = this.ndarrayScopes.length === 0 ? + null : + this.ndarrayScopes[this.ndarrayScopes.length - 1]; + resultArrays.forEach(function (val) { + if (!_this.isNDArrayDataInList(val, _this.activeScopeNDArraysToKeep)) { + _this.track(val); + } + }); + this.ndarraysToKeep.pop(); + this.activeScopeNDArraysToKeep = this.ndarraysToKeep.length === 0 ? + null : + this.ndarraysToKeep[this.ndarraysToKeep.length - 1]; + }; + NDArrayMath.prototype.isNDArrayDataInList = function (ndarray, ndarrayList) { + for (var i = 0; i < ndarrayList.length; i++) { + if (ndarrayList[i].id === ndarray.id) { + return true; + } + } + return false; + }; + NDArrayMath.prototype.keep = function (result) { + if (this.activeScope == null) { + if (this.safeMode) { + throw new Error('You are using math in safe mode. Enclose all ' + + 'math.method() calls inside a scope: ' + + 'math.scope(() => {math.method();...}) to avoid memory ' + + 'leaks.'); + } + return result; + } + this.activeScopeNDArraysToKeep.push(result); + return result; + }; + NDArrayMath.prototype.track = function (result) { + if (this.activeScope == null) { + if (this.safeMode) { + throw new Error('You are using math in safe mode. Enclose all ' + + 'math.method() calls inside a scope: ' + + 'math.scope(() => {math.method();...}) to avoid memory ' + + 'leaks.'); + } + return result; + } + this.activeScope.push(result); + return result; + }; + NDArrayMath.prototype.dispose = function () { + if (this.customBackend) { + this.backend.dispose(); + } + }; + NDArrayMath.prototype.matMul = function (a, b, aOrientation, bOrientation) { + var _this = this; + if (aOrientation === void 0) { aOrientation = matmul_1.MatrixOrientation.REGULAR; } + if (bOrientation === void 0) { bOrientation = matmul_1.MatrixOrientation.REGULAR; } + var innerShapeA = (aOrientation === matmul_1.MatrixOrientation.REGULAR) ? a.shape[1] : a.shape[0]; + var innerShapeB = (bOrientation === matmul_1.MatrixOrientation.REGULAR) ? b.shape[0] : b.shape[1]; + util.assert(a.rank === 2 && b.rank === 2, "Error in matMul: inputs must be rank 2, got ranks " + a.rank + + (" and " + b.rank + ".")); + util.assert(innerShapeA === innerShapeB, "Error in matMul: inner shapes (" + innerShapeA + ") and (" + + (innerShapeB + ") of NDArrays with shapes " + a.shape + " and ") + + (b.shape + " and orientations " + matmul_1.MatrixOrientation[aOrientation]) + + (" and " + matmul_1.MatrixOrientation[bOrientation] + " must match.")); + return this.backendEngine.executeKernel('MatMul', { inputs: { a: a, b: b }, args: { aOrientation: aOrientation, bOrientation: bOrientation } }, function (dy, y) { + return { + a: function () { return _this.matMul(dy, b, matmul_1.MatrixOrientation.REGULAR, matmul_1.MatrixOrientation.TRANSPOSED); }, + b: function () { return _this.matMul(a, dy, matmul_1.MatrixOrientation.TRANSPOSED, matmul_1.MatrixOrientation.REGULAR); } + }; + }); + }; + NDArrayMath.prototype.executeOp = function (name, f) { + return f(); + }; + NDArrayMath.prototype.vectorTimesMatrix = function (v, matrix) { + util.assert(v.rank === 1, "Error in vectorTimesMatrix: first input must be rank 1, but got " + + ("rank " + v.rank + ".")); + util.assert(matrix.rank === 2, "Error in vectorTimesMatrix: second input must be rank 2, but got " + + ("rank " + matrix.rank + ".")); + util.assert(v.size === matrix.shape[0], "Error in vectorTimesMatrix: size of vector (" + v.size + ") " + + ("must match first dimension of matrix (" + matrix.shape[0] + ")")); + return this.matMul(v.as2D(1, -1), matrix).as1D(); + }; + NDArrayMath.prototype.matrixTimesVector = function (matrix, v) { + util.assert(v.rank === 1, "Error in matrixTimesVector: second input must rank 1, but got " + + ("rank " + v.rank + ".")); + util.assert(matrix.rank === 2, "Error in matrixTimesVector: first input must be a rank 2, but got " + + ("rank " + matrix.rank + ".")); + util.assert(v.size === matrix.shape[1], "Error in matrixTimesVector: size of first rank 1 input " + v.size + " " + + "must match inner dimension of second rank 2 input, but got " + + ("shape " + matrix.shape + ".")); + return this.matMul(matrix, v.as2D(-1, 1)).as1D(); + }; + NDArrayMath.prototype.dotProduct = function (v1, v2) { + util.assert(v1.rank === 1 && v2.rank === 1, "Error in dotProduct: inputs must be rank 1, but got ranks " + + (v1.rank + " and " + v2.rank + ".")); + util.assert(v1.size === v2.size, "Error in dotProduct: size of inputs (" + v1.size + ") and (" + + (v2.size + ") must match.")); + return this.matMul(v1.as2D(1, -1), v2.as2D(-1, 1)).asScalar(); + }; + NDArrayMath.prototype.outerProduct = function (v1, v2) { + util.assert(v1.rank === 1 && v2.rank === 1, "Error in outerProduct: inputs must be rank 1, but got ranks " + + (v1.rank + " and " + v2.rank + ".")); + return this.matMul(v1.as2D(-1, 1), v2.as2D(1, -1)); + }; + NDArrayMath.prototype.clone = function (x) { + return this.backendEngine.executeKernel('Clone', { inputs: { x: x } }); + }; + NDArrayMath.prototype.reshape = function (ndarray, newShape) { + console.warn('math.reshape() is deprecated. Please call reshape() ' + + 'directly on the ndarray object'); + return ndarray.reshape(newShape); + }; + NDArrayMath.prototype.slice1D = function (x, begin, size) { + slice_util.assertParamsValid(x, [begin], [size]); + return this.backendEngine.executeKernel('Slice1D', { inputs: { x: x }, args: { begin: begin, size: size } }); + }; + NDArrayMath.prototype.slice2D = function (x, begin, size) { + slice_util.assertParamsValid(x, begin, size); + return this.backendEngine.executeKernel('Slice2D', { inputs: { x: x }, args: { begin: begin, size: size } }); + }; + NDArrayMath.prototype.slice3D = function (x, begin, size) { + slice_util.assertParamsValid(x, begin, size); + return this.backendEngine.executeKernel('Slice3D', { inputs: { x: x }, args: { begin: begin, size: size } }); + }; + NDArrayMath.prototype.slice4D = function (x, begin, size) { + slice_util.assertParamsValid(x, begin, size); + return this.backendEngine.executeKernel('Slice4D', { inputs: { x: x }, args: { begin: begin, size: size } }); + }; + NDArrayMath.prototype.concat1D = function (a, b) { + concat_util.assertParams(a.shape, b.shape, 0); + return this.backendEngine.executeKernel('Concat1D', { inputs: { a: a, b: b } }); + }; + NDArrayMath.prototype.concat2D = function (a, b, axis) { + concat_util.assertParams(a.shape, b.shape, axis); + return this.backendEngine.executeKernel('Concat2D', { inputs: { a: a, b: b }, args: { axis: axis } }); + }; + NDArrayMath.prototype.concat3D = function (a, b, axis) { + concat_util.assertParams(a.shape, b.shape, axis); + return this.backendEngine.executeKernel('Concat3D', { inputs: { a: a, b: b }, args: { axis: axis } }); + }; + NDArrayMath.prototype.concat4D = function (a, b, axis) { + concat_util.assertParams(a.shape, b.shape, axis); + return this.backendEngine.executeKernel('Concat4D', { inputs: { a: a, b: b }, args: { axis: axis } }); + }; + NDArrayMath.prototype.logSumExp = function (input, axis, keepDims) { + var _this = this; + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + var axes = axis_util.parseAxisParam(axis, input.shape); + return this.executeOp('logSumExp', function () { + var xMax = _this.max(input, axes, true); + var a = _this.subtract(input, xMax); + var b = _this.exp(a); + var c = _this.sum(b, axes); + var d = _this.log(c); + var res = _this.add(xMax.reshape(d.shape), d); + if (keepDims) { + var newShape = axis_util.expandShapeToKeepDim(res.shape, axes); + return res.reshape(newShape); + } + return res; + }); + }; + NDArrayMath.prototype.sum = function (x, axis, keepDims) { + var _this = this; + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + var origAxes = axis_util.parseAxisParam(axis, x.shape); + var axes = origAxes; + var permutedAxes = axis_util.getPermutedAxes(axes, x.rank); + return this.executeOp('sum', function () { + if (permutedAxes != null) { + x = _this.transpose(x, permutedAxes); + axes = axis_util.getInnerMostAxes(axes.length, x.rank); + } + var res = _this.backendEngine.executeKernel('Sum', { inputs: { x: x }, args: { axes: axes } }, function (dy, y) { + return { + x: function () { + if (axis != null) { + throw new Error("Gradients for sum with axis reduction not yet " + + "supported."); + } + return _this.multiply(dy, ndarray_1.NDArray.onesLike(x)); + } + }; + }); + if (keepDims) { + var newShape = axis_util.expandShapeToKeepDim(res.shape, origAxes); + return res.reshape(newShape); + } + return res; + }); + }; + NDArrayMath.prototype.mean = function (x, axis, keepDims) { + var _this = this; + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + var axes = axis_util.parseAxisParam(axis, x.shape); + var shapes = axis_util.computeOutAndReduceShapes(x.shape, axes); + var reduceShape = shapes[1]; + var reduceSize = util.sizeFromShape(reduceShape); + return this.executeOp('mean', function () { + return _this.scope(function (keep) { + var res = _this.divide(x, ndarray_1.Scalar.new(reduceSize)); + return _this.sum(res, axis, keepDims); + }); + }); + }; + NDArrayMath.prototype.argMin = function (x, axis) { + var _this = this; + if (axis === void 0) { axis = null; } + var axes = axis_util.parseAxisParam(axis, x.shape); + var permutedAxes = axis_util.getPermutedAxes(axes, x.rank); + return this.executeOp('argMin', function () { + if (permutedAxes != null) { + x = _this.transpose(x, permutedAxes); + axes = axis_util.getInnerMostAxes(axes.length, x.rank); + } + return _this.backendEngine.executeKernel('ArgMin', { inputs: { x: x }, args: { axes: axes } }); + }); + }; + NDArrayMath.prototype.argMax = function (x, axis) { + var _this = this; + if (axis === void 0) { axis = null; } + var axes = axis_util.parseAxisParam(axis, x.shape); + var permutedAxes = axis_util.getPermutedAxes(axes, x.rank); + return this.executeOp('argMax', function () { + if (permutedAxes != null) { + x = _this.transpose(x, permutedAxes); + axes = axis_util.getInnerMostAxes(axes.length, x.rank); + } + return _this.backendEngine.executeKernel('ArgMax', { inputs: { x: x }, args: { axes: axes } }); + }); + }; + NDArrayMath.prototype.argMaxEquals = function (x1, x2) { + var _this = this; + util.assertShapesMatch(x1.shape, x2.shape, 'Error in argMaxEquals: '); + return this.executeOp('argMaxEquals', function () { return _this.scope(function () { + return _this.equal(_this.argMax(x1), _this.argMax(x2)); + }); }); + }; + NDArrayMath.prototype.equal = function (a, b) { + return this.backendEngine.executeKernel('Equal', { inputs: { a: a, b: b } }); + }; + NDArrayMath.prototype.equalStrict = function (a, b) { + util.assertShapesMatch(a.shape, b.shape, 'Error in equalStrict: '); + return this.equal(a, b); + }; + NDArrayMath.prototype.topK = function (x, k) { + var _this = this; + util.assert(k <= x.size, "Error in topK: k value (" + k + ") must be less than size of input " + + ("ndarray, got shape " + x.shape + ".")); + var values; + var indices; + this.executeOp('topK', function () { + values = _this.backendEngine.executeKernel('TopKValues', { inputs: { x: x }, args: { k: k } }); + indices = _this.backendEngine.executeKernel('TopKIndices', { inputs: { x: x }, args: { k: k } }); + return values; + }); + var result = { values: values, indices: indices }; + return result; + }; + NDArrayMath.prototype.min = function (x, axis, keepDims) { + var _this = this; + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + var origAxes = axis_util.parseAxisParam(axis, x.shape); + var axes = origAxes; + var permutedAxes = axis_util.getPermutedAxes(axes, x.rank); + return this.executeOp('min', function () { + if (permutedAxes != null) { + x = _this.transpose(x, permutedAxes); + axes = axis_util.getInnerMostAxes(axes.length, x.rank); + } + var res = _this.backendEngine.executeKernel('Min', { inputs: { x: x }, args: { axes: axes } }); + if (keepDims) { + var newShape = axis_util.expandShapeToKeepDim(res.shape, origAxes); + return res.reshape(newShape); + } + return res; + }); + }; + NDArrayMath.prototype.max = function (x, axis, keepDims) { + var _this = this; + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + var origAxes = axis_util.parseAxisParam(axis, x.shape); + var axes = origAxes; + var permutedAxes = axis_util.getPermutedAxes(axes, x.rank); + return this.executeOp('max', function () { + if (permutedAxes != null) { + x = _this.transpose(x, permutedAxes); + axes = axis_util.getInnerMostAxes(axes.length, x.rank); + } + var res = _this.backendEngine.executeKernel('Max', { inputs: { x: x }, args: { axes: axes } }); + if (keepDims) { + var newShape = axis_util.expandShapeToKeepDim(res.shape, origAxes); + return res.reshape(newShape); + } + return res; + }); + }; + NDArrayMath.prototype.softmax = function (logits, dim) { + var _this = this; + if (dim === void 0) { dim = -1; } + if (dim === -1) { + dim = logits.rank - 1; + } + if (dim !== logits.rank - 1) { + throw Error('Softmax along a non-last dimension is not yet supported. ' + + ("Logits was rank " + logits.rank + " and dim was " + dim)); + } + return this.executeOp('softmax', function () { + return _this.scope(function () { + var lse = _this.logSumExp(logits, [dim], true); + var logResult = _this.subtract(logits, lse); + return _this.exp(logResult); + }); + }); + }; + NDArrayMath.prototype.switchDim = function (a, newDim) { + return this.transpose(a, newDim); + }; + NDArrayMath.prototype.tile = function (x, reps) { + util.assert(x.rank === reps.length, "Error in transpose: rank of input " + x.rank + " " + + ("must match length of reps " + reps + ".")); + return this.backendEngine.executeKernel('Tile', { inputs: { x: x }, args: { reps: reps } }); + }; + NDArrayMath.prototype.transpose = function (x, perm) { + if (perm == null) { + perm = x.shape.map(function (s, i) { return i; }).reverse(); + } + util.assert(x.rank === perm.length, "Error in transpose: rank of input " + x.rank + " " + + ("must match length of perm " + perm + ".")); + return this.backendEngine.executeKernel('Transpose', { inputs: { x: x }, args: { perm: perm } }); + }; + NDArrayMath.prototype.scalarPlusArray = function (c, a) { + util.assert(c.size === 1, "Error in scalarPlusArray: first argument must be rank 0, but got " + + ("rank " + c.rank + ".")); + return this.add(c, a); + }; + NDArrayMath.prototype.scalarMinusArray = function (c, a) { + util.assert(c.size === 1, "Error in scalarMinusArray: first argument must be rank 0, but got " + + ("rank " + c.rank + ".")); + return this.subtract(c, a); + }; + NDArrayMath.prototype.arrayMinusScalar = function (a, c) { + util.assert(c.size === 1, "Error in arrayMinusScalar: second argument must be rank 0, but " + + ("got rank " + c.rank + ".")); + return this.subtract(a, c); + }; + NDArrayMath.prototype.neg = function (x) { + return this.backendEngine.executeKernel('Neg', { inputs: { x: x } }); + }; + NDArrayMath.prototype.add = function (a, b) { + broadcast_util.assertAndGetBroadcastShape(a.shape, b.shape); + return this.backendEngine.executeKernel('Add', { inputs: { a: a, b: b } }); + }; + NDArrayMath.prototype.addStrict = function (a, b) { + util.assertShapesMatch(a.shape, b.shape, 'Error in addStrict: '); + return this.add(a, b); + }; + NDArrayMath.prototype.subtract = function (a, b) { + broadcast_util.assertAndGetBroadcastShape(a.shape, b.shape); + return this.backendEngine.executeKernel('Sub', { inputs: { a: a, b: b } }); + }; + NDArrayMath.prototype.pow = function (a, b) { + util.assert(b.dtype === 'int32', 'only supports int32 data type for the exponent parameter.'); + broadcast_util.assertAndGetBroadcastShape(a.shape, b.shape); + return this.backendEngine.executeKernel('Pow', { inputs: { a: a, b: b } }); + }; + NDArrayMath.prototype.powStrict = function (a, b) { + util.assertShapesMatch(a.shape, b.shape, 'Error in powStrict: '); + return this.pow(a, b); + }; + NDArrayMath.prototype.sub = function (a, b) { + return this.subtract(a, b); + }; + NDArrayMath.prototype.subStrict = function (a, b) { + util.assertShapesMatch(a.shape, b.shape, 'Error in subStrict: '); + return this.subtract(a, b); + }; + NDArrayMath.prototype.multiply = function (a, b) { + broadcast_util.assertAndGetBroadcastShape(a.shape, b.shape); + return this.backendEngine.executeKernel('Mul', { inputs: { a: a, b: b } }); + }; + NDArrayMath.prototype.elementWiseMul = function (a, b) { + return this.multiplyStrict(a, b); + }; + NDArrayMath.prototype.multiplyStrict = function (a, b) { + util.assertShapesMatch(a.shape, b.shape, 'Error in multiplyStrict: '); + return this.multiply(a, b); + }; + NDArrayMath.prototype.divide = function (a, b) { + broadcast_util.assertAndGetBroadcastShape(a.shape, b.shape); + return this.backendEngine.executeKernel('Div', { inputs: { a: a, b: b } }); + }; + NDArrayMath.prototype.divideStrict = function (a, b) { + util.assertShapesMatch(a.shape, b.shape, 'Error in divideStrict: '); + return this.divide(a, b); + }; + NDArrayMath.prototype.scalarDividedByArray = function (c, a) { + util.assert(c.size === 1, "Error in scalarDividedByArray: first argument must be rank 0, but " + + ("got NDArray of rank " + c.rank + ".")); + return this.divide(c, a); + }; + NDArrayMath.prototype.arrayDividedByScalar = function (a, c) { + util.assert(c.size === 1, "Error in arrayDividedByScalar: second argument must be rank 0, " + + ("but got NDArray of rank " + c.rank + ".")); + return this.divide(a, c); + }; + NDArrayMath.prototype.ceil = function (x) { + return this.backendEngine.executeKernel('Ceil', { inputs: { x: x } }); + }; + NDArrayMath.prototype.floor = function (x) { + return this.backendEngine.executeKernel('Floor', { inputs: { x: x } }); + }; + NDArrayMath.prototype.exp = function (x) { + return this.backendEngine.executeKernel('Exp', { inputs: { x: x } }); + }; + NDArrayMath.prototype.log = function (x) { + return this.backendEngine.executeKernel('Log', { inputs: { x: x } }); + }; + NDArrayMath.prototype.sqrt = function (x) { + return this.backendEngine.executeKernel('Sqrt', { inputs: { x: x } }); + }; + NDArrayMath.prototype.square = function (x) { + return this.backendEngine.executeKernel('Square', { inputs: { x: x } }); + }; + NDArrayMath.prototype.abs = function (x) { + return this.backendEngine.executeKernel('Abs', { inputs: { x: x } }); + }; + NDArrayMath.prototype.clip = function (x, min, max) { + util.assert((min <= max), "Error in clip: min (" + min + ") must be" + + ("less than or equal to max (" + max + ").")); + return this.backendEngine.executeKernel('Clip', { inputs: { x: x }, args: { min: min, max: max } }); + }; + NDArrayMath.prototype.relu = function (x) { + var _this = this; + return this.backendEngine.executeKernel('Relu', { inputs: { x: x } }, function (dy, y) { + return { x: function () { return _this.step(x); } }; + }); + }; + NDArrayMath.prototype.elu = function (x) { + return this.backendEngine.executeKernel('Elu', { inputs: { x: x } }); + }; + NDArrayMath.prototype.eluDer = function (x) { + return this.backendEngine.executeKernel('EluDer', { inputs: { x: x } }); + }; + NDArrayMath.prototype.selu = function (x) { + return this.backendEngine.executeKernel('Selu', { inputs: { x: x } }); + }; + NDArrayMath.prototype.leakyRelu = function (x, alpha) { + if (alpha === void 0) { alpha = 0.2; } + return this.backendEngine.executeKernel('LeakyRelu', { inputs: { x: x }, args: { alpha: alpha } }); + }; + NDArrayMath.prototype.prelu = function (x, alpha) { + return this.backendEngine.executeKernel('PReLU', { inputs: { x: x, alpha: alpha } }); + }; + NDArrayMath.prototype.preluDer = function (x, alpha) { + return this.backendEngine.executeKernel('PReLUDer', { inputs: { x: x, alpha: alpha } }); + }; + NDArrayMath.prototype.sigmoid = function (x) { + return this.backendEngine.executeKernel('Sigmoid', { inputs: { x: x } }); + }; + NDArrayMath.prototype.sin = function (x) { + return this.backendEngine.executeKernel('Sin', { inputs: { x: x } }); + }; + NDArrayMath.prototype.cos = function (x) { + return this.backendEngine.executeKernel('Cos', { inputs: { x: x } }); + }; + NDArrayMath.prototype.tan = function (x) { + return this.backendEngine.executeKernel('Tan', { inputs: { x: x } }); + }; + NDArrayMath.prototype.asin = function (x) { + return this.backendEngine.executeKernel('Asin', { inputs: { x: x } }); + }; + NDArrayMath.prototype.acos = function (x) { + return this.backendEngine.executeKernel('Acos', { inputs: { x: x } }); + }; + NDArrayMath.prototype.atan = function (x) { + return this.backendEngine.executeKernel('Atan', { inputs: { x: x } }); + }; + NDArrayMath.prototype.sinh = function (x) { + return this.backendEngine.executeKernel('Sinh', { inputs: { x: x } }); + }; + NDArrayMath.prototype.cosh = function (x) { + return this.backendEngine.executeKernel('Cosh', { inputs: { x: x } }); + }; + NDArrayMath.prototype.tanh = function (x) { + return this.backendEngine.executeKernel('Tanh', { inputs: { x: x } }); + }; + NDArrayMath.prototype.step = function (x, alpha) { + if (alpha === void 0) { alpha = 0.0; } + return this.backendEngine.executeKernel('Step', { inputs: { x: x }, args: { alpha: alpha } }); + }; + NDArrayMath.prototype.scaledArrayAdd = function (c1, a, c2, b) { + var _this = this; + util.assert(c1.size === 1, "Error in scaledArrayAdd: first argument must rank 0, but got " + + (" rank " + c1.rank + ".")); + util.assert(c2.size === 1, "Error in scaledArrayAdd: third argument must be rank 0, but got " + + ("NDArray of rank " + c2.rank + ".")); + util.assertShapesMatch(a.shape, b.shape, 'Error in scaledArrayAdd: '); + return this.executeOp('scaledArrayAdd', function () { + return _this.scope(function () { + return _this.add(_this.multiply(c1, a), _this.multiply(c2, b)); + }); + }); + }; + NDArrayMath.prototype.scalarTimesArray = function (c, a) { + util.assert(c.size === 1, "Error in arrayDividedByScalar: first argument must be rank 0, but " + + ("got rank " + c.rank + ".")); + return this.multiply(c, a); + }; + NDArrayMath.prototype.elementWiseMulBroadcast = function (a, b) { + util.assert(a.rank === 2, "Error in elementWiseMulBroadcast: first argument must be " + + ("rank 2, but got rank " + a.rank + ".")); + util.assert(b.rank === 2, "Error in elementWiseMulBroadcast: second argument must be " + + ("rank 2, but got rank " + b.rank + ".")); + return this.multiply(a, b); + }; + NDArrayMath.prototype.conv1d = function (input, filter, bias, stride, pad) { + var _this = this; + var input3D = input; + var reshapedTo3D = false; + if (input.rank === 2) { + reshapedTo3D = true; + input3D = input.as3D(1, input.shape[0], input.shape[1]); + } + util.assert(input3D.rank === 3, "Error in conv1d: input must be rank 3, but got rank " + input3D.rank + "."); + util.assert(filter.rank === 3, "Error in conv1d: filter must be rank 3, but got rank " + + (filter.rank + ".")); + if (bias != null) { + util.assert(bias.rank === 1, "Error in conv1d: bias must be rank 1, but got rank " + + (bias.rank + ".")); + } + util.assert(input3D.shape[2] === filter.shape[1], "Error in conv1d: depth of input (" + input3D.shape[2] + ") must match " + + ("input depth for filter " + filter.shape[1] + ".")); + var filter4D = filter.as4D(1, filter.shape[0], filter.shape[1], filter.shape[2]); + var input4D = input3D.as4D(input3D.shape[0], 1, input3D.shape[1], input3D.shape[2]); + var strides = [1, stride]; + return this.executeOp('Conv1D', function () { + var res = _this.conv2d(input4D, filter4D, bias, strides, pad); + if (reshapedTo3D) { + return res.as2D(res.shape[2], res.shape[3]); + } + return res.as3D(res.shape[0], res.shape[2], res.shape[3]); + }); + }; + NDArrayMath.prototype.conv2d = function (input, filter, bias, strides, pad) { + var _this = this; + var input4D = input; + var reshapedTo4D = false; + if (input.rank === 3) { + reshapedTo4D = true; + input4D = input.as4D(1, input.shape[0], input.shape[1], input.shape[2]); + } + util.assert(input4D.rank === 4, "Error in conv2d: input must be rank 4, but got rank " + input4D.rank + "."); + util.assert(filter.rank === 4, "Error in conv2d: filter must be rank 4, but got rank " + + (filter.rank + ".")); + if (bias != null) { + util.assert(bias.rank === 1, "Error in conv2d: bias must be rank 1, but got rank " + + (bias.rank + ".")); + } + util.assert(input4D.shape[3] === filter.shape[2], "Error in conv2d: depth of input (" + input4D.shape[3] + ") must match " + + ("input depth for filter " + filter.shape[2] + ".")); + var convInfo = conv_util.computeConv2DInfo(input4D.shape, filter.shape, strides, pad); + return this.executeOp('Conv2D', function () { + var res = _this.backendEngine.executeKernel('Conv2D', { inputs: { x: input4D, filter: filter, bias: bias }, args: { convInfo: convInfo } }); + if (reshapedTo4D) { + return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return res; + }); + }; + NDArrayMath.prototype.conv2dDerInput = function (inShape, dy, filter, strides, pad) { + var _this = this; + util.assert(inShape.length === dy.rank, "Length of inShape " + + ("(" + inShape.length + ") and rank of dy (" + dy.rank + ") must match")); + var inShape4D = inShape; + var dy4D = dy; + var reshapedTo4D = false; + if (dy.rank === 3) { + reshapedTo4D = true; + dy4D = dy.as4D(1, dy.shape[0], dy.shape[1], dy.shape[2]); + inShape4D = [1, inShape[0], inShape[1], inShape[2]]; + } + var inDepth = inShape4D[3]; + var outDepth = dy4D.shape[3]; + util.assert(inShape4D.length === 4, "Error in conv2dDerInput: inShape must be length 4, but got length " + + (inShape4D.length + ".")); + util.assert(dy4D.rank === 4, "Error in conv2dDerInput: dy must be rank 4, but got " + + ("rank " + dy4D.rank)); + util.assert(filter.rank === 4, "Error in conv2dDerInput: filter must be rank 4, but got " + + ("rank " + filter.rank)); + util.assert(inDepth === filter.shape[2], "Error in conv2dDerInput: depth of input (" + inDepth + ") must " + + ("match input depth for filter " + filter.shape[2] + ".")); + util.assert(outDepth === filter.shape[3], "Error in conv2dDerInput: depth of output (" + outDepth + ") must" + + ("match output depth for filter " + filter.shape[3] + ".")); + var convInfo = conv_util.computeConv2DInfo(inShape4D, filter.shape, strides, pad); + return this.executeOp('conv2dDerInput', function () { + var res = _this.backendEngine.executeKernel('Conv2DDerInput', { inputs: { dy: dy4D, filter: filter }, args: { convInfo: convInfo } }); + if (reshapedTo4D) { + return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return res; + }); + }; + NDArrayMath.prototype.conv2dDerBias = function (dy) { + var dy4D = dy; + if (dy.rank === 3) { + dy4D = dy.as4D(1, dy.shape[0], dy.shape[1], dy.shape[2]); + } + return this.backendEngine.executeKernel('Conv2DDerBias', { inputs: { dy: dy4D } }); + }; + NDArrayMath.prototype.conv2dDerFilter = function (input, dy, filterShape, strides, pad) { + var input4D = input; + if (input.rank === 3) { + input4D = input.as4D(1, input.shape[0], input.shape[1], input.shape[2]); + } + var dy4D = dy; + if (dy4D.rank === 3) { + dy4D = dy.as4D(1, dy.shape[0], dy.shape[1], dy.shape[2]); + } + util.assert(input4D.rank === 4, "Error in conv2dDerFilter: input must be rank 4, but got shape " + + (input4D.shape + ".")); + util.assert(dy4D.rank === 4, "Error in conv2dDerFilter: dy must be rank 4, but got shape " + + (dy4D.shape + ".")); + util.assert(filterShape.length === 4, "Error in conv2dDerFilter: filterShape must be length 4, but got " + + (filterShape + ".")); + util.assert(input4D.shape[3] === filterShape[2], "Error in conv2dDerFilter: depth of input " + input4D.shape[3] + ") must " + + ("match input depth in filter (" + filterShape[2] + ".")); + util.assert(dy4D.shape[3] === filterShape[3], "Error in conv2dDerFilter: depth of dy (" + dy4D.shape[3] + ") must " + + ("match output depth for filter (" + filterShape[3] + ").")); + var convInfo = conv_util.computeConv2DInfo(input4D.shape, filterShape, strides, pad); + return this.backendEngine.executeKernel('Conv2DDerFilter', { inputs: { x: input4D, dy: dy4D }, args: { convInfo: convInfo } }); + }; + NDArrayMath.prototype.conv2dTranspose = function (x, filter, outputShape, strides, pad) { + return this.conv2dDerInput(outputShape, x, filter, strides, pad); + }; + NDArrayMath.prototype.depthwiseConv2D = function (input, filter, strides, pad, rates) { + var _this = this; + if (rates === void 0) { rates = [1, 1]; } + var input4D = input; + var reshapedTo4D = false; + if (input.rank === 3) { + reshapedTo4D = true; + input4D = input.as4D(1, input.shape[0], input.shape[1], input.shape[2]); + } + util.assert(input4D.rank === 4, "Error in depthwiseConv2D: input must be rank 4, but got " + + ("rank " + input4D.rank + ".")); + util.assert(filter.rank === 4, "Error in depthwiseConv2D: filter must be rank 4, but got rank " + + (filter.rank + ".")); + util.assert(input4D.shape[3] === filter.shape[2], "Error in depthwiseConv2D: number of input channels " + + ("(" + input4D.shape[3] + ") must match the inChannels dimension in ") + + ("filter " + filter.shape[2] + ".")); + rates = rates || [1, 1]; + var _a = parseTupleParam(rates), rateHeight = _a[0], rateWidth = _a[1]; + util.assert(rateHeight === 1 && rateWidth === 1, 'Error in depthwiseConv2D: rates greater than 1 are not yet ' + + ("supported. Got rates '" + rates + "'")); + var convInfo = conv_util.computeConv2DInfo(input4D.shape, filter.shape, strides, pad, true); + return this.executeOp('depthwiseConv2D', function () { + var res = _this.backendEngine.executeKernel('DepthwiseConv2D', { inputs: { x: input4D, filter: filter }, args: { convInfo: convInfo } }); + if (reshapedTo4D) { + return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return res; + }); + }; + NDArrayMath.prototype.maxPool = function (input, filterSize, strides, pad) { + var _this = this; + var input4D = input; + var reshapedTo4D = false; + if (input.rank === 3) { + reshapedTo4D = true; + input4D = input.as4D(1, input.shape[0], input.shape[1], input.shape[2]); + } + util.assert(input4D.rank === 4, "Error in maxPool: input must be rank 4 but got rank " + input4D.rank + "."); + var convInfo = conv_util.computePool2DInfo(input4D.shape, filterSize, strides, pad); + return this.executeOp('maxPool', function () { + var res = _this.backendEngine.executeKernel('MaxPool', { inputs: { x: input4D }, args: { convInfo: convInfo } }); + if (reshapedTo4D) { + return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return res; + }); + }; + NDArrayMath.prototype.maxPoolBackprop = function (dy, input, filterSize, strides, pad) { + var _this = this; + util.assert(input.rank === dy.rank, "Rank of input (" + input.rank + ") does not match rank of dy (" + dy.rank + ")"); + var input4D = input; + var dy4D = dy; + var reshapedTo4D = false; + if (input.rank === 3) { + reshapedTo4D = true; + input4D = input.as4D(1, input.shape[0], input.shape[1], input.shape[2]); + dy4D = dy.as4D(1, dy.shape[0], dy.shape[1], dy.shape[2]); + } + util.assert(dy4D.rank === 4, "Error in maxPoolBackprop: dy must be rank 4 but got rank " + + (dy4D.rank + ".")); + util.assert(input4D.rank === 4, "Error in maxPoolBackprop: input must be rank 4 but got rank " + + (input4D.rank + ".")); + var convInfo = conv_util.computePool2DInfo(input4D.shape, filterSize, strides, pad); + return this.executeOp('maxPoolBackprop', function () { + var res = _this.backendEngine.executeKernel('MaxPoolBackprop', { inputs: { dy: dy4D, x: input4D }, args: { convInfo: convInfo } }); + if (reshapedTo4D) { + return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return res; + }); + }; + NDArrayMath.prototype.minPool = function (input, filterSize, strides, pad) { + var _this = this; + var input4D = input; + var reshapedTo4D = false; + if (input.rank === 3) { + reshapedTo4D = true; + input4D = input.as4D(1, input.shape[0], input.shape[1], input.shape[2]); + } + util.assert(input4D.rank === 4, "Error in minPool: x must be rank 4 but got rank " + input4D.rank + "."); + var convInfo = conv_util.computePool2DInfo(input4D.shape, filterSize, strides, pad); + return this.executeOp('minPool', function () { + var res = _this.backendEngine.executeKernel('MinPool', { inputs: { x: input4D }, args: { convInfo: convInfo } }); + if (reshapedTo4D) { + return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return res; + }); + }; + NDArrayMath.prototype.avgPool = function (input, filterSize, strides, pad) { + var _this = this; + var input4D = input; + var reshapedTo4D = false; + if (input.rank === 3) { + reshapedTo4D = true; + input4D = input.as4D(1, input.shape[0], input.shape[1], input.shape[2]); + } + util.assert(input4D.rank === 4, "Error in avgPool: x must be rank 4 but got rank " + input4D.rank + "."); + var convInfo = conv_util.computePool2DInfo(input4D.shape, filterSize, strides, pad); + return this.executeOp('avgPool', function () { + var res = _this.backendEngine.executeKernel('AvgPool', { inputs: { x: input4D }, args: { convInfo: convInfo } }); + if (reshapedTo4D) { + return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return res; + }); + }; + NDArrayMath.prototype.resizeBilinear3D = function (x, newShape2D, alignCorners) { + if (alignCorners === void 0) { alignCorners = false; } + util.assert(x.rank === 3, "Error in resizeBilinear3D: x must be rank 3 but got rank " + x.rank + "."); + util.assert(newShape2D.length === 2, "Error in resizeBilinear3D: new shape must 2D, but got shape " + + (newShape2D + ".")); + return this.backendEngine.executeKernel('ResizeBilinear3D', { inputs: { x: x }, args: { newShape2D: newShape2D, alignCorners: alignCorners } }); + }; + NDArrayMath.prototype.batchNormalization2D = function (x, mean, variance, varianceEpsilon, scale, offset) { + if (varianceEpsilon === void 0) { varianceEpsilon = .001; } + util.assert(x.rank === 2, "Error in batchNormalization3D: x must be rank 3 but got rank " + + (x.rank + ".")); + util.assert(mean.rank === 2 || mean.rank === 1, "Error in batchNormalization2D: mean must be rank 2 or rank 1 but " + + ("got rank " + mean.rank + ".")); + util.assert(variance.rank === 2 || variance.rank === 1, "Error in batchNormalization2D: variance must be rank 2 or rank 1 " + + ("but got rank " + variance.rank + ".")); + if (scale != null) { + util.assert(scale.rank === 2 || scale.rank === 1, "Error in batchNormalization2D: scale must be rank 2 or rank 1 " + + ("but got rank " + scale.rank + ".")); + } + if (offset != null) { + util.assert(offset.rank === 2 || offset.rank === 1, "Error in batchNormalization2D: offset must be rank 2 or rank 1 " + + ("but got rank " + offset.rank + ".")); + } + return this.backendEngine.executeKernel('BatchNorm2D', { inputs: { x: x, mean: mean, variance: variance, scale: scale, offset: offset }, args: { varianceEpsilon: varianceEpsilon } }); + }; + NDArrayMath.prototype.batchNormalization3D = function (x, mean, variance, varianceEpsilon, scale, offset) { + if (varianceEpsilon === void 0) { varianceEpsilon = .001; } + util.assert(x.rank === 3, "Error in batchNormalization3D: x must be rank 3 but got rank " + + (x.rank + ".")); + util.assert(mean.rank === 3 || mean.rank === 1, "Error in batchNormalization3D: mean must be rank 3 or rank 1 but " + + ("got rank " + mean.rank + ".")); + util.assert(variance.rank === 3 || variance.rank === 1, "Error in batchNormalization3D: variance must be rank 3 or rank 1 " + + ("but got rank " + variance.rank + ".")); + if (scale != null) { + util.assert(scale.rank === 3 || scale.rank === 1, "Error in batchNormalization3D: scale must be rank 3 or rank 1 " + + ("but got rank " + scale.rank + ".")); + } + if (offset != null) { + util.assert(offset.rank === 3 || offset.rank === 1, "Error in batchNormalization3D: offset must be rank 3 or rank 1 " + + ("but got rank " + offset.rank + ".")); + } + return this.backendEngine.executeKernel('BatchNorm3D', { inputs: { x: x, mean: mean, variance: variance, scale: scale, offset: offset }, args: { varianceEpsilon: varianceEpsilon } }); + }; + NDArrayMath.prototype.multiRNNCell = function (lstmCells, data, c, h) { + var res = this.scope(function () { + var input = data; + var newStates = []; + for (var i = 0; i < lstmCells.length; i++) { + var output = lstmCells[i](input, c[i], h[i]); + newStates.push(output[0]); + newStates.push(output[1]); + input = output[1]; + } + return newStates; + }); + var newC = []; + var newH = []; + for (var i = 0; i < res.length; i += 2) { + newC.push(res[i]); + newH.push(res[i + 1]); + } + return [newC, newH]; + }; + NDArrayMath.prototype.basicLSTMCell = function (forgetBias, lstmKernel, lstmBias, data, c, h) { + var _this = this; + var res = this.scope(function () { + var combined = _this.concat2D(data, h, 1); + var weighted = _this.matMul(combined, lstmKernel); + var res = _this.add(weighted, lstmBias); + var batchSize = res.shape[0]; + var sliceCols = res.shape[1] / 4; + var sliceSize = [batchSize, sliceCols]; + var i = _this.slice2D(res, [0, 0], sliceSize); + var j = _this.slice2D(res, [0, sliceCols], sliceSize); + var f = _this.slice2D(res, [0, sliceCols * 2], sliceSize); + var o = _this.slice2D(res, [0, sliceCols * 3], sliceSize); + var newC = _this.addStrict(_this.multiplyStrict(c, _this.sigmoid(_this.scalarPlusArray(forgetBias, f))), _this.multiplyStrict(_this.sigmoid(i), _this.tanh(j))); + var newH = _this.multiplyStrict(_this.tanh(newC), _this.sigmoid(o)); + return [newC, newH]; + }); + return [res[0], res[1]]; + }; + NDArrayMath.prototype.multinomial = function (probabilities, numSamples, seed) { + var _this = this; + var numOutcomes = probabilities.size; + if (numOutcomes < 2) { + throw new Error("Error in multinomial: you need at least 2 outcomes, but got " + + (numOutcomes + ".")); + } + if (probabilities.rank > 2) { + throw new Error("Rank of probabilities must be 1 or 2, but is " + probabilities.rank); + } + seed = seed || Math.random(); + var origRank = probabilities.rank; + if (probabilities.rank === 1) { + probabilities = probabilities.as2D(1, -1); + } + return this.executeOp('multinomial', function () { + var res = _this.backendEngine.executeKernel('Multinomial', { + inputs: { probs: probabilities }, + args: { numSamples: numSamples, seed: seed } + }); + if (origRank === 1) { + return res.as1D(); + } + return res; + }); + }; + NDArrayMath.prototype.oneHot = function (indices, depth, onValue, offValue) { + if (onValue === void 0) { onValue = 1; } + if (offValue === void 0) { offValue = 0; } + if (depth < 2) { + throw new Error("Error in oneHot: depth must be >=2, but it is " + depth); + } + return this.backendEngine.executeKernel('OneHot', { inputs: { indices: indices }, args: { depth: depth, onValue: onValue, offValue: offValue } }); + }; + NDArrayMath.prototype.moments = function (x, axis, keepDims) { + var _this = this; + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + var axes = axis_util.parseAxisParam(axis, x.shape); + var result = this.scope(function () { + var mean = _this.mean(x, axes, keepDims); + var keepDimsShape = mean.shape; + if (!keepDims) { + keepDimsShape = axis_util.expandShapeToKeepDim(mean.shape, axes); + } + var devSquared = _this.square(_this.subtract(x, mean.reshape(keepDimsShape))); + var variance = _this.mean(devSquared, axes, keepDims); + return { mean: mean, variance: variance }; + }); + return result; + }; + NDArrayMath.prototype.norm = function (x, ord, axis, keepDims) { + var _this = this; + if (ord === void 0) { ord = 'euclidean'; } + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + return this.scope(function () { + var norm = _this.normInternal(x, ord, axis); + var keepDimsShape = norm.shape; + if (keepDims) { + var axes = axis_util.parseAxisParam(axis, x.shape); + keepDimsShape = axis_util.expandShapeToKeepDim(norm.shape, axes); + } + return norm.reshape(keepDimsShape); + }); + }; + NDArrayMath.prototype.normInternal = function (x, p, axis) { + if (axis === void 0) { axis = null; } + if (x.rank === 0) { + return this.abs(x); + } + if (x.rank !== 1 && axis === null) { + return this.normInternal(x.reshape([-1]), p, axis); + } + if (x.rank === 1 || typeof axis === 'number' || + axis instanceof Array && axis.length === 1) { + if (p === 1) { + return this.sum(this.abs(x), axis); + } + if (p === Infinity) { + return this.max(this.abs(x), axis); + } + if (p === -Infinity) { + return this.min(this.abs(x), axis); + } + if (p === 'euclidean' || p === 2) { + return this.sqrt(this.sum(this.pow(this.abs(x), ndarray_1.Scalar.new(2, 'int32')), axis)); + } + throw new Error("Error in norm: invalid ord value: " + p); + } + if (axis instanceof Array && axis.length === 2) { + if (p === 1) { + return this.max(this.sum(this.abs(x), axis[0]), axis[1] - 1); + } + if (p === Infinity) { + return this.max(this.sum(this.abs(x), axis[1]), axis[0]); + } + if (p === -Infinity) { + return this.min(this.sum(this.abs(x), axis[1]), axis[0]); + } + if (p === 'fro' || p === 'euclidean') { + return this.sqrt(this.sum(this.pow(x, ndarray_1.Scalar.new(2, 'int32')), axis)); + } + throw new Error("Error in norm: invalid ord value: " + p); + } + throw new Error("Error in norm: invalid axis: " + axis); + }; + NDArrayMath.prototype.gradientWrt = function (y, x) { + var xIsArray = x instanceof ndarray_1.NDArray; + var xs = []; + var xKeys; + if (xIsArray) { + xs.push(x); + } + else { + var xMap = x; + xKeys = Object.keys(xMap); + for (var i = 0; i < xKeys.length; i++) { + xs.push(xMap[xKeys[i]]); + } + } + var gradients = this.backendEngine.gradientWrt(y, xs); + if (xIsArray) { + return gradients[0]; + } + else { + var result = {}; + for (var i = 0; i < xKeys.length; i++) { + result[xKeys[i]] = gradients[i]; + } + return result; + } + }; + NDArrayMath.prototype.disposeData = function (id) { + this.backend.disposeData(id); + this.numArrays--; + }; + return NDArrayMath; +}()); +exports.NDArrayMath = NDArrayMath; +function parseTupleParam(param) { + return typeof param === 'number' ? [param, param] : param; +} + +},{"../environment":15,"../util":101,"./axis_util":54,"./backends/backend_engine":56,"./backends/types/matmul":61,"./broadcast_util":90,"./concat_util":91,"./conv_util":92,"./ndarray":95,"./slice_util":98}],95:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("../environment"); +var util = require("../util"); +var rand_1 = require("./rand"); +var DType; +(function (DType) { + DType["float32"] = "float32"; + DType["int32"] = "int32"; + DType["bool"] = "bool"; +})(DType = exports.DType || (exports.DType = {})); +var NDArray = (function () { + function NDArray(shape, dtype, values, id, math) { + this.isDisposed = false; + this.math = math || environment_1.ENV.math; + this.size = util.sizeFromShape(shape); + if (values != null) { + util.assert(this.size === values.length, "Constructing ndarray of shape (" + this.size + ") should match the " + + ("length of values (" + values.length + ")")); + } + this.shape = shape; + this.dtype = dtype || 'float32'; + var dim = this.shape.length; + if (dim < 2) { + this.strides = []; + } + else { + this.strides = new Array(dim - 1); + this.strides[dim - 2] = this.shape[dim - 1]; + for (var i = dim - 3; i >= 0; --i) { + this.strides[i] = this.strides[i + 1] * this.shape[i + 1]; + } + } + this.id = id; + if (this.id == null) { + this.id = NDArray.nextId++; + this.math.register(this); + this.math.write(this.id, values, this.dtype, this.shape); + } + } + NDArray.ones = function (shape, dtype) { + var values = makeOnesTypedArray(util.sizeFromShape(shape), dtype); + return NDArray.make(shape, { values: values }, dtype); + }; + NDArray.zeros = function (shape, dtype) { + var values = makeZerosTypedArray(util.sizeFromShape(shape), dtype); + return NDArray.make(shape, { values: values }, dtype); + }; + NDArray.onesLike = function (another) { + return NDArray.ones(another.shape, another.dtype); + }; + NDArray.zerosLike = function (another) { + return NDArray.zeros(another.shape, another.dtype); + }; + NDArray.like = function (another) { + var newValues = copyTypedArray(another.getValues(), another.dtype); + return NDArray.make(another.shape, { values: newValues }, another.dtype); + }; + NDArray.make = function (shape, data, dtype, math) { + switch (shape.length) { + case 0: + return new Scalar(shape, dtype, data.values, data.id, math); + case 1: + return new Array1D(shape, dtype, data.values, data.id, math); + case 2: + return new Array2D(shape, dtype, data.values, data.id, math); + case 3: + return new Array3D(shape, dtype, data.values, data.id, math); + case 4: + return new Array4D(shape, dtype, data.values, data.id, math); + default: + return new NDArray(shape, dtype, data.values, data.id, math); + } + }; + NDArray.fromPixels = function (pixels, numChannels, math) { + if (numChannels === void 0) { numChannels = 3; } + if (numChannels > 4) { + throw new Error('Cannot construct NDArray with more than 4 channels from pixels.'); + } + var ndarrayData = {}; + var shape = [pixels.height, pixels.width, numChannels]; + var res = NDArray.make(shape, ndarrayData, 'int32'); + math = math || environment_1.ENV.math; + math.writePixels(res.id, pixels, numChannels); + return res; + }; + NDArray.prototype.reshape = function (newShape) { + this.throwIfDisposed(); + newShape = util.inferFromImplicitShape(newShape, this.size); + if (util.arraysEqual(this.shape, newShape)) { + return this; + } + var data = { id: this.id }; + util.assert(this.size === util.sizeFromShape(newShape), 'new shape and old shape must have the same number of elements.'); + return NDArray.make(newShape, data, this.dtype); + }; + NDArray.prototype.flatten = function () { + this.throwIfDisposed(); + if (this instanceof Array1D) { + return this; + } + return this.as1D(); + }; + NDArray.prototype.asScalar = function () { + this.throwIfDisposed(); + util.assert(this.size === 1, 'The array must have only 1 element.'); + return this.reshape([]); + }; + NDArray.prototype.as1D = function () { + this.throwIfDisposed(); + return this.reshape([this.size]); + }; + NDArray.prototype.as2D = function (rows, columns) { + this.throwIfDisposed(); + return this.reshape([rows, columns]); + }; + NDArray.prototype.as3D = function (rows, columns, depth) { + this.throwIfDisposed(); + return this.reshape([rows, columns, depth]); + }; + NDArray.prototype.as4D = function (rows, columns, depth, depth2) { + this.throwIfDisposed(); + return this.reshape([rows, columns, depth, depth2]); + }; + NDArray.prototype.asType = function (dtype) { + this.throwIfDisposed(); + if (this.dtype === dtype) { + return this; + } + var vals = this.dataSync(); + var newVals = toTypedArray(vals, dtype); + return NDArray.make(this.shape, { values: newVals }, dtype); + }; + Object.defineProperty(NDArray.prototype, "rank", { + get: function () { + return this.shape.length; + }, + enumerable: true, + configurable: true + }); + NDArray.prototype.get = function () { + var locs = []; + for (var _i = 0; _i < arguments.length; _i++) { + locs[_i] = arguments[_i]; + } + var index = locs[locs.length - 1]; + for (var i = 0; i < locs.length - 1; ++i) { + index += this.strides[i] * locs[i]; + } + return this.getValues()[index]; + }; + NDArray.prototype.add = function (value) { + var locs = []; + for (var _i = 1; _i < arguments.length; _i++) { + locs[_i - 1] = arguments[_i]; + } + this.set.apply(this, [this.get.apply(this, locs) + value].concat(locs)); + }; + NDArray.prototype.set = function (value) { + var locs = []; + for (var _i = 1; _i < arguments.length; _i++) { + locs[_i - 1] = arguments[_i]; + } + this.throwIfDisposed(); + util.assert(locs.length === this.rank, "The number of provided coordinates (" + locs.length + ") must " + + ("match the rank (" + this.rank + ")")); + var index = locs.length > 0 ? locs[locs.length - 1] : 0; + for (var i = 0; i < locs.length - 1; ++i) { + index += this.strides[i] * locs[i]; + } + var vals = this.getValues(); + vals[index] = value; + this.math.disposeData(this.id); + this.math.write(this.id, vals, this.dtype, this.shape); + }; + NDArray.prototype.val = function () { + var locs = []; + for (var _i = 0; _i < arguments.length; _i++) { + locs[_i] = arguments[_i]; + } + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.throwIfDisposed(); + return [4, this.data()]; + case 1: + _a.sent(); + return [2, this.get.apply(this, locs)]; + } + }); + }); + }; + NDArray.prototype.locToIndex = function (locs) { + this.throwIfDisposed(); + var index = locs[locs.length - 1]; + for (var i = 0; i < locs.length - 1; ++i) { + index += this.strides[i] * locs[i]; + } + return index; + }; + NDArray.prototype.indexToLoc = function (index) { + this.throwIfDisposed(); + var locs = new Array(this.shape.length); + for (var i = 0; i < locs.length - 1; ++i) { + locs[i] = Math.floor(index / this.strides[i]); + index -= locs[i] * this.strides[i]; + } + locs[locs.length - 1] = index; + return locs; + }; + NDArray.prototype.fill = function (value) { + this.throwIfDisposed(); + var vals = this.getValues(); + vals.fill(value); + this.math.disposeData(this.id); + this.math.write(this.id, vals, this.dtype, this.shape); + }; + NDArray.prototype.getValues = function () { + return this.dataSync(); + }; + NDArray.prototype.getValuesAsync = function () { + return this.data(); + }; + NDArray.prototype.data = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + this.throwIfDisposed(); + return [2, this.math.read(this.id)]; + }); + }); + }; + NDArray.prototype.dataSync = function () { + this.throwIfDisposed(); + return this.math.readSync(this.id); + }; + NDArray.prototype.dispose = function () { + this.isDisposed = true; + this.math.disposeData(this.id); + }; + NDArray.prototype.equals = function (t) { + this.throwIfDisposed(); + return this.dtype === t.dtype && util.arraysEqual(this.shape, t.shape) && + util.arraysEqual(this.getValues(), t.getValues()); + }; + NDArray.rand = function (shape, randFunction, dtype) { + var size = util.sizeFromShape(shape); + var values = null; + if (dtype == null || dtype === 'float32') { + values = new Float32Array(size); + } + else if (dtype === 'int32') { + values = new Int32Array(size); + } + else if (dtype === 'bool') { + values = new Uint8Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } + for (var i = 0; i < size; i++) { + values[i] = randFunction(); + } + return NDArray.make(shape, { values: values }, dtype); + }; + NDArray.randNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, false, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + NDArray.randTruncatedNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, true, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + NDArray.randUniform = function (shape, a, b, dtype) { + return NDArray.rand(shape, function () { return util.randUniform(a, b); }, dtype); + }; + NDArray.prototype.throwIfDisposed = function () { + if (this.isDisposed) { + throw new Error("NDArray is disposed."); + } + }; + NDArray.nextId = 0; + return NDArray; +}()); +exports.NDArray = NDArray; +var Scalar = (function (_super) { + __extends(Scalar, _super); + function Scalar() { + return _super !== null && _super.apply(this, arguments) || this; + } + Scalar.new = function (value, dtype) { + var values = [value]; + return new Scalar([], dtype, toTypedArray(values, dtype)); + }; + Scalar.prototype.get = function () { + return this.getValues()[0]; + }; + Scalar.prototype.val = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.data()]; + case 1: + _a.sent(); + return [2, this.get()]; + } + }); + }); + }; + Scalar.prototype.add = function (value) { + this.getValues()[0] += value; + }; + Scalar.prototype.asType = function (dtype) { + return _super.prototype.asType.call(this, dtype); + }; + Scalar.prototype.locToIndex = function (loc) { + return 0; + }; + Scalar.prototype.indexToLoc = function (index) { + return []; + }; + return Scalar; +}(NDArray)); +exports.Scalar = Scalar; +var Array1D = (function (_super) { + __extends(Array1D, _super); + function Array1D() { + return _super !== null && _super.apply(this, arguments) || this; + } + Array1D.new = function (values, dtype) { + if (!instanceofTypedArray(values)) { + var inferredShape = util.inferShape(values); + util.assert(inferredShape.length === 1, "Error constructing Array1D. Shape of values " + inferredShape + " is " + + "not 1 dimensional."); + } + return new Array1D([values.length], dtype, toTypedArray(values, dtype)); + }; + Array1D.prototype.get = function (i) { + return this.getValues()[i]; + }; + Array1D.prototype.val = function (i) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.data()]; + case 1: + _a.sent(); + return [2, this.get(i)]; + } + }); + }); + }; + Array1D.prototype.add = function (value, i) { + this.getValues()[i] += value; + }; + Array1D.prototype.locToIndex = function (loc) { + return loc[0]; + }; + Array1D.prototype.indexToLoc = function (index) { + return [index]; + }; + Array1D.prototype.asType = function (dtype) { + return _super.prototype.asType.call(this, dtype); + }; + Array1D.ones = function (shape, dtype) { + return NDArray.ones(shape, dtype); + }; + Array1D.zeros = function (shape, dtype) { + return NDArray.zeros(shape, dtype); + }; + Array1D.randNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, false, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + Array1D.randTruncatedNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, true, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + Array1D.randUniform = function (shape, a, b, dtype) { + return NDArray.rand(shape, function () { return util.randUniform(a, b); }, dtype); + }; + return Array1D; +}(NDArray)); +exports.Array1D = Array1D; +var Array2D = (function (_super) { + __extends(Array2D, _super); + function Array2D(shape, dtype, values, id, math) { + var _this = this; + util.assert(shape.length === 2, 'Shape should be of length 2'); + _this = _super.call(this, shape, dtype, values, id, math) || this; + _this.stride0 = _this.strides[0]; + return _this; + } + Array2D.new = function (shape, values, dtype) { + if (!instanceofTypedArray(values)) { + var inferredShape = util.inferShape(values); + if (inferredShape.length > 1) { + util.assertShapesMatch(shape, inferredShape, "Error when constructing Array2D. Shape of values " + + (inferredShape + " does not match the provided shape ") + + (shape + ". ")); + } + } + return new Array2D(shape, dtype, toTypedArray(values, dtype)); + }; + Array2D.prototype.get = function (i, j) { + return this.getValues()[this.stride0 * i + j]; + }; + Array2D.prototype.add = function (value, i, j) { + this.getValues()[this.stride0 * i + j] += value; + }; + Array2D.prototype.val = function (i, j) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.data()]; + case 1: + _a.sent(); + return [2, this.get(i, j)]; + } + }); + }); + }; + Array2D.prototype.locToIndex = function (locs) { + return this.stride0 * locs[0] + locs[1]; + }; + Array2D.prototype.indexToLoc = function (index) { + return [Math.floor(index / this.stride0), index % this.stride0]; + }; + Array2D.prototype.asType = function (dtype) { + return _super.prototype.asType.call(this, dtype); + }; + Array2D.ones = function (shape, dtype) { + return NDArray.ones(shape, dtype); + }; + Array2D.zeros = function (shape, dtype) { + return NDArray.zeros(shape, dtype); + }; + Array2D.randNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, false, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + Array2D.randTruncatedNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, true, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + Array2D.randUniform = function (shape, a, b, dtype) { + return NDArray.rand(shape, function () { return util.randUniform(a, b); }, dtype); + }; + return Array2D; +}(NDArray)); +exports.Array2D = Array2D; +var Array3D = (function (_super) { + __extends(Array3D, _super); + function Array3D(shape, dtype, values, id, math) { + var _this = this; + util.assert(shape.length === 3, 'Shape should be of length 3'); + _this = _super.call(this, shape, dtype, values, id, math) || this; + _this.stride0 = _this.strides[0]; + _this.stride1 = _this.strides[1]; + return _this; + } + Array3D.new = function (shape, values, dtype) { + if (!instanceofTypedArray(values)) { + var inferredShape = util.inferShape(values); + if (inferredShape.length > 1) { + util.assertShapesMatch(shape, inferredShape, "Error when constructing Array3D. Shape of values " + + (inferredShape + " does not match the provided shape ") + + (shape + ". ")); + } + } + return new Array3D(shape, dtype, toTypedArray(values, dtype)); + }; + Array3D.prototype.get = function (i, j, k) { + return this.getValues()[this.stride0 * i + this.stride1 * j + k]; + }; + Array3D.prototype.val = function (i, j, k) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.data()]; + case 1: + _a.sent(); + return [2, this.get(i, j, k)]; + } + }); + }); + }; + Array3D.prototype.add = function (value, i, j, k) { + this.getValues()[this.stride0 * i + this.stride1 * j + k] += value; + }; + Array3D.prototype.locToIndex = function (locs) { + return this.stride0 * locs[0] + this.stride1 * locs[1] + locs[2]; + }; + Array3D.prototype.indexToLoc = function (index) { + var i = Math.floor(index / this.stride0); + index -= i * this.stride0; + return [i, Math.floor(index / this.stride1), index % this.stride1]; + }; + Array3D.prototype.asType = function (dtype) { + return _super.prototype.asType.call(this, dtype); + }; + Array3D.ones = function (shape, dtype) { + return NDArray.ones(shape, dtype); + }; + Array3D.zeros = function (shape, dtype) { + return NDArray.zeros(shape, dtype); + }; + Array3D.randNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, false, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + Array3D.randTruncatedNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, true, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + Array3D.randUniform = function (shape, a, b, dtype) { + return NDArray.rand(shape, function () { return util.randUniform(a, b); }, dtype); + }; + return Array3D; +}(NDArray)); +exports.Array3D = Array3D; +var Array4D = (function (_super) { + __extends(Array4D, _super); + function Array4D(shape, dtype, values, id, math) { + var _this = this; + util.assert(shape.length === 4, 'Shape should be of length 4'); + _this = _super.call(this, shape, dtype, values, id, math) || this; + _this.stride0 = _this.strides[0]; + _this.stride1 = _this.strides[1]; + _this.stride2 = _this.strides[2]; + return _this; + } + Array4D.new = function (shape, values, dtype) { + if (!instanceofTypedArray(values)) { + var inferredShape = util.inferShape(values); + if (inferredShape.length > 1) { + util.assertShapesMatch(shape, inferredShape, "Error when constructing Array4D. Shape of values " + + (inferredShape + " does not match the provided shape ") + + (shape + ". ")); + } + } + return new Array4D(shape, dtype, toTypedArray(values, dtype)); + }; + Array4D.prototype.get = function (i, j, k, l) { + return this.getValues()[this.stride0 * i + this.stride1 * j + this.stride2 * k + l]; + }; + Array4D.prototype.val = function (i, j, k, l) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.data()]; + case 1: + _a.sent(); + return [2, this.get(i, j, k, l)]; + } + }); + }); + }; + Array4D.prototype.add = function (value, i, j, k, l) { + this.getValues()[this.stride0 * i + this.stride1 * j + this.stride2 * k + l] += value; + }; + Array4D.prototype.locToIndex = function (locs) { + return this.stride0 * locs[0] + this.stride1 * locs[1] + + this.stride2 * locs[2] + locs[3]; + }; + Array4D.prototype.indexToLoc = function (index) { + var i = Math.floor(index / this.stride0); + index -= i * this.stride0; + var j = Math.floor(index / this.stride1); + index -= j * this.stride1; + return [i, j, Math.floor(index / this.stride2), index % this.stride2]; + }; + Array4D.prototype.asType = function (dtype) { + return _super.prototype.asType.call(this, dtype); + }; + Array4D.ones = function (shape, dtype) { + return NDArray.ones(shape, dtype); + }; + Array4D.zeros = function (shape, dtype) { + return NDArray.zeros(shape, dtype); + }; + Array4D.randNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, false, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + Array4D.randTruncatedNormal = function (shape, mean, stdDev, dtype, seed) { + if (mean === void 0) { mean = 0; } + if (stdDev === void 0) { stdDev = 1; } + if (dtype != null && dtype === 'bool') { + throw new Error("Unsupported data type " + dtype); + } + var randGauss = new rand_1.MPRandGauss(mean, stdDev, dtype, true, seed); + return NDArray.rand(shape, function () { return randGauss.nextValue(); }, dtype); + }; + Array4D.randUniform = function (shape, a, b, dtype) { + return NDArray.rand(shape, function () { return util.randUniform(a, b); }, dtype); + }; + return Array4D; +}(NDArray)); +exports.Array4D = Array4D; +function copyTypedArray(array, dtype) { + if (dtype == null || dtype === 'float32') { + return new Float32Array(array); + } + else if (dtype === 'int32') { + var vals = new Int32Array(array.length); + for (var i = 0; i < vals.length; ++i) { + var val = array[i]; + if (util.isValNaN(val, 'int32')) { + vals[i] = util.getNaN('int32'); + } + else { + vals[i] = val; + } + } + return vals; + } + else if (dtype === 'bool') { + var bool = new Uint8Array(array.length); + for (var i = 0; i < bool.length; ++i) { + var val = array[i]; + if (util.isValNaN(val, 'bool')) { + bool[i] = util.getNaN('bool'); + } + else if (Math.round(val) !== 0) { + bool[i] = 1; + } + } + return bool; + } + else { + throw new Error("Unknown data type " + dtype); + } +} +function instanceofTypedArray(a) { + return a instanceof Float32Array || a instanceof Int32Array || + a instanceof Uint8Array; +} +function noConversionNeeded(a, dtype) { + return (a instanceof Float32Array && dtype === 'float32') || + (a instanceof Int32Array && dtype === 'int32') || + (a instanceof Uint8Array && dtype === 'bool'); +} +function toTypedArray(a, dtype) { + if (noConversionNeeded(a, dtype)) { + return a; + } + if (Array.isArray(a)) { + a = util.flatten(a); + } + return copyTypedArray(a, dtype); +} +function makeZerosTypedArray(size, dtype) { + if (dtype == null || dtype === 'float32') { + return new Float32Array(size); + } + else if (dtype === 'int32') { + return new Int32Array(size); + } + else if (dtype === 'bool') { + return new Uint8Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } +} +function makeOnesTypedArray(size, dtype) { + var array = makeZerosTypedArray(size, dtype); + for (var i = 0; i < array.length; i++) { + array[i] = 1; + } + return array; +} + +},{"../environment":15,"../util":101,"./rand":96}],96:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var seedrandom = require("seedrandom"); +var MPRandGauss = (function () { + function MPRandGauss(mean, stdDeviation, dtype, truncated, seed) { + this.mean = mean; + this.stdDev = stdDeviation; + this.dtype = dtype; + this.nextVal = NaN; + this.truncated = truncated; + if (this.truncated) { + this.upper = this.mean + this.stdDev * 2; + this.lower = this.mean - this.stdDev * 2; + } + var seedValue = seed ? seed : Math.random(); + this.random = seedrandom.alea(seedValue.toString()); + } + MPRandGauss.prototype.nextValue = function () { + if (!isNaN(this.nextVal)) { + var value = this.nextVal; + this.nextVal = NaN; + return value; + } + var resultX, resultY; + var isValid = false; + while (!isValid) { + var v1 = void 0, v2 = void 0, s = void 0; + do { + v1 = 2 * this.random() - 1; + v2 = 2 * this.random() - 1; + s = v1 * v1 + v2 * v2; + } while (s >= 1 || s === 0); + var mul = Math.sqrt(-2.0 * Math.log(s) / s); + resultX = this.mean + this.stdDev * v1 * mul; + resultY = this.mean + this.stdDev * v2 * mul; + if (!this.truncated || this.isValidTruncated(resultX)) { + isValid = true; + } + } + if (!this.truncated || this.isValidTruncated(resultY)) { + this.nextVal = this.convertValue(resultY); + } + return this.convertValue(resultX); + }; + MPRandGauss.prototype.convertValue = function (value) { + if (this.dtype == null || this.dtype === 'float32') { + return value; + } + return Math.round(value); + }; + MPRandGauss.prototype.isValidTruncated = function (value) { + return value <= this.upper && value >= this.lower; + }; + return MPRandGauss; +}()); +exports.MPRandGauss = MPRandGauss; + +},{"seedrandom":2}],97:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PARALLELIZE_THRESHOLD = 30; +function computeOptimalWindowSize(inSize) { + if (inSize <= exports.PARALLELIZE_THRESHOLD) { + return inSize; + } + return nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); +} +exports.computeOptimalWindowSize = computeOptimalWindowSize; +function nearestDivisor(size, start) { + for (var i = start; i < size; ++i) { + if (size % i === 0) { + return i; + } + } + return size; +} + +},{}],98:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util = require("../util"); +function assertParamsValid(input, begin, size) { + util.assert(input.rank === begin.length, "Error in slice" + input.rank + "D: Length of begin " + begin + " must " + + ("match the rank of the array (" + input.rank + ").")); + util.assert(input.rank === size.length, "Error in slice" + input.rank + "D: Length of size " + size + " must " + + ("match the rank of the array (" + input.rank + ").")); + for (var i = 0; i < input.rank; ++i) { + util.assert(begin[i] + size[i] <= input.shape[i], "Error in slice" + input.rank + "D: begin[" + i + "] + size[" + i + "] " + + ("(" + (begin[i] + size[i]) + ") would overflow input.shape[" + i + "] (" + input.shape[i] + ")")); + } +} +exports.assertParamsValid = assertParamsValid; + +},{"../util":101}],99:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var SumTypesMap; +(function (SumTypesMap) { + SumTypesMap["float32"] = "float32"; + SumTypesMap["int32"] = "int32"; + SumTypesMap["bool"] = "int32"; +})(SumTypesMap = exports.SumTypesMap || (exports.SumTypesMap = {})); +var UpcastInt32AndMap; +(function (UpcastInt32AndMap) { + UpcastInt32AndMap["float32"] = "float32"; + UpcastInt32AndMap["int32"] = "int32"; + UpcastInt32AndMap["bool"] = "int32"; +})(UpcastInt32AndMap = exports.UpcastInt32AndMap || (exports.UpcastInt32AndMap = {})); +var UpcastBoolAndMap; +(function (UpcastBoolAndMap) { + UpcastBoolAndMap["float32"] = "float32"; + UpcastBoolAndMap["int32"] = "int32"; + UpcastBoolAndMap["bool"] = "bool"; +})(UpcastBoolAndMap = exports.UpcastBoolAndMap || (exports.UpcastBoolAndMap = {})); +var UpcastFloat32AndMap; +(function (UpcastFloat32AndMap) { + UpcastFloat32AndMap["float32"] = "float32"; + UpcastFloat32AndMap["int32"] = "float32"; + UpcastFloat32AndMap["bool"] = "float32"; +})(UpcastFloat32AndMap = exports.UpcastFloat32AndMap || (exports.UpcastFloat32AndMap = {})); +var upcastTypeMap = { + float32: UpcastFloat32AndMap, + int32: UpcastInt32AndMap, + bool: UpcastBoolAndMap +}; +function upcastType(typeA, typeB) { + return upcastTypeMap[typeA][typeB]; +} +exports.upcastType = upcastType; + +},{}],100:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var environment_1 = require("./environment"); +var backend_cpu_1 = require("./math/backends/backend_cpu"); +var backend_webgl_1 = require("./math/backends/backend_webgl"); +var math_1 = require("./math/math"); +var util = require("./util"); +exports.TEST_EPSILON = 1e-2; +function mean(values) { + var sum = 0; + for (var i = 0; i < values.length; i++) { + sum += values[i]; + } + return sum / values.length; +} +exports.mean = mean; +function standardDeviation(values, mean) { + var squareDiffSum = 0; + for (var i = 0; i < values.length; i++) { + var diff = values[i] - mean; + squareDiffSum += diff * diff; + } + return Math.sqrt(squareDiffSum / values.length); +} +exports.standardDeviation = standardDeviation; +function kurtosis(values) { + var valuesMean = mean(values); + var n = values.length; + var sum2 = 0; + var sum4 = 0; + for (var i = 0; i < n; i++) { + var v = values[i] - valuesMean; + sum2 += Math.pow(v, 2); + sum4 += Math.pow(v, 4); + } + return (1 / n) * sum4 / Math.pow((1 / n) * sum2, 2); +} +exports.kurtosis = kurtosis; +function skewness(values) { + var valuesMean = mean(values); + var n = values.length; + var sum2 = 0; + var sum3 = 0; + for (var i = 0; i < n; i++) { + var v = values[i] - valuesMean; + sum2 += Math.pow(v, 2); + sum3 += Math.pow(v, 3); + } + return (1 / n) * sum3 / Math.pow((1 / (n - 1)) * sum2, 3 / 2); +} +exports.skewness = skewness; +function jarqueBeraNormalityTest(values) { + var n = values.length; + var s = skewness(values); + var k = kurtosis(values); + var jb = n / 6 * (Math.pow(s, 2) + 0.25 * Math.pow(k - 3, 2)); + var CHI_SQUARE_2DEG = 5.991; + if (jb > CHI_SQUARE_2DEG) { + throw new Error("Invalid p-value for JB: " + jb); + } +} +exports.jarqueBeraNormalityTest = jarqueBeraNormalityTest; +function expectArrayInMeanStdRange(actual, expectedMean, expectedStdDev, epsilon) { + if (epsilon === void 0) { epsilon = exports.TEST_EPSILON; } + var actualMean = mean(actual); + expectNumbersClose(actualMean, expectedMean, epsilon); + expectNumbersClose(standardDeviation(actual, actualMean), expectedStdDev, epsilon); +} +exports.expectArrayInMeanStdRange = expectArrayInMeanStdRange; +function expectArraysClose(actual, expected, epsilon) { + if (epsilon === void 0) { epsilon = exports.TEST_EPSILON; } + var aType = actual.constructor.name; + var bType = expected.constructor.name; + if (aType !== bType) { + throw new Error("Arrays are of different type " + aType + " vs " + bType); + } + if (actual.length !== expected.length) { + throw new Error("Matrices have different lengths (" + actual.length + " vs " + + (expected.length + ").")); + } + for (var i = 0; i < expected.length; ++i) { + var a = actual[i]; + var e = expected[i]; + if (!areClose(a, e, epsilon)) { + var actualStr = "actual[" + i + "] === " + a; + var expectedStr = "expected[" + i + "] === " + e; + throw new Error('Arrays differ: ' + actualStr + ', ' + expectedStr); + } + } +} +exports.expectArraysClose = expectArraysClose; +function expectNumbersClose(a, e, epsilon) { + if (epsilon === void 0) { epsilon = exports.TEST_EPSILON; } + if (!areClose(a, e, epsilon)) { + throw new Error("Numbers differ: actual === " + a + ", expected === " + e); + } +} +exports.expectNumbersClose = expectNumbersClose; +function areClose(a, e, epsilon) { + if (isNaN(a) && isNaN(e)) { + return true; + } + if (isNaN(a) || isNaN(e) || Math.abs(a - e) > epsilon) { + return false; + } + return true; +} +function expectValuesInRange(actual, low, high) { + for (var i = 0; i < actual.length; i++) { + if (actual[i] < low || actual[i] > high) { + throw new Error("Value out of range:" + actual[i] + " low: " + low + ", high: " + high); + } + } +} +exports.expectValuesInRange = expectValuesInRange; +function randomArrayInRange(n, minValue, maxValue) { + var v = new Float32Array(n); + var range = maxValue - minValue; + for (var i = 0; i < n; ++i) { + v[i] = (Math.random() * range) + minValue; + } + return v; +} +exports.randomArrayInRange = randomArrayInRange; +function makeIdentity(n) { + var i = new Float32Array(n * n); + for (var j = 0; j < n; ++j) { + i[(j * n) + j] = 1; + } + return i; +} +exports.makeIdentity = makeIdentity; +function cpuMultiplyMatrix(a, aRow, aCol, b, bRow, bCol) { + var result = new Float32Array(aRow * bCol); + for (var r = 0; r < aRow; ++r) { + var aOffset = (r * aCol); + var cOffset = (r * bCol); + for (var c = 0; c < bCol; ++c) { + var d = 0; + for (var k = 0; k < aCol; ++k) { + d += a[aOffset + k] * b[(k * bCol) + c]; + } + result[cOffset + c] = d; + } + } + return result; +} +exports.cpuMultiplyMatrix = cpuMultiplyMatrix; +function cpuDotProduct(a, b) { + if (a.length !== b.length) { + throw new Error('cpuDotProduct: incompatible vectors.'); + } + var d = 0; + for (var i = 0; i < a.length; ++i) { + d += a[i] * b[i]; + } + return d; +} +exports.cpuDotProduct = cpuDotProduct; +function describeMathCPU(name, tests, featuresList) { + var testNameBase = 'CPU: math.' + name; + describeWithFeaturesAndExecutor(testNameBase, tests, function (testName, tests, features) { return executeMathTests(testName, tests, function () { + var safeMode = true; + return new math_1.NDArrayMath(new backend_cpu_1.MathBackendCPU(), safeMode); + }, features); }, featuresList); +} +exports.describeMathCPU = describeMathCPU; +function describeMathGPU(name, tests, featuresList) { + var testNameBase = 'WebGL: math.' + name; + describeWithFeaturesAndExecutor(testNameBase, tests, function (testName, tests, features) { return executeMathTests(testName, tests, function () { + var safeMode = true; + return new math_1.NDArrayMath(new backend_webgl_1.MathBackendWebGL(), safeMode); + }, features); }, featuresList); +} +exports.describeMathGPU = describeMathGPU; +function describeCustom(name, tests, featuresList, customBeforeEach, customAfterEach) { + describeWithFeaturesAndExecutor(name, [tests], function (testName, tests, features) { return executeTests(testName, tests, features, customBeforeEach, customAfterEach); }, featuresList); +} +exports.describeCustom = describeCustom; +function describeWithFeaturesAndExecutor(testNameBase, tests, executor, featuresList) { + if (featuresList != null) { + featuresList.forEach(function (features) { + var testName = testNameBase + ' ' + JSON.stringify(features); + executor(testName, tests, features); + }); + } + else { + executor(testNameBase, tests); + } +} +var PROMISE_IT = function (name, testFunc) { + it(name, function (done) { + var result = testFunc(); + if (result instanceof Promise) { + result.then(done, function (e) { + fail(e); + done(); + }); + } + else { + done(); + } + }); +}; +function executeMathTests(testName, tests, mathFactory, features) { + var math; + var customBeforeEach = function () { + math = mathFactory(); + environment_1.ENV.setMath(math); + math.startScope(); + }; + var customAfterEach = function () { + math.endScope(null); + math.dispose(); + }; + var customIt = function (name, testFunc) { + PROMISE_IT(name, function () { return testFunc(math); }); + }; + executeTests(testName, tests, features, customBeforeEach, customAfterEach, customIt); +} +exports.executeMathTests = executeMathTests; +function executeTests(testName, tests, features, customBeforeEach, customAfterEach, customIt) { + if (customIt === void 0) { customIt = PROMISE_IT; } + describe(testName, function () { + beforeEach(function () { + if (features != null) { + environment_1.ENV.setFeatures(features); + environment_1.ENV.registerBackend('webgl', function () { return new backend_webgl_1.MathBackendWebGL(); }); + environment_1.ENV.registerBackend('cpu', function () { return new backend_cpu_1.MathBackendCPU(); }); + } + if (customBeforeEach != null) { + customBeforeEach(); + } + }); + afterEach(function () { + if (customAfterEach != null) { + customAfterEach(); + } + if (features != null) { + environment_1.ENV.reset(); + } + }); + tests.forEach(function (test) { return test(customIt); }); + }); +} +exports.executeTests = executeTests; +function assertIsNan(val, dtype) { + if (!util.isValNaN(val, dtype)) { + throw new Error("Value " + val + " does not represent NaN for dtype " + dtype); + } +} +exports.assertIsNan = assertIsNan; + +},{"./environment":15,"./math/backends/backend_cpu":55,"./math/backends/backend_webgl":57,"./math/math":94,"./util":101}],101:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function shuffle(array) { + var counter = array.length; + var temp = 0; + var index = 0; + while (counter > 0) { + index = (Math.random() * counter) | 0; + counter--; + temp = array[counter]; + array[counter] = array[index]; + array[index] = temp; + } +} +exports.shuffle = shuffle; +function clamp(min, x, max) { + return Math.max(min, Math.min(x, max)); +} +exports.clamp = clamp; +function randUniform(a, b) { + return Math.random() * (b - a) + a; +} +exports.randUniform = randUniform; +function distSquared(a, b) { + var result = 0; + for (var i = 0; i < a.length; i++) { + var diff = Number(a[i]) - Number(b[i]); + result += diff * diff; + } + return result; +} +exports.distSquared = distSquared; +function assert(expr, msg) { + if (!expr) { + throw new Error(msg); + } +} +exports.assert = assert; +function assertShapesMatch(shapeA, shapeB, errorMessagePrefix) { + if (errorMessagePrefix === void 0) { errorMessagePrefix = ''; } + assert(arraysEqual(shapeA, shapeB), errorMessagePrefix + ("Shapes " + shapeA + " and " + shapeB + " must match")); +} +exports.assertShapesMatch = assertShapesMatch; +function flatten(arr, ret) { + if (ret === void 0) { ret = []; } + if (Array.isArray(arr)) { + for (var i = 0; i < arr.length; ++i) { + flatten(arr[i], ret); + } + } + else { + ret.push(arr); + } + return ret; +} +exports.flatten = flatten; +function inferShape(arr) { + var shape = []; + while (arr instanceof Array) { + shape.push(arr.length); + arr = arr[0]; + } + return shape; +} +exports.inferShape = inferShape; +function sizeFromShape(shape) { + if (shape.length === 0) { + return 1; + } + var size = shape[0]; + for (var i = 1; i < shape.length; i++) { + size *= shape[i]; + } + return size; +} +exports.sizeFromShape = sizeFromShape; +function isScalarShape(shape) { + return shape.length === 0; +} +exports.isScalarShape = isScalarShape; +function arraysEqual(n1, n2) { + if (n1.length !== n2.length) { + return false; + } + for (var i = 0; i < n1.length; i++) { + if (n1[i] !== n2[i]) { + return false; + } + } + return true; +} +exports.arraysEqual = arraysEqual; +function isInt(a) { + return a % 1 === 0; +} +exports.isInt = isInt; +function tanh(x) { + if (Math.tanh != null) { + return Math.tanh(x); + } + if (x === Infinity) { + return 1; + } + else if (x === -Infinity) { + return -1; + } + else { + var e2x = Math.exp(2 * x); + return (e2x - 1) / (e2x + 1); + } +} +exports.tanh = tanh; +function sizeToSquarishShape(size) { + for (var a = Math.floor(Math.sqrt(size)); a > 1; --a) { + if (size % a === 0) { + return [a, size / a]; + } + } + return [1, size]; +} +exports.sizeToSquarishShape = sizeToSquarishShape; +function createShuffledIndices(n) { + var shuffledIndices = new Uint32Array(n); + for (var i = 0; i < n; ++i) { + shuffledIndices[i] = i; + } + shuffle(shuffledIndices); + return shuffledIndices; +} +exports.createShuffledIndices = createShuffledIndices; +function rightPad(a, size) { + if (size <= a.length) { + return a; + } + return a + ' '.repeat(size - a.length); +} +exports.rightPad = rightPad; +function repeatedTry(checkFn, delayFn, maxCounter) { + if (delayFn === void 0) { delayFn = function (counter) { return 0; }; } + return new Promise(function (resolve, reject) { + var tryCount = 0; + var tryFn = function () { + if (checkFn()) { + resolve(); + return; + } + tryCount++; + var nextBackoff = delayFn(tryCount); + if (maxCounter != null && tryCount >= maxCounter) { + reject(); + return; + } + setTimeout(tryFn, nextBackoff); + }; + setTimeout(tryFn, 0); + }); +} +exports.repeatedTry = repeatedTry; +function getQueryParams(queryString) { + var params = {}; + queryString.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g, function (s) { + var t = []; + for (var _i = 1; _i < arguments.length; _i++) { + t[_i - 1] = arguments[_i]; + } + decodeParam(params, t[0], t[1]); + return t.join('='); + }); + return params; +} +exports.getQueryParams = getQueryParams; +function decodeParam(params, name, value) { + params[decodeURIComponent(name)] = decodeURIComponent(value || ''); +} +function inferFromImplicitShape(shape, size) { + var shapeProd = 1; + var implicitIdx = -1; + for (var i = 0; i < shape.length; ++i) { + if (shape[i] > 0) { + shapeProd *= shape[i]; + } + else if (shape[i] === -1) { + if (implicitIdx !== -1) { + throw Error("Shapes can only have 1 implicit size. " + + ("Found -1 at dim " + implicitIdx + " and dim " + i)); + } + implicitIdx = i; + } + else if (shape[i] <= 0) { + throw Error("Shapes can not be <= 0. Found " + shape[i] + " at dim " + i); + } + } + if (implicitIdx === -1) { + if (size > 0 && size !== shapeProd) { + throw Error("Size (" + size + ") must match the product of shape " + shape); + } + return shape; + } + if (size % shapeProd !== 0) { + throw Error("The implicit shape can't be a fractional number. " + + ("Got " + size + " / " + shapeProd)); + } + var newShape = shape.slice(); + newShape[implicitIdx] = size / shapeProd; + return newShape; +} +exports.inferFromImplicitShape = inferFromImplicitShape; +exports.NAN_INT32 = 1 << 31; +exports.NAN_BOOL = 255; +exports.NAN_FLOAT32 = NaN; +function getNaN(dtype) { + if (dtype === 'float32') { + return exports.NAN_FLOAT32; + } + else if (dtype === 'int32') { + return exports.NAN_INT32; + } + else if (dtype === 'bool') { + return exports.NAN_BOOL; + } + else { + throw new Error("Unknown dtype " + dtype); + } +} +exports.getNaN = getNaN; +function isValNaN(val, dtype) { + if (isNaN(val)) { + return true; + } + if (dtype === 'float32') { + return false; + } + else if (dtype === 'int32') { + return val === exports.NAN_INT32; + } + else if (dtype === 'bool') { + return val === exports.NAN_BOOL; + } + else { + throw new Error("Unknown dtype " + dtype); + } +} +exports.isValNaN = isValNaN; +function squeezeShape(shape) { + var newShape = []; + var keptDims = []; + for (var i = 0; i < shape.length; ++i) { + if (shape[i] > 1) { + newShape.push(shape[i]); + keptDims.push(i); + } + } + return { newShape: newShape, keptDims: keptDims }; +} +exports.squeezeShape = squeezeShape; +function getTypedArrayFromDType(dtype, size) { + var values = null; + if (dtype == null || dtype === 'float32') { + values = new Float32Array(size); + } + else if (dtype === 'int32') { + values = new Int32Array(size); + } + else if (dtype === 'bool') { + values = new Uint8Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } + return values; +} +exports.getTypedArrayFromDType = getTypedArrayFromDType; + +},{}],102:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var version = '0.3.15'; +exports.version = version; + +},{}]},{},[51])(51) +}); +this.dl = this.deeplearn; diff --git a/server/static/edges2cats-input.png b/server/static/edges2cats-input.png index e48918c8523851d6e00d33a785d1cb2709c5447a..9536f954685a79c9d516b973e7fa5a549315d69d 100644 Binary files a/server/static/edges2cats-input.png and b/server/static/edges2cats-input.png differ diff --git a/server/static/edges2cats-output.png b/server/static/edges2cats-output.png index b6049e8b609534706dfc53f92d4b268dc2b35a2a..bf747fe0e7e455d016ce5f31034011c2113ec2b1 100644 Binary files a/server/static/edges2cats-output.png and b/server/static/edges2cats-output.png differ diff --git a/server/static/edges2cats-sheet.jpg b/server/static/edges2cats-sheet.jpg index 40b8508d3ccb9349a251af8e1a71d554078e1f89..0136f8ac706921d571fbd208a77800b0ce1f5c19 100644 Binary files a/server/static/edges2cats-sheet.jpg and b/server/static/edges2cats-sheet.jpg differ diff --git a/server/static/edges2handbags-input.png b/server/static/edges2handbags-input.png deleted file mode 100644 index 8e342bf48c50a7a1ea940846fc53388acb662499..0000000000000000000000000000000000000000 Binary files a/server/static/edges2handbags-input.png and /dev/null differ diff --git a/server/static/edges2handbags-output.png b/server/static/edges2handbags-output.png deleted file mode 100644 index 0d4e8330fd1e638d69e4e33c8e66c9ba2882240f..0000000000000000000000000000000000000000 Binary files a/server/static/edges2handbags-output.png and /dev/null differ diff --git a/server/static/edges2handbags-sheet.jpg b/server/static/edges2handbags-sheet.jpg deleted file mode 100644 index e06ec790abdaa85c1c75fa75fd702aacf2054dad..0000000000000000000000000000000000000000 Binary files a/server/static/edges2handbags-sheet.jpg and /dev/null differ diff --git a/server/static/edges2shoes-input.png b/server/static/edges2shoes-input.png index 296f5b661d9b83c4aa835074b65cde359aa135c0..797ff675bf5b8f050d1d178e971975f90bd2b24b 100644 Binary files a/server/static/edges2shoes-input.png and b/server/static/edges2shoes-input.png differ diff --git a/server/static/edges2shoes-output.png b/server/static/edges2shoes-output.png index 4faa4e59c6d982aae2c2466002dbbe569ed23712..3d875725f31d1510f3622469d5c1c7c088467742 100644 Binary files a/server/static/edges2shoes-output.png and b/server/static/edges2shoes-output.png differ diff --git a/server/static/edges2shoes-sheet.jpg b/server/static/edges2shoes-sheet.jpg index e535c5ef97d55ec1f0bb2d7732f05d041277ee8f..80e10f6019d236602211644bb0032de46e38af59 100644 Binary files a/server/static/edges2shoes-sheet.jpg and b/server/static/edges2shoes-sheet.jpg differ diff --git a/server/static/eraser.png b/server/static/eraser.png new file mode 100644 index 0000000000000000000000000000000000000000..bbfc67fe5dc599fddb2894ccd2111f03e1c26116 Binary files /dev/null and b/server/static/eraser.png differ diff --git a/server/static/facades-input.png b/server/static/facades-input.png index f405fc4f8b4ad113199cb067d13064fe1550a649..d8ba69af8c2a931e20c60282a7259320fdbdbda7 100644 Binary files a/server/static/facades-input.png and b/server/static/facades-input.png differ diff --git a/server/static/facades-output.png b/server/static/facades-output.png index 03e092b132cd20ac044b2b8262ee7e18fa484f85..dc0353311f10644b8d947197272006c74e6418ad 100644 Binary files a/server/static/facades-output.png and b/server/static/facades-output.png differ diff --git a/server/static/facades-sheet.jpg b/server/static/facades-sheet.jpg index e1c4961235fd53a9944112c276953b3535cb6755..5fce2c4283725a6e3646124c00672a6cf98f11d0 100644 Binary files a/server/static/facades-sheet.jpg and b/server/static/facades-sheet.jpg differ diff --git a/server/static/index.html b/server/static/index.html index 7e358b3e17db2af3bb9bb7349375068f0a6f9c22..d5b1b321bdabdd40dd9166c75bdb63d0d6038632 100644 --- a/server/static/index.html +++ b/server/static/index.html @@ -1,29 +1,29 @@ <html> <body> +<div>edges2cats</div> +<div id="edges2cats"></div> + <div>edges2shoes</div> <div id="edges2shoes"></div> -<div>facades</div> -<div id="facades"></div> - <div>edges2handbags</div> <div id="edges2handbags"></div> -<div>edges2cats</div> -<div id="edges2cats"></div> +<div>facades</div> +<div id="facades"></div> +<script src="deeplearn-0.3.15.js"></script> <script> var editor_background = new Image() editor_background.src = "editor.png" +var DEBUG = false var SIZE = 256 var editors = [] var request_in_progress = false -var last_request_failed = false -var base_url = "" // this will cause it to talk to the server of this file function main() { var create_editor = function(config) { @@ -34,8 +34,8 @@ function main() { } create_editor({ - name: "edges2shoes", - generate_url: base_url + "/edges2shoes_AtoB", + name: "edges2cats", + weights_url: "/models/edges2cats_AtoB.pict", mode: "line", clear: "#FFFFFF", colors: { @@ -43,14 +43,14 @@ function main() { eraser: "#ffffff", }, draw: "#000000", - initial_input: "/edges2shoes-input.png", - initial_output: "/edges2shoes-output.png", - sheet_url: "/edges2shoes-sheet.jpg", + initial_input: "/edges2cats-input.png", + initial_output: "/edges2cats-output.png", + sheet_url: "/edges2cats-sheet.jpg", }) create_editor({ - name: "edges2handbags", - generate_url: base_url + "/edges2handbags_AtoB", + name: "edges2shoes", + weights_url: "/models/edges2shoes_AtoB.pict", mode: "line", clear: "#FFFFFF", colors: { @@ -58,14 +58,14 @@ function main() { eraser: "#ffffff", }, draw: "#000000", - initial_input: "/edges2handbags-input.png", - initial_output: "/edges2handbags-output.png", - sheet_url: "/edges2handbags-sheet.jpg", + initial_input: "/edges2shoes-input.png", + initial_output: "/edges2shoes-output.png", + sheet_url: "/edges2shoes-sheet.jpg", }) create_editor({ - name: "edges2cats", - generate_url: base_url + "/edges2cats_AtoB", + name: "edges2handbags", + weights_url: "/models/edges2handbags_AtoB.pict", mode: "line", clear: "#FFFFFF", colors: { @@ -73,14 +73,14 @@ function main() { eraser: "#ffffff", }, draw: "#000000", - initial_input: "/edges2cats-input.png", - initial_output: "/edges2cats-output.png", - sheet_url: "/edges2cats-sheet.jpg", + initial_input: "/edges2handbags-input.png", + initial_output: "/edges2handbags-output.png", + sheet_url: "/edges2handbags-sheet.jpg", }) create_editor({ name: "facades", - generate_url: base_url + "/facades_BtoA", + weights_url: "/models/facades_BtoA.pict", mode: "rect", colors: { background: "#0006d9", @@ -89,7 +89,7 @@ function main() { "window": "#0075ff", "window sill": "#68f898", "window head": "#1dffdd", - "shutter": "#eeed28", + shutter: "#eeed28", balcony: "#b8ff38", trim: "#ff9204", cornice: "#ff4401", @@ -103,7 +103,7 @@ function main() { sheet_url: "/facades-sheet.jpg", }) - init() + window.requestAnimationFrame(frame) } window.onload = main @@ -113,6 +113,156 @@ function render() { } } + +// model + +var weights_cache = {} +function fetch_weights(path, progress_cb) { + return new Promise(function(resolve, reject) { + if (path in weights_cache) { + resolve(weights_cache[path]) + return + } + + var xhr = new XMLHttpRequest() + xhr.open("GET", path, true) + xhr.responseType = "arraybuffer" + + xhr.onprogress = function(e) { + progress_cb(e.loaded, e.total) + } + + xhr.onload = function(e) { + if (xhr.status != 200) { + reject("missing model") + return + } + var buf = xhr.response + if (!buf) { + reject("invalid arraybuffer") + return + } + + var parts = [] + var offset = 0 + while (offset < buf.byteLength) { + var b = new Uint8Array(buf.slice(offset, offset+4)) + offset += 4 + var len = (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3] + parts.push(buf.slice(offset, offset + len)) + offset += len + } + + var shapes = JSON.parse((new TextDecoder("utf8")).decode(parts[0])) + var index = new Float32Array(parts[1]) + var encoded = new Uint8Array(parts[2]) + + // decode using index + var arr = new Float32Array(encoded.length) + for (var i = 0; i < arr.length; i++) { + arr[i] = index[encoded[i]] + } + + var weights = {} + var offset = 0 + for (var i = 0; i < shapes.length; i++) { + var shape = shapes[i].shape + var size = shape.reduce((total, num) => total * num) + var values = arr.slice(offset, offset+size) + var dlarr = dl.Array1D.new(values, "float32") + weights[shapes[i].name] = dlarr.reshape(shape) + offset += size + } + weights_cache[path] = weights + resolve(weights) + } + xhr.send(null) + }) +} + +function model(input, weights) { + const math = dl.ENV.math + + function preprocess(input) { + return math.subtract(math.multiply(input, dl.Scalar.new(2)), dl.Scalar.new(1)) + } + + function deprocess(input) { + return math.divide(math.add(input, dl.Scalar.new(1)), dl.Scalar.new(2)) + } + + function batchnorm(input, scale, offset) { + var moments = math.moments(input, [0, 1]) + const varianceEpsilon = 1e-5 + return math.batchNormalization3D(input, moments.mean, moments.variance, varianceEpsilon, scale, offset) + } + + function conv2d(input, filter, bias) { + return math.conv2d(input, filter, bias, [2, 2], "same") + } + + function deconv2d(input, filter, bias) { + var convolved = math.conv2dTranspose(input, filter, [input.shape[0]*2, input.shape[1]*2, filter.shape[2]], [2, 2], "same") + var biased = math.add(convolved, bias) + return biased + } + + var preprocessed_input = preprocess(input) + + var layers = [] + + var filter = weights["generator/encoder_1/conv2d/kernel"] + var bias = weights["generator/encoder_1/conv2d/bias"] + var convolved = conv2d(preprocessed_input, filter, bias) + layers.push(convolved) + + for (var i = 2; i <= 8; i++) { + var scope = "generator/encoder_" + i.toString() + var filter = weights[scope + "/conv2d/kernel"] + var bias = weights[scope + "/conv2d/bias"] + var layer_input = layers[layers.length - 1] + var rectified = math.leakyRelu(layer_input, 0.2) + var convolved = conv2d(rectified, filter, bias) + var scale = weights[scope + "/batch_normalization/gamma"] + var offset = weights[scope + "/batch_normalization/beta"] + var normalized = batchnorm(convolved, scale, offset) + layers.push(normalized) + } + + for (var i = 8; i >= 2; i--) { + if (i == 8) { + var layer_input = layers[layers.length - 1] + } else { + var skip_layer = i - 1 + var layer_input = math.concat3D(layers[layers.length - 1], layers[skip_layer], 2) + } + var rectified = math.relu(layer_input) + var scope = "generator/decoder_" + i.toString() + var filter = weights[scope + "/conv2d_transpose/kernel"] + var bias = weights[scope + "/conv2d_transpose/bias"] + var convolved = deconv2d(rectified, filter, bias) + var scale = weights[scope + "/batch_normalization/gamma"] + var offset = weights[scope + "/batch_normalization/beta"] + var normalized = batchnorm(convolved, scale, offset) + // missing dropout + layers.push(normalized) + } + + var layer_input = math.concat3D(layers[layers.length - 1], layers[0], 2) + var rectified = math.relu(layer_input) + var filter = weights["generator/decoder_1/conv2d_transpose/kernel"] + var bias = weights["generator/decoder_1/conv2d_transpose/bias"] + var convolved = deconv2d(rectified, filter, bias) + var rectified = math.tanh(convolved) + layers.push(rectified) + + var output = layers[layers.length - 1] + var deprocessed_output = deprocess(output) + + return deprocessed_output +} + + // editor function Editor(config) { @@ -138,6 +288,9 @@ function Editor(config) { this.output.drawImage(output, 0, 0) } + this.progress = null + this.last_failure = null + this.sheet_loaded = false this.sheet = new Image() this.sheet.src = this.config.sheet_url @@ -164,7 +317,7 @@ Editor.prototype = { } this.buffer = this.buffers.pop() }, -render: function() { + render: function() { var v = this.view v.ctx.clearRect(0, 0, v.f.width, v.f.height) @@ -181,7 +334,7 @@ render: function() { if (v.contains(mouse_pos)) { cursor_style = "pointer" } - + if (mouse_released && v.contains(mouse_pos)) { this.config.draw = color update() @@ -275,7 +428,7 @@ render: function() { if (mouse_down) { v.ctx.save() v.ctx.rect(0, 0, v.f.width, v.f.height) - v.ctx.clip(); + v.ctx.clip() v.ctx.fillStyle = this.config.draw v.ctx.fillRect(start.x, start.y, width, height) v.ctx.restore() @@ -291,47 +444,73 @@ render: function() { }) v.frame("process_button", 461 - 32, 148, 32*2, 40, () => { - if (request_in_progress) { - do_button(v, "...") + if (this.progress != null) { + v.ctx.font = "12px Arial" + v.ctx.fillStyle = "#000" + var s = "downloading" + v.ctx.fillText(s, (v.f.width - v.ctx.measureText(s).width)/2, 5) + s = "model" + v.ctx.fillText(s, (v.f.width - v.ctx.measureText(s).width)/2, 15) + + v.frame("progress_bar", 0, 25, v.f.width, 15, () => { + v.ctx.fillStyle = "#f92672" + v.ctx.fillRect(0, 0, v.f.width * this.progress, v.f.height) + }) + } else if (request_in_progress) { + do_button(v, "running") } else { if (do_button(v, "process")) { if (request_in_progress) { console.log("request already in progress") return } + request_in_progress = true + this.last_failure = null - last_request_failed = false - var convert = createContext(SIZE, SIZE, 1) - convert.drawImage(this.buffer.canvas, 0, 0, convert.canvas.width, convert.canvas.height) - var input_b64 = convert.canvas.toDataURL("image/png").replace(/^data:image\/png;base64,/, "") - var xhr = new XMLHttpRequest() - xhr.open("POST", this.config.generate_url, true) - xhr.setRequestHeader("Content-Type", "image/png") - xhr.responseType = "arraybuffer" - xhr.timeout = 45000 - - xhr.onreadystatechange = () => { - if (xhr.readyState == 4) { - request_in_progress = false - update() - if (xhr.status == 200) { - var output_bin = new Uint8Array(xhr.response) - var output_b64 = bin_to_b64(output_bin) - var output = new Image() - output.src = "data:image\/png;base64," + output_b64 - output.onload = () => { - // browsers besides chrome need to wait for the image to load - this.output.drawImage(output, 0, 0) - update() - } - } else { - last_request_failed = true - } - } + this.progress = 0 + progress_cb = (retrieved, total) => { + this.progress = retrieved/total + update() } - request_in_progress = true - update() - xhr.send(b64_to_bin(input_b64)) + + fetch_weights(this.config.weights_url, progress_cb).then((weights) => { + this.progress = null + update() + // delay a short period of time so that UI updates before the model uses all the CPU + delay(() => { + // var g = new dl.Graph() + + var convert = createContext(SIZE, SIZE, 1) + convert.drawImage(this.buffer.canvas, 0, 0, convert.canvas.width, convert.canvas.height) + var input_uint8_data = convert.getImageData(0, 0, SIZE, SIZE).data + var input_float32_data = Float32Array.from(input_uint8_data, (x) => x / 255) + + console.time('render') + const math = dl.ENV.math + math.startScope() + var input_rgba = dl.Array3D.new([SIZE, SIZE, 4], input_float32_data, "float32") + var input_rgb = math.slice3D(input_rgba, [0, 0, 0], [SIZE, SIZE, 3]) + + var output_rgb = model(input_rgb, weights) + + var alpha = dl.Array3D.ones([SIZE, SIZE, 1]) + var output_rgba = math.concat3D(output_rgb, alpha, 2) + + output_rgba.getValuesAsync().then((output_float32_data) => { + var output_uint8_data = Uint8ClampedArray.from(output_float32_data, (x) => x * 255) + this.output.putImageData(new ImageData(output_uint8_data, SIZE, SIZE), 0, 0) + math.endScope() + console.timeEnd('render') + request_in_progress = false + update() + }) + }) + }, (e) => { + this.last_failure = e + this.progress = null + request_in_progress = false + update() + }) } } }) @@ -384,19 +563,19 @@ render: function() { a.href = url a.download = "pix2pix.png" // use createEvent instead of .click() to work in firefox - // also can't revoke the object url because firefox breaks + // also can"t revoke the object url because firefox breaks var event = document.createEvent("MouseEvents") event.initEvent("click", true, true) a.dispatchEvent(event) - // safari doesn't work at all + // safari doesn"t work at all } }) - if (last_request_failed) { + if (this.last_failure != null) { v.frame("server_error", 50, 350, v.f.width, 50, () => { v.ctx.font = "20px Arial" v.ctx.fillStyle = "red" - v.center_text("error connecting to server, try again later") + v.center_text(fmt("error %s", this.last_failure)) }) } }, @@ -427,17 +606,128 @@ function b64_to_bin(str) { return bin } -function bin_to_b64(bin) { - var parts = [] - for (var i = 0; i < bin.length; i++) { - parts.push(String.fromCharCode(bin[i])) +function delay(fn) { + setTimeout(fn, 0) +} + +function default_format(obj) { + if (typeof(obj) === "string") { + return obj + } else { + return JSON.stringify(obj) } - var binstr = parts.join("") - return btoa(binstr) } +function fmt() { + if (arguments.length === 0) { + return "error" + } + + var format = arguments[0] + var output = "" + + var arg_index = 1 + var i = 0 + + while (i < format.length) { + var c = format[i] + i++ + + if (c != "%") { + output += c + continue + } + + if (i === format.length) { + output += "%!(NOVERB)" + break + } -// immediate mode + var flag = format[i] + i++ + + var pad_char = " " + + if (flag == "0") { + pad_char = "0" + } else { + // not a flag + i-- + } + + var width = 0 + while (format[i] >= "0" && format[i] <= "9") { + width *= 10 + width += parseInt(format[i], 10) + i++ + } + + var f = format[i] + i++ + + if (f === "%") { + output += "%" + continue + } + + if (arg_index === arguments.length) { + output += "%!" + f + "(MISSING)" + continue + } + + var arg = arguments[arg_index] + arg_index++ + + var o = null + + if (f === "v") { + o = default_format(arg) + } else if (f === "s" && typeof(arg) === "string") { + o = arg + } else if (f === "T") { + o = typeof(arg) + } else if (f === "d" && typeof(arg) === "number") { + o = arg.toFixed(0) + } else if (f === "f" && typeof(arg) === "number") { + o = arg.toString() + } else if (f === "x" && typeof(arg) === "number") { + o = Math.round(arg).toString(16) + } else if (f === "t" && typeof(arg) === "boolean") { + if (arg) { + o = "true" + } else { + o = "false" + } + } else { + output += "%!" + f + "(" + typeof(arg) + "=" + default_format(arg) + ")" + } + + if (o !== null) { + if (o.length < width) { + output += Array(width - o.length + 1).join(pad_char) + } + output += o + } + } + + if (arg_index < arguments.length) { + output += "%!(EXTRA " + while (arg_index < arguments.length) { + var arg = arguments[arg_index] + output += typeof(arg) + "=" + default_format(arg) + if (arg_index < arguments.length - 1) { + output += ", " + } + arg_index++ + } + output += ")" + } + + return output +} + + +// immediate mode UI var SCALE = 2 @@ -456,6 +746,32 @@ var mouse_down = false var mouse_pressed = false var mouse_released = false +if (DEBUG) { + var fps_elem = document.createElement("div") + stylize(fps_elem, { + width: "300px", + height: "20px", + margin: "5px", + fontFamily: "Monaco", + fontSize: "12px", + position: "absolute", + top: fmt("%dpx", 10), + right: fmt("%dpx", 10), + }) + document.body.insertBefore(fps_elem, document.body.firstChild) + + var status_elem = document.createElement("div") + stylize(status_elem, { + width: "10px", + height: "10px", + margin: "5px", + position: "absolute", + top: fmt("%dpx", 10), + left: fmt("%dpx", 10), + }) + document.body.insertBefore(status_elem, document.body.firstChild) +} + function View(name, width, height) { this.ctx = createContext(width, height, SCALE) // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingText/AddingText.html @@ -574,8 +890,14 @@ function frame() { var raf = window.requestAnimationFrame(frame) if (!updated && Object.keys(animations).length == 0) { + if (DEBUG) { + status_elem.style.backgroundColor = "black" + } return } + if (DEBUG) { + status_elem.style.backgroundColor = "red" + } now = new Date() cursor_style = null @@ -594,6 +916,13 @@ function frame() { document.body.style.cursor = cursor_style } + if (DEBUG) { + var decay = 0.9 + var current_frame_rate = 1 / ((now - last_frame) / 1000) + frame_rate = frame_rate * decay + current_frame_rate * (1 - decay) + fps_elem.textContent = fmt("fps: %d", frame_rate) + } + last_frame = now last_mouse_pos = mouse_pos mouse_pressed = false @@ -689,126 +1018,6 @@ document.addEventListener("mouseup", function(e) { update() }) -function default_format(obj) { - if (typeof(obj) === "string") { - return obj - } else { - return JSON.stringify(obj) - } -} - -function fmt() { - if (arguments.length === 0) { - return "error" - } - - var format = arguments[0] - var output = "" - - var arg_index = 1 - var i = 0 - - while (i < format.length) { - var c = format[i] - i++ - - if (c != "%") { - output += c - continue - } - - if (i === format.length) { - output += "%!(NOVERB)" - break - } - - var flag = format[i] - i++ - - var pad_char = " " - - if (flag == "0") { - pad_char = "0" - } else { - // not a flag - i-- - } - - var width = 0 - while (format[i] >= "0" && format[i] <= "9") { - width *= 10 - width += parseInt(format[i], 10) - i++ - } - - var f = format[i] - i++ - - if (f === "%") { - output += "%" - continue - } - - if (arg_index === arguments.length) { - output += "%!" + f + "(MISSING)" - continue - } - - var arg = arguments[arg_index] - arg_index++ - - var o = null - - if (f === "v") { - o = default_format(arg) - } else if (f === "s" && typeof(arg) === "string") { - o = arg - } else if (f === "T") { - o = typeof(arg) - } else if (f === "d" && typeof(arg) === "number") { - o = arg.toFixed(0) - } else if (f === "f" && typeof(arg) === "number") { - o = arg.toString() - } else if (f === "x" && typeof(arg) === "number") { - o = Math.round(arg).toString(16) - } else if (f === "t" && typeof(arg) === "boolean") { - if (arg) { - o = "true" - } else { - o = "false" - } - } else { - output += "%!" + f + "(" + typeof(arg) + "=" + default_format(arg) + ")" - } - - if (o !== null) { - if (o.length < width) { - output += Array(width - o.length + 1).join(pad_char) - } - output += o - } - } - - if (arg_index < arguments.length) { - output += "%!(EXTRA " - while (arg_index < arguments.length) { - var arg = arguments[arg_index] - output += typeof(arg) + "=" + default_format(arg) - if (arg_index < arguments.length - 1) { - output += ", " - } - arg_index++ - } - output += ")" - } - - return output -} - -function init() { - window.requestAnimationFrame(frame) -} - </script> </body> diff --git a/server/terraform.tfvars.example b/server/terraform.tfvars.example deleted file mode 100644 index dc870d733f2c360bb9ccbfec30e286dce809bd6c..0000000000000000000000000000000000000000 --- a/server/terraform.tfvars.example +++ /dev/null @@ -1,5 +0,0 @@ -google_project = "example" - -google_credentials_file = "service-account.json" - -server_image_version = "v1" \ No newline at end of file diff --git a/server/tools/dump_checkpoints/checkpoint_dumper.py b/server/tools/dump_checkpoints/checkpoint_dumper.py new file mode 100644 index 0000000000000000000000000000000000000000..6db211d41daa66489d02d9bc38243bea601a2296 --- /dev/null +++ b/server/tools/dump_checkpoints/checkpoint_dumper.py @@ -0,0 +1,138 @@ +# 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. +# ============================================================================== + +"""This script defines CheckpointDumper class. + +This class serves as a base class for other deeplearning checkpoint dumper +classes and defines common methods, attributes etc. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import json +import os +import re +import string + +class CheckpointDumper(object): + + """Base Checkpoint Dumper class. + + Attributes + ---------- + checkpoint_file : str + Path to the model checkpoint + FILENAME_CHARS : str + Allowed file char names + manifest : dict + Manifest file defining variables + output_dir : str + Output directory path + remove_variables_regex : str + Regex expression for variables to be ignored + remove_variables_regex_re : sre.SRE_Pattern + Compiled `remove variable` regex + """ + + FILENAME_CHARS = string.ascii_letters + string.digits + '_' + + def __init__(self, checkpoint_file, output_dir, remove_variables_regex): + """Constructs object for Checkpoint Dumper. + + Parameters + ---------- + checkpoint_file : str + Path to the model checkpoint + output_dir : str + Output directory path + remove_variables_regex : str + Regex expression for variables to be ignored + """ + self.checkpoint_file = os.path.expanduser(checkpoint_file) + self.output_dir = os.path.expanduser(output_dir) + self.remove_variables_regex = remove_variables_regex + + self.manifest = {} + self.remove_variables_regex_re = re.compile(self.remove_variables_regex) + + self.make_dir(self.output_dir) + + + @staticmethod + def make_dir(directory): + """Makes directory if not existing. + + Parameters + ---------- + directory : str + Path to directory + """ + if not os.path.exists(directory): + os.makedirs(directory) + + + def should_ignore(self, name): + """Checks whether name should be ignored or not. + + Parameters + ---------- + name : str + Name to be checked + + Returns + ------- + bool + Whether to ignore the name or not + """ + return self.remove_variables_regex and re.match(self.remove_variables_regex_re, name) + + + def dump_weights(self, variable_name, filename, shape, weights): + """Creates a file with given name and dumps byte weights in it. + + Parameters + ---------- + variable_name : str + Name of given variable + filename : str + File name for given variable + shape : list + Shape of given variable + weights : ndarray + Weights for given variable + """ + self.manifest[variable_name] = {'filename': filename, 'shape': shape} + + print('Writing variable ' + variable_name + '...') + with open(os.path.join(self.output_dir, filename), 'wb') as f: + f.write(weights.tobytes()) + + + def dump_manifest(self, filename='manifest.json'): + """Creates a manifest file with given name and dumps meta information + related to model. + + Parameters + ---------- + filename : str, optional + Manifest file name + """ + manifest_fpath = os.path.join(self.output_dir, filename) + + print('Writing manifest to ' + manifest_fpath) + with open(manifest_fpath, 'w') as f: + f.write(json.dumps(self.manifest, indent=2, sort_keys=True)) diff --git a/server/tools/dump_checkpoints/dump_checkpoint_vars.py b/server/tools/dump_checkpoints/dump_checkpoint_vars.py new file mode 100644 index 0000000000000000000000000000000000000000..87f999f617e97741f54814d7431cc61d4ce97a5d --- /dev/null +++ b/server/tools/dump_checkpoints/dump_checkpoint_vars.py @@ -0,0 +1,95 @@ +# 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. +# ============================================================================== + +""" +This script is an entry point for dumping checkpoints for various deeplearning +frameworks. +""" +from __future__ import print_function + +import argparse + + +def get_checkpoint_dumper(model_type, checkpoint_file, output_dir, remove_variables_regex): + """Returns Checkpoint dumper instance for a given model type. + + Parameters + ---------- + model_type : str + Type of deeplearning framework + checkpoint_file : str + Path to checkpoint file + output_dir : str + Path to output directory + remove_variables_regex : str + Regex for variables to be ignored + + Returns + ------- + (TensorflowCheckpointDumper, PytorchCheckpointDumper) + Checkpoint Dumper Instance for corresponding model type + + Raises + ------ + Error + If particular model type is not supported + """ + if model_type == 'tensorflow': + from tensorflow_checkpoint_dumper import TensorflowCheckpointDumper + + return TensorflowCheckpointDumper( + checkpoint_file, output_dir, remove_variables_regex) + elif model_type == 'pytorch': + from pytorch_checkpoint_dumper import PytorchCheckpointDumper + + return PytorchCheckpointDumper( + checkpoint_file, output_dir, remove_variables_regex) + else: + raise Error('Currently, "%s" models are not supported'.format(model_type)) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--model_type', + type=str, + required=True, + help='Model checkpoint type') + parser.add_argument( + '--checkpoint_file', + type=str, + required=True, + help='Path to the model checkpoint') + parser.add_argument( + '--output_dir', + type=str, + required=True, + help='The output directory where to store the converted weights') + parser.add_argument( + '--remove_variables_regex', + type=str, + default='', + help='A regular expression to match against variable names that should ' + 'not be included') + FLAGS, unparsed = parser.parse_known_args() + + if unparsed: + parser.print_help() + print('Unrecognized flags: ', unparsed) + exit(-1) + + checkpoint_dumper = get_checkpoint_dumper( + FLAGS.model_type, FLAGS.checkpoint_file, FLAGS.output_dir, FLAGS.remove_variables_regex) + checkpoint_dumper.build_and_dump_vars() diff --git a/server/tools/dump_checkpoints/pytorch_checkpoint_dumper.py b/server/tools/dump_checkpoints/pytorch_checkpoint_dumper.py new file mode 100644 index 0000000000000000000000000000000000000000..e3568da20e23519d943c03bb0d1e7bd268a0059c --- /dev/null +++ b/server/tools/dump_checkpoints/pytorch_checkpoint_dumper.py @@ -0,0 +1,104 @@ +# 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. +# ============================================================================== + +"""This script defines PytorchCheckpointDumper class. + +This class takes a pytorch checkpoint file and writes all of the variables in the +checkpoint to a directory which deeplearnjs can take as input. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from six import iteritems + +import argparse +import os +import re +import json +import string + +import numpy as np + +import torch + +from checkpoint_dumper import CheckpointDumper + +class PytorchCheckpointDumper(CheckpointDumper): + + """Class for dumping Pytorch Checkpoints. + + Attributes + ---------- + state_dictionary : dict + Dictionary defining checkpoint variables and weights + """ + + def __init__(self, checkpoint_file, output_dir, remove_variables_regex): + """Constructs object for Pytorch Checkpoint Dumper. + + Parameters + ---------- + checkpoint_file : str + Path to the model checkpoint + output_dir : str + Output directory path + remove_variables_regex : str + Regex expression for variables to be ignored + """ + super(PytorchCheckpointDumper, self).__init__( + checkpoint_file, output_dir, remove_variables_regex) + + self.state_dictionary = torch.load(self.checkpoint_file) + + def var_name_to_filename(self, var_name): + """Converts variable names to standard file names. + + Parameters + ---------- + var_name : str + Variable name to be converted + + Returns + ------- + str + Standardized file name + """ + chars = [] + + for c in var_name: + if c in CheckpointDumper.FILENAME_CHARS: + chars.append(c) + elif c == '.': + chars.append('_') + + return ''.join(chars) + + def build_and_dump_vars(self): + """Builds and dumps variables and a manifest file. + """ + for (var_name, var_weights) in iteritems(self.state_dictionary): + if (self.should_ignore(var_name)): + print('Ignoring ' + var_name) + continue + + var_filename = self.var_name_to_filename(var_name) + var_shape = list(map(int, list(var_weights.size()))) + tensor = var_weights.cpu().numpy() + + self.dump_weights(var_name, var_filename, var_shape, tensor) + + self.dump_manifest() diff --git a/server/tools/dump_checkpoints/tensorflow_checkpoint_dumper.py b/server/tools/dump_checkpoints/tensorflow_checkpoint_dumper.py new file mode 100644 index 0000000000000000000000000000000000000000..7c95ace1e2f5386db80375d9088b7a3c285972e8 --- /dev/null +++ b/server/tools/dump_checkpoints/tensorflow_checkpoint_dumper.py @@ -0,0 +1,103 @@ +# 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. +# ============================================================================== + +"""This script defines TensorflowCheckpointDumper class. + +This class takes a tensorflow checkpoint file and writes all of the variables in the +checkpoint to a directory which deeplearnjs can take as input. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from six import iteritems + +import argparse +import json +import os +import re + +import tensorflow as tf + +from checkpoint_dumper import CheckpointDumper + +class TensorflowCheckpointDumper(CheckpointDumper): + + """Class for dumping Tensorflow Checkpoints. + + Attributes + ---------- + reader : NewCheckpointReader + Reader for given tensorflow checkpoint + """ + + def __init__(self, checkpoint_file, output_dir, remove_variables_regex): + """Constructs object for Tensorflow Checkpoint Dumper. + + Parameters + ---------- + checkpoint_file : str + Path to the model checkpoint + output_dir : str + Output directory path + remove_variables_regex : str + Regex expression for variables to be ignored + """ + super(TensorflowCheckpointDumper, self).__init__( + checkpoint_file, output_dir, remove_variables_regex) + + self.reader = tf.train.NewCheckpointReader(self.checkpoint_file) + + def var_name_to_filename(self, var_name): + """Converts variable names to standard file names. + + Parameters + ---------- + var_name : str + Variable name to be converted + + Returns + ------- + str + Standardized file name + """ + chars = [] + + for c in var_name: + if c in CheckpointDumper.FILENAME_CHARS: + chars.append(c) + elif c == '/': + chars.append('_') + + return ''.join(chars) + + def build_and_dump_vars(self): + """Builds and dumps variables and a manifest file. + """ + var_to_shape_map = self.reader.get_variable_to_shape_map() + + for (var_name, var_shape) in iteritems(var_to_shape_map): + if self.should_ignore(var_name) or var_name == 'global_step': + print('Ignoring ' + var_name) + continue + + var_filename = self.var_name_to_filename(var_name) + self.manifest[var_name] = {'filename': var_filename, 'shape': var_shape} + + tensor = self.reader.get_tensor(var_name) + self.dump_weights(var_name, var_filename, var_shape, tensor) + + self.dump_manifest() diff --git a/server/tools/export-checkpoint.py b/server/tools/export-checkpoint.py new file mode 100644 index 0000000000000000000000000000000000000000..253e421286d8aff82ec4519d2ef7e50e03a9f8ab --- /dev/null +++ b/server/tools/export-checkpoint.py @@ -0,0 +1,101 @@ +import argparse +import os +import tempfile +import subprocess as sp +import json +import struct +import time + +import numpy as np + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + + +def log_quantize(data, mu, bins): + # mu-law encoding + scale = np.max(np.abs(data)) + norm_data = data / scale + log_data = np.sign(data) * np.log(1 + mu * np.abs(norm_data)) / np.log(1 + mu) + + _counts, edges = np.histogram(log_data, bins=bins) + log_points = (edges[:-1] + edges[1:]) / 2 + return np.sign(log_points) * (1 / mu) * ((1 + mu)**np.abs(log_points) - 1) * scale + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--checkpoint", required=True, help="directory with checkpoint to resume training from or use for testing") + parser.add_argument("--output_file", required=True, help="where to write output") + args = parser.parse_args() + + model_path = None + with open(os.path.join(args.checkpoint, "checkpoint")) as f: + for line in f: + line = line.strip() + if line == "": + continue + key, _sep, val = line.partition(": ") + val = val[1:-1] # remove quotes + if key == "model_checkpoint_path": + model_path = val + + if model_path is None: + raise Exception("failed to find model path") + + checkpoint_file = os.path.join(args.checkpoint, model_path) + with tempfile.TemporaryDirectory() as tmp_dir: + cmd = ["python", "-u", os.path.join(SCRIPT_DIR, "dump_checkpoints/dump_checkpoint_vars.py"), "--model_type", "tensorflow", "--output_dir", tmp_dir, "--checkpoint_file", checkpoint_file] + sp.check_call(cmd) + + with open(os.path.join(tmp_dir, "manifest.json")) as f: + manifest = json.loads(f.read()) + + names = [] + for key in manifest.keys(): + if not key.startswith("generator") or "Adam" in key or "_loss" in key or "_train" in key or "_moving_" in key: + continue + names.append(key) + names = sorted(names) + + arrays = [] + for name in names: + value = manifest[name] + with open(os.path.join(tmp_dir, value["filename"]), "rb") as f: + arr = np.frombuffer(f.read(), dtype=np.float32).copy().reshape(value["shape"]) + arrays.append(arr) + + shapes = [] + for name, arr in zip(names, arrays): + shapes.append(dict( + name=name, + shape=arr.shape, + )) + + flat = np.hstack([arr.reshape(-1) for arr in arrays]) + + start = time.time() + index = log_quantize(flat, mu=255, bins=256).astype(np.float32) + print("index found in %0.2fs" % (time.time() - start)) + + print("quantizing") + encoded = np.zeros(flat.shape, dtype=np.uint8) + elem_count = 0 + for i, x in enumerate(flat): + distances = np.abs(index - x) + nearest = np.argmin(distances) + encoded[i] = nearest + elem_count += 1 + if elem_count % 1000000 == 0: + print("rate", int(elem_count / (time.time() - start))) + + with open(args.output_file, "wb") as f: + def write(name, buf): + print("%s bytes %d" % (name, len(buf))) + f.write(struct.pack(">L", len(buf))) + f.write(buf) + + write("shape", json.dumps(shapes).encode("utf8")) + write("index", index.tobytes()) + write("encoded", encoded.tobytes()) + +main() \ No newline at end of file diff --git a/server/tools/export-example-model.py b/server/tools/export-example-model.py deleted file mode 100644 index 92997fdda698a734d0ce72cca008fdba565bb94e..0000000000000000000000000000000000000000 --- a/server/tools/export-example-model.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import tensorflow as tf -import json -import os -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument("--output_dir", required=True, help="directory to put exported model in") -a = parser.parse_args() - - -def main(): - if not os.path.exists(a.output_dir): - os.makedirs(a.output_dir) - - input = tf.placeholder(tf.string, shape=[1]) - key = tf.placeholder(tf.string, shape=[1]) - - in_data = tf.decode_base64(input[0]) - img = tf.image.decode_png(in_data) - img = tf.image.rgb_to_grayscale(img) - out_data = tf.image.encode_png(img) - output = tf.convert_to_tensor([tf.encode_base64(out_data)]) - - variable_to_allow_model_saving = tf.Variable(1, dtype=tf.float32) - - inputs = { - "key": key.name, - "input": input.name - } - tf.add_to_collection("inputs", json.dumps(inputs)) - outputs = { - "key": tf.identity(key).name, - "output": output.name, - } - tf.add_to_collection("outputs", json.dumps(outputs)) - - init_op = tf.global_variables_initializer() - with tf.Session() as sess: - sess.run(init_op) - saver = tf.train.Saver() - saver.export_meta_graph(filename=os.path.join(a.output_dir, "export.meta")) - saver.save(sess, os.path.join(a.output_dir, "export"), write_meta_graph=False) - - print("exported example model to %s" % a.output_dir) - -main() diff --git a/server/tools/process-cloud.py b/server/tools/process-cloud.py deleted file mode 100644 index 4f0c9396c098580335475fb3aa06ff8896d3ad9e..0000000000000000000000000000000000000000 --- a/server/tools/process-cloud.py +++ /dev/null @@ -1,44 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import argparse -import json -import base64 -import oauth2client.service_account -import googleapiclient.discovery - - -parser = argparse.ArgumentParser() -parser.add_argument("--model_name", required=True, help="name of Cloud Machine Learning model") -parser.add_argument("--input_file", required=True, help="input PNG image file") -parser.add_argument("--output_file", required=True, help="output PNG image file") -parser.add_argument("--credentials", required=True, help="JSON credentials for a Google Cloud Platform service account") -a = parser.parse_args() - -scopes = ["https://www.googleapis.com/auth/cloud-platform"] -credentials = oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name(a.credentials, scopes) -ml = googleapiclient.discovery.build("ml", "v1beta1", credentials=credentials) - - -def main(): - with open(a.credentials) as f: - project_id = json.loads(f.read())["project_id"] - - with open(a.input_file) as f: - input_data = f.read() - - input_instance = dict(input=base64.urlsafe_b64encode(input_data), key="0") - input_instance = json.loads(json.dumps(input_instance)) - request = ml.projects().predict(name="projects/" + project_id + "/models/" + a.model_name, body={"instances": [input_instance]}) - response = request.execute() - output_instance = json.loads(json.dumps(response["predictions"][0])) - - b64data = output_instance["output"].encode("ascii") - b64data += "=" * (-len(b64data) % 4) - output_data = base64.urlsafe_b64decode(b64data) - - with open(a.output_file, "w") as f: - f.write(output_data) - -main() \ No newline at end of file diff --git a/server/tools/process-local.py b/server/tools/process-local.py deleted file mode 100644 index 269096cbe0425d4da1cdca2e7c450966f6ab0d60..0000000000000000000000000000000000000000 --- a/server/tools/process-local.py +++ /dev/null @@ -1,45 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import tensorflow as tf -import numpy as np -import argparse -import json -import base64 - - -parser = argparse.ArgumentParser() -parser.add_argument("--model_dir", required=True, help="directory containing exported model") -parser.add_argument("--input_file", required=True, help="input PNG image file") -parser.add_argument("--output_file", required=True, help="output PNG image file") -a = parser.parse_args() - -def main(): - with open(a.input_file, "rb") as f: - input_data = f.read() - - input_instance = dict(input=base64.urlsafe_b64encode(input_data).decode("ascii"), key="0") - input_instance = json.loads(json.dumps(input_instance)) - - with tf.Session() as sess: - saver = tf.train.import_meta_graph(a.model_dir + "/export.meta") - saver.restore(sess, a.model_dir + "/export") - input_vars = json.loads(tf.get_collection("inputs")[0]) - output_vars = json.loads(tf.get_collection("outputs")[0]) - input = tf.get_default_graph().get_tensor_by_name(input_vars["input"]) - output = tf.get_default_graph().get_tensor_by_name(output_vars["output"]) - - input_value = np.array(input_instance["input"]) - output_value = sess.run(output, feed_dict={input: np.expand_dims(input_value, axis=0)})[0] - - output_instance = dict(output=output_value.decode("ascii"), key="0") - - b64data = output_instance["output"] - b64data += "=" * (-len(b64data) % 4) - output_data = base64.urlsafe_b64decode(b64data.encode("ascii")) - - with open(a.output_file, "wb") as f: - f.write(output_data) - -main() diff --git a/server/tools/process-remote.py b/server/tools/process-remote.py deleted file mode 100644 index 870472f3e327c9a5a8f7c7902b88fd935c86c4a2..0000000000000000000000000000000000000000 --- a/server/tools/process-remote.py +++ /dev/null @@ -1,28 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -try: - from urllib.request import urlopen # python 3 -except ImportError: - from urllib2 import urlopen # python 2 -import argparse - - -parser = argparse.ArgumentParser() -parser.add_argument("--input_file", required=True, help="input PNG image file") -parser.add_argument("--url", required=True, help="url to use for processing") -parser.add_argument("--output_file", required=True, help="output PNG image file") -a = parser.parse_args() - - -def main(): - with open(a.input_file, "rb") as f: - input_data = f.read() - - output_data = urlopen(a.url, data=input_data).read() - - with open(a.output_file, "wb") as f: - f.write(output_data) - -main() diff --git a/server/tools/rolling-update.py b/server/tools/rolling-update.py deleted file mode 100644 index c483cf92b6026e47f9f7d46d8c48e58d8dafd35f..0000000000000000000000000000000000000000 --- a/server/tools/rolling-update.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import subprocess -import json - - -def main(): - output = subprocess.check_output("gcloud compute instance-groups managed list-instances pix2pix-manager --zone us-central1-c --format json", shell=True) - instances = json.loads(output) - for i, instance in enumerate(instances): - name = instance["instance"].split("/")[-1] - print("recreating %s (%d/%d)" % (name, i+1, len(instances))) - subprocess.check_call("gcloud compute instance-groups managed recreate-instances pix2pix-manager --zone us-central1-c --instances " + name, shell=True) - subprocess.check_call("gcloud compute instance-groups managed wait-until-stable pix2pix-manager --zone us-central1-c", shell=True) - -main() \ No newline at end of file diff --git a/server/tools/upload-image.py b/server/tools/upload-image.py deleted file mode 100644 index 358465396105acc403f26123fe4b89646309dad7..0000000000000000000000000000000000000000 --- a/server/tools/upload-image.py +++ /dev/null @@ -1,22 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import argparse -import subprocess - -parser = argparse.ArgumentParser() -parser.add_argument("--version", required=True, help="version to build") -parser.add_argument("--project", required=True, help="Google Cloud Project to use") -a = parser.parse_args() - -def main(): - version_tag = "us.gcr.io/%s/pix2pix-server:%s" % (a.project, a.version) - latest_tag = "us.gcr.io/%s/pix2pix-server:latest" % (a.project) - - subprocess.check_call("docker build --tag %s ." % version_tag, shell=True) - subprocess.check_call("docker tag %s %s" % (version_tag, latest_tag), shell=True) - for tag in [version_tag, latest_tag]: - subprocess.check_call("gcloud docker -- push %s" % tag, shell=True) - -main() diff --git a/server/tools/upload-model.py b/server/tools/upload-model.py deleted file mode 100644 index ff10bcac982553e753331c29795fd782ab130be0..0000000000000000000000000000000000000000 --- a/server/tools/upload-model.py +++ /dev/null @@ -1,101 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import argparse -import json -import os -import time -import sys -import base64 -import oauth2client.service_account -import googleapiclient.discovery -import google.cloud.storage - - -parser = argparse.ArgumentParser() -parser.add_argument("--bucket", required=True, help="Google Cloud Storage bucket to upload to") -parser.add_argument("--model_name", required=True, help="name of Google Cloud Machine Learning model to create or update") -parser.add_argument("--model_dir", required=True, help="path to directory containing exported model") -parser.add_argument("--runtime_version", default="0.12", help="tensorflow version to use for the model") -parser.add_argument("--credentials", help="JSON credentials for a Google Cloud Platform service account") -parser.add_argument("--project", help="Google Cloud Project to use to override project detection") -a = parser.parse_args() - -scopes = ["https://www.googleapis.com/auth/cloud-platform"] -if a.credentials is None: - credentials = oauth2client.client.GoogleCredentials.get_application_default() - storage = google.cloud.storage.Client() - project_id = storage.project - if a.project is not None: - project_id = a.project -else: - credentials = oauth2client.service_account.ServiceAccountCredentials.from_json_keyfile_name(a.credentials, scopes) - with open(a.credentials) as f: - project_id = json.loads(f.read())["project_id"] - storage = google.cloud.storage.Client.from_service_account_json(a.credentials, project=project_id) - -ml = googleapiclient.discovery.build("ml", "v1beta1", credentials=credentials) - - -def main(): - try: - bucket = storage.get_bucket(a.bucket) - except google.cloud.exceptions.NotFound as e: - print("creating bucket %s" % a.bucket) - bucket = storage.create_bucket(a.bucket) - - project_path = "projects/%s" % project_id - model_path = "%s/models/%s" % (project_path, a.model_name) - - try: - ml.projects().models().get(name=model_path).execute() - except googleapiclient.errors.HttpError as e: - if e.resp["status"] != "404": - raise - print("creating model %s" % a.model_name) - ml.projects().models().create(parent=project_path, body=dict(name=a.model_name)).execute() - - version_number = 0 - resp = ml.projects().models().versions().list(parent=model_path).execute() - for version in resp.get("versions", []): - name = version["name"] - number = int(name.split("/")[-1][1:]) - if number > version_number: - version_number = number - - version_number += 1 - print("creating version v%d" % version_number) - - for filename in os.listdir(a.model_dir): - if not filename.startswith("export.") and filename != "checkpoint": - continue - - print("uploading", filename) - filepath = os.path.join(a.model_dir, filename) - blob = bucket.blob("%s-v%d/%s" % (a.model_name, version_number, filename)) - blob.upload_from_filename(filepath) - - version_path = "%s/versions/v%d" % (model_path, version_number) - version = dict( - name="v%d" % version_number, - runtimeVersion=a.runtime_version, - deploymentUri="gs://%s/%s-v%d/" % (a.bucket, a.model_name, version_number), - ) - operation = ml.projects().models().versions().create(parent=model_path, body=version).execute() - - sys.stdout.write("waiting for creation to finish") - while True: - operation = ml.projects().operations().get(name=operation["name"]).execute() - if "done" in operation and operation["done"]: - break - sys.stdout.write(".") - sys.stdout.flush() - time.sleep(10) - print() - - print("setting version %d as default" % version_number) - ml.projects().models().versions().setDefault(name=version_path, body=dict()).execute() - - -main() \ No newline at end of file diff --git a/tools/dockrun.py b/tools/dockrun.py index b3e8d473cc36a0909ea6b769528af8de221ef329..594af1fe9e7829aa81554bce94b30f06eeadbde4 100644 --- a/tools/dockrun.py +++ b/tools/dockrun.py @@ -4,10 +4,7 @@ from __future__ import print_function import os import sys -import argparse - -parser = argparse.ArgumentParser() -parser.add_argument("--port", type=int, help="port to publish from the container") +import shlex # from python 3.3 source # https://github.com/python/cpython/blob/master/Lib/shutil.py @@ -73,21 +70,13 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None): def main(): - args = sys.argv[1:] - i = 0 - while i < len(args): - if not args[i].startswith("--"): - break - i += 2 - - a = parser.parse_args(args[:i]) - cmd = args[i:] + cmd = sys.argv[1:] # check if nvidia-docker or docker are on path docker_path = which("nvidia-docker") if docker_path is None: docker_path = which("docker") - + if docker_path is None: raise Exception("docker not found") @@ -103,14 +92,15 @@ def main(): "CUDA_CACHE_PATH=/host/tmp/cuda-cache", ] - if a.port is not None: - docker_args += ["--publish", "%d:%d" % (a.port, a.port)] + if "CUDA_VISIBLE_DEVICES" in os.environ: + docker_args.extend(["--env", "CUDA_VISIBLE_DEVICES=%s" % os.environ["CUDA_VISIBLE_DEVICES"]]) - args = [docker_path, "run"] + docker_args + ["affinelayer/pix2pix-tensorflow:v2"] + cmd + args = [docker_path, "run"] + docker_args + ["affinelayer/pix2pix-tensorflow:v3"] + cmd if not os.access("/var/run/docker.sock", os.R_OK): args = ["sudo"] + args + print("running", " ".join(shlex.quote(a) for a in args)) os.execvp(args[0], args) diff --git a/tools/test.py b/tools/test.py index ba6fe86d8e2cf520680245f8f06a4645b70c3068..d31afa88c6f6e8755a07bb94441ff16e692ba091 100644 --- a/tools/test.py +++ b/tools/test.py @@ -6,61 +6,58 @@ import subprocess import os import sys import time -import argparse +import shutil +import shlex +INPUT_DIR = os.path.abspath("../data") +OUTPUT_DIR = os.path.expanduser("~/data/pix2pix/test") -parser = argparse.ArgumentParser() -parser.add_argument("--long", action="store_true") -a = parser.parse_args() +def main(): + start = time.time() -def run(cmd, image="affinelayer/pix2pix-tensorflow"): - docker = "docker" - if sys.platform.startswith("linux"): - docker = "nvidia-docker" + images = { + "affinelayer": "affinelayer/pix2pix-tensorflow:v3", + # "py2-tensorflow": "tensorflow/tensorflow:1.4.1-gpu", + # "py3-tensorflow": "tensorflow/tensorflow:1.4.1-gpu-py3", + } - datapath = os.path.abspath("../data") - prefix = [docker, "run", "--rm", "--volume", os.getcwd() + ":/prj", "--volume", datapath + ":/data", "--workdir", "/prj", "--env", "PYTHONUNBUFFERED=x", "--volume", "/tmp/cuda-cache:/cuda-cache", "--env", "CUDA_CACHE_PATH=/cuda-cache", image] - args = prefix + cmd.split(" ") - print(" ".join(args)) - subprocess.check_call(args) + if os.path.exists(OUTPUT_DIR): + shutil.rmtree(OUTPUT_DIR) + for image_name, image in images.items(): + def run(cmd): + docker = "docker" + if sys.platform.startswith("linux"): + docker = "nvidia-docker" -def main(): - start = time.time() + prefix = [docker, "run", "--rm", "--volume", os.getcwd() + ":/prj", "--volume", INPUT_DIR + ":/input", "--volume", os.path.join(OUTPUT_DIR, image_name) + ":/output","--workdir", "/prj", "--env", "PYTHONUNBUFFERED=x", "--volume", "/tmp/cuda-cache:/cuda-cache", "--env", "CUDA_CACHE_PATH=/cuda-cache", image] + args = prefix + shlex.split(cmd) + print(" ".join(args)) + subprocess.check_call(args) - if a.long: - run("python pix2pix.py --mode train --output_dir test/facades_BtoA_train --max_epochs 200 --input_dir /data/official/facades/train --which_direction BtoA --seed 0") - run("python pix2pix.py --mode test --output_dir test/facades_BtoA_test --input_dir /data/official/facades/val --seed 0 --checkpoint test/facades_BtoA_train") + run("python tools/process.py --input_dir /input/pusheen/original --operation resize --output_dir /output/process_resize") + if image_name == "affinelayer": + run("python tools/process.py --input_dir /output/process_resize --operation edges --output_dir /output/process_edges") - run("python pix2pix.py --mode train --output_dir test/color-lab_AtoB_train --max_epochs 10 --input_dir /data/color-lab/train --which_direction AtoB --seed 0 --lab_colorization") - run("python pix2pix.py --mode test --output_dir test/color-lab_AtoB_test --input_dir /data/color-lab/val --seed 0 --checkpoint test/color-lab_AtoB_train") - else: - # training for direction in ["AtoB", "BtoA"]: - for dataset in ["facades"]: + for dataset in ["facades", "maps"]: name = dataset + "_" + direction - run("python pix2pix.py --mode train --output_dir test/%s_train --max_steps 1 --input_dir /data/official/%s/train --which_direction %s --seed 0" % (name, dataset, direction)) - run("python pix2pix.py --mode test --output_dir test/%s_test --max_steps 1 --input_dir /data/official/%s/val --seed 0 --checkpoint test/%s_train" % (name, dataset, name)) + run("python pix2pix.py --mode train --input_dir /input/official/%s/train --output_dir /output/%s_train --display_freq 1 --max_steps 1 --which_direction %s --seed 0" % (dataset, name, direction)) + run("python pix2pix.py --mode test --input_dir /input/official/%s/val --output_dir /output/%s_test --display_freq 1 --max_steps 1 --checkpoint /output/%s_train --seed 0" % (dataset, name, name)) - # test lab colorization dataset = "color-lab" name = dataset + "_" + direction - run("python pix2pix.py --mode train --output_dir test/%s_train --max_steps 1 --input_dir /data/%s/train --which_direction %s --seed 0 --lab_colorization" % (name, dataset, direction)) - run("python pix2pix.py --mode test --output_dir test/%s_test --max_steps 1 --input_dir /data/%s/val --seed 0 --checkpoint test/%s_train" % (name, dataset, name)) + run("python pix2pix.py --mode train --input_dir /input/%s/train --output_dir /output/%s_train --display_freq 1 --max_steps 1 --which_direction %s --lab_colorization --seed 0" % (dataset, name, direction)) + run("python pix2pix.py --mode test --input_dir /input/%s/val --output_dir /output/%s_test --display_freq 1 --max_steps 1 --checkpoint /output/%s_train --seed 0" % (dataset, name, name)) - # using pretrained model (can't use pretrained models from tensorflow 0.12, so disabled for now) + # using pretrained model # for dataset, direction in [("facades", "BtoA")]: # name = dataset + "_" + direction - # run("python pix2pix.py --mode test --output_dir test/%s_pretrained_test --input_dir /data/official/%s/val --max_steps 100 --which_direction %s --seed 0 --checkpoint /data/pretrained/%s" % (name, dataset, direction, name)) - # run("python pix2pix.py --mode export --output_dir test/%s_pretrained_export --checkpoint /data/pretrained/%s" % (name, name)) - - # test python3 - run("python pix2pix.py --mode train --output_dir test/py3_facades_AtoB_train --max_steps 1 --input_dir /data/official/facades/train --which_direction AtoB --seed 0", image="tensorflow/tensorflow:1.0.0-gpu-py3") - run("python pix2pix.py --mode test --output_dir test/py3_facades_AtoB_test --max_steps 1 --input_dir /data/official/facades/val --seed 0 --checkpoint test/py3_facades_AtoB_train", image="tensorflow/tensorflow:1.0.0-gpu-py3") + # run("python pix2pix.py --mode test --output_dir test/%s_pretrained_test --input_dir /input/official/%s/val --max_steps 100 --which_direction %s --seed 0 --checkpoint /input/pretrained/%s" % (name, dataset, direction, name)) + # run("python pix2pix.py --mode export --output_dir test/%s_pretrained_export --checkpoint /input/pretrained/%s" % (name, name)) print("elapsed", int(time.time() - start)) - # long: about 9 hours (linux) main()