Files
TinyTorch/tests/test_tensor_activations_integration.py
Vijay Janapa Reddi bfb14ce61b feat: Restructure integration tests and optimize module timing
- Flattened tests/ directory structure (removed integration/ and system/ subdirectories)
- Renamed all integration tests with _integration.py suffix for clarity
- Created test_utils.py with setup_integration_test() function
- Updated integration tests to use ONLY tinytorch package imports
- Ensured all modules are exported before running tests via tito export --all
- Optimized module test timing for fast execution (under 5 seconds each)
- Fixed MLOps test reliability and reduced timing parameters across modules
- Exported all modules (compression, kernels, benchmarking, mlops) to tinytorch package
2025-07-14 23:37:50 -04:00

220 lines
7.6 KiB
Python

"""
Integration Tests - Tensor and Activations
Tests real integration between Tensor and Activation modules.
Uses actual TinyTorch components to verify they work together correctly.
"""
import pytest
import numpy as np
from test_utils import setup_integration_test
# Ensure proper setup before importing
setup_integration_test()
# Import ONLY from TinyTorch package
from tinytorch.core.tensor import Tensor
from tinytorch.core.activations import ReLU, Sigmoid, Tanh, Softmax
class TestTensorActivationIntegration:
"""Test real integration between Tensor and Activation modules."""
def test_relu_with_real_tensors(self):
"""Test ReLU activation with real Tensor objects."""
relu = ReLU()
# Test with negative, zero, and positive values
x = Tensor([[-2.0, -1.0, 0.0, 1.0, 2.0]])
result = relu(x)
# Verify it returns a real Tensor
assert isinstance(result, Tensor)
assert result.shape == x.shape
# Verify ReLU behavior: max(0, x)
expected = np.array([[0.0, 0.0, 0.0, 1.0, 2.0]])
np.testing.assert_allclose(result.data, expected)
def test_sigmoid_with_real_tensors(self):
"""Test Sigmoid activation with real Tensor objects."""
sigmoid = Sigmoid()
# Test with various inputs
x = Tensor([[-5.0, -1.0, 0.0, 1.0, 5.0]])
result = sigmoid(x)
# Verify it returns a real Tensor
assert isinstance(result, Tensor)
assert result.shape == x.shape
# Verify sigmoid properties
assert np.all(result.data > 0.0) # All positive
assert np.all(result.data < 1.0) # All less than 1
assert np.isclose(result.data[0, 2], 0.5, atol=1e-6) # sigmoid(0) = 0.5
def test_tanh_with_real_tensors(self):
"""Test Tanh activation with real Tensor objects."""
tanh = Tanh()
x = Tensor([[-2.0, -1.0, 0.0, 1.0, 2.0]])
result = tanh(x)
# Verify it returns a real Tensor
assert isinstance(result, Tensor)
assert result.shape == x.shape
# Verify tanh properties
assert np.all(result.data > -1.0) # All greater than -1
assert np.all(result.data < 1.0) # All less than 1
assert np.isclose(result.data[0, 2], 0.0, atol=1e-6) # tanh(0) = 0
def test_softmax_with_real_tensors(self):
"""Test Softmax activation with real Tensor objects."""
softmax = Softmax()
# Test with logits
x = Tensor([[1.0, 2.0, 3.0]])
result = softmax(x)
# Verify it returns a real Tensor
assert isinstance(result, Tensor)
assert result.shape == x.shape
# Verify softmax properties
assert np.all(result.data > 0.0) # All positive
assert np.all(result.data < 1.0) # All less than 1
assert np.isclose(np.sum(result.data), 1.0, atol=1e-6) # Sums to 1
def test_activation_chaining_with_real_tensors(self):
"""Test chaining activations with real Tensors."""
relu = ReLU()
sigmoid = Sigmoid()
# Start with mixed positive/negative values
x = Tensor([[-1.0, 0.0, 1.0, 2.0]])
# Apply ReLU first: negative values become 0
relu_result = relu(x)
expected_after_relu = np.array([[0.0, 0.0, 1.0, 2.0]])
np.testing.assert_allclose(relu_result.data, expected_after_relu)
# Apply Sigmoid to ReLU output
final_result = sigmoid(relu_result)
# Verify final result properties
assert isinstance(final_result, Tensor)
assert np.all(final_result.data > 0.0)
assert np.all(final_result.data < 1.0)
# First two should be sigmoid(0) = 0.5
assert np.isclose(final_result.data[0, 0], 0.5, atol=1e-6)
assert np.isclose(final_result.data[0, 1], 0.5, atol=1e-6)
def test_batch_processing_integration(self):
"""Test activation functions work with batched tensors."""
activations = [ReLU(), Sigmoid(), Tanh()]
# Create batch of samples
batch_x = Tensor([
[-2.0, -1.0, 0.0, 1.0, 2.0],
[0.5, 1.5, -0.5, -1.5, 0.0],
[3.0, -3.0, 1.0, -1.0, 0.0]
])
for activation in activations:
result = activation(batch_x)
# Verify batch processing preserves shape
assert isinstance(result, Tensor)
assert result.shape == batch_x.shape
assert not np.any(np.isnan(result.data))
assert not np.any(np.isinf(result.data))
def test_softmax_batch_integration(self):
"""Test Softmax works correctly with batched tensors."""
softmax = Softmax()
# Create batch of logits
batch_x = Tensor([
[1.0, 2.0, 3.0],
[0.0, 0.0, 0.0],
[10.0, 20.0, 30.0]
])
result = softmax(batch_x)
# Verify batch processing
assert isinstance(result, Tensor)
assert result.shape == batch_x.shape
# Each row should sum to 1
for i in range(batch_x.shape[0]):
row_sum = np.sum(result.data[i])
assert np.isclose(row_sum, 1.0, atol=1e-6)
def test_tensor_type_preservation(self):
"""Test that activations preserve tensor type and properties."""
activations = [ReLU(), Sigmoid(), Tanh(), Softmax()]
# Test with different tensor shapes
test_tensors = [
Tensor([5.0]), # Scalar
Tensor([1.0, 2.0, 3.0]), # 1D
Tensor([[1.0, 2.0], [3.0, 4.0]]), # 2D
]
for tensor in test_tensors:
for activation in activations:
result = activation(tensor)
# Verify type preservation
assert isinstance(result, Tensor)
assert result.shape == tensor.shape
assert hasattr(result, 'data')
assert hasattr(result, 'shape')
def test_numerical_stability_integration(self):
"""Test numerical stability when using real tensors with activations."""
# Test with extreme values
extreme_tensor = Tensor([[-1000.0, 1000.0, 0.0]])
# ReLU should handle extreme values
relu = ReLU()
relu_result = relu(extreme_tensor)
assert np.all(np.isfinite(relu_result.data))
# Sigmoid should handle extreme values
sigmoid = Sigmoid()
sigmoid_result = sigmoid(extreme_tensor)
assert np.all(np.isfinite(sigmoid_result.data))
assert np.all(sigmoid_result.data >= 0.0)
assert np.all(sigmoid_result.data <= 1.0)
# Tanh should handle extreme values
tanh = Tanh()
tanh_result = tanh(extreme_tensor)
assert np.all(np.isfinite(tanh_result.data))
assert np.all(tanh_result.data >= -1.0)
assert np.all(tanh_result.data <= 1.0)
class TestActivationPolymorphism:
"""Test that activations work with different tensor-like objects."""
def test_activation_type_preservation(self):
"""Test that activations preserve input type."""
relu = ReLU()
# Test with real Tensor
tensor_input = Tensor([[1.0, -1.0, 2.0]])
tensor_result = relu(tensor_input)
# Should return same type as input
assert type(tensor_result) == type(tensor_input)
assert isinstance(tensor_result, Tensor)
if __name__ == "__main__":
# Run integration tests
pytest.main([__file__, "-v"])