Files
2026-07-13 13:30:25 +08:00

90 lines
2.4 KiB
Python
Executable File

import numpy as np
class Tensor(object):
"""
a base class for tensor object
"""
__array_ufunc__ = None
def __init__(self, value, function=None):
"""
construct Tensor object
Parameters
----------
value : array_like
value of this tensor
function : Function
function output this tensor
"""
if not isinstance(value, (int, float, np.number, np.ndarray)):
raise TypeError(
"Unsupported class for Tensor: {}".format(type(value))
)
self.value = value
self.function = function
def __format__(self, *args, **kwargs):
return self.__repr__()
def __repr__(self):
if isinstance(self.value, np.ndarray):
return (
"{0}(shape={1.shape}, dtype={1.dtype})"
.format(self.__class__.__name__, self.value)
)
else:
return (
"{0}(value={1})".format(self.__class__.__name__, self.value)
)
@property
def ndim(self):
if hasattr(self.value, "ndim"):
return self.value.ndim
else:
return 0
@property
def shape(self):
if hasattr(self.value, "shape"):
return self.value.shape
else:
return ()
@property
def size(self):
if hasattr(self.value, "size"):
return self.value.size
else:
return 1
def backward(self, delta=1, **kwargs):
"""
back-propagate error
Parameters
----------
delta : array_like
derivative with respect to this array
"""
if isinstance(delta, np.ndarray):
if delta.shape != self.shape:
raise ValueError(
"shapes {} and {} not aligned"
.format(delta.shape, self.shape)
)
elif isinstance(delta, (int, float, np.number)):
if self.shape != ():
raise ValueError(
"delta must be np.ndarray"
)
else:
raise TypeError(
"unsupported class for delta"
)
self._backward(delta, **kwargs)
def _backward(self, delta, **kwargs):
if hasattr(self.function, "backward"):
self.function.backward(delta, **kwargs)