|
6 | 6 | from keras.src.backend.openvino.core import OPENVINO_DTYPES
|
7 | 7 | from keras.src.backend.openvino.core import OpenVINOKerasTensor
|
8 | 8 | from keras.src.backend.openvino.core import convert_to_numpy
|
| 9 | +from keras.src.backend.openvino.core import get_ov_output |
9 | 10 | from keras.src.random.seed_generator import SeedGenerator
|
10 | 11 | from keras.src.random.seed_generator import draw_seed
|
11 | 12 | from keras.src.random.seed_generator import make_default_seed
|
@@ -39,9 +40,63 @@ def uniform(shape, minval=0.0, maxval=1.0, dtype=None, seed=None):
|
39 | 40 |
|
40 | 41 |
|
41 | 42 | def categorical(logits, num_samples, dtype="int64", seed=None):
|
42 |
| - raise NotImplementedError( |
43 |
| - "`categorical` is not supported with openvino backend" |
| 43 | + def get_shape_dims(x): |
| 44 | + shape = ov_opset.shape_of(x, Type.i32) |
| 45 | + rank_tensor = ov_opset.shape_of(shape, Type.i32) |
| 46 | + rank_scalar = ov_opset.squeeze( |
| 47 | + rank_tensor, ov_opset.constant([0], Type.i32) |
| 48 | + ) |
| 49 | + indices = ov_opset.range( |
| 50 | + ov_opset.constant(0, Type.i32), |
| 51 | + rank_scalar, |
| 52 | + ov_opset.constant(1, Type.i32), |
| 53 | + output_type=Type.i32, |
| 54 | + ) |
| 55 | + return ov_opset.gather(shape, indices, axis=0) |
| 56 | + |
| 57 | + dtype = dtype or "int64" |
| 58 | + ov_dtype = OPENVINO_DTYPES[dtype] |
| 59 | + logits = get_ov_output(logits) |
| 60 | + probs = ov_opset.softmax(logits, axis=-1) |
| 61 | + cumsum_probs = ov_opset.cumsum(probs, ov_opset.constant(-1, dtype="int32")) |
| 62 | + shape = get_shape_dims(logits) |
| 63 | + rank_tensor = ov_opset.shape_of(shape, Type.i32) |
| 64 | + rank = ov_opset.squeeze(rank_tensor, ov_opset.constant([0], dtype=Type.i32)) |
| 65 | + rank_minus_1 = ov_opset.subtract(rank, ov_opset.constant(1, dtype=Type.i32)) |
| 66 | + indices = ov_opset.range( |
| 67 | + ov_opset.constant(0, dtype=Type.i32), |
| 68 | + rank_minus_1, |
| 69 | + ov_opset.constant(1, dtype=Type.i32), |
| 70 | + output_type=Type.i32, |
| 71 | + ) |
| 72 | + batch_shape = ov_opset.gather(shape, indices, axis=0) |
| 73 | + final_shape = ov_opset.concat( |
| 74 | + [batch_shape, ov_opset.constant([num_samples], dtype=Type.i32)], axis=0 |
| 75 | + ) |
| 76 | + seed_tensor = draw_seed(seed) |
| 77 | + if isinstance(seed_tensor, OpenVINOKerasTensor): |
| 78 | + seed1, seed2 = convert_to_numpy(seed_tensor) |
| 79 | + else: |
| 80 | + seed1, seed2 = seed_tensor.data |
| 81 | + rand = ov_opset.random_uniform( |
| 82 | + final_shape, |
| 83 | + ov_opset.constant(0.0, dtype=probs.get_element_type()), |
| 84 | + ov_opset.constant(1.0, dtype=probs.get_element_type()), |
| 85 | + probs.get_element_type(), |
| 86 | + seed1, |
| 87 | + seed2, |
| 88 | + ) |
| 89 | + rand = ov_opset.unsqueeze(rand, [-1]) |
| 90 | + cumsum_probs = ov_opset.unsqueeze( |
| 91 | + cumsum_probs, ov_opset.constant([1], dtype=Type.i32) |
| 92 | + ) |
| 93 | + greater = ov_opset.greater(rand, cumsum_probs) |
| 94 | + samples = ov_opset.reduce_sum( |
| 95 | + ov_opset.convert(greater, Type.i32), |
| 96 | + ov_opset.constant([-1], dtype=Type.i32), |
44 | 97 | )
|
| 98 | + samples = ov_opset.convert(samples, ov_dtype) |
| 99 | + return OpenVINOKerasTensor(samples.output(0)) |
45 | 100 |
|
46 | 101 |
|
47 | 102 | def randint(shape, minval, maxval, dtype="int32", seed=None):
|
|
0 commit comments