Skip to content

SS-VAE - #107

Closed
karalets wants to merge 23 commits into
devfrom
SS-VAE
Closed

SS-VAE#107
karalets wants to merge 23 commits into
devfrom
SS-VAE

Conversation

@karalets

@karalets karalets commented Sep 12, 2017

Copy link
Copy Markdown
Collaborator

DO NOT MERGE YET, WIP

Closes #210

Added some lacking stuff.

  1. a version with the hypothetical integrated out done barefoot variable in "examples/vae_bernoulli_ss_integrated.py" . A clean version would be Summing out discrete variables in ELBo  #99

  2. a 2layer deep ss-vae with the model P(x,z1, z2, class) = P(x|z1) P(z1|z2, class) P(class) P(z2)
    This matches what the Kingma paper has as the M2 model closer, but is trained jointly instead of pretraining M1 and then learning M2.

  3. some visualization and t-sne routines in workflow which analyze what is going on. This can be improved, obviously.

Still pending:

  1. I will review @eb8680 's condition and do poutines tomorrow and consider utilizing them to add the observe statement into the guide (refers should observe be a special case of sample? #29 )
  2. Whether or not I use (1) , I will add the auxiliary loss to ensure that the guide for the class is always trained in the semi-supervised case, it is currently not contained in these models.

We can either leave this pr open until it is complete or we can do many smaller PRs until all the issues related to SS-learning are resolved.

References issue #79 , #94

@karalets
karalets requested review from OptimusLime, jpchen, ngoodman and rohitsingh0812 and removed request for jpchen September 12, 2017 05:11
@karalets
karalets requested a review from jpchen September 12, 2017 18:24
Comment thread examples/vae_bernoulli_ss_integrated.py Outdated
import pyro
from torch.autograd import Variable
from pyro.infer.kl_qp import KL_QP
from pyro.infer.abstract_infer import lw_expectation

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lw_expectation no longer exists

Comment thread examples/vae_bernoulli_ss_2l.py Outdated
import pyro
from torch.autograd import Variable
from pyro.infer.kl_qp import KL_QP
from pyro.infer.abstract_infer import lw_expectation

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lw_expectation no longer exists

@karalets

Copy link
Copy Markdown
Collaborator Author

I added some notes on the math contained in the Kingma paper to #79 , to keep them permanent.

Comment thread examples/vae_bernoulli_ss_integrated.py Outdated
pyro.observe("obs", Bernoulli(img_mu), data.view(-1, 784))


def model_latent(data):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karalets this is the barefoot bit?

@karalets karalets Sep 19, 2017

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This here is supposed to be the barefoot bit. About line 170 currently.

def model_latent(data):
    """
    analytically integrate over all classes
    """
    nr_classes = 10
    alpha = Variable(torch.ones([data.size(0), 10])) / 10.
    #cll = pyro.sample('latent_class', Categorical(alpha))
    for ic in range(nr_classes):
        cll = Variable(torch.zeros([data.size(0), 10]))
        cll[:,ic] = 1
        pyro.observe("latent_class", Categorical(alpha), cll)
        model_observed(data, cll)
    pass

Have a look in the code [edited by jpchen: got it to show correctly]. It comments that it suppsoedly does that. All it does is score each choice of extra.

So I am calculating this here:
Sum_y [ log P(x|y,z) + logP(y|x) ]

@karalets

karalets commented Sep 19, 2017

Copy link
Copy Markdown
Collaborator Author

Note:
Currently, the instantiated math of these observes does not work in the 'barefoot' integrated version.

The reason is that I replaced a sample statement over a latent variable with a sum of observes, which will do the 'right thing' only for some terms in the ELBO:
Sum_y logP(x|y,z) + logP(y) , but will not also add -logQ(y) because in KLqp we only do that at sample statements.

I am working out if I can change this to similar logic to still asymptote to an approximation.

