Skip to content

Commit 8767027

Browse files
committed
model for 3x3 grid and created life step function for tensors
1 parent 30da570 commit 8767027

File tree

5 files changed

+161
-89
lines changed

5 files changed

+161
-89
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/.ipynb_checkpoints
2-
/.vscode
2+
/.vscode
3+
**/__pycache__

CostumisedLayers.py

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44

55
class CyclicPadding2D(keras.layers.Layer):
6+
"""
7+
It adds cyclic padding around the two last dimensions of the tensor. No weights to train.
8+
"""
69

710
def __init__(self,):
811
super(CyclicPadding2D, self).__init__()
@@ -13,6 +16,13 @@ def build(self, input_shape):
1316
super(CyclicPadding2D, self).build(input_shape)
1417

1518
def call(self, inputs):
19+
"""
20+
Args:
21+
inputs: a 3D tensor of shape (batch_size, d1, d2)
22+
23+
Returns:
24+
The padded 3D tensor of shape (batch_size, d1+2, d+2)
25+
"""
1626

1727
self.grid[:,1:-1, 1:-1].assign(inputs)
1828
self.grid[:,0,0].assign(inputs[:,-1,-1])
@@ -27,11 +37,14 @@ def call(self, inputs):
2737
return self.grid
2838

2939
class DenseSymmetric2D(tf.keras.layers.Layer):
40+
"""
41+
It creates a dense layer where the weight matrix is symmetric along the two axes.
42+
"""
3043

3144
def __init__(self,):
3245
super(DenseSymmetric2D, self).__init__()
3346

34-
def __call__(self, input_shape):
47+
def build(self, input_shape):
3548

3649
w1 = tf.constant(tf.keras.initializers.RandomUniform(minval=0.01, maxval=0.09),
3750
shape=(input_shape[0], input_shape[1], input_shape[2]))
@@ -44,23 +57,13 @@ def __call__(self, input_shape):
4457
w2 = tf.transpose(w1)
4558
self.W = w1 + w2
4659

60+
def call(self, x):
61+
# TODO: to do it all
4762

48-
def __init__(self,):
49-
50-
def build(self, input_shape):
51-
self.grid = tf.Variable(tf.zeros(shape=(input_shape[0], input_shape[1]+2, input_shape[2]+2), dtype=tf.float32),
52-
trainable=False, validate_shape=True)
53-
super(CyclicPadding2D, self).build(input_shape)
54-
55-
def call(self, inputs):
56-
57-
self.grid[:,1:-1, 1:-1].assign(inputs)
58-
self.grid[:,0,0].assign(inputs[:,-1,-1])
59-
self.grid[:,0,-1].assign( inputs[:,-1,0])
60-
self.grid[:,-1,0].assign(inputs[:,0,-1])
61-
self.grid[:,-1,-1].assign(inputs[:,0,0])
62-
6363
class LocallyDense(keras.layers.Layer):
64+
"""
65+
Warning: to be used after an instance of CyclicPadding2D.
66+
"""
6467

6568
def __init__(self, ):
6669
super(LocallyDense, self).__init__()
@@ -81,6 +84,14 @@ def build(self, input_shape):
8184
self.b = self.add_weight(name="b", shape=(m,n), initializer='zeros', trainable=True)
8285

8386
def call(self, padded_input):
87+
"""
88+
Args:
89+
padded_input (3D tensor): A tensor with shape (batch_size, d1, d2). A list of grids with cyclic padding.
90+
91+
Returns:
92+
3D tensor of shape (batch_size, d1-2, d2-2). Weighted sum of the elements in the 3x3 grid around each cell,
93+
with bias.
94+
"""
8495
p00 = padded_input[:,:-2,:-2]
8596
p01 = padded_input[:,:-2,1:-1]
8697
p02 = padded_input[:,:-2,2:]
@@ -91,17 +102,20 @@ def call(self, padded_input):
91102
p21 = padded_input[:,2:,1:-1]
92103
p22 = padded_input[:,2:,2:]
93104

