diff --git a/build/tensor.o b/build/tensor.o index 85b704a..10402c8 100644 Binary files a/build/tensor.o and b/build/tensor.o differ diff --git a/norch/__pycache__/tensor.cpython-38.pyc b/norch/__pycache__/tensor.cpython-38.pyc index 1192401..141689f 100644 Binary files a/norch/__pycache__/tensor.cpython-38.pyc and b/norch/__pycache__/tensor.cpython-38.pyc differ diff --git a/norch/csrc/tensor.cpp b/norch/csrc/tensor.cpp index 63568cc..889fff6 100644 --- a/norch/csrc/tensor.cpp +++ b/norch/csrc/tensor.cpp @@ -639,7 +639,7 @@ extern "C" { Tensor* tensor_div_tensor(Tensor* tensor1, Tensor* tensor2) { if (tensor1->ndim != tensor2->ndim) { - fprintf(stderr, "Tensors must have the same number of dimensions %d and %d for element-wise multiplication\n", tensor1->ndim, tensor2->ndim); + fprintf(stderr, "Tensors must have the same number of dimensions %d and %d for element-wise division\n", tensor1->ndim, tensor2->ndim); exit(1); } @@ -664,7 +664,7 @@ extern "C" { for (int i = 0; i < ndim; i++) { if (tensor1->shape[i] != tensor2->shape[i]) { - fprintf(stderr, "Tensors must have the same shape %d and %d at index %d for subtraction\n", tensor1->shape[i], tensor2->shape[i], i); + fprintf(stderr, "Tensors must have the same shape %d and %d at index %d for division\n", tensor1->shape[i], tensor2->shape[i], i); exit(1); } shape[i] = tensor1->shape[i]; diff --git a/norch/libtensor.so b/norch/libtensor.so index de7ec33..81254ad 100755 Binary files a/norch/libtensor.so and b/norch/libtensor.so differ diff --git a/norch/nn/functional.py b/norch/nn/functional.py index 9b5c3ec..75654cf 100644 --- a/norch/nn/functional.py +++ b/norch/nn/functional.py @@ -4,15 +4,15 @@ def sigmoid(x): return 1.0 / (1.0 + (math.e) ** (-x)) def softmax(x, dim=None): - e = math.e ** x - s = e.sum(axis=dim, keepdim=True) - #l = s.log() - print('x', x) - print('\n\n') - #print('log', l) + if dim is not None and dim < 0: + dim = x.ndim + dim + + x_max = x.max(axis=dim, keepdim=True) + exp_x = math.e ** (x - x_max) - print('\n\n') - #print('x-log', x - l) - - - #return math.e ** (x - sum.log()) \ No newline at end of file + if dim is not None: + sum_exp_x = exp_x.sum(axis=dim, keepdim=True) + exp_x.zeros_like() + return exp_x / sum_exp_x + else: + sum_exp_x = exp_x.sum() + return exp_x / sum_exp_x \ No newline at end of file diff --git a/norch/tensor.py b/norch/tensor.py index 52a5558..49df15d 100644 --- a/norch/tensor.py +++ b/norch/tensor.py @@ -613,6 +613,9 @@ class Tensor: result_data.grad_fn = DivisionBackward(self, other) elif isinstance(self, Tensor) and isinstance(other, Tensor): + if other.numel == 1: + return self.__truediv__(other.tensor.contents.data[0]) + Tensor._C.tensor_div_tensor.argtypes = [ctypes.POINTER(CTensor), ctypes.POINTER(CTensor)] Tensor._C.tensor_div_tensor.restype = ctypes.POINTER(CTensor) @@ -749,8 +752,12 @@ class Tensor: return result_data def sum(self, axis=None, keepdim=False): + if axis is not None and axis < 0: + axis = self.ndim + axis + if axis == None: axis = -1 + Tensor._C.sum_tensor.argtypes = [ctypes.POINTER(CTensor), ctypes.c_int, ctypes.c_bool] Tensor._C.sum_tensor.restype = ctypes.POINTER(CTensor) @@ -786,12 +793,15 @@ class Tensor: return result_data def max(self, axis=None, keepdim=False): + if axis is not None and axis < 0: + axis = self.ndim + axis + if axis == None: axis = -1 + Tensor._C.max_tensor.argtypes = [ctypes.POINTER(CTensor), ctypes.c_int, ctypes.c_bool] Tensor._C.max_tensor.restype = ctypes.POINTER(CTensor) - print(axis, keepdim) result_tensor_ptr = Tensor._C.max_tensor(self.tensor, axis, keepdim) result_data = Tensor() @@ -824,8 +834,12 @@ class Tensor: return result_data def min(self, axis=None, keepdim=False): + if axis is not None and axis < 0: + axis = self.ndim + axis + if axis == None: axis = -1 + Tensor._C.min_tensor.argtypes = [ctypes.POINTER(CTensor), ctypes.c_int, ctypes.c_bool] Tensor._C.min_tensor.restype = ctypes.POINTER(CTensor) diff --git a/test.py b/test.py index f6125ae..6bd8b2a 100644 --- a/test.py +++ b/test.py @@ -7,8 +7,9 @@ import random random.seed(1) torch_tensor = norch.Tensor([[[2, 2], [-1, -1]], [[1., 2], [3, 3]]], requires_grad=True)#.to(self.device) +torch_tensor = norch.Tensor([[[2, 2], [2, 2]], [[2, 2.], [2, 2]]]) b = norch.nn.functional.softmax(torch_tensor) - +print(b) """a = norch.Tensor([[[4.186502456665039]]]) b = norch.Tensor([[[2.0, 2.0,],[-1.0, -1.0,]],[[1.0, 2.0,],[3.0, 3.0,]]]) diff --git a/tests/test_nn.py b/tests/test_nn.py index daaac21..1010c82 100644 --- a/tests/test_nn.py +++ b/tests/test_nn.py @@ -95,13 +95,13 @@ class TestNNModuleActivationFn(unittest.TestCase): """ # Test different axes - axes = [None, 0, 1, -1] + axes = [0, 1, 2, -1] # Define the input tensors for different test cases test_cases = [ - (norch.Tensor([[1., 2, 3], [4, 5, 6]]), torch.tensor([[1., 2, 3], [4, 5, 6]])), - (norch.Tensor([[1., -1, 0], [2, -2, 0]]), torch.tensor([[1., -1, 0], [2, -2, 0]])), - (norch.Tensor([[0., 0, 0], [0, 0, 0]]), torch.tensor([[0., 0, 0], [0, 0, 0]])) + (norch.Tensor([[[1., 2, 3], [4, 5, 6]]]), torch.tensor([[[1., 2, 3], [4, 5, 6]]])), + (norch.Tensor([[[1., -1, 0], [2, -2, 0]]]), torch.tensor([[[1., -1, 0], [2, -2, 0]]])), + (norch.Tensor([[[0., 0, 0], [0, 0, 0]]]), torch.tensor([[[0., 0, 0], [0, 0, 0]]])) ] for dim in axes: @@ -121,7 +121,5 @@ class TestNNModuleActivationFn(unittest.TestCase): softmax_torch_expected = softmax_fn_torch.forward(torch_input) # Compare the results - print(softmax_torch_result) - print(softmax_torch_expected) self.assertTrue(utils.compare_torch(softmax_torch_result, softmax_torch_expected)) diff --git a/tests/test_operations.py b/tests/test_operations.py index dffe0a1..961cb17 100644 --- a/tests/test_operations.py +++ b/tests/test_operations.py @@ -260,6 +260,17 @@ class TestTensorOperations(unittest.TestCase): self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + # negative axis + + norch_tensor = norch.Tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + norch_result = norch_tensor.sum(axis=-2) + torch_result = utils.to_torch(norch_result).to(self.device) + + torch_tensor = torch.tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + torch_expected = torch.sum(torch_tensor, dim=-2) + + self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + def test_sum_axis_keepdim(self): """ @@ -301,6 +312,17 @@ class TestTensorOperations(unittest.TestCase): self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + # negative axis + + norch_tensor = norch.Tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + norch_result = norch_tensor.max(axis=-1) + torch_result = utils.to_torch(norch_result).to(self.device) + + torch_tensor = torch.tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + torch_expected, _ = torch.max(torch_tensor, dim=-1) + + self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + def test_max_axis_keepdim(self): """ @@ -341,6 +363,17 @@ class TestTensorOperations(unittest.TestCase): self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + # negative axis + + norch_tensor = norch.Tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + norch_result = norch_tensor.min(axis=-1) + torch_result = utils.to_torch(norch_result).to(self.device) + + torch_tensor = torch.tensor([[[1, 2], [3, -4]], [[5, 6], [7, 8]]]).to(self.device) + torch_expected, _ = torch.min(torch_tensor, dim=-1) + + self.assertTrue(utils.compare_torch(torch_result, torch_expected)) + def test_min_axis_keepdim(self): """