[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:
@@ -7,4 +7,3 @@ images
|
||||
__pycache__
|
||||
*.npzdata
|
||||
.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
|
||||
|
||||
|
||||
class TestModel(Model):
|
||||
class BinaryAEModel(Model):
|
||||
def __init__(self, name: str, work_dir: str = '.'):
|
||||
super().__init__(name, work_dir)
|
||||
self.unit1 = Entity(
|
||||
@@ -41,11 +41,18 @@ def make_bars_and_stripes(n_cases: int, n: int = N) -> Mat:
|
||||
return data
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
prj_name = "binary_autoencoder"
|
||||
work_dir = "results"
|
||||
def test_binary_autoencoder():
|
||||
model = BinaryAEModel("binary_autoencoder_pytest", "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)
|
||||
|
||||
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}")
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -12,7 +12,7 @@ N_HID = 32
|
||||
N_CASES = 400
|
||||
|
||||
|
||||
class TestModel(Model):
|
||||
class GaussianAEModel(Model):
|
||||
def __init__(self, name: str, work_dir: str = '.'):
|
||||
super().__init__(name, work_dir)
|
||||
self.unit1 = Entity(
|
||||
@@ -41,11 +41,19 @@ def make_gaussian_blobs(n_cases: int, n: int = N) -> Mat:
|
||||
return data
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
prj_name = "gaussian_autoencoder"
|
||||
work_dir = "results"
|
||||
def test_gaussian_autoencoder():
|
||||
model = GaussianAEModel("gaussian_autoencoder_pytest", "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)
|
||||
|
||||
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}")
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -7,7 +7,7 @@ WORK_DIR = "../../results"
|
||||
USE_OPTIMIZER = True
|
||||
N_VIS = 3000
|
||||
N_CASES = 1000
|
||||
class TestModel(Model):
|
||||
class LinearModel(Model):
|
||||
def __init__(self, name: str, work_dir: str = '.', do_gaussian_hidden=False):
|
||||
super().__init__(name, work_dir)
|
||||
|
||||
@@ -28,39 +28,40 @@ class TestModel(Model):
|
||||
x = self.unit1.reconstruct(x)
|
||||
return x
|
||||
|
||||
def linear():
|
||||
work_dir = "results"
|
||||
prj_name = "linear"
|
||||
prj_root = "/home/jens/work/repos/Rbm"
|
||||
class _SmallLinearModel(Model):
|
||||
def __init__(self):
|
||||
super().__init__("linear_pytest", "results")
|
||||
self.unit1 = Entity((64, 32), EntityParams(do_gaussian_visible=True),
|
||||
TrainingParams(learning_rate=0.005, momentum=0.9, num_epochs=100))
|
||||
|
||||
# Create layer
|
||||
model = TestModel(prj_name, "results")
|
||||
def forward(self, x: Mat):
|
||||
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)
|
||||
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()
|
||||
|
||||
# Prepare training data
|
||||
training_batch = np.random.randn(N_CASES, N_VIS, dtype=np.float64)
|
||||
|
||||
# Normalize training data
|
||||
training_batch_norm = normalize(training_batch)
|
||||
|
||||
# Train layer
|
||||
model.train(training_batch_norm)
|
||||
|
||||
# Save weights
|
||||
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__":
|
||||
linear()
|
||||
print("Test: [passed]")
|
||||
main()
|
||||
@@ -2,7 +2,7 @@ from model.model import Model
|
||||
from rbm.entity import Entity, EntityParams, TrainingParams
|
||||
from rbm.matrix import Mat, np
|
||||
|
||||
class TestModel(Model):
|
||||
class DeepModel(Model):
|
||||
def __init__(self, name: str, work_dir: str = '.'):
|
||||
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))
|
||||
@@ -24,28 +24,33 @@ class TestModel(Model):
|
||||
x = self.unit1.reconstruct(x)
|
||||
return x
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Create model
|
||||
model = TestModel("TestModel", "results")
|
||||
|
||||
# Init state
|
||||
def test_deep_model():
|
||||
model = DeepModel("TestModel_pytest", "results")
|
||||
model.unit1.training_params.num_epochs = 100
|
||||
model.unit2.training_params.num_epochs = 100
|
||||
model.unit3.training_params.num_epochs = 100
|
||||
model.unit4.training_params.num_epochs = 100
|
||||
model.init(0.1)
|
||||
|
||||
# load state
|
||||
model.load()
|
||||
|
||||
# create batch
|
||||
batch = (np.random.rand(64, 1024) > 0.5).astype(np.float64)
|
||||
|
||||
# Train
|
||||
batch = (np.random.rand(32, 1024) > 0.5).astype(np.float64)
|
||||
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()
|
||||
|
||||
for index, inp in enumerate(batch):
|
||||
out = model.backward(model.forward(inp))[0]
|
||||
print(f"- Pattern {index} -------------------------")
|
||||
print(f"Input : {inp}")
|
||||
print(f"Output : {(out > 0.9).astype(np.float64)}")
|
||||
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