forked from tinygrad/tinygrad
_one_hot_along_dim and one_hot to mixin (#15861)
This commit is contained in:
@@ -62,6 +62,11 @@ class TestTensorUOpCumalu(unittest.TestCase):
|
||||
def test_cumsum_large(self): _check(self, _t(600), lambda x: x.cumsum()) # exercises _split_cumalu
|
||||
def test_cumprod(self): _check(self, _t(4), lambda x: x.cumprod(0))
|
||||
|
||||
class TestTensorUOpOneHot(unittest.TestCase):
|
||||
def test_one_hot(self):
|
||||
t = _t(5)
|
||||
self.assertIs(_strip_unique(t.one_hot(5).uop), _strip_unique(t.uop.one_hot(5)))
|
||||
|
||||
class TestTensorUOpCat(unittest.TestCase):
|
||||
def test_cat_dim0(self): _check(self, _t(2, 3), lambda x: x.cat(x, dim=0))
|
||||
def test_cat_dim1(self): _check(self, _t(2, 3), lambda x: x.cat(x, dim=1))
|
||||
|
||||
@@ -575,6 +575,27 @@ class OpMixin(ElementwiseMixin, ReduceMixin):
|
||||
"""
|
||||
return self._split_cumalu(axis, Ops.MUL)
|
||||
|
||||
# helper function commonly used for indexing
|
||||
def _one_hot_along_dim(self, num_classes:sint, dim:int=-1) -> Self:
|
||||
from tinygrad.uop.ops import sint_to_uop
|
||||
if not dtypes.is_int(self.dtype): raise RuntimeError(f"_one_hot_along_dim expects int index tensor, getting {self.dtype}")
|
||||
offset = self.ndim - self._resolve_dim(dim) - 1
|
||||
dt = dtypes.int64 if sint_to_uop(num_classes).overflows(dtypes.int32) else dtypes.int32
|
||||
return self.eq(type(self).arange(num_classes, dtype=dt, device=self.device).reshape((num_classes,) + (1,) * offset))
|
||||
|
||||
def one_hot(self, num_classes:int) -> Self:
|
||||
"""
|
||||
Converts `self` to a one-hot tensor.
|
||||
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
t = Tensor([0, 1, 3, 3, 4])
|
||||
print(t.one_hot(5).numpy())
|
||||
```
|
||||
"""
|
||||
if not dtypes.is_int(self.dtype): raise RuntimeError(f"expect integer dtype, getting {self.dtype=}")
|
||||
if num_classes < 0: raise ValueError(f"num_classes must be non-negative, got {num_classes}")
|
||||
return self[..., None]._one_hot_along_dim(num_classes).where(1, 0)
|
||||
|
||||
# ***** functional nn ops *****
|
||||
|
||||
def linear(self, weight:Self, bias:Self|None=None, dtype:DTypeLike|None=None) -> Self:
|
||||
|
||||
+1
-22
@@ -11,8 +11,7 @@ from tinygrad.helpers import resolve_pool_pads, IMAGE, FLOAT16, WINO, Metadata,
|
||||
from tinygrad.helpers import suppress_finalizing, disable_gc
|
||||
from tinygrad.gradient import compute_gradient
|
||||
from tinygrad.mixin import OpMixin, ReductionStr
|
||||
from tinygrad.uop.ops import smax, UOp, Ops, sint, all_metadata, _index_to_concrete_int, sint_to_uop, Variable
|
||||
from tinygrad.uop.ops import _broadcast_shape
|
||||
from tinygrad.uop.ops import smax, UOp, Ops, sint, all_metadata, _index_to_concrete_int, Variable, _broadcast_shape
|
||||
from tinygrad.schedule import ExecItem, create_linear_with_vars, linear_to_schedule
|
||||
from tinygrad.device import Buffer, canonicalize_device
|
||||
from tinygrad.engine.realize import run_linear
|
||||
@@ -2006,26 +2005,6 @@ class Tensor(OpMixin):
|
||||
if p == 1: return self.zeros_like()
|
||||
return (Tensor.rand_like(self, requires_grad=False, dtype=dtypes.default_float, contiguous=False) >= p).contiguous().where(self, 0) / (1.0 - p)
|
||||
|
||||
# helper function commonly used for indexing
|
||||
def _one_hot_along_dim(self:Tensor, num_classes:sint, dim:int=-1) -> Tensor:
|
||||
if not dtypes.is_int(self.dtype): raise RuntimeError(f"_one_hot_along_dim expects int index tensor, getting {self.dtype}")
|
||||
offset = self.ndim - self._resolve_dim(dim) - 1
|
||||
dt = dtypes.int64 if sint_to_uop(num_classes).overflows(dtypes.int32) else dtypes.int32
|
||||
return self == Tensor.arange(num_classes, dtype=dt, device=self.device, requires_grad=False).reshape((num_classes,) + (1,) * offset)
|
||||
|
||||
def one_hot(self, num_classes:int) -> Tensor:
|
||||
"""
|
||||
Converts `self` to a one-hot tensor.
|
||||
|
||||
```python exec="true" source="above" session="tensor" result="python"
|
||||
t = Tensor([0, 1, 3, 3, 4])
|
||||
print(t.one_hot(5).numpy())
|
||||
```
|
||||
"""
|
||||
if not dtypes.is_int(self.dtype): raise RuntimeError(f"expect integer dtype, getting {self.dtype=}")
|
||||
if num_classes < 0: raise ValueError(f"num_classes must be non-negative, got {num_classes}")
|
||||
return self[..., None]._one_hot_along_dim(num_classes).where(1, 0)
|
||||
|
||||
def scaled_dot_product_attention(self, key:Tensor, value:Tensor, attn_mask:Tensor|None=None, dropout_p:float=0.0,
|
||||
is_causal:bool=False, enable_gqa:bool=False) -> Tensor:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user