…f the sin gle layer model, one with the joint loss included in model so it looks like the kingma paper and one that adds an auxiliary loss so we can train both the model and the guide but do not mix the loss functions
@karalets

karalets commented Oct 6, 2017

Copy link
Copy Markdown
Collaborator Author

Update:

I removed the non-functioning integrated version and added 2 new files.

vae_bernoulli_ss_extra_loss_one_kl.py is a version of the single hidden layer model that looks like the kingma paper int hat I made the classifier be trained as part of the model.

vae_bernoulli_ss_extra_loss_seperate_kl.py has a new model_classifier() and guide_classifier() and an auxiliary inference class which is called at each observed update to also train a classifier. It thius does not mix the models.

@rohitsingh0812 check it out.

T.

…observed data and (2) print accuracy at every training step and finally when testing. Also, added outputs for 3 short runs -- these should be removed from the repo later but can be used now for debugging.
@rohitsingh0812

Copy link
Copy Markdown
Collaborator

I have modified one of the files to show how running the one-loss KL with 5% supervised data leads to (1) negative and increasing loss (2) bad accuracy numbers
vae_bernoulli_ss_extra_loss_one_kl.txt

I'm guessing that there is some sort of scaling issue since we have different losses for the supervised and unsupervised case. But, it does seem like at least one of them is increasing while the other one may be decreasing.

The loss decreases steadily for the 100% supervised case -- but the accuracy doesn't improve sequentially.

… KL_QP. _m2_kingma.py file implements the experiment (M2 model) from the Kingma 2014 paper. unsup_vae file is a simple example with no supervision on y's -- this run has a negative loss value that increases (possibly a bug somewhere)
@rohitsingh0812

Copy link
Copy Markdown
Collaborator

I have also added the code for running the experiments for a model from the Kingma paper -- there is an issue with running a simple model (with no supervision) - the output of the run looks like this - there is a negative loss that is increasing in value:

(penv) rohits@rohits-desktop:~/Uber/pyro-ss-vae/examples/ss-vae$ python unsup_vae_simple.py
Training set size: 60000, Testing set size: 10000
0 epoch: avg loss -532236.384533 training accuracy 0.0521
1 epoch: avg loss -324544.614933 training accuracy 0.0353333333333
2 epoch: avg loss -296422.807467 training accuracy 0.0421666666667
3 epoch: avg loss -280602.259733 training accuracy 0.0358
4 epoch: avg loss -265358.666667 training accuracy 0.0137666666667
5 epoch: avg loss -251472.546667 training accuracy 0.0422166666667
6 epoch: avg loss -239120.933867 training accuracy 0.0417333333333
7 epoch: avg loss -226917.885867 training accuracy 0.0423333333333
8 epoch: avg loss -216207.408533 training accuracy 0.0423166666667
9 epoch: avg loss -208189.238267 training accuracy 0.0844
testing accuracy 0.0863

@ngoodman

Copy link
Copy Markdown
Collaborator

@rohitsingh0812 that setting should reduce to a standard VAE right? you could try running the VAE example on the same data, to make sure it behaves reasonably. (and double check your optimizer (adam) and step size choices -- one reason for diverging objectives can be an oscillating optimizer.)

@rohitsingh0812

Copy link
Copy Markdown
Collaborator

@ngoodman -- The pure VAE works fine (in my implementation) as you expected
Training set size: 60000, Testing set size: 10000
0 epoch: avg loss 380.089657812 training accuracy 0.0804833333333
1 epoch: avg loss 233.30479987 training accuracy 0.0804833333333
2 epoch: avg loss 214.803815885 training accuracy 0.0804833333333
3 epoch: avg loss 203.996767969 training accuracy 0.0804833333333
4 epoch: avg loss 193.369017187 training accuracy 0.0804833333333
5 epoch: avg loss 184.212199609 training accuracy 0.0804833333333
6 epoch: avg loss 176.385195313 training accuracy 0.0804833333333
7 epoch: avg loss 167.298282943 training accuracy 0.0804833333333
8 epoch: avg loss 159.579077865 training accuracy 0.0804833333333
9 epoch: avg loss 153.748164714 training accuracy 0.0804833333333
testing accuracy 0.0773

