1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#!/usr/bin/env python3
import pickle
import math
import numpy as np
import re
import sys
model_file = sys.argv[1]
trim_trailing_zeros = re.compile('0+p')
def small_hex(f):
hf = float(f).hex()
return trim_trailing_zeros.sub('p', hf)
def process_column(v, pad):
""" process and pad """
return [small_hex(f) for f in v] + [small_hex(0.0)] * pad
def cformatM(fh, name, X, nr=None, nc=None):
nrq = int(math.ceil(X.shape[1] / 4.0))
pad = nrq * 4 - X.shape[1]
lines = map(lambda v: ', '.join(process_column(v, pad)), X)
if nr is None:
nr = X.shape[1]
else:
nrq = int(math.ceil(nr / 4.0))
if nc is None:
nc = X.shape[0]
fh.write('float {}[] = {}\n'.format('__' + name, '{'))
fh.write('\t' + ',\n\t'.join(lines))
fh.write('};\n')
fh.write('_Mat {} = {}\n\t.nr = {},\n\t.nrq = {},\n\t.nc = {},\n\t.stride = {},\n\t.data.f = {}\n{};\n'.format('_' + name, '{', nr, nrq, nc, nrq * 4, '__' + name, '}'))
fh.write('const scrappie_matrix {} = &{};\n\n'.format(name, '_' + name))
def cformatV(fh, name, X):
nrq = int(math.ceil(X.shape[0] / 4.0))
pad = nrq * 4 - X.shape[0]
lines = ', '.join(list(map(lambda f: small_hex(f), X)) + [small_hex(0.)] * pad)
fh.write('float {}[] = {}\n'.format( '__' + name, '{'))
fh.write('\t' + lines)
fh.write('};\n')
fh.write('_Mat {} = {}\n\t.nr = {},\n\t.nrq = {},\n\t.nc = {},\n\t.stride = {},\n\t.data.f = {}\n{};\n'.format('_' + name, '{', X.shape[0], nrq, 1, nrq * 4, '__' + name, '}'))
fh.write('const scrappie_matrix {} = &{};\n\n'.format(name, '_' + name))
with open(model_file, 'rb') as fh:
network = pickle.load(fh, encoding='latin1')
assert network.version == 1, "Sloika model must be version 1. Perhaps you need to run Sloika's model_upgrade.py"
sys.stdout.write("""#pragma once
#ifndef NANONET_RAW_MODEL_H
#define NANONET_RAW_MODEL_H
#include <assert.h>
#include "../util.h"
""")
""" First LSTM layer
"""
filterW = network.sublayers[0].W.get_value()
nfilter, _ , winlen = filterW.shape
cformatM(sys.stdout, 'conv_raw_W', filterW.reshape(-1, 1), nr = winlen * 4 - 3, nc=nfilter)
cformatV(sys.stdout, 'conv_raw_b', network.sublayers[0].b.get_value().reshape(-1))
sys.stdout.write("const int conv_raw_stride = {};\n".format(network.sublayers[0].stride))
sys.stdout.write("""const size_t _conv_nfilter = {};
const size_t _conv_winlen = {};
""".format(nfilter, winlen))
bigru1 = network.sublayers[1]
gru = bigru1.sublayers[0]
cformatM(sys.stdout, 'gruF1_raw_iW', gru.iW.get_value())
cformatM(sys.stdout, 'gruF1_raw_sW', gru.sW.get_value())
cformatM(sys.stdout, 'gruF1_raw_sW2', gru.sW2.get_value())
cformatV(sys.stdout, 'gruF1_raw_b', gru.b.get_value().reshape(-1))
gru = bigru1.sublayers[1].sublayers[0]
cformatM(sys.stdout, 'gruB1_raw_iW', gru.iW.get_value())
cformatM(sys.stdout, 'gruB1_raw_sW', gru.sW.get_value())
cformatM(sys.stdout, 'gruB1_raw_sW2', gru.sW2.get_value())
cformatV(sys.stdout, 'gruB1_raw_b', gru.b.get_value().reshape(-1))
""" First feed forward layer
"""
assert(network.sublayers[2].insize % 2 == 0)
size = network.sublayers[2].insize // 2
cformatM(sys.stdout, 'FF1_raw_Wf', network.sublayers[2].W.get_value()[:, : size])
cformatM(sys.stdout, 'FF1_raw_Wb', network.sublayers[2].W.get_value()[:, size : 2 * size])
cformatV(sys.stdout, 'FF1_raw_b', network.sublayers[2].b.get_value())
""" Second GRU layer
"""
bigru1 = network.sublayers[3]
gru = bigru1.sublayers[0]
cformatM(sys.stdout, 'gruF2_raw_iW', gru.iW.get_value())
cformatM(sys.stdout, 'gruF2_raw_sW', gru.sW.get_value())
cformatM(sys.stdout, 'gruF2_raw_sW2', gru.sW2.get_value())
cformatV(sys.stdout, 'gruF2_raw_b', gru.b.get_value().reshape(-1))
gru = bigru1.sublayers[1].sublayers[0]
cformatM(sys.stdout, 'gruB2_raw_iW', gru.iW.get_value())
cformatM(sys.stdout, 'gruB2_raw_sW', gru.sW.get_value())
cformatM(sys.stdout, 'gruB2_raw_sW2', gru.sW2.get_value())
cformatV(sys.stdout, 'gruB2_raw_b', gru.b.get_value().reshape(-1))
""" Second feed forward layer
"""
size = network.sublayers[4].insize // 2
assert(network.sublayers[4].insize % 2 == 0)
cformatM(sys.stdout, 'FF2_raw_Wf', network.sublayers[4].W.get_value()[:, : size])
cformatM(sys.stdout, 'FF2_raw_Wb', network.sublayers[4].W.get_value()[:, size : 2 * size])
cformatV(sys.stdout, 'FF2_raw_b', network.sublayers[4].b.get_value())
""" Softmax layer
"""
nstate = network.sublayers[5].W.get_value().shape[0]
shuffle = np.append(np.arange(nstate - 1) + 1, 0)
cformatM(sys.stdout, 'FF3_raw_W', network.sublayers[5].W.get_value()[shuffle])
cformatV(sys.stdout, 'FF3_raw_b', network.sublayers[5].b.get_value()[shuffle])
sys.stdout.write('#endif /* NANONET_RAW_MODEL_H */')
|