94-
return tf.matmul(p00, self.w00) + tf.matmul(p01, self.w01) + tf.matmul(p02, self.w02) +
95-
tf.matmul(p10, self.w10) + tf.matmul(p11, self.w11) + tf.matmul(p12, self.w12) +
96-
tf.matmul(p20, self.w20) + tf.matmul(p21, self.w21) + tf.matmul(p22, self.w22) + self.b
105+
return tf.matmul(p00, self.w00) + tf.matmul(p01, self.w01) + tf.matmul(p02, self.w02) + \
106+
tf.matmul(p10, self.w10) + tf.matmul(p11, self.w11) + tf.matmul(p12, self.w12) + \
107+
tf.matmul(p20, self.w20) + tf.matmul(p21, self.w21) + tf.matmul(p22, self.w22) + self.b
97108

98109
class Conv2D(keras.layers.Layer):
99-
110+
"""
111+
Just a function, no weights to train.
112+
"""
113+
# TODO: check if I can just use tf.nn.conv2d in the model
114+
100115
def __init__(self,kernel):
101116
super(Conv2D, self).__init__()
102117
self.kernel = kernel
103118

104119
def call(self, x):
105-
print(x.shape)
106120
x = tf.nn.conv2d(x, self.kernel, strides=1, padding='VALID')
107121
return x

GenerateInput.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,22 @@ def generate_input(trials, grid_shape=(25,25), v_min=0.1, v_max=0.9, steps_befor
2020
samples_1_step (3D tensor): the state of the generated grids after one step
2121
"""
2222

23-
samples = []
24-
samples_1_step = []
23+
samples = []
24+
samples_1_step = []
2525

26-
probs = np.random.uniform(v_min, v_max, trials)
26+
probs = np.random.uniform(v_min, v_max, trials)
2727

28-
for prob in probs:
29-
grid = np.random.binomial(n=1, p=prob, size=grid_shape)
30-
for _ in range(steps_before_generating_output):
31-
grid = life_step_for_arrays(grid)
32-
33-
if grid.sum() > 0:
34-
samples.append(grid)
35-
grid_1_step = life_step_for_arrays(grid)
36-
samples_1_step.append(grid_1_step)
28+
for prob in probs:
29+
grid = np.random.binomial(n=1, p=prob, size=grid_shape)
30+
for _ in range(steps_before_generating_output):
31+
grid = life_step_for_arrays(grid)
32+
33+
if grid.sum() > 0:
34+
samples.append(grid)
35+
grid_1_step = life_step_for_arrays(grid)
36+
samples_1_step.append(grid_1_step)
3737

38-
samples = tf.constant(np.array(samples).astype(float), dtype="float32")
39-
samples_1_step = tf.constant(np.array(samples_1_step).astype(float), dtype="float32")
38+
samples = tf.constant(np.array(samples).astype(float), dtype="float32")
39+
samples_1_step = tf.constant(np.array(samples_1_step).astype(float), dtype="float32")
4040

41-
return samples, samples_1_step
41+
return samples, samples_1_step

LifeStepFunctions.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
import numpy as np
22
from scipy.signal import convolve2d
3+
import tensorflow as tf
34

45

56
def life_step_for_arrays(X):
67
nbrs_count = convolve2d(X, np.ones((3, 3)), mode='same', boundary='wrap') - X
78
return (nbrs_count == 3) | (X & (nbrs_count == 2))
9+
10+
def life_step_for_tensors(X):
11+
"""
12+
Args:
13+
X: 3D tensor of shape (batch_size, d1, d2).
14+
"""
15+
16+
X = tf.reshape(X, (X.shape[0], X.shape[1], X.shape[2], 1))
17+
kernel = tf.ones(shape=(3,3,1,1))
18+
X = tf.nn.conv2d(X, filters=kernel, padding='VALID')
19+
return X
20+
21+
def life_step_for_tensors_cyclic(X):
22+
# TODO
23+
return

Models.ipynb

Lines changed: 93 additions & 52 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)