but this model is slightly different : in the unsup VAE we have p(z) = Normal(0,I) and p(x|z) = Bernoulli(nn_mu(z)) in the model but for any % of supervision, we have to add a "y" random variable to the model and make the nn_mu a function of both y and z. This seems to lead to a blow up and weird behavior with the loss. Essentially, the above version with y may not make sense as a model but it might be the easiest thing to debug if we agree that the model with "y" when "y" is not observed should still give a reasonable loss value that should decrease.

I see the same negative loss in the SS-VAE model with 5% supervision -- maybe I'm doing something wrong. I'll try the original simple model and see how my implementation might differ from it.

…dular version. The accuracies are not good and it seems like enumeration might be the only missing part that may have an impact on them
@rohitsingh0812

Copy link
Copy Markdown
Collaborator

The latest run with enumeration and the loss hacked to be exactly as in the paper looks like this: the accuracies go up to 91% for now and will probably go further if we tune parameters or debug the nan loss issue. This is way better than running this without enumeration where the accuracies were 10-20%.

This run was using 50% supervision and the annealed extra loss term. I'll run some instances overnight but we may setup the pipeline tomorrow for running this on OPUS GPUs.

(penv) rohits@rohits-desktop:~/Uber/pyro-ss-vae/examples/ss-vae$ python partial_sup_vae_simple.py --hack 1 -n 100 -sup 50
Training set size: 60000, Testing set size: 10000
/home/rohits/Uber/pyro-ss-vae/examples/ss-vae/networks.py:37: UserWarning: Implicit dimension choice for softmax has been deprecated. Change the call to include dim=X as an argument.
rval = self.softmax(self.fc21(h1))
0 epoch: avg losses 171.62682207 169.248123151 training accuracy 0.775916666667
1 epoch: avg losses 119.462234147 118.27069793 training accuracy 0.81305
2 epoch: avg losses 105.85720127 105.001999876 training accuracy 0.820533333333
3 epoch: avg losses 99.6170245768 98.7261415726 training accuracy 0.825216666667
4 epoch: avg losses 95.6711033854 94.8989783091 training accuracy 0.847933333333
5 epoch: avg losses 93.1587971517 92.3942525678 training accuracy 0.861466666667
6 epoch: avg losses 91.4259227051 90.6918825109 training accuracy 0.858333333333
7 epoch: avg losses 90.0472637044 89.3601098188 training accuracy 0.870833333333
8 epoch: avg losses 88.943725651 88.2757949572 training accuracy 0.880566666667
9 epoch: avg losses 88.0483576009 87.4154113126 training accuracy 0.887266666667
10 epoch: avg losses 87.3472978678 86.7322128047 training accuracy 0.895233333333
11 epoch: avg losses 86.7051885417 86.1824783951 training accuracy 0.8987
12 epoch: avg losses 86.1837203776 85.6813451797 training accuracy 0.903666666667
13 epoch: avg losses 85.7290929687 85.1680412287 training accuracy 0.912516666667
Traceback (most recent call last):
File "partial_sup_vae_simple.py", line 163, in
inference.run(num_epochs=NUM_EPOCHS)
File "/home/rohits/Uber/pyro-ss-vae/examples/ss-vae/inference.py", line 39, in run
epoch_losses, batch_counts = self.run_inference_batches()
File "/home/rohits/Uber/pyro-ss-vae/examples/ss-vae/inference.py", line 31, in run_inference_batches
assert not math.isnan(new_loss)
AssertionError

@ngoodman

Copy link
Copy Markdown
Collaborator

progress!

