7254f7b4d1
Build / Build (macos-latest) (push) Has been cancelled
Build / Build (ubuntu-latest) (push) Has been cancelled
Build / Build (windows-latest) (push) Has been cancelled
Build / Analyze (javascript) (push) Has been cancelled
Build / Analyze (python) (push) Has been cancelled
169 lines
5.0 KiB
JavaScript
169 lines
5.0 KiB
JavaScript
|
|
const hickle = {};
|
|
|
|
hickle.ModelFactory = class {
|
|
|
|
async match(context) {
|
|
const group = await context.peek('hdf5');
|
|
if (group && group.attributes && group.attributes.get('CLASS') === 'hickle') {
|
|
return context.set('hickle', group);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
async open(context) {
|
|
return new hickle.Model(context.value);
|
|
}
|
|
};
|
|
|
|
hickle.Model = class {
|
|
|
|
constructor(group) {
|
|
this.format = 'Hickle Weights';
|
|
this.modules = [new hickle.Graph(group)];
|
|
}
|
|
};
|
|
|
|
hickle.Graph = class {
|
|
|
|
constructor(group) {
|
|
this.inputs = [];
|
|
this.outputs = [];
|
|
const deserialize = (group) => {
|
|
if (group && group.attributes.has('type')) {
|
|
const type = group.attributes.get('type');
|
|
if (Array.isArray(type) && type.length && typeof type[0] === 'string') {
|
|
switch (type[0]) {
|
|
case 'hickle':
|
|
case 'dict_item': {
|
|
if (group.groups.size === 1) {
|
|
return deserialize(group.groups.values().next().value);
|
|
}
|
|
throw new hickle.Error(`Invalid Hickle type value '${type[0]}'.`);
|
|
}
|
|
case 'dict': {
|
|
const dict = new Map();
|
|
for (const [name, obj] of group.groups) {
|
|
const value = deserialize(obj);
|
|
dict.set(name, value);
|
|
}
|
|
return dict;
|
|
}
|
|
case 'ndarray': {
|
|
return group.value;
|
|
}
|
|
default: {
|
|
throw new hickle.Error(`Unsupported Hickle type '${type[0]}'`);
|
|
}
|
|
}
|
|
}
|
|
throw new hickle.Error(`Unsupported Hickle type '${JSON.stringify(type)}'`);
|
|
}
|
|
throw new hickle.Error('Unsupported Hickle group.');
|
|
};
|
|
const obj = deserialize(group);
|
|
const layers = new Map();
|
|
if (obj && obj instanceof Map && Array.from(obj.values()).every((value) => value.type && value.shape)) {
|
|
for (const [key, value] of obj) {
|
|
const tensor = new hickle.Tensor(key, value.shape, value.type, value.littleEndian, value.type === 'string' ? value.value : value.data);
|
|
const bits = key.split('.');
|
|
const parameter = bits.pop();
|
|
const layer = bits.join('.');
|
|
if (!layers.has(layer)) {
|
|
layers.set(layer, []);
|
|
}
|
|
layers.get(layer).push({ name: parameter, value: tensor });
|
|
}
|
|
}
|
|
this.nodes = Array.from(layers).map(([name, value]) => new hickle.Node(name, value));
|
|
}
|
|
};
|
|
|
|
hickle.Argument = class {
|
|
|
|
constructor(name, value) {
|
|
this.name = name;
|
|
this.value = value;
|
|
}
|
|
};
|
|
|
|
hickle.Value = class {
|
|
|
|
constructor(name, type, initializer = null) {
|
|
if (typeof name !== 'string') {
|
|
throw new hickle.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);
|
|
}
|
|
this.name = name;
|
|
this.type = !type && initializer ? initializer.type : type;
|
|
this.initializer = initializer;
|
|
}
|
|
};
|
|
|
|
hickle.Node = class {
|
|
|
|
constructor(name, parameters) {
|
|
this.type = { name: 'Weights' };
|
|
this.name = name;
|
|
this.inputs = parameters.map((parameter) => {
|
|
return new hickle.Argument(parameter.name, [
|
|
new hickle.Value(parameter.value.name, null, parameter.value)
|
|
]);
|
|
});
|
|
this.outputs = [];
|
|
this.attributes = [];
|
|
}
|
|
};
|
|
|
|
hickle.Tensor = class {
|
|
|
|
constructor(name, shape, type, littleEndian, data) {
|
|
this.name = name;
|
|
this.type = new hickle.TensorType(type, new hickle.TensorShape(shape));
|
|
this.encoding = littleEndian ? '<' : '>';
|
|
this._data = data;
|
|
}
|
|
|
|
get values() {
|
|
if (Array.isArray(this._data) || this._data === null) {
|
|
return null;
|
|
}
|
|
if (this._data instanceof Uint8Array) {
|
|
return this._data;
|
|
}
|
|
return this._data.peek();
|
|
}
|
|
};
|
|
|
|
hickle.TensorType = class {
|
|
|
|
constructor(dataType, shape) {
|
|
this.dataType = dataType;
|
|
this.shape = shape;
|
|
}
|
|
|
|
toString() {
|
|
return this.dataType + this.shape.toString();
|
|
}
|
|
};
|
|
|
|
hickle.TensorShape = class {
|
|
|
|
constructor(dimensions) {
|
|
this.dimensions = dimensions;
|
|
}
|
|
|
|
toString() {
|
|
return this.dimensions ? (`[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`) : '';
|
|
}
|
|
};
|
|
|
|
hickle.Error = class extends Error {
|
|
|
|
constructor(message) {
|
|
super(message);
|
|
this.name = 'Error loading Hickle model.';
|
|
}
|
|
};
|
|
|
|
export const ModelFactory = hickle.ModelFactory;
|