Skip to content

Instantly share code, notes, and snippets.

@Denbergvanthijs
Last active April 13, 2024 12:44
Show Gist options
  • Save Denbergvanthijs/a634d249e8784e340aa8d5d90d527711 to your computer and use it in GitHub Desktop.
Save Denbergvanthijs/a634d249e8784e340aa8d5d90d527711 to your computer and use it in GitHub Desktop.

Revisions

  1. Denbergvanthijs revised this gist Jun 3, 2021. No changes.
  2. Denbergvanthijs revised this gist Jun 3, 2021. 1 changed file with 4 additions and 5 deletions.
    9 changes: 4 additions & 5 deletions game_of_life_keras.py
    Original file line number Diff line number Diff line change
    @@ -6,14 +6,13 @@
    from tensorflow.keras.models import Sequential

    size = 128
    full_size = (1, size, size, 1)
    padded_size = (1, size + 2, size + 2, 1)
    padded_size = (1, size, size, 1)
    n_frames = 240
    glider = ((1, 2), (2, 3), (3, 1), (3, 2), (3, 3))
    full_size = (1, size, size, 1)

    env = np.random.randint(0, 2, full_size)

    # env = np.zeros(full_size, dtype=int)
    # glider = ((1, 2), (2, 3), (3, 1), (3, 2), (3, 3))
    # for pos in glider:
    # env[(0,) + pos] = 1

    @@ -44,7 +43,7 @@ def kernel(shape, dtype=None):


    # convolve2d of scipy does support torus-padding but that's obviously not as cool as a neural network
    model = Sequential([InputLayer(input_shape=padded_size[1:]),
    model = Sequential([InputLayer(input_shape=full_size[1:]),
    TorusPaddingLayer(),
    Conv2D(1, 3, padding="valid", activation=None, use_bias=False, kernel_initializer=kernel)])

  3. Denbergvanthijs revised this gist Jun 3, 2021. 1 changed file with 23 additions and 20 deletions.
    43 changes: 23 additions & 20 deletions game_of_life_keras.py
    Original file line number Diff line number Diff line change
    @@ -5,16 +5,17 @@
    from tensorflow.keras.layers import Conv2D, InputLayer, Layer
    from tensorflow.keras.models import Sequential

    size = 10
    size = 128
    full_size = (1, size, size, 1)
    padded_size = (1, size + 2, size + 2, 1)
    n_frames = 120
    padded_size = (1, size, size, 1)
    n_frames = 240
    glider = ((1, 2), (2, 3), (3, 1), (3, 2), (3, 3))

    # env = np.random.randint(0, 2, full_size)
    env = np.zeros(full_size, dtype=int)
    for pos in glider:
    env[(0,) + pos] = 1
    env = np.random.randint(0, 2, full_size)
    # env = np.zeros(full_size, dtype=int)
    # for pos in glider:
    # env[(0,) + pos] = 1


    class TorusPaddingLayer(Layer):
    @@ -26,33 +27,35 @@ def __init__(self, **kwargs):
    top_row[0, -1] = 1
    bottom_row[-1, 0] = 1

    self.pre = tf.convert_to_tensor(np.vstack((top_row, np.eye(size), bottom_row)), dtype=tf.int32)
    self.pre = tf.convert_to_tensor(np.vstack((top_row, np.eye(size), bottom_row)), dtype=tf.float32)
    self.pre = tf.expand_dims(self.pre, 0)
    self.pre = tf.expand_dims(self.pre, -1)
    self.pre_T = tf.transpose(self.pre)

    def call(self, inputs):
    squeezed = tf.squeeze(inputs)
    result = self.pre @ squeezed @ self.pre_T
    result = tf.expand_dims(result, 0)
    result = tf.expand_dims(result, -1)
    return result
    """Matrix product of three matrices of shape (1, size, size, 1) while keeping outer dimensions."""
    return tf.einsum("abcd,ecfg,hfij->abij", self.pre, inputs, self.pre_T)


    torus_padding = TorusPaddingLayer()
    def kernel(shape, dtype=None):
    kernel = np.ones(shape)
    kernel[1, 1] = 0 # Don't count the cell itself in the number of neighbours
    return tf.convert_to_tensor(kernel, dtype=dtype)


    # convolve2d of scipy does support torus-padding but that's obviously not as cool as a neural network
    model = Sequential([InputLayer(input_shape=padded_size[1:]),
    Conv2D(1, 3, padding="valid", activation=None, use_bias=False, kernel_initializer="ones")])
    TorusPaddingLayer(),
    Conv2D(1, 3, padding="valid", activation=None, use_bias=False, kernel_initializer=kernel)])

    frames = []
    for i in range(n_frames):
    # 2D sliding window of 3x3 including summation
    # NOTE: convolve2d of scipy does support torus-padding but that's obviously not as cool as a neural network
    # TODO: Add custom layer to Sequential model, causing bugs at the moment
    padded = torus_padding(env)
    neighbours = (model(padded) - env) # Don't count the cell itself in the number of neighbours
    neighbours = model(env)
    env = np.where((env & np.isin(neighbours, (2, 3))) | ((env == 0) & (neighbours == 3)), 1, 0)
    frames.append(env.squeeze())


    fig = plt.figure()
    fig = plt.figure(figsize=(6, 6))
    ax = plt.axes(xlim=(0, size), ylim=(0, size))
    render = plt.imshow(frames[0], interpolation="none", cmap="binary")

  4. Denbergvanthijs revised this gist May 31, 2021. 1 changed file with 36 additions and 10 deletions.
    46 changes: 36 additions & 10 deletions game_of_life_keras.py
    Original file line number Diff line number Diff line change
    @@ -1,33 +1,59 @@
    import matplotlib.pyplot as plt
    import numpy as np
    import tensorflow as tf
    from matplotlib.animation import FuncAnimation
    from tensorflow.keras.layers import Conv2D, InputLayer
    from tensorflow.keras.layers import Conv2D, InputLayer, Layer
    from tensorflow.keras.models import Sequential

    size = (10, 10)
    expanded_size = (1, *size, 1)
    size = 10
    full_size = (1, size, size, 1)
    padded_size = (1, size + 2, size + 2, 1)
    n_frames = 120
    glider = ((1, 2), (2, 3), (3, 1), (3, 2), (3, 3))

    # env = np.random.randint(0, 2, expanded_size)
    env = np.zeros(expanded_size, dtype=int)
    # env = np.random.randint(0, 2, full_size)
    env = np.zeros(full_size, dtype=int)
    for pos in glider:
    env[(0,) + pos] = 1

    model = Sequential([InputLayer(input_shape=expanded_size[1:]),
    Conv2D(1, 3, padding="same", activation=None, use_bias=False, kernel_initializer="ones")])

    class TorusPaddingLayer(Layer):
    def __init__(self, **kwargs):
    """Based on: https://stackoverflow.com/questions/39088489/tensorflow-periodic-padding"""
    super(TorusPaddingLayer, self).__init__(**kwargs)
    top_row = np.zeros((1, size))
    bottom_row = np.zeros((1, size))
    top_row[0, -1] = 1
    bottom_row[-1, 0] = 1

    self.pre = tf.convert_to_tensor(np.vstack((top_row, np.eye(size), bottom_row)), dtype=tf.int32)
    self.pre_T = tf.transpose(self.pre)

    def call(self, inputs):
    squeezed = tf.squeeze(inputs)
    result = self.pre @ squeezed @ self.pre_T
    result = tf.expand_dims(result, 0)
    result = tf.expand_dims(result, -1)
    return result


    torus_padding = TorusPaddingLayer()
    model = Sequential([InputLayer(input_shape=padded_size[1:]),
    Conv2D(1, 3, padding="valid", activation=None, use_bias=False, kernel_initializer="ones")])

    frames = []
    for i in range(n_frames):
    # 2D sliding window of 3x3 including summation TODO: add torus-style wrapping
    # 2D sliding window of 3x3 including summation
    # NOTE: convolve2d of scipy does support torus-padding but that's obviously not as cool as a neural network
    neighbours = model(env) - env # Don't count the cell itself in the number of neighbours
    # TODO: Add custom layer to Sequential model, causing bugs at the moment
    padded = torus_padding(env)
    neighbours = (model(padded) - env) # Don't count the cell itself in the number of neighbours
    env = np.where((env & np.isin(neighbours, (2, 3))) | ((env == 0) & (neighbours == 3)), 1, 0)
    frames.append(env.squeeze())


    fig = plt.figure()
    ax = plt.axes(xlim=(0, size[0]), ylim=(0, size[1]))
    ax = plt.axes(xlim=(0, size), ylim=(0, size))
    render = plt.imshow(frames[0], interpolation="none", cmap="binary")


  5. Denbergvanthijs revised this gist May 31, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions game_of_life_keras.py
    Original file line number Diff line number Diff line change
    @@ -20,6 +20,7 @@
    frames = []
    for i in range(n_frames):
    # 2D sliding window of 3x3 including summation TODO: add torus-style wrapping
    # NOTE: convolve2d of scipy does support torus-padding but that's obviously not as cool as a neural network
    neighbours = model(env) - env # Don't count the cell itself in the number of neighbours
    env = np.where((env & np.isin(neighbours, (2, 3))) | ((env == 0) & (neighbours == 3)), 1, 0)
    frames.append(env.squeeze())
  6. Denbergvanthijs created this gist May 30, 2021.
    42 changes: 42 additions & 0 deletions game_of_life_keras.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.animation import FuncAnimation
    from tensorflow.keras.layers import Conv2D, InputLayer
    from tensorflow.keras.models import Sequential

    size = (10, 10)
    expanded_size = (1, *size, 1)
    n_frames = 120
    glider = ((1, 2), (2, 3), (3, 1), (3, 2), (3, 3))

    # env = np.random.randint(0, 2, expanded_size)
    env = np.zeros(expanded_size, dtype=int)
    for pos in glider:
    env[(0,) + pos] = 1

    model = Sequential([InputLayer(input_shape=expanded_size[1:]),
    Conv2D(1, 3, padding="same", activation=None, use_bias=False, kernel_initializer="ones")])

    frames = []
    for i in range(n_frames):
    # 2D sliding window of 3x3 including summation TODO: add torus-style wrapping
    neighbours = model(env) - env # Don't count the cell itself in the number of neighbours
    env = np.where((env & np.isin(neighbours, (2, 3))) | ((env == 0) & (neighbours == 3)), 1, 0)
    frames.append(env.squeeze())


    fig = plt.figure()
    ax = plt.axes(xlim=(0, size[0]), ylim=(0, size[1]))
    render = plt.imshow(frames[0], interpolation="none", cmap="binary")


    def animate(i: int):
    render.set_array(frames[i])
    return [render]


    anim = FuncAnimation(fig, animate, frames=n_frames, interval=30, blit=True)
    plt.axis("off")
    plt.gca().invert_yaxis()
    anim.save("glider.gif", fps=30)
    plt.show()