any idea where that nan error is coming from? (that's the sort of thing we want to track down and squash before release!)

…ical distribution -- trying to see if this stabilizes the issue of NNs eventually learning nan weights. Also, implemented checkpointing.
…- no more nans in the outputs and the accuracy matches the paper.

@fritzo fritzo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far!

Comment thread examples/ss-vae/example.py Outdated
assert np.isfinite(self.nn_mu_x.sum_params())

"""
The model corresponds to:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be helpful to comment the meanings, which as I understand are

p(z) = DiagNormal(0,I)           # handwriting style
p(y|x) = Categorical(I/10.)      # which digit
p(x|y,z) = Bernoulli(mu(y,z))    # a binarized image

also nit: move this down to be the docstring of model()

Comment thread examples/ss-vae/example.py Outdated
alpha_prior = Variable(torch.ones([self.batch_size, self.output_size])
/ (1.0 * self.output_size))

if not is_supervised:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be kind of cool in a python way to define

def model(self, xs, ys=None):
    is_supervised = (ys is not None)
    ...
    if ys is None:
        ys = pyro.sample(...)

This is nice in that it generalizes well to more variables, where each may or may not be observed.

Comment thread examples/ss-vae/example.py Outdated



"""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto: add comments on meaning and move below into guide()

Comment thread examples/ss-vae/example.py Outdated

zs = pyro.sample("z", DiagNormal(mu, sigma))

"""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: move into optimize() body so that it's a pythonic docstring

Comment thread examples/ss-vae/example.py Outdated

parser = argparse.ArgumentParser(description="parse args")
parser.add_argument('--seed', default=None, type=int)
parser.add_argument('-cuda',action='store_true') #default is False

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please name this --cuda rather than -cuda so that this example will be discovered by test_examples.py?

Comment thread examples/ss-vae/example.py Outdated
import torch
import pyro
from torch.autograd import Variable
from pyro.distributions import DiagNormal

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're trying to migrate to lower-case diagnormal functions etc. rather than uppercase DiagNormal classes.

Comment thread examples/ss-vae/example.py Outdated
assert not np.isnan(torch.sum(mu).data[0]), "mu nn z produced a nan"
assert not np.isnan(torch.sum(sigma).data[0]), "sigma nn z produced a nan"

zs = pyro.sample("z", DiagNormal(mu, sigma))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're trying to migrate to the function-versions in examples:

zs = pyro.sample("z", diagnormal, mu, sigma)

@fritzo fritzo mentioned this pull request Oct 27, 2017
9 tasks
@rohitsingh0812

Copy link
Copy Markdown
Collaborator

I've updated the code with comments and I've removed the low-level debugging code.

@rohitsingh0812

rohitsingh0812 commented Nov 2, 2017

Copy link
Copy Markdown
Collaborator

With the latest commits, this now depends on resolving:

-- issue: #451 (possible resolution = merging: #453)
-- merging: #444
-- and merging: #452

Comment thread examples/vae_bernoulli_ss.py Outdated
import torch.optim as optim
import numpy as np
import visdom
import pdb as pdb

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove pdb

from functools import reduce
from torch.utils.data import DataLoader


Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a high level comment about the purpose of the code in this file?

:param ys: (optional) a batch of the class labels i.e.
the digit corresponding to the image(s)
:return: None
"""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need a comment re: iarange here?

output_activation=ClippedSoftmax, epsilon_scale=self.epsilon_scale,
use_cuda=self.use_cuda)

# a split in the final layer's size is used foir multiple outputs

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: foir

Comment thread examples/ss-vae/mlp.py
from pyro.nn import ClippedSoftmax, ClippedSigmoid


def is_variable(val):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this different from

type(val) == torch.autograd.Variable

??

@rohitsingh0812

Copy link
Copy Markdown
Collaborator

We've unified this branch (manually) with vae-examples #448.

Closing this PR and branch.

@rohitsingh0812
rohitsingh0812 deleted the SS-VAE branch November 3, 2017 00:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tutorial for SS-VAE

6 participants