UNPKG

@tensorflow/tfjs-layers

Version:

TensorFlow layers API in JavaScript

101 lines 11.9 kB
/** * @license * Copyright 2019 Google LLC * * Use of this source code is governed by an MIT-style * license that can be found in the LICENSE file or at * https://opensource.org/licenses/MIT. * ============================================================================= */ /** Utility functions related to user-defined metadata. */ // Maximum recommended serialized size for user-defined metadata. // Beyond this limit, a warning message will be printed during model loading and // saving. export const MAX_USER_DEFINED_METADATA_SERIALIZED_LENGTH = 1 * 1024 * 1024; /** * Check validity of user-defined metadata. * * @param userDefinedMetadata * @param modelName Name of the model that the user-defined metadata belongs to. * Used during construction of error messages. * @param checkSize Whether to check the size of the metadata is under * recommended limit. Default: `false`. If `true`, will try stringify the * JSON object and print a console warning if the serialzied size is above the * limit. * @throws Error if `userDefinedMetadata` is not a plain JSON object. */ export function checkUserDefinedMetadata(userDefinedMetadata, modelName, checkSize = false) { if (userDefinedMetadata == null || typeof userDefinedMetadata !== 'object' || Object.getPrototypeOf(userDefinedMetadata) !== Object.prototype || !plainObjectCheck(userDefinedMetadata)) { throw new Error('User-defined metadata is expected to be a JSON object, but is not.'); } if (checkSize) { const out = JSON.stringify(userDefinedMetadata); if (out.length > MAX_USER_DEFINED_METADATA_SERIALIZED_LENGTH) { console.warn(`User-defined metadata of model "${modelName}" is too large in ` + `size (length=${out.length} when serialized). It is not ` + `recommended to store such large objects in user-defined metadata. ` + `Please make sure its serialized length is <= ` + `${MAX_USER_DEFINED_METADATA_SERIALIZED_LENGTH}.`); } } } /** * Check if an input is plain JSON object or any valid subfield of it. * * @param x The input to be checked. * @param assertObject Whether to assert `x` is a JSON object, i.e., reject * cases of arrays and primitives. * @return Returns `true` if and only if `x` is a plain JSON object, * a JSON-valid primitive including string, number, boolean and null, * or an array of the said types. */ // tslint:disable-next-line:no-any export function plainObjectCheck(x) { if (x === null) { // Note: typeof `null` is 'object', and `null` is valid in JSON. return true; } else if (typeof x === 'object') { if (Object.getPrototypeOf(x) === Object.prototype) { // `x` is a JavaScript object and its prototype is Object. const keys = Object.keys(x); for (const key of keys) { if (typeof key !== 'string') { // JSON keys must be strings. return false; } if (!plainObjectCheck(x[key])) { // Recursive call. return false; } } return true; } else { // `x` is a JavaScript object but its prototype is not Object. if (Array.isArray(x)) { // `x` is a JavaScript array. for (const item of x) { if (!plainObjectCheck(item)) { // Recursive call. return false; } } return true; } else { // `x` is a JavaScript object and its prototype is not Object, // and it's not an Array. I.e., it's a complex object such as // `Error` and `Date`. return false; } } } else { // `x` is not a JavaScript object or `null`. const xType = typeof x; return xType === 'string' || xType === 'number' || xType === 'boolean'; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlcl9kZWZpbmVkX21ldGFkYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGZqcy1sYXllcnMvc3JjL3VzZXJfZGVmaW5lZF9tZXRhZGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUVILDBEQUEwRDtBQUUxRCxpRUFBaUU7QUFDakUsZ0ZBQWdGO0FBQ2hGLFVBQVU7QUFDVixNQUFNLENBQUMsTUFBTSwyQ0FBMkMsR0FBRyxDQUFDLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQztBQUUzRTs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sVUFBVSx3QkFBd0IsQ0FDcEMsbUJBQXVCLEVBQUUsU0FBaUIsRUFBRSxTQUFTLEdBQUcsS0FBSztJQUMvRCxJQUFJLG1CQUFtQixJQUFJLElBQUk7UUFDM0IsT0FBTyxtQkFBbUIsS0FBSyxRQUFRO1FBQ3ZDLE1BQU0sQ0FBQyxjQUFjLENBQUMsbUJBQW1CLENBQUMsS0FBSyxNQUFNLENBQUMsU0FBUztRQUMvRCxDQUFDLGdCQUFnQixDQUFDLG1CQUFtQixDQUFDLEVBQUU7UUFDMUMsTUFBTSxJQUFJLEtBQUssQ0FDWCxvRUFBb0UsQ0FBQyxDQUFDO0tBQzNFO0lBRUQsSUFBSSxTQUFTLEVBQUU7UUFDYixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDaEQsSUFBSSxHQUFHLENBQUMsTUFBTSxHQUFHLDJDQUEyQyxFQUFFO1lBQzVELE9BQU8sQ0FBQyxJQUFJLENBQ1IsbUNBQW1DLFNBQVMsb0JBQW9CO2dCQUNoRSxnQkFBZ0IsR0FBRyxDQUFDLE1BQU0sK0JBQStCO2dCQUN6RCxvRUFBb0U7Z0JBQ3BFLCtDQUErQztnQkFDL0MsR0FBRywyQ0FBMkMsR0FBRyxDQUFDLENBQUM7U0FDeEQ7S0FDRjtBQUNILENBQUM7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxrQ0FBa0M7QUFDbEMsTUFBTSxVQUFVLGdCQUFnQixDQUFDLENBQU07SUFDckMsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFO1FBQ2QsZ0VBQWdFO1FBQ2hFLE9BQU8sSUFBSSxDQUFDO0tBQ2I7U0FBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUNoQyxJQUFJLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxDQUFDLFNBQVMsRUFBRTtZQUNqRCwwREFBMEQ7WUFDMUQsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1QixLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRTtnQkFDdEIsSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRLEVBQUU7b0JBQzNCLDZCQUE2QjtvQkFDN0IsT0FBTyxLQUFLLENBQUM7aUJBQ2Q7Z0JBQ0QsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUcsa0JBQWtCO29CQUNsRCxPQUFPLEtBQUssQ0FBQztpQkFDZDthQUNGO1lBQ0QsT0FBTyxJQUFJLENBQUM7U0FDYjthQUFNO1lBQ0wsOERBQThEO1lBQzlELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDcEIsNkJBQTZCO2dCQUM3QixLQUFLLE1BQU0sSUFBSSxJQUFJLENBQUMsRUFBRTtvQkFDcEIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUcsa0JBQWtCO3dCQUNoRCxPQUFPLEtBQUssQ0FBQztxQkFDZDtpQkFDRjtnQkFDRCxPQUFPLElBQUksQ0FBQzthQUNiO2lCQUFNO2dCQUNMLDhEQUE4RDtnQkFDOUQsNkRBQTZEO2dCQUM3RCxzQkFBc0I7Z0JBQ3RCLE9BQU8sS0FBSyxDQUFDO2FBQ2Q7U0FDRjtLQUNGO1NBQU07UUFDTCw0Q0FBNEM7UUFDNUMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLENBQUM7UUFDdkIsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxLQUFLLFNBQVMsQ0FBQztLQUN4RTtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlXG4gKiBsaWNlbnNlIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgb3IgYXRcbiAqIGh0dHBzOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvTUlULlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vKiogVXRpbGl0eSBmdW5jdGlvbnMgcmVsYXRlZCB0byB1c2VyLWRlZmluZWQgbWV0YWRhdGEuICovXG5cbi8vIE1heGltdW0gcmVjb21tZW5kZWQgc2VyaWFsaXplZCBzaXplIGZvciB1c2VyLWRlZmluZWQgbWV0YWRhdGEuXG4vLyBCZXlvbmQgdGhpcyBsaW1pdCwgYSB3YXJuaW5nIG1lc3NhZ2Ugd2lsbCBiZSBwcmludGVkIGR1cmluZyBtb2RlbCBsb2FkaW5nIGFuZFxuLy8gc2F2aW5nLlxuZXhwb3J0IGNvbnN0IE1BWF9VU0VSX0RFRklORURfTUVUQURBVEFfU0VSSUFMSVpFRF9MRU5HVEggPSAxICogMTAyNCAqIDEwMjQ7XG5cbi8qKlxuICogQ2hlY2sgdmFsaWRpdHkgb2YgdXNlci1kZWZpbmVkIG1ldGFkYXRhLlxuICpcbiAqIEBwYXJhbSB1c2VyRGVmaW5lZE1ldGFkYXRhXG4gKiBAcGFyYW0gbW9kZWxOYW1lIE5hbWUgb2YgdGhlIG1vZGVsIHRoYXQgdGhlIHVzZXItZGVmaW5lZCBtZXRhZGF0YSBiZWxvbmdzIHRvLlxuICogICBVc2VkIGR1cmluZyBjb25zdHJ1Y3Rpb24gb2YgZXJyb3IgbWVzc2FnZXMuXG4gKiBAcGFyYW0gY2hlY2tTaXplIFdoZXRoZXIgdG8gY2hlY2sgdGhlIHNpemUgb2YgdGhlIG1ldGFkYXRhIGlzIHVuZGVyXG4gKiAgIHJlY29tbWVuZGVkIGxpbWl0LiBEZWZhdWx0OiBgZmFsc2VgLiBJZiBgdHJ1ZWAsIHdpbGwgdHJ5IHN0cmluZ2lmeSB0aGVcbiAqICAgSlNPTiBvYmplY3QgYW5kIHByaW50IGEgY29uc29sZSB3YXJuaW5nIGlmIHRoZSBzZXJpYWx6aWVkIHNpemUgaXMgYWJvdmUgdGhlXG4gKiAgIGxpbWl0LlxuICogQHRocm93cyBFcnJvciBpZiBgdXNlckRlZmluZWRNZXRhZGF0YWAgaXMgbm90IGEgcGxhaW4gSlNPTiBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGVja1VzZXJEZWZpbmVkTWV0YWRhdGEoXG4gICAgdXNlckRlZmluZWRNZXRhZGF0YToge30sIG1vZGVsTmFtZTogc3RyaW5nLCBjaGVja1NpemUgPSBmYWxzZSk6IHZvaWQge1xuICBpZiAodXNlckRlZmluZWRNZXRhZGF0YSA9PSBudWxsIHx8XG4gICAgICB0eXBlb2YgdXNlckRlZmluZWRNZXRhZGF0YSAhPT0gJ29iamVjdCcgfHxcbiAgICAgIE9iamVjdC5nZXRQcm90b3R5cGVPZih1c2VyRGVmaW5lZE1ldGFkYXRhKSAhPT0gT2JqZWN0LnByb3RvdHlwZSB8fFxuICAgICAgIXBsYWluT2JqZWN0Q2hlY2sodXNlckRlZmluZWRNZXRhZGF0YSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdVc2VyLWRlZmluZWQgbWV0YWRhdGEgaXMgZXhwZWN0ZWQgdG8gYmUgYSBKU09OIG9iamVjdCwgYnV0IGlzIG5vdC4nKTtcbiAgfVxuXG4gIGlmIChjaGVja1NpemUpIHtcbiAgICBjb25zdCBvdXQgPSBKU09OLnN0cmluZ2lmeSh1c2VyRGVmaW5lZE1ldGFkYXRhKTtcbiAgICBpZiAob3V0Lmxlbmd0aCA+IE1BWF9VU0VSX0RFRklORURfTUVUQURBVEFfU0VSSUFMSVpFRF9MRU5HVEgpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBgVXNlci1kZWZpbmVkIG1ldGFkYXRhIG9mIG1vZGVsIFwiJHttb2RlbE5hbWV9XCIgaXMgdG9vIGxhcmdlIGluIGAgK1xuICAgICAgICAgIGBzaXplIChsZW5ndGg9JHtvdXQubGVuZ3RofSB3aGVuIHNlcmlhbGl6ZWQpLiBJdCBpcyBub3QgYCArXG4gICAgICAgICAgYHJlY29tbWVuZGVkIHRvIHN0b3JlIHN1Y2ggbGFyZ2Ugb2JqZWN0cyBpbiB1c2VyLWRlZmluZWQgbWV0YWRhdGEuIGAgK1xuICAgICAgICAgIGBQbGVhc2UgbWFrZSBzdXJlIGl0cyBzZXJpYWxpemVkIGxlbmd0aCBpcyA8PSBgICtcbiAgICAgICAgICBgJHtNQVhfVVNFUl9ERUZJTkVEX01FVEFEQVRBX1NFUklBTElaRURfTEVOR1RIfS5gKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhbiBpbnB1dCBpcyBwbGFpbiBKU09OIG9iamVjdCBvciBhbnkgdmFsaWQgc3ViZmllbGQgb2YgaXQuXG4gKlxuICogQHBhcmFtIHggVGhlIGlucHV0IHRvIGJlIGNoZWNrZWQuXG4gKiBAcGFyYW0gYXNzZXJ0T2JqZWN0IFdoZXRoZXIgdG8gYXNzZXJ0IGB4YCBpcyBhIEpTT04gb2JqZWN0LCBpLmUuLCByZWplY3RcbiAqICAgY2FzZXMgb2YgYXJyYXlzIGFuZCBwcmltaXRpdmVzLlxuICogQHJldHVybiBSZXR1cm5zIGB0cnVlYCBpZiBhbmQgb25seSBpZiBgeGAgaXMgYSBwbGFpbiBKU09OIG9iamVjdCxcbiAqICAgYSBKU09OLXZhbGlkIHByaW1pdGl2ZSBpbmNsdWRpbmcgc3RyaW5nLCBudW1iZXIsIGJvb2xlYW4gYW5kIG51bGwsXG4gKiAgIG9yIGFuIGFycmF5IG9mIHRoZSBzYWlkIHR5cGVzLlxuICovXG4vLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYW55XG5leHBvcnQgZnVuY3Rpb24gcGxhaW5PYmplY3RDaGVjayh4OiBhbnkpOiBib29sZWFuIHtcbiAgaWYgKHggPT09IG51bGwpIHtcbiAgICAvLyBOb3RlOiB0eXBlb2YgYG51bGxgIGlzICdvYmplY3QnLCBhbmQgYG51bGxgIGlzIHZhbGlkIGluIEpTT04uXG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHggPT09ICdvYmplY3QnKSB7XG4gICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZih4KSA9PT0gT2JqZWN0LnByb3RvdHlwZSkge1xuICAgICAgLy8gYHhgIGlzIGEgSmF2YVNjcmlwdCBvYmplY3QgYW5kIGl0cyBwcm90b3R5cGUgaXMgT2JqZWN0LlxuICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHgpO1xuICAgICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgICAgICBpZiAodHlwZW9mIGtleSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAvLyBKU09OIGtleXMgbXVzdCBiZSBzdHJpbmdzLlxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXBsYWluT2JqZWN0Q2hlY2soeFtrZXldKSkgeyAgLy8gUmVjdXJzaXZlIGNhbGwuXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gYHhgIGlzIGEgSmF2YVNjcmlwdCBvYmplY3QgYnV0IGl0cyBwcm90b3R5cGUgaXMgbm90IE9iamVjdC5cbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHgpKSB7XG4gICAgICAgIC8vIGB4YCBpcyBhIEphdmFTY3JpcHQgYXJyYXkuXG4gICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiB4KSB7XG4gICAgICAgICAgaWYgKCFwbGFpbk9iamVjdENoZWNrKGl0ZW0pKSB7ICAvLyBSZWN1cnNpdmUgY2FsbC5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBgeGAgaXMgYSBKYXZhU2NyaXB0IG9iamVjdCBhbmQgaXRzIHByb3RvdHlwZSBpcyBub3QgT2JqZWN0LFxuICAgICAgICAvLyBhbmQgaXQncyBub3QgYW4gQXJyYXkuIEkuZS4sIGl0J3MgYSBjb21wbGV4IG9iamVjdCBzdWNoIGFzXG4gICAgICAgIC8vIGBFcnJvcmAgYW5kIGBEYXRlYC5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBgeGAgaXMgbm90IGEgSmF2YVNjcmlwdCBvYmplY3Qgb3IgYG51bGxgLlxuICAgIGNvbnN0IHhUeXBlID0gdHlwZW9mIHg7XG4gICAgcmV0dXJuIHhUeXBlID09PSAnc3RyaW5nJyB8fCB4VHlwZSA9PT0gJ251bWJlcicgfHwgeFR5cGUgPT09ICdib29sZWFuJztcbiAgfVxufVxuIl19