Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion test/specialfunctions/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ set(fppFiles
fypp_f90("${fyppFlags}" "${fppFiles}" outFiles)

ADDTEST(specialfunctions_gamma)
ADDTEST(specialfunctions_activations)
ADDTEST(specialfunctions_activations)

target_link_libraries(specialfunctions_activations PRIVATE stdlib_io)
Binary file added test/specialfunctions/data/elu_derivative.npy
Binary file not shown.
Binary file added test/specialfunctions/data/elu_input.npy
Binary file not shown.
Binary file added test/specialfunctions/data/elu_output.npy
Binary file not shown.
Binary file added test/specialfunctions/data/relu_derivative.npy
Binary file not shown.
Binary file added test/specialfunctions/data/relu_input.npy
Binary file not shown.
Binary file added test/specialfunctions/data/relu_output.npy
Binary file not shown.
Binary file added test/specialfunctions/data/selu_derivative.npy
Binary file not shown.
Binary file added test/specialfunctions/data/selu_input.npy
Binary file not shown.
Binary file added test/specialfunctions/data/selu_output.npy
Binary file not shown.
Binary file added test/specialfunctions/data/sigmoid_derivative.npy
Binary file not shown.
Binary file added test/specialfunctions/data/sigmoid_input.npy
Binary file not shown.
Binary file added test/specialfunctions/data/sigmoid_output.npy
Binary file not shown.
Binary file not shown.
Binary file added test/specialfunctions/data/softplus_input.npy
Binary file not shown.
Binary file added test/specialfunctions/data/softplus_output.npy
Binary file not shown.
Binary file not shown.
Binary file added test/specialfunctions/data/softsign_input.npy
Binary file not shown.
Binary file added test/specialfunctions/data/softsign_output.npy
Binary file not shown.
Binary file added test/specialfunctions/data/tanh_derivative.npy
Binary file not shown.
Binary file added test/specialfunctions/data/tanh_input.npy
Binary file not shown.
Binary file added test/specialfunctions/data/tanh_output.npy
Binary file not shown.
47 changes: 47 additions & 0 deletions test/specialfunctions/generate_activation_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# --- python script: generate_activation_data.py ---
# place this in test/specialfunctions/

import numpy as np
import torch
import os

# create a directory to store the reference data
data_dir = 'data'
if not os.path.exists(data_dir):
os.makedirs(data_dir)

# define a range of inputs to test
x_np = np.linspace(-10.0, 10.0, num=1001, dtype=np.float64)
x_torch = torch.tensor(x_np, requires_grad=True)

# map the activation functions available in stdlib to their PyTorch equivalents
activations = {
"sigmoid": torch.sigmoid,
"tanh": torch.tanh,
"relu": torch.relu,
"elu": torch.nn.functional.elu,
"selu": torch.nn.functional.selu,
"softplus": torch.nn.functional.softplus,
"softsign": torch.nn.functional.softsign,
}

print("Generating reference data...")

for name, func in activations.items():
# Reset gradients for each function
if x_torch.grad is not None:
x_torch.grad.zero_()

# calculate the function and its derivative
y = func(x_torch)
y.sum().backward()
derivative = x_torch.grad.numpy()

# save input, output, and derivative as .npy files
np.save(f'{data_dir}/{name}_input.npy', x_np)
np.save(f'{data_dir}/{name}_output.npy', y.detach().numpy())
np.save(f'{data_dir}/{name}_derivative.npy', derivative)

print(f"Generated data for: {name}")

print("All reference data generated successfully.")
27 changes: 26 additions & 1 deletion test/specialfunctions/test_specialfunctions_activations.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module test_specialfunctions_activation
use stdlib_kinds
use stdlib_specialfunctions
use stdlib_math, only: linspace
use stdlib_io_npy_load, only: load_npy
implicit none
private

Expand All @@ -31,7 +32,8 @@ contains
new_unittest("sigmoid", test_sigmoid), &
new_unittest("silu" , test_silu), &
new_unittest("softmax", test_softmax), &
new_unittest("logsoftmax", test_logsoftmax) &
new_unittest("logsoftmax", test_logsoftmax), &
new_unittest("sigmoid_pytorch", test_sigmoid_pytorch) &
]
end subroutine collect_specialfunctions_activation

Expand Down Expand Up @@ -382,6 +384,29 @@ contains
#:endfor
end subroutine test_logsoftmax

subroutine test_sigmoid_pytorch(error)
type(error_type), allocatable, intent(out) :: error

real(dp), allocatable :: x(:), y_ref(:), y_calc(:)
integer :: n

! 1. Load the data generated by Python
! Make sure you ran 'python generate_data.py' in this folder first!
call load_npy('data/sigmoid_input.npy', x)
call load_npy('data/sigmoid_output.npy', y_ref)

n = size(x)
allocate(y_calc(n))

! 2. Calculate using stdlib
y_calc = sigmoid(x)

! 3. Compare
call check(error, norm2(y_calc - y_ref) < 1.0e-9_dp, &
"Sigmoid mismatch against PyTorch reference")
if (allocated(error)) return

end subroutine test_sigmoid_pytorch

end module test_specialfunctions_activation

Expand Down