|
|
@@ -1,6 +1,7 @@
|
|
|
/* jshint esversion: 6 */
|
|
|
|
|
|
var paddle = paddle || {};
|
|
|
+var flatbuffers = flatbuffers || require('./flatbuffers');
|
|
|
var protobuf = protobuf || require('./protobuf');
|
|
|
|
|
|
paddle.ModelFactory = class {
|
|
|
@@ -20,143 +21,147 @@ paddle.ModelFactory = class {
|
|
|
return 'paddle.pbtxt';
|
|
|
}
|
|
|
}
|
|
|
- if (paddle.Container.open(context)) {
|
|
|
- return 'paddle.container';
|
|
|
- }
|
|
|
const stream = context.stream;
|
|
|
if (stream.length > 16 && stream.peek(16).every((value) => value === 0x00)) {
|
|
|
return 'paddle.params';
|
|
|
}
|
|
|
+ if (paddle.Weights.open(context)) {
|
|
|
+ return 'paddle.weights';
|
|
|
+ }
|
|
|
+ if (paddle.NaiveBuffer.open(context)) {
|
|
|
+ return 'paddle.naive';
|
|
|
+ }
|
|
|
return undefined;
|
|
|
}
|
|
|
|
|
|
open(context, match) {
|
|
|
return paddle.Metadata.open(context).then((metadata) => {
|
|
|
- return context.require('./paddle-proto').then(() => {
|
|
|
- paddle.proto = protobuf.get('paddle').paddle.framework.proto;
|
|
|
- const identifier = context.identifier;
|
|
|
- const parts = identifier.split('.');
|
|
|
- const extension = parts.pop().toLowerCase();
|
|
|
- const base = parts.join('.');
|
|
|
- const openProgram = (stream, match) => {
|
|
|
- const program = {};
|
|
|
- program.format = 'PaddlePaddle';
|
|
|
- switch (match) {
|
|
|
- case 'paddle.pbtxt': {
|
|
|
- try {
|
|
|
- const reader = protobuf.TextReader.open(stream);
|
|
|
- program.desc = paddle.proto.ProgramDesc.decodeText(reader);
|
|
|
- }
|
|
|
- catch (error) {
|
|
|
- const message = error && error.message ? error.message : error.toString();
|
|
|
- throw new paddle.Error('File text format is not paddle.ProgramDesc (' + message.replace(/\.$/, '') + ').');
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- case 'paddle.pb': {
|
|
|
- try {
|
|
|
- const reader = protobuf.BinaryReader.open(stream);
|
|
|
- program.desc = paddle.proto.ProgramDesc.decode(reader);
|
|
|
- }
|
|
|
- catch (error) {
|
|
|
- const message = error && error.message ? error.message : error.toString();
|
|
|
- throw new paddle.Error('File format is not paddle.ProgramDesc (' + message.replace(/\.$/, '') + ').');
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- default: {
|
|
|
- throw new paddle.Error("Unknown Paddle format '" + match + "'.");
|
|
|
- }
|
|
|
- }
|
|
|
- const programDesc = program.desc;
|
|
|
- if (programDesc.version && programDesc.version.version && programDesc.version.version.toNumber) {
|
|
|
- const version = programDesc.version.version.toNumber();
|
|
|
- if (version > 0) {
|
|
|
- const list = [ Math.floor(version / 1000000) % 1000, Math.floor(version / 1000) % 1000, version % 1000 ];
|
|
|
- if (list.slice(-1).pop() === 0) {
|
|
|
- list.pop();
|
|
|
- if (list.slice(-1).pop() === 0) {
|
|
|
- list.pop();
|
|
|
+ switch (match) {
|
|
|
+ case 'paddle.naive': {
|
|
|
+ return context.require('./paddle-schema').then(() => {
|
|
|
+ paddle.schema = flatbuffers.get('paddlelite').paddle.lite.fbs.proto;
|
|
|
+ const file = paddle.NaiveBuffer.open(context);
|
|
|
+ return new paddle.Model(metadata, file.format, file.model, file.weights);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ default: {
|
|
|
+ return context.require('./paddle-proto').then(() => {
|
|
|
+ paddle.proto = protobuf.get('paddle').paddle.framework.proto;
|
|
|
+ const identifier = context.identifier;
|
|
|
+ const parts = identifier.split('.');
|
|
|
+ const extension = parts.pop().toLowerCase();
|
|
|
+ const base = parts.join('.');
|
|
|
+ const openProgram = (stream, match) => {
|
|
|
+ const program = {};
|
|
|
+ program.format = 'PaddlePaddle';
|
|
|
+ switch (match) {
|
|
|
+ case 'paddle.pbtxt': {
|
|
|
+ try {
|
|
|
+ const reader = protobuf.TextReader.open(stream);
|
|
|
+ program.desc = paddle.proto.ProgramDesc.decodeText(reader);
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ const message = error && error.message ? error.message : error.toString();
|
|
|
+ throw new paddle.Error('File text format is not paddle.ProgramDesc (' + message.replace(/\.$/, '') + ').');
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case 'paddle.pb': {
|
|
|
+ try {
|
|
|
+ const reader = protobuf.BinaryReader.open(stream);
|
|
|
+ program.desc = paddle.proto.ProgramDesc.decode(reader);
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ const message = error && error.message ? error.message : error.toString();
|
|
|
+ throw new paddle.Error('File format is not paddle.ProgramDesc (' + message.replace(/\.$/, '') + ').');
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default: {
|
|
|
+ throw new paddle.Error("Unknown Paddle format '" + match + "'.");
|
|
|
}
|
|
|
}
|
|
|
- program.format += ' v' + list.map((item) => item.toString()).join('.');
|
|
|
- }
|
|
|
- }
|
|
|
- const variables = new Set();
|
|
|
- for (const block of programDesc.blocks) {
|
|
|
- const blockVars = new Set();
|
|
|
- for (const variable of block.vars) {
|
|
|
- if (variable.persistable && variable.type &&
|
|
|
- variable.type.type != paddle.proto.VarType.Type.FETCH_LIST &&
|
|
|
- variable.type.type != paddle.proto.VarType.Type.FEED_MINIBATCH) {
|
|
|
- blockVars.add(variable.name);
|
|
|
- }
|
|
|
- }
|
|
|
- for (const op of block.ops) {
|
|
|
- for (const input of op.inputs) {
|
|
|
- for (const argument of input.arguments) {
|
|
|
- if (blockVars.has(argument)) {
|
|
|
- variables.add(argument);
|
|
|
+ const programDesc = program.desc;
|
|
|
+ program.format += paddle.Utility.formatVersion(programDesc.version);
|
|
|
+ const variables = new Set();
|
|
|
+ for (const block of programDesc.blocks) {
|
|
|
+ const blockVars = new Set();
|
|
|
+ for (const variable of block.vars) {
|
|
|
+ if (variable.persistable && variable.type &&
|
|
|
+ variable.type.type != paddle.DataType.FETCH_LIST &&
|
|
|
+ variable.type.type != paddle.DataType.FEED_MINIBATCH) {
|
|
|
+ blockVars.add(variable.name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (const op of block.ops) {
|
|
|
+ for (const input of op.inputs) {
|
|
|
+ for (const argument of input.arguments) {
|
|
|
+ if (blockVars.has(argument)) {
|
|
|
+ variables.add(argument);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
- program.vars = Array.from(variables).sort();
|
|
|
- return program;
|
|
|
- };
|
|
|
- const loadParams = (metadata, program, stream) => {
|
|
|
- const tensors = new Map();
|
|
|
- while (stream.position < stream.length) {
|
|
|
- tensors.set(program.vars.shift(), new paddle.Tensor(null, stream));
|
|
|
- }
|
|
|
- return new paddle.Model(metadata, program.format, program.desc, tensors);
|
|
|
- };
|
|
|
- switch (match) {
|
|
|
- case 'paddle.container': {
|
|
|
- const container = paddle.Container.open(context);
|
|
|
- return new paddle.Model(metadata, container.format, null, container.weights);
|
|
|
- }
|
|
|
- case 'paddle.params': {
|
|
|
- const file = identifier !== 'params' ? base + '.pdmodel' : 'model';
|
|
|
- return context.request(file, null).then((stream) => {
|
|
|
- const program = openProgram(stream, 'paddle.pb');
|
|
|
- return loadParams(metadata, program, context.stream);
|
|
|
- });
|
|
|
- }
|
|
|
- case 'paddle.pb':
|
|
|
- case 'paddle.pbtxt': {
|
|
|
- const program = openProgram(context.stream, match);
|
|
|
- const loadEntries = (context, program) => {
|
|
|
- const promises = program.vars.map((name) => context.request(name, null));
|
|
|
+ program.vars = Array.from(variables).sort();
|
|
|
+ return program;
|
|
|
+ };
|
|
|
+ const loadParams = (metadata, program, stream) => {
|
|
|
const tensors = new Map();
|
|
|
- return Promise.all(promises).then((streams) => {
|
|
|
- for (let i = 0; i < program.vars.length; i++) {
|
|
|
- tensors.set(program.vars[i], new paddle.Tensor(null, streams[i]));
|
|
|
- }
|
|
|
- return new paddle.Model(metadata, program.format, program.desc, tensors);
|
|
|
- }).catch((/* err */) => {
|
|
|
- return new paddle.Model(metadata, program.format, program.desc, tensors);
|
|
|
- });
|
|
|
+ while (stream.position < stream.length) {
|
|
|
+ const tensor = paddle.Utility.openTensor(stream);
|
|
|
+ tensors.set(program.vars.shift(), tensor);
|
|
|
+ }
|
|
|
+ return new paddle.Model(metadata, program.format, program.desc, tensors);
|
|
|
};
|
|
|
- if (extension === 'pdmodel') {
|
|
|
- return context.request(base + '.pdiparams', null).then((stream) => {
|
|
|
- return loadParams(metadata, program, stream);
|
|
|
- }).catch((/* err */) => {
|
|
|
- return loadEntries(context, program);
|
|
|
- });
|
|
|
- }
|
|
|
- if (identifier === 'model') {
|
|
|
- return context.request('params', null).then((stream) => {
|
|
|
- return loadParams(metadata, program, stream);
|
|
|
- }).catch((/* err */) => {
|
|
|
+ switch (match) {
|
|
|
+ case 'paddle.weights': {
|
|
|
+ const container = paddle.Weights.open(context);
|
|
|
+ return new paddle.Model(metadata, container.format, null, container.weights);
|
|
|
+ }
|
|
|
+ case 'paddle.params': {
|
|
|
+ const file = identifier !== 'params' ? base + '.pdmodel' : 'model';
|
|
|
+ return context.request(file, null).then((stream) => {
|
|
|
+ const program = openProgram(stream, 'paddle.pb');
|
|
|
+ return loadParams(metadata, program, context.stream);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ case 'paddle.pb':
|
|
|
+ case 'paddle.pbtxt': {
|
|
|
+ const program = openProgram(context.stream, match);
|
|
|
+ const loadEntries = (context, program) => {
|
|
|
+ const promises = program.vars.map((name) => context.request(name, null));
|
|
|
+ const tensors = new Map();
|
|
|
+ return Promise.all(promises).then((streams) => {
|
|
|
+ for (let i = 0; i < program.vars.length; i++) {
|
|
|
+ const tensor = paddle.Utility.openTensor(streams[i]);
|
|
|
+ tensors.set(program.vars[i], tensor);
|
|
|
+ }
|
|
|
+ return new paddle.Model(metadata, program.format, program.desc, tensors);
|
|
|
+ }).catch((/* err */) => {
|
|
|
+ return new paddle.Model(metadata, program.format, program.desc, tensors);
|
|
|
+ });
|
|
|
+ };
|
|
|
+ if (extension === 'pdmodel') {
|
|
|
+ return context.request(base + '.pdiparams', null).then((stream) => {
|
|
|
+ return loadParams(metadata, program, stream);
|
|
|
+ }).catch((/* err */) => {
|
|
|
+ return loadEntries(context, program);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (identifier === 'model') {
|
|
|
+ return context.request('params', null).then((stream) => {
|
|
|
+ return loadParams(metadata, program, stream);
|
|
|
+ }).catch((/* err */) => {
|
|
|
+ return loadEntries(context, program);
|
|
|
+ });
|
|
|
+ }
|
|
|
return loadEntries(context, program);
|
|
|
- });
|
|
|
+ }
|
|
|
}
|
|
|
- return loadEntries(context, program);
|
|
|
- }
|
|
|
+ });
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
});
|
|
|
}
|
|
|
};
|
|
|
@@ -190,8 +195,8 @@ paddle.Graph = class {
|
|
|
|
|
|
const args = new Map();
|
|
|
for (const variable of block.vars) {
|
|
|
- const type = variable.type && variable.type.type && variable.type.lod_tensor && variable.type.lod_tensor.tensor ? paddle.Utility.createTensorType(variable.type.lod_tensor.tensor) : null;
|
|
|
- const tensor = variable.persistable && variable.type && variable.type.type != paddle.proto.VarType.Type.FETCH_LIST && variable.type.type != paddle.proto.VarType.Type.FEED_MINIBATCH ? (tensors.get(variable.name) || new paddle.Tensor(type)) : null;
|
|
|
+ const type = variable.type && variable.type.type && variable.type.lod_tensor && variable.type.lod_tensor.tensor ? paddle.Utility.createTensorType(variable.type.lod_tensor.tensor.data_type, variable.type.lod_tensor.tensor.dims) : null;
|
|
|
+ const tensor = variable.persistable && variable.type && variable.type.type != paddle.DataType.FETCH_LIST && variable.type.type != paddle.DataType.FEED_MINIBATCH ? (tensors.get(variable.name) || new paddle.Tensor(type)) : null;
|
|
|
args.set(variable.name, new paddle.Argument(variable.name, type, tensor));
|
|
|
}
|
|
|
|
|
|
@@ -436,42 +441,42 @@ paddle.Attribute = class {
|
|
|
this._name = attr.name;
|
|
|
this._value = '?';
|
|
|
switch (attr.type) {
|
|
|
- case paddle.proto.AttrType.STRING:
|
|
|
+ case paddle.AttributeType.STRING:
|
|
|
this._type = 'string';
|
|
|
this._value = attr.s;
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.STRINGS:
|
|
|
+ case paddle.AttributeType.STRINGS:
|
|
|
this._type = 'string[]';
|
|
|
- this._value = attr.strings;
|
|
|
+ this._value = Array.from(attr.strings);
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.BOOLEAN:
|
|
|
+ case paddle.AttributeType.BOOLEAN:
|
|
|
this._type = 'boolean';
|
|
|
this._value = attr.b;
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.BOOLEANS:
|
|
|
+ case paddle.AttributeType.BOOLEANS:
|
|
|
this._type = 'boolean[]';
|
|
|
- this._value = attr.bools;
|
|
|
+ this._value = Array.from(attr.bools);
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.FLOAT:
|
|
|
+ case paddle.AttributeType.FLOAT:
|
|
|
this._type = 'float32';
|
|
|
this._value = attr.f;
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.FLOATS:
|
|
|
+ case paddle.AttributeType.FLOATS:
|
|
|
this._type = 'float[]';
|
|
|
- this._value = attr.floats;
|
|
|
+ this._value = Array.from(attr.floats);
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.INT:
|
|
|
+ case paddle.AttributeType.INT:
|
|
|
this._type = 'int32';
|
|
|
this._value = attr.i;
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.INTS:
|
|
|
+ case paddle.AttributeType.INTS:
|
|
|
this._type = 'int32[]';
|
|
|
- this._value = attr.ints;
|
|
|
+ this._value = Array.from(attr.ints);
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.LONG:
|
|
|
+ case paddle.AttributeType.LONG:
|
|
|
this._type = 'int64';
|
|
|
break;
|
|
|
- case paddle.proto.AttrType.LONGS:
|
|
|
+ case paddle.AttributeType.LONGS:
|
|
|
this._type = 'int64[]';
|
|
|
break;
|
|
|
default:
|
|
|
@@ -524,39 +529,10 @@ paddle.Attribute = class {
|
|
|
|
|
|
paddle.Tensor = class {
|
|
|
|
|
|
- constructor(type, data) {
|
|
|
+ constructor(type, data, kind) {
|
|
|
this._type = type;
|
|
|
- if (data && !Array.isArray(data)) {
|
|
|
- if (data.__class__ && data.__class__.__module__ === 'numpy' && data.__class__.__name__ === 'ndarray') {
|
|
|
- this._type = new paddle.TensorType(data.dtype.name, new paddle.TensorShape(data.shape));
|
|
|
- this._data = data.data;
|
|
|
- this._kind = 'NumPy Array';
|
|
|
- }
|
|
|
- else {
|
|
|
- const uint32 = (stream) => {
|
|
|
- const buffer = stream.read(4);
|
|
|
- const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
|
- return view.getUint32(0, true);
|
|
|
- };
|
|
|
- const stream = data;
|
|
|
- const signature = stream.read(16);
|
|
|
- if (!signature.every((value) => value === 0x00)) {
|
|
|
- throw new paddle.Error('Invalid paddle.TensorDesc signature.');
|
|
|
- }
|
|
|
- const length = uint32(stream);
|
|
|
- const buffer = stream.read(length);
|
|
|
- const reader = protobuf.BinaryReader.open(buffer);
|
|
|
- const tensorDesc = paddle.proto.VarType.TensorDesc.decode(reader);
|
|
|
- const size = tensorDesc.dims.reduce((a, b) => a * b.toNumber(), 1);
|
|
|
- let itemsize = 0;
|
|
|
- switch (tensorDesc.data_type) {
|
|
|
- case paddle.proto.VarType.Type.FP32: itemsize = 4; break;
|
|
|
- default: throw new paddle.Error("Invalid inference params data type '" + tensorDesc.data_type + "'.");
|
|
|
- }
|
|
|
- this._type = paddle.Utility.createTensorType(tensorDesc);
|
|
|
- this._data = stream.read(itemsize * size);
|
|
|
- }
|
|
|
- }
|
|
|
+ this._data = data;
|
|
|
+ this._kind = kind || '';
|
|
|
}
|
|
|
|
|
|
get kind() {
|
|
|
@@ -737,12 +713,12 @@ paddle.TensorShape = class {
|
|
|
|
|
|
paddle.Utility = class {
|
|
|
|
|
|
- static createTensorType(desc) {
|
|
|
+ static createTensorType(data_type, shape) {
|
|
|
if (!paddle.Utility._dataTypes) {
|
|
|
- const length = Math.max.apply(null, Object.values(paddle.proto.VarType.Type));
|
|
|
+ const length = Math.max.apply(null, Object.values(paddle.DataType));
|
|
|
paddle.Utility._dataTypes = new Array(length);
|
|
|
- for (const key of Object.keys(paddle.proto.VarType.Type)) {
|
|
|
- const index = paddle.proto.VarType.Type[key];
|
|
|
+ for (const key of Object.keys(paddle.DataType)) {
|
|
|
+ const index = paddle.DataType[key];
|
|
|
let name = key.toLowerCase();
|
|
|
switch (name) {
|
|
|
case 'bool': name = 'boolean'; break;
|
|
|
@@ -754,24 +730,66 @@ paddle.Utility = class {
|
|
|
paddle.Utility._dataTypes[index] = name;
|
|
|
}
|
|
|
}
|
|
|
- const dataType = desc.data_type < paddle.Utility._dataTypes.length ? paddle.Utility._dataTypes[desc.data_type] : '?';
|
|
|
- return new paddle.TensorType(dataType, new paddle.TensorShape(desc.dims));
|
|
|
+ const dataType = data_type < paddle.Utility._dataTypes.length ? paddle.Utility._dataTypes[data_type] : '?';
|
|
|
+ return new paddle.TensorType(dataType, new paddle.TensorShape(shape));
|
|
|
+ }
|
|
|
+
|
|
|
+ static openTensor(stream) {
|
|
|
+ const uint32 = (stream) => {
|
|
|
+ const buffer = stream.read(4);
|
|
|
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
|
+ return view.getUint32(0, true);
|
|
|
+ };
|
|
|
+ const signature = stream.read(16);
|
|
|
+ if (!signature.every((value) => value === 0x00)) {
|
|
|
+ throw new paddle.Error('Invalid paddle.TensorDesc signature.');
|
|
|
+ }
|
|
|
+ const length = uint32(stream);
|
|
|
+ const buffer = stream.read(length);
|
|
|
+ const reader = protobuf.BinaryReader.open(buffer);
|
|
|
+ const tensorDesc = paddle.proto.VarType.TensorDesc.decode(reader);
|
|
|
+ const size = tensorDesc.dims.reduce((a, b) => a * b.toNumber(), 1);
|
|
|
+ let itemsize = 0;
|
|
|
+ switch (tensorDesc.data_type) {
|
|
|
+ case paddle.DataType.FP32: itemsize = 4; break;
|
|
|
+ default: throw new paddle.Error("Invalid inference params data type '" + tensorDesc.data_type + "'.");
|
|
|
+ }
|
|
|
+ const type = paddle.Utility.createTensorType(tensorDesc.data_type, tensorDesc.dims);
|
|
|
+ const data = stream.read(itemsize * size);
|
|
|
+ return new paddle.Tensor(type, data);
|
|
|
+ }
|
|
|
+
|
|
|
+ static formatVersion(version) {
|
|
|
+ if (version && version.version && version.version.toNumber) {
|
|
|
+ const number = version.version.toNumber();
|
|
|
+ if (number > 0) {
|
|
|
+ const list = [ Math.floor(number / 1000000) % 1000, Math.floor(number / 1000) % 1000, number % 1000 ];
|
|
|
+ if (list.slice(-1).pop() === 0) {
|
|
|
+ list.pop();
|
|
|
+ if (list.slice(-1).pop() === 0) {
|
|
|
+ list.pop();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ' v' + list.map((item) => item.toString()).join('.');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return '';
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-paddle.Container = class {
|
|
|
+paddle.Weights = class {
|
|
|
|
|
|
static open(context) {
|
|
|
const extension = [ 'zip', 'tar' ].find((extension) => context.entries(extension).size > 0);
|
|
|
if (extension) {
|
|
|
const entries = new Map(Array.from(context.entries(extension)).filter((entry) => !entry[0].endsWith('/') && !entry[0].split('/').pop().startsWith('.')).slice());
|
|
|
if (entries.size > 2 && Array.from(entries).every((entry) => entry[0].split('_').length > 0 && entry[1].peek(16).every((value) => value === 0x00))) {
|
|
|
- return new paddle.Container('entries', entries);
|
|
|
+ return new paddle.Weights('entries', entries);
|
|
|
}
|
|
|
}
|
|
|
const obj = context.open('pkl');
|
|
|
if (obj && !Array.isArray(obj) && Object(obj) === obj) {
|
|
|
- return new paddle.Container('pdparams', obj);
|
|
|
+ return new paddle.Weights('pdparams', obj);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
@@ -820,7 +838,7 @@ paddle.Container = class {
|
|
|
if (entry[0].startsWith(rootFolder)) {
|
|
|
const name = entry[0].substring(rootFolder.length);
|
|
|
const stream = entry[1];
|
|
|
- const tensor = new paddle.Tensor(null, stream);
|
|
|
+ const tensor = paddle.Utility.openTensor(stream);
|
|
|
this._weights.set(name, tensor);
|
|
|
}
|
|
|
}
|
|
|
@@ -833,7 +851,10 @@ paddle.Container = class {
|
|
|
const value = this._data[key];
|
|
|
if (value && !Array.isArray(value) && value.__class__ && value.__class__.__module__ === 'numpy' && value.__class__.__name__ === 'ndarray') {
|
|
|
const name = map ? map[key] : key;
|
|
|
- this._weights.set(name, new paddle.Tensor(null, value));
|
|
|
+ const type = new paddle.TensorType(value.dtype.name, new paddle.TensorShape(value.shape));
|
|
|
+ const data = value.data;
|
|
|
+ const tensor = new paddle.Tensor(type, data, 'NumPy Array');
|
|
|
+ this._weights.set(name, tensor);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
@@ -844,6 +865,186 @@ paddle.Container = class {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+paddle.NaiveBuffer = class {
|
|
|
+
|
|
|
+ static open(context) {
|
|
|
+ const stream = context.stream;
|
|
|
+ if (stream.length > 4) {
|
|
|
+ const buffer = stream.peek();
|
|
|
+ const reader = new paddle.BinaryReader(buffer);
|
|
|
+ if (context.identifier === '__model__.nb' || context.identifier === 'param.nb') {
|
|
|
+ if (buffer[0] > 2 || buffer[1] !== 0x00 || buffer[2] !== 0x76 || buffer[2] !== 0x32) {
|
|
|
+ return new paddle.NaiveBuffer(reader, -1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const meta_version = reader.uint16();
|
|
|
+ if (meta_version <= 2) {
|
|
|
+ return new paddle.NaiveBuffer(reader, meta_version);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ constructor(reader, meta_version) {
|
|
|
+ this.reader = reader;
|
|
|
+ this.meta_version = meta_version;
|
|
|
+ }
|
|
|
+
|
|
|
+ get format() {
|
|
|
+ this._read();
|
|
|
+ return 'Paddle Lite' + (this.opt_version ? ' ' + this.opt_version : '');
|
|
|
+ }
|
|
|
+
|
|
|
+ get model() {
|
|
|
+ this._read();
|
|
|
+ return this._model;
|
|
|
+ }
|
|
|
+
|
|
|
+ get weights() {
|
|
|
+ this._read();
|
|
|
+ return this._weights;
|
|
|
+ }
|
|
|
+
|
|
|
+ _read() {
|
|
|
+ if (this.reader) {
|
|
|
+ const reader = this.reader;
|
|
|
+ delete this.reader;
|
|
|
+ const decoder = new TextDecoder();
|
|
|
+ const opt_version = reader.read(16);
|
|
|
+ this.opt_version = decoder.decode(opt_version.slice(0, opt_version.indexOf(0x00)));
|
|
|
+ const topo_size = reader.uint64();
|
|
|
+ const openProgramDesc = (buffer) => {
|
|
|
+ const reader = flatbuffers.BinaryReader.open(buffer);
|
|
|
+ return paddle.schema.ProgramDesc.create(reader);
|
|
|
+ };
|
|
|
+ const openParamDesc = (buffer) => {
|
|
|
+ const reader = flatbuffers.BinaryReader.open(buffer);
|
|
|
+ return paddle.schema.ParamDesc.create(reader);
|
|
|
+ };
|
|
|
+ switch (this.meta_version) {
|
|
|
+ case -1: {
|
|
|
+ throw new paddle.Error('Paddle Lite naive buffer format is deprecated.');
|
|
|
+ }
|
|
|
+ case 0:
|
|
|
+ case 1: {
|
|
|
+ throw new paddle.Error('Paddle Lite meta format ' + this.meta_version.toString() + ' is deprecated.');
|
|
|
+ }
|
|
|
+ case 2: {
|
|
|
+ const topo_data = new Uint8Array(topo_size);
|
|
|
+ topo_data.set(reader.read(topo_size), 0);
|
|
|
+ this._model = openProgramDesc(topo_data);
|
|
|
+ reader.uint16(); // version
|
|
|
+ reader.uint16(); // meta_size
|
|
|
+ const header_size = reader.uint16();
|
|
|
+ const params_size = reader.uint16();
|
|
|
+ reader.uint32(); // max_tensor_size
|
|
|
+ reader.skip(header_size - 6);
|
|
|
+ this._weights = new Map();
|
|
|
+ for (let i = 0; i < params_size; i++) {
|
|
|
+ const total_size = reader.uint32();
|
|
|
+ const offset = reader.uint32();
|
|
|
+ const param_bytes = total_size - offset;
|
|
|
+ const param_data = reader.read(param_bytes);
|
|
|
+ const desc = openParamDesc(param_data);
|
|
|
+ const data = desc.variable.data;
|
|
|
+ const data_type = desc.variable.data_type;
|
|
|
+ const dim = desc.variable.dim;
|
|
|
+ const type = paddle.Utility.createTensorType(data_type, dim);
|
|
|
+ const tensor = new paddle.Tensor(type, data);
|
|
|
+ this._weights.set(desc.name, tensor);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default: {
|
|
|
+ throw new paddle.Error('Paddle Lite naive buffer meta format ' + this.meta_version.toString() + ' not supported.');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+paddle.BinaryReader = class {
|
|
|
+
|
|
|
+ constructor(data) {
|
|
|
+ this._buffer = data instanceof Uint8Array ? data : data.peek();
|
|
|
+ this._position = 0;
|
|
|
+ this._dataView = new DataView(this._buffer.buffer, this._buffer.byteOffset, this._buffer.byteLength);
|
|
|
+ }
|
|
|
+
|
|
|
+ skip(offset) {
|
|
|
+ const position = this._position;
|
|
|
+ this._position += offset;
|
|
|
+ if (this._position > this._length) {
|
|
|
+ throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
|
|
|
+ }
|
|
|
+ return position;
|
|
|
+ }
|
|
|
+
|
|
|
+ read(size) {
|
|
|
+ const position = this._position;
|
|
|
+ this.skip(size);
|
|
|
+ return this._buffer.subarray(position, this._position);
|
|
|
+ }
|
|
|
+
|
|
|
+ uint16() {
|
|
|
+ const position = this.skip(2);
|
|
|
+ return this._dataView.getUint16(position, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ uint32() {
|
|
|
+ const position = this.skip(4);
|
|
|
+ return this._dataView.getUint32(position, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ uint64() {
|
|
|
+ const position = this.skip(8);
|
|
|
+ return this._dataView.getUint64(position, true).toNumber();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+paddle.DataType = {
|
|
|
+ BOOL: 0,
|
|
|
+ INT16: 1,
|
|
|
+ INT32: 2,
|
|
|
+ INT64: 3,
|
|
|
+ FP16: 4,
|
|
|
+ FP32: 5,
|
|
|
+ FP64: 6,
|
|
|
+ LOD_TENSOR: 7,
|
|
|
+ SELECTED_ROWS: 8,
|
|
|
+ FEED_MINIBATCH: 9,
|
|
|
+ FETCH_LIST: 10,
|
|
|
+ STEP_SCOPES: 11,
|
|
|
+ LOD_RANK_TABLE: 12,
|
|
|
+ LOD_TENSOR_ARRAY: 13,
|
|
|
+ PLACE_LIST: 14,
|
|
|
+ READER: 15,
|
|
|
+ RAW: 17,
|
|
|
+ TUPLE: 18,
|
|
|
+ SIZE_T: 19,
|
|
|
+ UINT8: 20,
|
|
|
+ INT8: 21,
|
|
|
+ BF16: 22,
|
|
|
+ COMPLEX64: 23,
|
|
|
+ COMPLEX128: 24,
|
|
|
+};
|
|
|
+
|
|
|
+paddle.AttributeType = {
|
|
|
+ INT: 0,
|
|
|
+ FLOAT: 1,
|
|
|
+ STRING: 2,
|
|
|
+ INTS: 3,
|
|
|
+ FLOATS: 4,
|
|
|
+ STRINGS: 5,
|
|
|
+ BOOLEAN: 6,
|
|
|
+ BOOLEANS: 7,
|
|
|
+ BLOCK: 8,
|
|
|
+ LONG: 9,
|
|
|
+ BLOCKS: 10,
|
|
|
+ LONGS: 11,
|
|
|
+ FLOAT64S: 12
|
|
|
+};
|
|
|
+
|
|
|
paddle.Metadata = class {
|
|
|
|
|
|
static open(context) {
|