Skip to content

Commit e325797

Browse files
Progress on DataGenerator.
1 parent 842d8af commit e325797

8 files changed

Lines changed: 246 additions & 32 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'''Generates synthetic data for training and testing autoencoders.'''
2+
3+
import autoencodersb.constants as cn
4+
5+
import itertools
6+
import numpy as np # type: ignore
7+
from torch.utils.data import DataLoader
8+
import pandas as pd # type: ignore
9+
from typing import cast, Optional, Tuple
10+
11+
12+
class DataGenerator(object):
13+
14+
def __init__(self,
15+
num_sample: int = 1000,
16+
num_independent_feature: int = 2,
17+
num_feature: int = 10,
18+
num_data_value: int = 10,
19+
data_density: float = 1.0, # Number of values per integer interval
20+
noise_std: float = 0.0
21+
):
22+
self.num_sample = num_sample
23+
self.num_independent_feature = num_independent_feature
24+
self.num_feature = num_feature
25+
self.num_data_value = num_data_value
26+
self.data_density = data_density
27+
self.noise_std = noise_std
28+
29+
def generateFullData(self) -> DataLoader:
30+
"""Generates the full synthetic dataset."""
31+
raise NotImplementedError("This method should be overridden by subclasses.")
32+
33+
def generateIndependentFeatures(self) -> np.ndarray:
34+
"""
35+
Generates an array of independent features.
36+
37+
Returns:
38+
np.ndarray (N X I): An array of size independent features.
39+
N is self.num_sample
40+
I self.num_independent_feature
41+
"""
42+
raise NotImplementedError("This method should be overridden by subclasses.")
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'''Generates synthetic data where the independent variables are iid.'''
2+
3+
import autoencodersb.constants as cn
4+
from autoencodersb.data_generator import DataGenerator # type: ignore
5+
6+
import itertools
7+
import numpy as np # type: ignore
8+
from torch.utils.data import DataLoader
9+
import pandas as pd # type: ignore
10+
from typing import cast, Optional, Tuple
11+
12+
13+
class DataGeneratorIID(DataGenerator):
14+
15+
def __init__(self,
16+
num_sample: int = 1000,
17+
num_independent_feature: int = 2,
18+
num_feature: int = 10,
19+
num_data_value: int = 10,
20+
data_density: float = 1.0, # Number of values per integer interval
21+
noise_std: float = 0.0
22+
):
23+
super().__init__(
24+
num_sample=num_sample,
25+
num_independent_feature=num_independent_feature,
26+
num_feature=num_feature,
27+
num_data_value=num_data_value,
28+
data_density=data_density,
29+
noise_std=noise_std
30+
)
31+
32+
def generateIndependentFeatures(self) -> np.ndarray:
33+
"""
34+
Generates an array of independent features.
35+
36+
Returns:
37+
np.ndarray (N X I): An array of size independent features.
38+
N is self.num_sample
39+
I self.num_independent_feature
40+
"""
41+
return np.random.randint(1, self.num_data_value + 1,
42+
(self.num_sample, self.num_independent_feature)).astype(np.float32) / self.data_density
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'''Generates synthetic data where the independent variables are a random walk.'''
2+
3+
import autoencodersb.constants as cn
4+
from autoencodersb.data_generator import DataGenerator # type: ignore
5+
6+
import numpy as np # type: ignore
7+
import pandas as pd # type: ignore
8+
from typing import cast, Optional, Tuple
9+
10+
11+
class DataGeneratorPath(DataGenerator):
12+
13+
def __init__(self,
14+
num_sample: int = 1000,
15+
num_independent_feature: int = 2,
16+
num_feature: int = 10,
17+
num_data_value: int = 10,
18+
data_density: float = 1.0, # Number of values per integer interval
19+
noise_std: float = 0.0
20+
):
21+
super().__init__(
22+
num_sample=num_sample,
23+
num_independent_feature=num_independent_feature,
24+
num_feature=num_feature,
25+
num_data_value=num_data_value,
26+
data_density=data_density,
27+
noise_std=noise_std
28+
)
29+
30+
def generateIndependentFeature(self) -> np.ndarray:
31+
"""
32+
Generates a random walk
33+
34+
Returns:
35+
np.ndarray (N X I): An array of size independent features.
36+
N is self.num_sample
37+
I is self.num_independent_feature
38+
"""
39+
path = np.zeros((self.num_sample, self.num_independent_feature), dtype=np.float32)
40+
for i in range(1, self.num_sample):
41+
path[i] = path[i - 1] + np.random.normal(0, self.noise_std, size=(self.num_independent_feature,))
42+
return path
43+
44+
N is self.num_sample
45+
I self.num_independent_feature
46+
"""
47+
return np.random.randint(1, self.num_data_value + 1,
48+
(self.num_sample, self.num_independent_feature)).astype(np.float32) / self.data_density
49+
50+
def generateIndependentFeatures(self) -> np.ndarray:
51+
"""
52+
Generates an array of independent features.
53+
54+
Returns:
55+
np.ndarray (N X I): An array of size independent features.
56+
N is self.num_sample
57+
I self.num_independent_feature
58+
"""
59+
return np.random.randint(1, self.num_data_value + 1,
60+
(self.num_sample, self.num_independent_feature)).astype(np.float32) / self.data_density

src/autoencodersb/polynomial.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'''Constructs a polynomial of arrays.'''
2+
3+
from autoencodersb.polynomial_rational import PolynomialRational # type: ignore
4+
5+
import numpy as np
6+
from typing import List
7+
8+
"""
9+
A PolynomialTerm of D variables has a coefficient and specifies exponents for 0 or more
10+
independent variables. The term represents the product of the independent variables raised
11+
to the power of the exponents times the coefficient.
12+
A PolynomialDivision is the ratio of two PolynomialTerm.
13+
An expression is a collection of PolynomialTerm and PolynomialDivision.
14+
"""
15+
16+
class Polynomial(object):
17+
18+
def __init__(self, polynomial_rationals: List[PolynomialRational] ):
19+
self.num_variable = np.sum([t.num_variable for t in polynomial_rationals])
20+
self.num_term = len(polynomial_rationals)
21+
self.terms = polynomial_rationals
22+
23+
def __repr__(self):
24+
return " + ".join([str(term) for term in self.terms])
25+
26+
def evaluate(self, independent_variable_arr: np.ndarray) -> np.ndarray:
27+
"""Evaluate the polynomial at the given independent variable values."""
28+
return np.sum([term.evaluate(independent_variable_arr) for term in self.terms], axis=0)
29+
30+
def make_polynomial(self, degree: int) -> np.ndarray:
31+
"""Construct a polynomial of the given degree."""
32+
# Create a grid of independent variable values
33+
x = np.linspace(-1, 1, 100)
34+
X = np.array(np.meshgrid(*[x]*self.num_variable)).T.reshape(-1, self.num_variable)
35+
# Compute the polynomial features
36+
poly = np.hstack([X**d for d in range(1, degree + 1)])
37+
return poly

src/autoencodersb/polynomial_maker.py

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'''Represents a product of independent variables raised to an exponent.'''
2+
3+
from autoencodersb.polynomial_term import PolynomialTerm # type: ignore
4+
5+
import numpy as np
6+
import pandas as pd # type: ignore
7+
from typing import List
8+
9+
10+
class PolynomialRational(object):
11+
12+
def __init__(self, numerator: PolynomialTerm, denominator: PolynomialTerm):
13+
self.numerator = numerator
14+
self.denominator = denominator
15+
exponents = numerator.exponent_arr + denominator.exponent_arr
16+
self.num_variable = len([e for e in exponents if e != 0])
17+
18+
def __repr__(self):
19+
return f"({self.numerator}) / ({self.denominator})"
20+
21+
def evaluate(self, independent_variable_arr: np.ndarray) -> np.ndarray:
22+
"""Divide this polynomial term by another polynomial term.
23+
24+
Args:
25+
other (PolynomialTerm): The polynomial term to divide by.
26+
27+
Returns:
28+
PolynomialTerm: The resulting polynomial term after division.
29+
"""
30+
numerator_value = self.numerator.evaluate(independent_variable_arr)
31+
denominator_value = self.denominator.evaluate(independent_variable_arr)
32+
return numerator_value / denominator_value
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'''Represents a product of independent variables raised to an exponent.'''
2+
3+
import numpy as np
4+
import pandas as pd # type: ignore
5+
from typing import List
6+
7+
8+
class PolynomialTerm(object):
9+
10+
def __init__(self, coefficient: float, exponents: List[float]):
11+
self.coefficient = coefficient
12+
self.exponent_arr = np.array(exponents)
13+
self.num_variable = len([e for e in exponents if e != 0])
14+
15+
def __repr__(self):
16+
term_strs = [f"X_{n}**{p}" for n, p in enumerate(self.exponent_arr) if p != 0]
17+
term_str = f"{self.coefficient} * {' * '.join(term_strs)}"
18+
return term_str
19+
20+
def evaluate(self, independent_variable_arr: np.ndarray) -> np.ndarray:
21+
"""Evaluate the polynomial term.
22+
23+
Args:
24+
independent_variable_arr (np.ndarray): N X I array of independent variables
25+
26+
Returns:
27+
np.ndarray: Result of the evaluation
28+
"""
29+
# Evaluate the term by multiplying the coefficient with the independent variables raised to the appropriate powers
30+
return self.coefficient * np.prod(independent_variable_arr ** self.exponent_arr, axis=1)

tests/test_dataset_csv.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
from iplane.dataset_csv import DatasetCSV # type: ignore
2-
import iplane.constants as cn # type: ignore
1+
from autoencodersb.dataset_csv import DatasetCSV # type: ignore
2+
import autoencodersb.constants as cn # type: ignore
33

44
import pandas as pd # type: ignore
55
import unittest
66

77
IGNORE_TESTS = False
8-
IS_PLOT = False
8+
IS_PLOT = False:while
99
NUM_EPOCH = 3
1010

1111
DATASET_CSV_PATH = "tests/test_dataset_csv.csv"

0 commit comments

Comments
 (0)