async predict(inputData) {
    this.isRunning = true
    this.runningProgress = 0
    this.events.emit('predictProgress', 0)

    if (!_.isEqual(_.keys(inputData).sort(), this.inputLayerNames)) {
      this.isRunning = false
      throw new Error(
        '[Model] predict() must take an object where the keys are the named inputs of the model: ' +
          JSON.stringify(this.inputLayerNames)
      )
    }
    if (!_.every(this.inputLayerNames, name => inputData[name] instanceof Float32Array)) {
      this.isRunning = false
      throw new Error('[Model] predict() must take an object where the values are the flattened data as Float32Array.')
    }

    // reset hasOutput and visited flags in all layers
    this.finishedLayerNames = []
    this.modelLayersMap.forEach(layer => {
      layer.hasOutput = false
      layer.visited = false
    })

    // load data to input tensors
    let start = now()
    this.loadData(inputData)
    this.predictStats.loadData = now() - start

    // start traversing DAG at inputs
    start = now()
    await this._traverseDAG(this.inputLayerNames, 'predictProgress')
    this.predictStats.forwardPass = now() - start

    // transfer intermediate outputs if specified
    this._maybeTransferIntermediateOutputs()

    // outputs are layers with no outbound nodes
    const modelClass = this.modelConfig.class_name
    const outputData = {}
    if (modelClass === 'Sequential') {
      const outputLayer = this.modelLayersMap.get(this.outputLayerNames[0])
      outputData['output'] = outputLayer.output.tensor.data
    } else if (modelClass === 'Model') {
      this.outputLayerNames.forEach(layerName => {
        const outputLayer = this.modelLayersMap.get(layerName)
        outputData[layerName] = outputLayer.output.tensor.data
      })
    }

    // update visualizations
    start = now()
    this.visMap.forEach(visInstance => {
      visInstance.update()
    })
    this.predictStats.visualizations = now() - start

    this.isRunning = false
    this.events.emit('predictProgress', 100)
    return outputData
  }
Predict

@param {Object} inputData - object where the keys are the named inputs of the model,
and values the TypedArray numeric data
@returns {Promise} - outputData object where the keys are the named outputs of the model,
and values the TypedArray numeric data