|
11 | 11 |
|
12 | 12 | import numpy as np |
13 | 13 | from numpy.typing import NDArray |
| 14 | +from quantizers import get_fixed_quantizer_np |
14 | 15 |
|
15 | 16 | from hls4ml.model.layers import ( |
16 | 17 | Activation, |
|
22 | 23 | Dense, |
23 | 24 | Einsum, |
24 | 25 | EinsumDense, |
| 26 | + Embedding, |
25 | 27 | GlobalPooling1D, |
26 | 28 | GlobalPooling2D, |
27 | 29 | Input, |
@@ -654,6 +656,27 @@ def _(layer: DACombinational): |
654 | 656 | return k.astype(np.int16), i.astype(np.int16), f.astype(np.int16) |
655 | 657 |
|
656 | 658 |
|
| 659 | +@_produce_kif.register |
| 660 | +def _(layer: Embedding): |
| 661 | + _, out_quantizers = get_output_layers_and_quantizers(layer) |
| 662 | + assert len(out_quantizers) == 1, 'Embedding layer should have exactly one consumer' |
| 663 | + quant = out_quantizers[0] |
| 664 | + k, b, i = quant.mask_kbi |
| 665 | + k, b, i = k[0], b[0], i[0] |
| 666 | + i, f = i - k, b - i |
| 667 | + k, i, f = np.max([k, i, f], axis=1) if isinstance(k, np.ndarray) else (k, i, f) |
| 668 | + quant = get_fixed_quantizer_np(quant.RND, quant.SAT) |
| 669 | + data = layer.attributes['embeddings'].data |
| 670 | + qdata = quant(data, k, i, f) |
| 671 | + layer.attributes['embeddings'].data = qdata |
| 672 | + k, i, f = minimal_kif(qdata) |
| 673 | + shape = get_output_shape(layer) |
| 674 | + k = np.broadcast_to(np.max(k, axis=0).astype(np.int16), shape) |
| 675 | + i = np.broadcast_to(np.max(i, axis=0).astype(np.int16), shape) |
| 676 | + f = np.broadcast_to(np.max(f, axis=0).astype(np.int16), shape) |
| 677 | + return k, i, f |
| 678 | + |
| 679 | + |
657 | 680 | def kif_arrs_to_ints(arr: tuple[np.ndarray, np.ndarray, np.ndarray]): |
658 | 681 | return tuple(int(np.max(a)) for a in arr) |
659 | 682 |
|
|
0 commit comments