alecGraves / BVAE-tf

Disentangled Variational Auto-Encoder in TensorFlow / Keras (Beta-VAE)
The Unlicense
54 stars 13 forks source link

Applying to 1D data #5

Closed rojinsafavi closed 5 years ago

rojinsafavi commented 5 years ago

Hi, Thanks for providing the code! I was wondering if you know how to apply the code to a 1D data instead an image? I have done some edits to the code, but I am getting the following error:

Here is my edits to the code: `class Darknet19Encoder(Architecture): ''' This encoder predicts distributions then randomly samples them. Regularization may be applied to the latent space output

a simple, fully convolutional architecture inspried by 
    pjreddie's darknet architecture
https://github.com/pjreddie/darknet/blob/master/cfg/darknet19.cfg
'''
def __init__(self, inputShape=(16889,), batchSize=32,
             latentSize=1024, latentConstraints='bvae', beta=100., capacity=0.,
             randomSample=True):
    '''
    params
    -------
    latentConstraints : str
        Either 'bvae', 'vae', or 'no'
        Determines whether regularization is applied
            to the latent space representation.
    beta : float
        beta > 1, used for 'bvae' latent_regularizer
        (Unused if 'bvae' not selected, default 100)
    capacity : float
        used for 'bvae' to try to break input down to a set number
            of basis. (e.g. at 25, the network will try to use 
            25 dimensions of the latent space)
        (unused if 'bvae' not selected)
    randomSample : bool
        whether or not to use random sampling when selecting from distribution.
        if false, the latent vector equals the mean, essentially turning this into a
            standard autoencoder.
    '''
    self.latentConstraints = latentConstraints
    self.beta = beta
    self.latentCapacity = capacity
    self.randomSample = randomSample
    print('inputShape ', inputShape, 'batchSize ', batchSize,'latentSize ',  latentSize)

    super().__init__(inputShape, batchSize, latentSize)

def Build(self):

    # create the input layer for feeding the netowrk
    inLayer = Input(shape=(16889,))
    net = Dense(1024, activation='relu',kernel_initializer='glorot_uniform')(inLayer)
    net = BatchNormalization()(net)
    net = Activation('relu')(net)

    mean = Dense(1024, name = 'mean')(net)
    stddev = Dense(1024, name = 'std')(net)

    sample = SampleLayer(self.latentConstraints, self.beta,
                        self.latentCapacity, self.randomSample)([mean, stddev])

    return Model(inputs=inLayer, outputs=sample)`

and this is the error that I'm getting:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-124-14cadf28fcb2> in <module>()
----> 1 d19e = Darknet19Encoder()
      2 d19e.model()

<ipython-input-123-3d464c6af1ad> in __init__(self, inputShape, batchSize, latentSize, latentConstraints, beta, capacity, randomSample)
     78         print('inputShape ', inputShape, 'batchSize ', batchSize,'latentSize ',  latentSize)
     79 
---> 80         super().__init__(inputShape, batchSize, latentSize)
     81 
     82     def Build(self):

<ipython-input-123-3d464c6af1ad> in __init__(self, inputShape, batchSize, latentSize)
     37         self.latentSize = latentSize
     38 
---> 39         self.model = self.Build()
     40 
     41 

<ipython-input-123-3d464c6af1ad> in Build(self)
     93 
     94         sample = SampleLayer(self.latentConstraints, self.beta,
---> 95                             self.latentCapacity, self.randomSample)([mean, stddev])
     96 
     97         return Model(inputs=inLayer, outputs=sample)

/projects/sysbio/projects/czi/immune/anaconda2/envs/py36/lib/python3.6/site-packages/tensorflow/python/keras/engine/base_layer.py in __call__(self, inputs, *args, **kwargs)
    734 
    735       if not in_deferred_mode:
