From 97cb1ff79346103f672148fbac793b262d123ff4 Mon Sep 17 00:00:00 2001 From: fengwuyao <131706622+fengwuyao@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:21:25 -0700 Subject: [PATCH] [Layers] Update weights loading for keras v3. (#7761) * Support Keras V3 Conversion * Add script to mapping TFJS classes with TF modules This reverts commit 3bd7e8fb681095500caaf742a5e8220f5ca9cc2b. * Put into another branch * Script for building the map Draft a script for build map of TFJS class and TF module path. * Add tfjs to v3 converter * Rename the file * Merge remote-tracking branch 'upstream/master' into V3ScriptForMapping * Improve the code snippet for texture to tensor (#7694) DOC * Improve example * add * Fix tfjs-release not updating all tfjs versions of subpackages (#7550) Some TFJS packages, like wasm, have examples or demos in them. These usually depend on the parent package, but the parent package is not marked as to be updated when updating the subpackage dependency versions. For an example of this, see #7547. Update the TFJS dependencies of these subpackages to the release version if they are `link:` dependencies. * [wasm] Fix cos and tan for large float numbers (#7689) * Fix sin/cos workaround * Add tests for large numbers * Fix tan * Exclude new tests in webgl and webgpu * Fix * Exclude tests in tfjs-node * Update * Fix * Fix * Fix * Remove comments * [wasm] Update xnnpack (#7507) * wip * Add xnn_caches * Upgrade xnnpack * exp * Update xnnpack deps * Fix xnn cache * TEST * Cleanup * Cleanup * Cleanup * Update xnnpack * Add flag to avoid unused function * Add comment * Add config to turn xnnpack logs off * Add sha256 for emsdk * Update xnnpack and toolchain, and disable xnn caches * Fix lint * Remove unused include * Recover the default backend (#7709) * Do not throw an error when killing the verdaccio process (#7695) Killing the verdaccio process throws an error because the disconnect event emits when the process is killed. We throw an error on a disconnect to catch any unexpected verdaccio disconnections. Fix this by deregistering the disconnect handler before killing the verdaccio process. * webgpu: Optimize SpaceToBatchND (#7703) * webgpu: Optimize SpaceToBatchND Fuse pad and transpose to one shader. See 20% improvement for SpaceToBatchND in DeepLabV3 * webgpu: Replace timestamp-query-in-passes with timestamp-query (#7714) * webgpu: Replace timestamp-query-in-passes with timestamp-query Timestamp-query has a broader support than timestamp-query-in-passes on all platforms, including macOS. Note that Chrome switch '--disable-dawn-features=disallow_unsafe_apis' is still needed now as the timestamp has the accuracy of nanosecond, which is too accurate to be safe. Later changes in Chrome may lift this limitation. * webgpu: Fix timestamp query (#7723) If a pass that needs timestamp query follows a pass without timestamp query, querySet may not be created as expected. This PR fixes this issue. * webgpu: Move the readSync warning position (#7724) The warning should only happen when there is real data reading from gpu to cpu. * Fix indexeddb for 1GB models (#7725) * Fix indexeddb for 1GB models Fixes #7702 by concatenating model weights into a single ArrayBuffer before sending them to IndexedDB. A better solution would be to store the model as multiple records, but this quick fix is easy to implement solves the issue for most current models (~1GB). * Use CompositeArrayBuffer.join * Add npmVersion command line argument to benchmark NPM versions (#7674) * npmVersion CLIarg * add readme description --------- Co-authored-by: Linchenn <40653845+Linchenn@users.noreply.github.com> Co-authored-by: Matthew Soulanille * Migrate stale management probot to Github action. (#7570) Update the workflow file to replace 'stale-master' probot with a github action. It will add 'stale' label to inactive issues/PRs if contains 'stat:awaiting response' label in case of further inactivity it will close the issue with proper comment. * Fix getLayer() API (#7665) * Fix getLayer() API * Apply suggested changes * Script for building the map Draft a script for build map of TFJS class and TF module path. * build(deps): bump socket.io-parser from 4.2.2 to 4.2.4 in /tfjs-vis (#7731) Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 4.2.2 to 4.2.4. - [Release notes](https://github.com/socketio/socket.io-parser/releases) - [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md) - [Commits](https://github.com/socketio/socket.io-parser/compare/4.2.2...4.2.4) --- updated-dependencies: - dependency-name: socket.io-parser dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matthew Soulanille * build(deps): bump socket.io-parser from 4.2.1 to 4.2.4 in /tfjs-automl (#7730) Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 4.2.1 to 4.2.4. - [Release notes](https://github.com/socketio/socket.io-parser/releases) - [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md) - [Commits](https://github.com/socketio/socket.io-parser/compare/4.2.1...4.2.4) --- updated-dependencies: - dependency-name: socket.io-parser dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump socket.io-parser from 4.2.1 to 4.2.4 in /tfjs (#7729) Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 4.2.1 to 4.2.4. - [Release notes](https://github.com/socketio/socket.io-parser/releases) - [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md) - [Commits](https://github.com/socketio/socket.io-parser/compare/4.2.1...4.2.4) --- updated-dependencies: - dependency-name: socket.io-parser dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [webgpu] More preparation for element-wise binary op restructuring (#7666) The current code isn't great in that the vec4 shaders have diverged from the scalar ones more than necessary. Here is the common preparation work, so that following refactoring can be done on a per-op basis. * Revert "[wasm] Update xnnpack (#7507)" (#7735) This reverts commit c66f302ea5e8b16da55283688e47e303e4590d60. * Github token (#7734) * Github token * Github token * Github token Github token * Apply suggestions from code review Co-authored-by: Matthew Soulanille --------- Co-authored-by: Matthew Soulanille * [webgpu] Update ADD,COMPLEX_MULTIPLY_*,DIV,MUL,SQUARED_DIFFERENCE,SUB (#7737) * Add register name when register the class object (#7717) * Save model * Support Keras V3 Conversion * Run yarn before running the release e2e tests (#7687) * Registered name prototype * Update register class method to support registered name * Revert "Support Keras V3 Conversion" This reverts commit 3bd7e8fb681095500caaf742a5e8220f5ca9cc2b. * revert converter changes * Apply suggested changes * Apply suggested changes * Fix lint * fix lint * Remove throw errors --------- Co-authored-by: Matthew Soulanille * Rename the file * Merge remote-tracking branch 'upstream/master' into V3ScriptForMapping * move script location * Merge branch 'V3ScriptForMapping' into SupportV3 * Add v3 conversion functions in converter * Fix some nit * Merge branch 'SupportV3' into AddE2ETestForV3 * remove unused import * remove blank * fix import * fix import * Add tests for the mapper and rename the files * update import * fix store path * resolve comments * Update license and remove build_map() function * use private function * remove build_map() usage since script has been updated. * Merge branch 'V3ScriptForMapping' into SupportV3 Update the loadWeights() to support weights loading in for keras v3 format. * add exception * Update the build file * add module mapper into build file * Remove unused functions. * Merge branch 'SupportV3' into loadModelV3 * remove comments * fix lint * build(deps-dev): bump semver from 7.3.7 to 7.5.2 (#7779) Bumps [semver](https://github.com/npm/node-semver) from 7.3.7 to 7.5.2. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v7.3.7...v7.5.2) --- updated-dependencies: - dependency-name: semver dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update README.md (#7763) * Update README.md (#7762) * Polyfill string.matchAll to unblock #7770 (#7776) Manually write a polyfill for string.matchAll to unblock #7770. This should be replaced with core-js in the future. * Update tf.data hyperlink in README.md (#7777) Co-authored-by: Ping Yu <4018+pyu10055@users.noreply.github.com> * fix lint * remove blank * fix naming * Merge remote-tracking branch 'upstream/master' into loadModelV3 --------- Signed-off-by: dependabot[bot] Co-authored-by: Linchenn <40653845+Linchenn@users.noreply.github.com> Co-authored-by: Matthew Soulanille Co-authored-by: Chunnien Chan <121328115+chunnienc@users.noreply.github.com> Co-authored-by: Jiajia Qin Co-authored-by: Yang Gu Co-authored-by: wrighkv1 Co-authored-by: Shivam Mishra <124146945+shmishra99@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jiajie Hu Co-authored-by: Dedongala <133151251+Dedongala@users.noreply.github.com> Co-authored-by: Matthew Soulanille Co-authored-by: gaikwadrahul8 <115997457+gaikwadrahul8@users.noreply.github.com> Co-authored-by: Ping Yu <4018+pyu10055@users.noreply.github.com> --- tfjs-layers/src/engine/container.ts | 18 ++++++++++++++---- tfjs-layers/src/engine/topology_test.ts | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/tfjs-layers/src/engine/container.ts b/tfjs-layers/src/engine/container.ts index 088c774dc83..f6d1d74508a 100644 --- a/tfjs-layers/src/engine/container.ts +++ b/tfjs-layers/src/engine/container.ts @@ -594,12 +594,22 @@ export abstract class Container extends Layer { loadWeights(weights: NamedTensorMap, strict = true) { const nameToWeight: {[name: string]: LayerVariable} = {}; let totalWeightsCount = 0; + // get weights key from tensor map in order to check if it is from keras v3. + // e.g. dense/0 + const key = Object.keys(weights)[0].split('/'); + const isKerasSavedModelFormat = !isNaN(parseInt(key[key.length - 1], 10)); + // Check if weights from keras v3. for (const layer of this.layers) { - for (const weight of layer.weights) { - if (nameToWeight[weight.originalName] != null) { - throw new ValueError(`Duplicate weight name: ${weight.originalName}`); + for (const [index, weight] of layer.weights.entries()) { + // Parse the name to layerName/index. + // e.g. dense/0, dense/1, dense_1/0, dense_1/1 + const parsedName = isKerasSavedModelFormat ? + `${weight.name.split('/').slice(0, -1).join('/') + '/'}${index}` : + weight.originalName; + if (nameToWeight[parsedName] != null) { + throw new ValueError(`Duplicate weight name: ${parsedName}`); } - nameToWeight[weight.originalName] = weight; + nameToWeight[parsedName] = weight; totalWeightsCount++; } } diff --git a/tfjs-layers/src/engine/topology_test.ts b/tfjs-layers/src/engine/topology_test.ts index 0b7260ddb43..eaa93449eaf 100644 --- a/tfjs-layers/src/engine/topology_test.ts +++ b/tfjs-layers/src/engine/topology_test.ts @@ -1087,6 +1087,23 @@ describeMathCPUAndGPU('loadWeightsFromNamedTensorMap', () => { expectTensorsClose(denseLayer.weights[1].read(), tensor1d([10, 20])); }); + it('load keras weights', () => { + const denseLayer = + tfl.layers.dense({units: 2, useBias: true, name: 'dense_layer'}); + const output = denseLayer.apply(inputTensor) as SymbolicTensor; + const model = tfl.model({inputs: inputTensor, outputs: output}); + + const namedWeightsMap: NamedTensorMap = {}; + namedWeightsMap[denseLayer.weights[0].originalName.split('/')[0] + '/0'] = + tensor2d([1, 2, 3, 4, 5, 6], [3, 2]); + namedWeightsMap[denseLayer.weights[1].originalName.split('/')[0] + '/1'] = + tensor1d([10, 20]); + model.loadWeights(namedWeightsMap); + expectTensorsClose( + denseLayer.weights[0].read(), tensor2d([1, 2, 3, 4, 5, 6], [3, 2])); + expectTensorsClose(denseLayer.weights[1].read(), tensor1d([10, 20])); + }); + it('Mismatching shape throws an error even in non-strict mode', () => { const denseLayer = tfl.layers.dense({units: 2, useBias: true, name: 'dense_layer'});