[refactor] move tests to tests/, add pytest functions and main() entrypoints
- Moved src/tests/ → tests/ - Added test_* functions with assertions to script-style test files - Added main() to each so IDEs offer it as a separate run target from pytest - Fixed cupy_test.py: remove spurious x_gpu += x_cpu, fix duplicate xlabel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+1
-2
@@ -6,5 +6,4 @@ images
|
|||||||
*.egg-info
|
*.egg-info
|
||||||
__pycache__
|
__pycache__
|
||||||
*.npzdata
|
*.npzdata
|
||||||
.ipynb_checkpoints/
|
.ipynb_checkpoints/
|
||||||
cupy_test.py
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
from image.sub_image import SubImageExtract
|
|
||||||
from rbm.matrix import np
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
n = 2
|
|
||||||
c = 3
|
|
||||||
w = 8
|
|
||||||
h = 8
|
|
||||||
img_rbb = np.reshape(np.linspace(1, n*c*w*h, num=n*c*w*h, dtype=np.float64), (n, c, w, h))
|
|
||||||
sub = SubImageExtract(4, 4, 1, 1)
|
|
||||||
sub(img_rbb, 3)
|
|
||||||
|
|
||||||
img_gray = np.reshape(np.linspace(1, n*w*h, num=n*w*h, dtype=np.float64), (n, w, h))
|
|
||||||
sub(img_gray, 1)
|
|
||||||
|
|
||||||
|
|
||||||
print("Test: [passed]")
|
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import cupy as cp
|
||||||
|
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
def warmup_cupy():
|
||||||
|
a = cp.random.random((10,10))
|
||||||
|
b = cp.random.random((10,10))
|
||||||
|
_ = cp.dot(a, b)
|
||||||
|
|
||||||
|
def calc_cpu(a: np.array, b: np.array):
|
||||||
|
return np.dot(a, b)
|
||||||
|
|
||||||
|
def calc_gpu(a: np.array, b: np.array):
|
||||||
|
return cp.dot(a, b)
|
||||||
|
|
||||||
|
def perf_test_2():
|
||||||
|
### Numpy and CPU
|
||||||
|
print("Creation")
|
||||||
|
s = time.time()
|
||||||
|
x_cpu = np.ones((1000, 1000, 1000))
|
||||||
|
e = time.time()
|
||||||
|
time_cpu = e - s
|
||||||
|
s = time.time()
|
||||||
|
x_gpu = cp.ones((1000, 1000, 1000))
|
||||||
|
cp.cuda.Stream.null.synchronize()
|
||||||
|
e = time.time()
|
||||||
|
time_gpu = e - s
|
||||||
|
print(f"Speedup: {time_cpu/time_gpu}")
|
||||||
|
|
||||||
|
### Numpy and CPU
|
||||||
|
print("Multiply with constant")
|
||||||
|
s = time.time()
|
||||||
|
x_cpu *= 5
|
||||||
|
e = time.time()
|
||||||
|
time_cpu = e - s
|
||||||
|
s = time.time()
|
||||||
|
x_gpu *= 5
|
||||||
|
cp.cuda.Stream.null.synchronize()
|
||||||
|
e = time.time()
|
||||||
|
time_gpu = e - s
|
||||||
|
print(f"Speedup: {time_cpu/time_gpu}")
|
||||||
|
|
||||||
|
### Numpy and CPU
|
||||||
|
print("Multiply with constant, Square, Square")
|
||||||
|
s = time.time()
|
||||||
|
x_cpu *= 5
|
||||||
|
x_cpu *= x_cpu
|
||||||
|
x_cpu += x_cpu
|
||||||
|
e = time.time()
|
||||||
|
time_cpu = e - s
|
||||||
|
s = time.time()
|
||||||
|
x_gpu *= 5
|
||||||
|
x_gpu *= x_gpu
|
||||||
|
x_gpu += x_gpu
|
||||||
|
cp.cuda.Stream.null.synchronize()
|
||||||
|
e = time.time()
|
||||||
|
time_gpu = e - s
|
||||||
|
print(f"Speedup: {time_cpu/time_gpu}")
|
||||||
|
|
||||||
|
def perf_test_1():
|
||||||
|
n_values = []
|
||||||
|
np_times = []
|
||||||
|
cp_times = []
|
||||||
|
ratio_times = []
|
||||||
|
|
||||||
|
for N in range(100, 5100, 100):
|
||||||
|
a_np = np.random.rand(1024, N)
|
||||||
|
b_np = np.random.rand(N, 1024)
|
||||||
|
|
||||||
|
a_cp = cp.asarray(a_np)
|
||||||
|
b_cp = cp.asarray(b_np)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
c_np = calc_cpu(a_np, b_np)
|
||||||
|
end_time = time.time()
|
||||||
|
numpy_time = end_time - start_time
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
c_cp = calc_gpu(a_cp, b_cp)
|
||||||
|
c_np = cp.asnumpy(c_cp)
|
||||||
|
end_time = time.time()
|
||||||
|
cupy_time = end_time - start_time
|
||||||
|
|
||||||
|
n_values.append(N)
|
||||||
|
np_times.append(numpy_time)
|
||||||
|
cp_times.append(cupy_time)
|
||||||
|
ratio_times.append(numpy_time/cupy_time)
|
||||||
|
|
||||||
|
plt.plot(n_values, np_times, label='numpy time')
|
||||||
|
plt.plot(n_values, cp_times, label='cupy time')
|
||||||
|
plt.plot(n_values, ratio_times, label='numpy/cupy time')
|
||||||
|
plt.xlabel("Matrix size [N]")
|
||||||
|
plt.ylabel("Time [s]")
|
||||||
|
plt.title("Performance numpy vs cupy")
|
||||||
|
plt.grid()
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
warmup_cupy()
|
||||||
|
perf_test_2()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -11,7 +11,7 @@ N_HID = 32
|
|||||||
N_CASES = 400
|
N_CASES = 400
|
||||||
|
|
||||||
|
|
||||||
class TestModel(Model):
|
class BinaryAEModel(Model):
|
||||||
def __init__(self, name: str, work_dir: str = '.'):
|
def __init__(self, name: str, work_dir: str = '.'):
|
||||||
super().__init__(name, work_dir)
|
super().__init__(name, work_dir)
|
||||||
self.unit1 = Entity(
|
self.unit1 = Entity(
|
||||||
@@ -41,11 +41,18 @@ def make_bars_and_stripes(n_cases: int, n: int = N) -> Mat:
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def test_binary_autoencoder():
|
||||||
prj_name = "binary_autoencoder"
|
model = BinaryAEModel("binary_autoencoder_pytest", "results")
|
||||||
work_dir = "results"
|
model.unit1.training_params.num_epochs = 500
|
||||||
|
model.init(0.01)
|
||||||
|
train_batch = make_bars_and_stripes(N_CASES)
|
||||||
|
model.train(train_batch)
|
||||||
|
mae = float(np.mean(np.abs(train_batch - np.array([model.reconstruct(model.forward(x)) for x in train_batch]))))
|
||||||
|
assert mae < 0.4, f"Reconstruction MAE {mae:.4f} too high"
|
||||||
|
|
||||||
model = TestModel(prj_name, work_dir)
|
|
||||||
|
def main():
|
||||||
|
model = BinaryAEModel("binary_autoencoder", "results")
|
||||||
model.init(0.01)
|
model.init(0.01)
|
||||||
|
|
||||||
train_batch = make_bars_and_stripes(N_CASES)
|
train_batch = make_bars_and_stripes(N_CASES)
|
||||||
@@ -73,3 +80,7 @@ if __name__ == "__main__":
|
|||||||
print(f"Mean reconstruction error: {total_error / n_show:.4f}")
|
print(f"Mean reconstruction error: {total_error / n_show:.4f}")
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -12,7 +12,7 @@ N_HID = 32
|
|||||||
N_CASES = 400
|
N_CASES = 400
|
||||||
|
|
||||||
|
|
||||||
class TestModel(Model):
|
class GaussianAEModel(Model):
|
||||||
def __init__(self, name: str, work_dir: str = '.'):
|
def __init__(self, name: str, work_dir: str = '.'):
|
||||||
super().__init__(name, work_dir)
|
super().__init__(name, work_dir)
|
||||||
self.unit1 = Entity(
|
self.unit1 = Entity(
|
||||||
@@ -41,11 +41,19 @@ def make_gaussian_blobs(n_cases: int, n: int = N) -> Mat:
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def test_gaussian_autoencoder():
|
||||||
prj_name = "gaussian_autoencoder"
|
model = GaussianAEModel("gaussian_autoencoder_pytest", "results")
|
||||||
work_dir = "results"
|
model.unit1.training_params.num_epochs = 1500
|
||||||
|
model.init(0.01)
|
||||||
|
train_batch = normalize(make_gaussian_blobs(N_CASES))
|
||||||
|
model.train(train_batch)
|
||||||
|
for x in train_batch[:10]:
|
||||||
|
recon = model.reconstruct(model.forward(x))
|
||||||
|
assert recon.size == x.size
|
||||||
|
|
||||||
model = TestModel(prj_name, work_dir)
|
|
||||||
|
def main():
|
||||||
|
model = GaussianAEModel("gaussian_autoencoder", "results")
|
||||||
model.init(0.01)
|
model.init(0.01)
|
||||||
|
|
||||||
train_batch = normalize(make_gaussian_blobs(N_CASES))
|
train_batch = normalize(make_gaussian_blobs(N_CASES))
|
||||||
@@ -73,3 +81,7 @@ if __name__ == "__main__":
|
|||||||
print(f"Mean reconstruction error: {total_error / n_show:.4f}")
|
print(f"Mean reconstruction error: {total_error / n_show:.4f}")
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -7,7 +7,7 @@ WORK_DIR = "../../results"
|
|||||||
USE_OPTIMIZER = True
|
USE_OPTIMIZER = True
|
||||||
N_VIS = 3000
|
N_VIS = 3000
|
||||||
N_CASES = 1000
|
N_CASES = 1000
|
||||||
class TestModel(Model):
|
class LinearModel(Model):
|
||||||
def __init__(self, name: str, work_dir: str = '.', do_gaussian_hidden=False):
|
def __init__(self, name: str, work_dir: str = '.', do_gaussian_hidden=False):
|
||||||
super().__init__(name, work_dir)
|
super().__init__(name, work_dir)
|
||||||
|
|
||||||
@@ -28,39 +28,40 @@ class TestModel(Model):
|
|||||||
x = self.unit1.reconstruct(x)
|
x = self.unit1.reconstruct(x)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
def linear():
|
class _SmallLinearModel(Model):
|
||||||
work_dir = "results"
|
def __init__(self):
|
||||||
prj_name = "linear"
|
super().__init__("linear_pytest", "results")
|
||||||
prj_root = "/home/jens/work/repos/Rbm"
|
self.unit1 = Entity((64, 32), EntityParams(do_gaussian_visible=True),
|
||||||
|
TrainingParams(learning_rate=0.005, momentum=0.9, num_epochs=100))
|
||||||
|
|
||||||
# Create layer
|
def forward(self, x: Mat):
|
||||||
model = TestModel(prj_name, "results")
|
return self.unit1.forward(x)
|
||||||
|
|
||||||
# Init weights
|
def reconstruct(self, x: Mat):
|
||||||
|
return self.unit1.reconstruct(x)
|
||||||
|
|
||||||
|
|
||||||
|
def test_linear():
|
||||||
|
model = _SmallLinearModel()
|
||||||
model.init(0.1)
|
model.init(0.1)
|
||||||
|
batch = normalize(np.random.randn(50, 64, dtype=np.float64))
|
||||||
|
model.train(batch)
|
||||||
|
for pattern in batch:
|
||||||
|
recon = model.reconstruct(model.forward(pattern))
|
||||||
|
assert recon.size == pattern.size
|
||||||
|
|
||||||
# Load weights (if exists)
|
|
||||||
|
def main():
|
||||||
|
model = LinearModel("linear", "results")
|
||||||
|
model.init(0.1)
|
||||||
model.load()
|
model.load()
|
||||||
|
|
||||||
# Prepare training data
|
|
||||||
training_batch = np.random.randn(N_CASES, N_VIS, dtype=np.float64)
|
training_batch = np.random.randn(N_CASES, N_VIS, dtype=np.float64)
|
||||||
|
|
||||||
# Normalize training data
|
|
||||||
training_batch_norm = normalize(training_batch)
|
training_batch_norm = normalize(training_batch)
|
||||||
|
|
||||||
# Train layer
|
|
||||||
model.train(training_batch_norm)
|
model.train(training_batch_norm)
|
||||||
|
|
||||||
# Save weights
|
|
||||||
model.save()
|
model.save()
|
||||||
|
for pattern in training_batch:
|
||||||
|
model.reconstruct(model.forward(pattern))
|
||||||
|
|
||||||
# Test with test data
|
|
||||||
test_batch = training_batch
|
|
||||||
for pattern in test_batch:
|
|
||||||
h = model.forward(pattern)
|
|
||||||
v = model.reconstruct(h)
|
|
||||||
# print(f"P{pattern} : {v}")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
linear()
|
main()
|
||||||
print("Test: [passed]")
|
|
||||||
@@ -2,7 +2,7 @@ from model.model import Model
|
|||||||
from rbm.entity import Entity, EntityParams, TrainingParams
|
from rbm.entity import Entity, EntityParams, TrainingParams
|
||||||
from rbm.matrix import Mat, np
|
from rbm.matrix import Mat, np
|
||||||
|
|
||||||
class TestModel(Model):
|
class DeepModel(Model):
|
||||||
def __init__(self, name: str, work_dir: str = '.'):
|
def __init__(self, name: str, work_dir: str = '.'):
|
||||||
super().__init__(name, work_dir)
|
super().__init__(name, work_dir)
|
||||||
self.unit1 = Entity((1024, 333), EntityParams(), TrainingParams(learning_rate=0.1, momentum=0.9, do_rao_blackwell=True, num_epochs=1000))
|
self.unit1 = Entity((1024, 333), EntityParams(), TrainingParams(learning_rate=0.1, momentum=0.9, do_rao_blackwell=True, num_epochs=1000))
|
||||||
@@ -24,28 +24,33 @@ class TestModel(Model):
|
|||||||
x = self.unit1.reconstruct(x)
|
x = self.unit1.reconstruct(x)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def test_deep_model():
|
||||||
# Create model
|
model = DeepModel("TestModel_pytest", "results")
|
||||||
model = TestModel("TestModel", "results")
|
model.unit1.training_params.num_epochs = 100
|
||||||
|
model.unit2.training_params.num_epochs = 100
|
||||||
# Init state
|
model.unit3.training_params.num_epochs = 100
|
||||||
|
model.unit4.training_params.num_epochs = 100
|
||||||
model.init(0.1)
|
model.init(0.1)
|
||||||
|
batch = (np.random.rand(32, 1024) > 0.5).astype(np.float64)
|
||||||
# load state
|
|
||||||
model.load()
|
|
||||||
|
|
||||||
# create batch
|
|
||||||
batch = (np.random.rand(64, 1024) > 0.5).astype(np.float64)
|
|
||||||
|
|
||||||
# Train
|
|
||||||
model.train(batch)
|
model.train(batch)
|
||||||
|
errors = [float(np.mean((model.backward(model.forward(x)) - x) ** 2)) for x in batch]
|
||||||
|
assert sum(errors) / len(errors) < 0.5, "Deep model reconstruction MSE too high"
|
||||||
|
|
||||||
# save state
|
|
||||||
|
def main():
|
||||||
|
model = DeepModel("TestModel", "results")
|
||||||
|
model.init(0.1)
|
||||||
|
model.load()
|
||||||
|
batch = (np.random.rand(64, 1024) > 0.5).astype(np.float64)
|
||||||
|
model.train(batch)
|
||||||
model.save()
|
model.save()
|
||||||
|
|
||||||
for index, inp in enumerate(batch):
|
for index, inp in enumerate(batch):
|
||||||
out = model.backward(model.forward(inp))[0]
|
out = model.backward(model.forward(inp))[0]
|
||||||
print(f"- Pattern {index} -------------------------")
|
print(f"- Pattern {index} -------------------------")
|
||||||
print(f"Input : {inp}")
|
print(f"Input : {inp}")
|
||||||
print(f"Output : {(out > 0.9).astype(np.float64)}")
|
print(f"Output : {(out > 0.9).astype(np.float64)}")
|
||||||
print(f"Error : {np.mean((out - inp)**2):0.3f}")
|
print(f"Error : {np.mean((out - inp)**2):0.3f}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
from image.sub_image import SubImageExtract
|
||||||
|
from rbm.matrix import np
|
||||||
|
|
||||||
|
|
||||||
|
def test_sub_image_rgb():
|
||||||
|
n, c, w, h = 2, 3, 8, 8
|
||||||
|
img = np.reshape(np.linspace(1, n*c*w*h, num=n*c*w*h, dtype=np.float64), (n, c, w, h))
|
||||||
|
sub = SubImageExtract(4, 4, 1, 1)
|
||||||
|
result = sub(img, 3)
|
||||||
|
assert result.shape[1] == 3
|
||||||
|
assert result.shape[2] == 4 and result.shape[3] == 4
|
||||||
|
|
||||||
|
|
||||||
|
def test_sub_image_gray():
|
||||||
|
n, w, h = 2, 8, 8
|
||||||
|
img = np.reshape(np.linspace(1, n*w*h, num=n*w*h, dtype=np.float64), (n, w, h))
|
||||||
|
sub = SubImageExtract(4, 4, 1, 1)
|
||||||
|
result = sub(img, 1)
|
||||||
|
assert result.shape[1] == 1
|
||||||
|
assert result.shape[2] == 4 and result.shape[3] == 4
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_sub_image_rgb()
|
||||||
|
test_sub_image_gray()
|
||||||
|
print("Test: [passed]")
|
||||||
Reference in New Issue
Block a user