You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
6.0 KiB

import numpy as np
import quantizer
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + '/'
QUANT_MODE = 1
def pool2d(input, kernel=3, stride=2, padding=0, pooltype='max', poolmode='valid'):
assert pooltype in ['max', 'avg']
assert poolmode in ['valid', 'full']
channel, height, width = input.shape
# padding
if padding > 0:
pad_w = np.zeros((channel, height, padding), dtype=np.uint8)
inputp = np.concatenate((pad_w, input, pad_w), axis=2)
pad_h = np.zeros((channel, padding, width + 2*padding), dtype=np.uint8)
inputp = np.concatenate((pad_h, inputp, pad_h), axis=1)
else:
inputp = input
# mode
height = height + 2*padding
width = width + 2*padding
if poolmode == 'full':
modh = (height - kernel) % stride
modw = (width - kernel) % stride
if modh != 0:
pad_w = np.zeros((channel, height, stride - modh), dtype=np.uint8)
inputp = np.concatenate((inputp, pad_w), axis=2)
width += stride - modh
if modw != 0:
pad_h = np.zeros((channel, stride - modw, width), dtype=np.uint8)
inputp = np.concatenate((inputp, pad_h), axis=1)
height += stride - modw
oheight = int((height - kernel) / stride + 1)
owidth = int((width - kernel) / stride + 1)
# pooling
output = np.zeros((channel, oheight, owidth), dtype=np.uint8)
oy = ox = 0
for y in range(0, height, stride):
if y + kernel > height:
continue
for x in range(0, width, stride):
if x + kernel > width:
continue
pool_data = inputp[:, y:y+kernel, x:x+kernel]
pool_data = quantizer.anti_quantize(pool_data)
if pooltype == 'max':
out_data = np.max(pool_data.reshape(channel, -1), axis=1).astype(np.float32)
else:
out_data = np.average(pool_data.reshape(channel, -1), axis=1).astype(np.float32)
output[:, oy, ox] = quantizer.quantize(out_data, QUANT_MODE)
ox += 1
if ox >= owidth:
ox = 0
oy += 1
return output.astype(np.uint8)
def relu(input):
shape = input.shape
output = quantizer.anti_quantize(input)
output = output.reshape(-1)
for i, elem in enumerate(output):
if elem < 0:
output[i] = 0
output = quantizer.quantize(output, QUANT_MODE)
return output.reshape(*shape)
def elemwize_add(input0, input1):
input0 = quantizer.anti_quantize(input0)
input1 = quantizer.anti_quantize(input1)
output = np.add(input0, input1)
output = quantizer.quantize(output, QUANT_MODE)
return output
def feature_reshape(data, layout='CHW'):
assert layout in ['CHW', 'HWC']
if layout == 'CHW':
data = data.transpose((1, 2, 0))
h, w, c = data.shape
oc = int((c + 63) / 64)
outdata = np.zeros((oc, h, w, 64), dtype=np.uint8)
for oci in range(oc):
start = oci * 64
end = (oci + 1) * 64
if end > c:
end = c
cnum = end - start
outdata[oci, :, :, 0 : cnum] = data[:, :, start : end]
return outdata
if __name__ == '__main__':
import json
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('mode')
args = parser.parse_args()
quantizer.generate_quant_binfile(BASE_DIR + 'quant.bin', QUANT_MODE)
if args.mode == 'pool':
with open(BASE_DIR + 'pool.json', 'r') as f:
instr = json.load(f)[0]
c, w, h = (instr['input_channel'], instr['input_height'], instr['input_width'])
kernel, pad, stride= (instr['kernel_size'], 0, instr['stride'])
pooltype = 'max' if instr['pool_type'] & 0x2 == 0 else 'avg'
infile_name = BASE_DIR + 'pool/pool_input.bin'
outfile_name = BASE_DIR + 'pool/' + pooltype + '_pool_output.bin'
input_data = np.arange(c * w * h).reshape(c, w, h).astype(np.uint8)
output_data = pool2d(input_data, kernel=kernel, stride=stride, padding=pad, pooltype=pooltype, poolmode='full')
# print(output_data.shape)
np.set_printoptions(formatter={'int': hex})
indata = feature_reshape(input_data)
outdata = feature_reshape(output_data)
with open(infile_name, 'wb') as f:
f.write(indata.tobytes())
with open(outfile_name, 'wb') as f:
f.write(outdata.tobytes())
elif args.mode == 'active':
with open(BASE_DIR + 'active.json', 'r') as f:
instr = json.load(f)[0]
c, w, h = (instr['input_channel'], instr['input_height'], instr['input_width'])
infile_name = BASE_DIR + 'active/active_input.bin'
outfile_name = BASE_DIR + 'active/active_output.bin'
input_data = np.arange(c * w * h).reshape(c, w, h).astype(np.uint8)
# input_data = np.ones(c * w * h).reshape(c, w, h).astype(np.uint8) * -2
output_data = relu(input_data)
np.set_printoptions(formatter={'int': hex})
indata = feature_reshape(input_data)
outdata = feature_reshape(output_data)
with open(infile_name, 'wb') as f:
f.write(indata.tobytes())
with open(outfile_name, 'wb') as f:
f.write(outdata.tobytes())
elif args.mode == 'eltwise':
with open(BASE_DIR + 'eltwise.json', 'r') as f:
instr = json.load(f)[0]
c, w, h = (instr['input_channel'], instr['input_height'], instr['input_width'])
infile_name = BASE_DIR + 'eltwise/eltwise_input.bin'
outfile_name = BASE_DIR + 'eltwise/eltwise_output.bin'
input_data = np.arange(c * w * h).reshape(c, w, h).astype(np.uint8)
output_data = elemwize_add(input_data, input_data)
# print(output_data.shape)
np.set_printoptions(formatter={'int': hex})
indata = feature_reshape(input_data)
outdata = feature_reshape(output_data)
with open(infile_name, 'wb') as f:
f.write(indata.tobytes())
with open(outfile_name, 'wb') as f:
f.write(outdata.tobytes())