|
|
|
|
|
|
from collections import defaultdict |
|
|
|
import numpy as np |
|
|
|
import json |
|
|
|
import struct # convert from Python values and C structs |
|
|
|
import struct # convert from Python values and C structs |
|
|
|
import re |
|
|
|
import argparse |
|
|
|
import os.path |
|
|
|
|
|
|
self.globals = [] |
|
|
|
self.memories = [] |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, **entries): self.__dict__.update(entries) |
|
|
|
|
|
|
|
def __init__(self, **entries): |
|
|
|
self.__dict__.update(entries) |
|
|
|
|
|
|
|
parser.add_argument('source_file', help=help) |
|
|
|
parser.add_argument('target_file', help='output Barracuda binary file') |
|
|
|
parser.add_argument('-trim', '--trim-unused-by-output') |
|
|
|
parser.add_argument('--print-layers', action='store_true') |
|
|
|
parser.add_argument('--print-source-json', action='store_true') |
|
|
|
parser.add_argument('-json', '--print-barracuda-json', action='store_true') |
|
|
|
parser.add_argument('--print-layer-links', action='store_true') |
|
|
|
parser.add_argument('--print-patterns', action='store_true') |
|
|
|
parser.add_argument('--print-tensors', action='store_true') |
|
|
|
parser.add_argument('--print-supported-ops', action='store_true') |
|
|
|
parser.add_argument('--verbose', action='store_true') |
|
|
|
parser.add_argument("source_file", help=help) |
|
|
|
parser.add_argument("target_file", help="output Barracuda binary file") |
|
|
|
parser.add_argument("-trim", "--trim-unused-by-output") |
|
|
|
parser.add_argument("--print-layers", action="store_true") |
|
|
|
parser.add_argument("--print-source-json", action="store_true") |
|
|
|
parser.add_argument("-json", "--print-barracuda-json", action="store_true") |
|
|
|
parser.add_argument("--print-layer-links", action="store_true") |
|
|
|
parser.add_argument("--print-patterns", action="store_true") |
|
|
|
parser.add_argument("--print-tensors", action="store_true") |
|
|
|
parser.add_argument("--print-supported-ops", action="store_true") |
|
|
|
parser.add_argument("--verbose", action="store_true") |
|
|
|
args.compress_f16 = False # TEMP: disabled, until properly implemented parser.add_argument('-f16', '--compress-f16', action='store_true') |
|
|
|
|
|
|
|
output_extension = '.bc' if not args.compress_f16 else '.f16.bc' |
|
|
|
args.compress_f16 = ( |
|
|
|
False |
|
|
|
) # TEMP: disabled, until properly implemented parser.add_argument('-f16', '--compress-f16', action='store_true') |
|
|
|
|
|
|
|
output_extension = ".bc" if not args.compress_f16 else ".f16.bc" |
|
|
|
print('File', args.source_file, 'does not exist.') |
|
|
|
print("File", args.source_file, "does not exist.") |
|
|
|
return os.path.splitext(os.path.basename(filename))[0] + newExtenstion; |
|
|
|
return os.path.splitext(os.path.basename(filename))[0] + newExtenstion |
|
|
|
args.target_file = os.path.join(args.target_file, replaceFilenameExtension(args.source_file, output_extension)) |
|
|
|
args.target_file = os.path.join( |
|
|
|
args.target_file, |
|
|
|
replaceFilenameExtension(args.source_file, output_extension), |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
# Fuse training time BatchNorm tensors into Scale & Bias |
|
|
|
def fuse_batchnorm_weights(gamma, beta, mean, var, epsilon): |
|
|
|
|
|
|
bias = beta - gamma * mean / np.sqrt(var + epsilon) |
|
|
|
return [scale, bias] |
|
|
|
|
|
|
|
|
|
|
|
if hasattr(model, 'layers'): |
|
|
|
if hasattr(model, "layers"): |
|
|
|
model = model.layers |
|
|
|
inputs_and_memories = set(list(inputs) + list(memories[1::3])) |
|
|
|
|
|
|
|
|
|
|
ready.add(l.name) |
|
|
|
return missing |
|
|
|
|
|
|
|
# Class to represent a graph |
|
|
|
# Class to represent a graph |
|
|
|
class Graph: |
|
|
|
def __init__(self,vertices): |
|
|
|
self.graph = defaultdict(list) #dictionary containing adjacency List |
|
|
|
self.V = vertices #No. of vertices |
|
|
|
|
|
|
|
# function to add an edge to graph |
|
|
|
def addEdge(self,u,v): |
|
|
|
self.graph[u].append(v) |
|
|
|
|
|
|
|
# A recursive function used by topologicalSort |
|
|
|
def topologicalSortUtil(self,v,visited,stack): |
|
|
|
|
|
|
|
# Mark the current node as visited. |
|
|
|
class Graph: |
|
|
|
def __init__(self, vertices): |
|
|
|
self.graph = defaultdict(list) # dictionary containing adjacency List |
|
|
|
self.V = vertices # No. of vertices |
|
|
|
|
|
|
|
# function to add an edge to graph |
|
|
|
def addEdge(self, u, v): |
|
|
|
self.graph[u].append(v) |
|
|
|
|
|
|
|
# A recursive function used by topologicalSort |
|
|
|
def topologicalSortUtil(self, v, visited, stack): |
|
|
|
|
|
|
|
# Mark the current node as visited. |
|
|
|
|
|
|
|
# Recur for all the vertices adjacent to this vertex |
|
|
|
for i in self.graph[v]: |
|
|
|
if visited[i] == False: |
|
|
|
self.topologicalSortUtil(i,visited,stack) |
|
|
|
|
|
|
|
# Push current vertex to stack which stores result |
|
|
|
stack.insert(0,v) |
|
|
|
|
|
|
|
# Recur for all the vertices adjacent to this vertex |
|
|
|
for i in self.graph[v]: |
|
|
|
if visited[i] == False: |
|
|
|
self.topologicalSortUtil(i, visited, stack) |
|
|
|
|
|
|
|
# Push current vertex to stack which stores result |
|
|
|
stack.insert(0, v) |
|
|
|
|
|
|
|
# The function to do Topological Sort. It uses recursive |
|
|
|
# topologicalSortUtil() |
|
|
|
def topologicalSort(self): |
|
|
|
# Mark all the vertices as not visited |
|
|
|
visited = [False] * self.V |
|
|
|
stack = [] |
|
|
|
|
|
|
|
# Call the recursive helper function to store Topological |
|
|
|
# Sort starting from all vertices one by one |
|
|
|
for i in range(self.V): |
|
|
|
if visited[i] == False: |
|
|
|
self.topologicalSortUtil(i, visited, stack) |
|
|
|
# The function to do Topological Sort. It uses recursive |
|
|
|
# topologicalSortUtil() |
|
|
|
def topologicalSort(self): |
|
|
|
# Mark all the vertices as not visited |
|
|
|
visited = [False]*self.V |
|
|
|
stack =[] |
|
|
|
|
|
|
|
# Call the recursive helper function to store Topological |
|
|
|
# Sort starting from all vertices one by one |
|
|
|
for i in range(self.V): |
|
|
|
if visited[i] == False: |
|
|
|
self.topologicalSortUtil(i,visited,stack) |
|
|
|
|
|
|
|
#print(stack) |
|
|
|
# print(stack) |
|
|
|
if (len(find_missing_inputs(model, inputs_and_memories)) == 0): |
|
|
|
if len(find_missing_inputs(model, inputs_and_memories)) == 0: |
|
|
|
return model |
|
|
|
|
|
|
|
g = Graph(len(model)) |
|
|
|
|
|
|
for l in model: |
|
|
|
layers[l.name] = id; |
|
|
|
layers[l.name] = id |
|
|
|
id += 1 |
|
|
|
|
|
|
|
for layer in model: |
|
|
|
|
|
|
print("SORTED:", sorted_layer_indices) |
|
|
|
new_model = [model[idx] for idx in sorted_layer_indices] |
|
|
|
|
|
|
|
assert(len(find_missing_inputs(new_model, inputs_and_memories)) == 0) |
|
|
|
assert len(find_missing_inputs(new_model, inputs_and_memories)) == 0 |
|
|
|
|
|
|
|
if hasattr(model, 'layers'): |
|
|
|
if hasattr(model, "layers"): |
|
|
|
def flatten(items,enter=lambda x:isinstance(x, list)): |
|
|
|
def flatten(items, enter=lambda x: isinstance(x, list)): |
|
|
|
# http://stackoverflow.com/a/40857703 |
|
|
|
# https://github.com/ctmakro/canton/blob/master/canton/misc.py |
|
|
|
"""Yield items from any nested iterable; see REF.""" |
|
|
|
|
|
|
yield x |
|
|
|
|
|
|
|
def trim_model(model, outputs): |
|
|
|
layers = {l.name:l for l in model} |
|
|
|
layers = {l.name: l for l in model} |
|
|
|
connected = {o for o in outputs} |
|
|
|
while len(outputs) > 0: |
|
|
|
outputs = set(flatten([layers[o].inputs for o in outputs if o in layers])) |
|
|
|
|
|
|
connected.add(o) |
|
|
|
|
|
|
|
trimmed = [l.name for l in model if l.name not in connected] |
|
|
|
|
|
|
|
return str(arr)[1:-1] # array to string without brackets |
|
|
|
return str(arr)[1:-1] # array to string without brackets |
|
|
|
|
|
|
|
print("TRIMMED:", array_without_brackets(trimmed)) |
|
|
|
|
|
|
|
return [l for l in model if l.name in connected] |
|
|
|
|
|
|
print("Trimming model given outputs to preserve:", preserve_outputs) |
|
|
|
model = trim_model(model, preserve_outputs) |
|
|
|
else: |
|
|
|
print("WARNING: Trim couldn't find any layers to match:", criteria_regexp_string) |
|
|
|
print( |
|
|
|
"WARNING: Trim couldn't find any layers to match:", criteria_regexp_string |
|
|
|
) |
|
|
|
|
|
|
|
if model[i].type == model[i+1].type and model[i].type == 255: # Load |
|
|
|
model[i].tensors += model[i+1].tensors |
|
|
|
del model[i+1] |
|
|
|
if model[i].type == model[i + 1].type and model[i].type == 255: # Load |
|
|
|
model[i].tensors += model[i + 1].tensors |
|
|
|
del model[i + 1] |
|
|
|
|
|
|
|
compress_classes = { |
|
|
|
'Dense' |
|
|
|
} |
|
|
|
compress_classes = {"Dense"} |
|
|
|
if (l.class_name in compress_classes): |
|
|
|
print("Compressing %s layer '%s' weights to float16" % (l.class_name, l.name)) |
|
|
|
if l.class_name in compress_classes: |
|
|
|
print( |
|
|
|
"Compressing %s layer '%s' weights to float16" % (l.class_name, l.name) |
|
|
|
) |
|
|
|
|
|
|
|
if isinstance(o, np.ndarray): # skip binary data packed inside ndarray |
|
|
|
if isinstance(o, np.ndarray): # skip binary data packed inside ndarray |
|
|
|
if getattr(o, '__dict__', None): |
|
|
|
if getattr(o, "__dict__", None): |
|
|
|
s = json.dumps(model.layers, cls=StructEncoder, separators=(', ',':')) |
|
|
|
s = json.dumps(model.layers, cls=StructEncoder, separators=(", ", ":")) |
|
|
|
s = s.replace(']}, {', ']},\n{') |
|
|
|
s = s.replace(':[{', ':[\n\t{') |
|
|
|
s = s.replace('}, {', '},\n\t{') |
|
|
|
s = s.replace("]}, {", "]},\n{") |
|
|
|
s = s.replace(":[{", ":[\n\t{") |
|
|
|
s = s.replace("}, {", "},\n\t{") |
|
|
|
|
|
|
|
return str(arr)[1:-1] # array to string without brackets |
|
|
|
return str(arr)[1:-1] # array to string without brackets |
|
|
|
|
|
|
|
if print_layer_links: |
|
|
|
for l in model.layers: |
|
|
|
|
|
|
|
|
|
|
if model.globals: |
|
|
|
if isinstance(model.globals, dict): |
|
|
|
model.globals = {x.name:x.shape for x in model.globals} |
|
|
|
model.globals = {x.name: x.shape for x in model.globals} |
|
|
|
ins = {i:model.inputs[i] for i in l.inputs if i in model.inputs} |
|
|
|
ins = {i: model.inputs[i] for i in l.inputs if i in model.inputs} |
|
|
|
else: |
|
|
|
ins = [i for i in l.inputs if i in model.inputs] |
|
|
|
if ins: |
|
|
|
|
|
|
print("OUT:", array_without_brackets(model.outputs)) |
|
|
|
|
|
|
|
if (print_tensors): |
|
|
|
if print_tensors: |
|
|
|
|
|
|
|
def __init__(self, scope=''): |
|
|
|
def __init__(self, scope=""): |
|
|
|
if attr == '_': |
|
|
|
if attr == "_": |
|
|
|
return self.layers[-1].name if len(self.layer) > 0 else self.scope |
|
|
|
raise AttributeError(attr) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i = 1 |
|
|
|
while name in self.names_taken: |
|
|
|
name = self.layers[-1].op + '_' + str(i) |
|
|
|
name = self.layers[-1].op + "_" + str(i) |
|
|
|
self.layers[-1].name = self.scope + ('/' if self.scope else '') + name |
|
|
|
self.layers[-1].name = self.scope + ("/" if self.scope else "") + name |
|
|
|
def concat(self, a, b, axis=-1, out=''): |
|
|
|
self.layers += [Struct(name=out, op='Concat', axis=axis, input=[a, b])] |
|
|
|
def concat(self, a, b, axis=-1, out=""): |
|
|
|
self.layers += [Struct(name=out, op="Concat", axis=axis, input=[a, b])] |
|
|
|
def mad(self, x, kernel, bias, out=''): |
|
|
|
self.layers += [Struct(name=out, op='Dense', input=[x, kernel, bias])] |
|
|
|
|
|
|
|
def mad(self, x, kernel, bias, out=""): |
|
|
|
self.layers += [Struct(name=out, op="Dense", input=[x, kernel, bias])] |
|
|
|
def mul(self, a, b, out=''): |
|
|
|
self.layers += [Struct(name=out, op='Mul', input=[a, b])] |
|
|
|
|
|
|
|
def mul(self, a, b, out=""): |
|
|
|
self.layers += [Struct(name=out, op="Mul", input=[a, b])] |
|
|
|
def add(self, a, b, out=''): |
|
|
|
self.layers += [Struct(name=out, op='Add', input=[a, b])] |
|
|
|
|
|
|
|
def add(self, a, b, out=""): |
|
|
|
self.layers += [Struct(name=out, op="Add", input=[a, b])] |
|
|
|
def sub(self, a, b, out=''): |
|
|
|
self.layers += [Struct(name=out, op='Sub', input=[a, b])] |
|
|
|
|
|
|
|
def sub(self, a, b, out=""): |
|
|
|
self.layers += [Struct(name=out, op="Sub", input=[a, b])] |
|
|
|
def sigmoid(self, x, out=''): |
|
|
|
self.layers += [Struct(name=out, op='Sigmoid', input=[x])] |
|
|
|
|
|
|
|
def sigmoid(self, x, out=""): |
|
|
|
self.layers += [Struct(name=out, op="Sigmoid", input=[x])] |
|
|
|
def tanh(self, x, out=''): |
|
|
|
self.layers += [Struct(name=out, op='Tanh', input=[x])] |
|
|
|
|
|
|
|
def tanh(self, x, out=""): |
|
|
|
self.layers += [Struct(name=out, op="Tanh", input=[x])] |
|
|
|
def reduce(self, op, x, axis=-1, out=''): |
|
|
|
self.layers += [Struct(name=out, op='Reduce'+op, axis=axis, input=[x])] |
|
|
|
|
|
|
|
def reduce(self, op, x, axis=-1, out=""): |
|
|
|
self.layers += [Struct(name=out, op="Reduce" + op, axis=axis, input=[x])] |
|
|
|
def pool(self, op, x, out=''): |
|
|
|
self.layers += [Struct(name=out, op=op+'Pool', input=[x])] |
|
|
|
|
|
|
|
def pool(self, op, x, out=""): |
|
|
|
self.layers += [Struct(name=out, op=op + "Pool", input=[x])] |
|
|
|
def strided_slice(self, x, begin, end, strides, rank, out=''): |
|
|
|
self.layers += [Struct(name=out, op='StridedSlice', rank=rank, starts=begin, ends=end, slice_strides=strides, input=[x])] |
|
|
|
|
|
|
|
def strided_slice(self, x, begin, end, strides, rank, out=""): |
|
|
|
self.layers += [ |
|
|
|
Struct( |
|
|
|
name=out, |
|
|
|
op="StridedSlice", |
|
|
|
rank=rank, |
|
|
|
starts=begin, |
|
|
|
ends=end, |
|
|
|
slice_strides=strides, |
|
|
|
input=[x], |
|
|
|
) |
|
|
|
] |
|
|
|
|
|
|
|
''' combines mean operation out of several simpler ops |
|
|
|
''' |
|
|
|
""" combines mean operation out of several simpler ops |
|
|
|
""" |
|
|
|
if np.array_equal(axis, [1,2]): |
|
|
|
nn.pool('GlobalAvg', input, out=name) |
|
|
|
elif np.array_equal(axis, [1,2,3]): |
|
|
|
nn.reduce('Mean', # over channels |
|
|
|
nn.pool('GlobalAvg', input), # over height & width |
|
|
|
out=name) |
|
|
|
elif np.array_equal(axis, [3]) or np.array_equal(axis, [-1]) or np.array_equal(axis, 3) or np.array_equal(axis, -1): |
|
|
|
nn.reduce('Mean', input, out=name) |
|
|
|
if np.array_equal(axis, [1, 2]): |
|
|
|
nn.pool("GlobalAvg", input, out=name) |
|
|
|
elif np.array_equal(axis, [1, 2, 3]): |
|
|
|
nn.reduce( |
|
|
|
"Mean", # over channels |
|
|
|
nn.pool("GlobalAvg", input), # over height & width |
|
|
|
out=name, |
|
|
|
) |
|
|
|
elif ( |
|
|
|
np.array_equal(axis, [3]) |
|
|
|
or np.array_equal(axis, [-1]) |
|
|
|
or np.array_equal(axis, 3) |
|
|
|
or np.array_equal(axis, -1) |
|
|
|
): |
|
|
|
nn.reduce("Mean", input, out=name) |
|
|
|
def rnn(name, input, state, kernel, bias, new_state, number_of_gates = 2): |
|
|
|
''' - Ht = f(Xt*Wi + Ht_1*Ri + Wbi + Rbi) |
|
|
|
''' |
|
|
|
|
|
|
|
def rnn(name, input, state, kernel, bias, new_state, number_of_gates=2): |
|
|
|
""" - Ht = f(Xt*Wi + Ht_1*Ri + Wbi + Rbi) |
|
|
|
""" |
|
|
|
nn.tanh( |
|
|
|
nn.mad(kernel=kernel, bias=bias, |
|
|
|
x=nn.concat(input, state)), |
|
|
|
out=new_state); |
|
|
|
nn.tanh(nn.mad(kernel=kernel, bias=bias, x=nn.concat(input, state)), out=new_state) |
|
|
|
def gru(name, input, state, kernel_r, kernel_u, kernel_c, bias_r, bias_u, bias_c, new_state, number_of_gates = 2): |
|
|
|
''' - zt = f(Xt*Wz + Ht_1*Rz + Wbz + Rbz) |
|
|
|
|
|
|
|
def gru( |
|
|
|
name, |
|
|
|
input, |
|
|
|
state, |
|
|
|
kernel_r, |
|
|
|
kernel_u, |
|
|
|
kernel_c, |
|
|
|
bias_r, |
|
|
|
bias_u, |
|
|
|
bias_c, |
|
|
|
new_state, |
|
|
|
number_of_gates=2, |
|
|
|
): |
|
|
|
""" - zt = f(Xt*Wz + Ht_1*Rz + Wbz + Rbz) |
|
|
|
''' |
|
|
|
""" |
|
|
|
nn = Build(name) |
|
|
|
inputs = nn.concat(input, state) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c = nn.tanh(nn.mad(kernel=kernel_c, bias=bias_c, |
|
|
|
x=nn.concat(input, r_state))) |
|
|
|
c = nn.tanh(nn.mad(kernel=kernel_c, bias=bias_c, x=nn.concat(input, r_state))) |
|
|
|
|
|
|
|
# new_h = u' * state + (1 - u') * c' |
|
|
|
# = u' * state + c' - u' * c' |
|
|
|
|
|
|
# - u' * c' |
|
|
|
nn.sub(nn._, nn.mul(u, c), |
|
|
|
out=new_state) |
|
|
|
nn.sub(nn._, nn.mul(u, c), out=new_state) |
|
|
|
return nn.layers; |
|
|
|
return nn.layers |
|
|
|
def lstm(name, input, state_c, state_h, kernel_i, kernel_j, kernel_f, kernel_o, bias_i, bias_j, bias_f, bias_o, new_state_c, new_state_h): |
|
|
|
''' Full: |
|
|
|
|
|
|
|
def lstm( |
|
|
|
name, |
|
|
|
input, |
|
|
|
state_c, |
|
|
|
state_h, |
|
|
|
kernel_i, |
|
|
|
kernel_j, |
|
|
|
kernel_f, |
|
|
|
kernel_o, |
|
|
|
bias_i, |
|
|
|
bias_j, |
|
|
|
bias_f, |
|
|
|
bias_o, |
|
|
|
new_state_c, |
|
|
|
new_state_h, |
|
|
|
): |
|
|
|
""" Full: |
|
|
|
- it = f(Xt*Wi + Ht_1*Ri + Pi . Ct_1 + Wbi + Rbi) |
|
|
|
- ft = f(Xt*Wf + Ht_1*Rf + Pf . Ct_1 + Wbf + Rbf) |
|
|
|
- ct = g(Xt*Wc + Ht_1*Rc + Wbc + Rbc) |
|
|
|
|
|
|
''' |
|
|
|
""" |
|
|
|
''' No peephole: |
|
|
|
""" No peephole: |
|
|
|
- it = f(Xt*Wi + Ht_1*Ri + Wbi + Rbi) |
|
|
|
- ft = f(Xt*Wf + Ht_1*Rf + Wbf + Rbf) |
|
|
|
- ct = g(Xt*Wc + Ht_1*Rc + Wbc + Rbc) |
|
|
|
|
|
|
''' |
|
|
|
""" |
|
|
|
j = nn.tanh(nn.mad(inputs, kernel_j, bias_j)) |
|
|
|
j = nn.tanh(nn.mad(inputs, kernel_j, bias_j)) |
|
|
|
nn.add( |
|
|
|
nn.mul(state_c, f), nn.mul(i, j), |
|
|
|
out=new_state_c) |
|
|
|
nn.add(nn.mul(state_c, f), nn.mul(i, j), out=new_state_c) |
|
|
|
# new_h = |
|
|
|
nn.mul(o, nn.tanh(new_state_c), |
|
|
|
out=new_state_h) |
|
|
|
# new_h = |
|
|
|
nn.mul(o, nn.tanh(new_state_c), out=new_state_h) |
|
|
|
|
|
|
|
self.f = open(filename, 'wb+') |
|
|
|
self.f = open(filename, "wb+") |
|
|
|
|
|
|
|
def __enter__(self): |
|
|
|
return self |
|
|
|
|
|
|
|
|
|
|
def write_str(self, s): |
|
|
|
self.write_int32(len(s)) |
|
|
|
self.f.write(s.encode('ascii')) |
|
|
|
self.f.write(s.encode("ascii")) |
|
|
|
self.f.write(struct.pack('<f', d)) |
|
|
|
self.f.write(struct.pack("<f", d)) |
|
|
|
self.f.write(struct.pack('<i', d)) |
|
|
|
self.f.write(struct.pack("<i", d)) |
|
|
|
self.f.write(struct.pack('<q', d)) |
|
|
|
self.f.write(struct.pack("<q", d)) |
|
|
|
|
|
|
|
def write_shape(self, s): |
|
|
|
self.write_int32(len(s)) |
|
|
|
|
|
|
def close(self): |
|
|
|
self.f.close() |
|
|
|
|
|
|
|
#VERSION = 0xBA22AC0DA000 + BARRACUDA_VERSION |
|
|
|
# VERSION = 0xBA22AC0DA000 + BARRACUDA_VERSION |
|
|
|
w.write_int64(BARRACUDA_VERSION) |
|
|
|
|
|
|
|
# inputs |
|
|
|
|
|
|
w.write_str_array(model.outputs) |
|
|
|
|
|
|
|
# memories |
|
|
|
w.write_int32(len(model.memories)//3) |
|
|
|
for mem_shape, mem_in, mem_out in zip(model.memories[0::3], model.memories[1::3], model.memories[2::3]): |
|
|
|
w.write_int32(len(model.memories) // 3) |
|
|
|
for mem_shape, mem_in, mem_out in zip( |
|
|
|
model.memories[0::3], model.memories[1::3], model.memories[2::3] |
|
|
|
): |
|
|
|
w.write_shape(mem_shape) |
|
|
|
w.write_str(mem_in) |
|
|
|
w.write_str(mem_out) |
|
|
|
|
|
|
w.write_int32(len(model.layers)) |
|
|
|
for l in model.layers: |
|
|
|
|
|
|
|
assert(not l.name in l.inputs) |
|
|
|
assert not l.name in l.inputs |
|
|
|
w.write_int32(0) #dummy |
|
|
|
w.write_int32(0) #dummy |
|
|
|
w.write_int32(0) # dummy |
|
|
|
w.write_int32(0) # dummy |
|
|
|
w.write_shape(l.pads) |
|
|
|
w.write_shape(l.strides) |
|
|
|
w.write_shape(l.pool_size) |
|
|
|
|
|
|
w.write_int32(0) #dummy |
|
|
|
w.write_int32(0) # dummy |
|
|
|
assert(len(x.shape) == 4) |
|
|
|
assert(x.data.nbytes % 4 == 0) |
|
|
|
length = x.data.nbytes >> 2 # length is measured in float32s (at least for now) |
|
|
|
assert len(x.shape) == 4 |
|
|
|
assert x.data.nbytes % 4 == 0 |
|
|
|
length = ( |
|
|
|
x.data.nbytes >> 2 |
|
|
|
) # length is measured in float32s (at least for now) |
|
|
|
|
|
|
|
w.write_str(x.name) |
|
|
|
w.write_shape(x.shape) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_known_operations(known_classes, known_activations): |
|
|
|
print('OPS supported by the converter:') |
|
|
|
print("OPS supported by the converter:") |
|
|
|
print('ACTIVATIONS supported by the converter:') |
|
|
|
print("ACTIVATIONS supported by the converter:") |
|
|
|
print(key) |
|
|
|
print(key) |