--> 736         outputs = self.call(inputs, *args, **kwargs)
    737         if outputs is None:
    738           raise ValueError('A layer\'s `call` method should return a Tensor '

<ipython-input-121-c50a024c4c69> in call(self, x)
    110 
    111         epsilon = K.random_normal(shape=self.shape,
--> 112                               mean=0., stddev=1.)
    113         if self.random:
    114             # 'reparameterization trick':

/projects/sysbio/projects/czi/immune/anaconda2/envs/py36/lib/python3.6/site-packages/tensorflow/python/keras/backend.py in random_normal(shape, mean, stddev, dtype, seed)
   4512     seed = np.random.randint(10e6)
   4513   return random_ops.random_normal(
-> 4514       shape, mean=mean, stddev=stddev, dtype=dtype, seed=seed)
   4515 
   4516 

/projects/sysbio/projects/czi/immune/anaconda2/envs/py36/lib/python3.6/site-packages/tensorflow/python/ops/random_ops.py in random_normal(shape, mean, stddev, dtype, seed, name)
     70   """
     71   with ops.name_scope(name, "random_normal", [shape, mean, stddev]) as name:
---> 72     shape_tensor = _ShapeTensor(shape)
     73     mean_tensor = ops.convert_to_tensor(mean, dtype=dtype, name="mean")
     74     stddev_tensor = ops.convert_to_tensor(stddev, dtype=dtype, name="stddev")

/projects/sysbio/projects/czi/immune/anaconda2/envs/py36/lib/python3.6/site-packages/tensorflow/python/ops/random_ops.py in _ShapeTensor(shape)
     41   else:
     42     dtype = None
---> 43   return ops.convert_to_tensor(shape, dtype=dtype, name="shape")
     44 
     45 

/projects/sysbio/projects/czi/immune/anaconda2/envs/py36/lib/python3.6/site-packages/tensorflow/python/framework/ops.py in convert_to_tensor(value, dtype, name, preferred_dtype)
    996       name=name,
    997       preferred_dtype=preferred_dtype,
--> 998       as_ref=False)
    999 
   1000 

/projects/sysbio/projects/czi/immune/anaconda2/envs/py36/lib/python3.6/site-packages/tensorflow/python/framework/ops.py in internal_convert_to_tensor(value, dtype, name, as_ref, preferred_dtype, ctx)
   1092 
   1093     if ret is None:
-> 1094       ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
   1095 
   1096     if ret is NotImplemented:

/projects/sysbio/projects/czi/immune/anaconda2/envs/py36/lib/python3.6/site-packages/tensorflow/python/framework/constant_op.py in _tensor_shape_tensor_conversion_function(s, dtype, name, as_ref)
    236   if not s.is_fully_defined():
    237     raise ValueError(
--> 238         "Cannot convert a partially known TensorShape to a Tensor: %s" % s)
    239   s_list = s.as_list()
    240   int64_value = 0

ValueError: Cannot convert a partially known TensorShape to a Tensor: (?, 1024)

and here some printing results that may help?

inputShape  (16889,) batchSize  32 latentSize  1024
len(x) 2 len(x[0].shape) 2 len(x[1].shape) 2 x [<tf.Tensor 'mean_10/BiasAdd:0' shape=(?, 1024) dtype=float32>, <tf.Tensor 'std_8/BiasAdd:0' shape=(?, 1024) dtype=float32>]
mean =  Tensor("mean_10/BiasAdd:0", shape=(?, 1024), dtype=float32)
stddev =  Tensor("std_8/BiasAdd:0", shape=(?, 1024), dtype=float32)
latent_loss Tensor("sample_layer_33/mul:0", shape=(), dtype=float32)
latent_loss Tensor("sample_layer_33/mul_1:0", shape=(), dtype=float32)
beldaz commented 5 years ago

Why not just leave the code unchanged and represent your 1D signal as a 2D signal of height 1?

alecGraves commented 5 years ago

Thank you for submitting your issue @rojinsafavi. The problem is that the layer stored input shape when the model is built, so when batch size was not defined (i.e. inLayer = Input(shape=(16889,))), it stored None for one of the shape values. This results in errors when .call() happens and it tries to make a random tensor with a shape of (None, 1024).

The error is resolved in commit 745a892df89b1fc851b44daa0acb66d18304b232