anchor.diff:  print discriminator
   
   let epochs = 10
  -let batchSize = 64
  -let validInterval = 32
  +let batchSize = 16
  +let validInterval = 100
   
   let mnist = MNIST("../data", train=true, transform=fun t -> (t - 0.5) / 0.5)
   let loader = mnist.loader(batchSize=batchSize, shuffle=true)
   
  -let gopt = Adam(generator, lr=dsharp.tensor(0.0001), beta1=dsharp.tensor(0.5))
  -let dopt = Adam(discriminator, lr=dsharp.tensor(0.0001), beta1=dsharp.tensor(0.5))
  +let gopt = Adam(generator, lr=dsharp.tensor(0.0002), beta1=dsharp.tensor(0.5))
  +let dopt = Adam(discriminator, lr=dsharp.tensor(0.0002), beta1=dsharp.tensor(0.5))
   
   let fixedNoise = dsharp.randn([batchSize; nz])
   
   let glosses = ResizeArray()
   let dlosses = ResizeArray()
  +let dxs = ResizeArray()
  +let dgzs = ResizeArray()
   
   let start = System.DateTime.Now
   for epoch = 1 to epochs do
       for i, x, _ in loader.epoch() do
  +        let labelReal = dsharp.ones([batchSize; 1])
  +        let labelFake = dsharp.zeros([batchSize; 1])
  +
           // update discriminator
           generator.noDiff()
  -        // generator.reverseDiff()
           discriminator.reverseDiff()
   
           let doutput = x --> discriminator
           let dx = doutput.mean() |> float
  -        let dlabelReal = dsharp.ones([batchSize; 1])
  -        let dlossReal = dsharp.bceLoss(doutput, dlabelReal)
  -        // dlossReal.reverse()
  +        let dlossReal = dsharp.bceLoss(doutput, labelReal)
   
           let z = dsharp.randn([batchSize; nz])
           let goutput = z --> generator
           let doutput = goutput --> discriminator
  -        let dgz1 = doutput.mean() |> float
  -        let dlabelFake = dsharp.zeros([batchSize; 1])
  -        let dlossFake = dsharp.bceLoss(doutput, dlabelFake)
  -        // dlossFake.reverse(zeroDerivatives=false)
  +        let dgz = doutput.mean() |> float
  +        let dlossFake = dsharp.bceLoss(doutput, labelFake)
   
           let dloss = dlossReal + dlossFake
           dloss.reverse()
           dopt.step()
           dlosses.Add(float dloss)
  +        dxs.Add(float dx)
  +        dgzs.Add(float dgz)
   
           // update generator
           generator.reverseDiff()
  
positive.code: 
          let goutput = z --> generator
          let doutput = goutput --> discriminator
          let dgz2 = doutput.mean() |> float
          let dlabelReal = dsharp.ones([batchSize; 1])
          let gloss = dsharp.bceLoss(doutput, dlabelReal)
          gloss.reverse()
          gopt.step()
          glosses.Add(float gloss)
  
          printfn "%A Epoch: %A/%A minibatch: %A/%A gloss: %A dloss: %A d(x): %A d(g(z)): %A / %A" (System.DateTime.Now - start) epoch epochs (i+1) loader.length (float gloss) (float dloss) dx dgz1 dgz2
  
          if i % validInterval = 0 then
              let realFileName = sprintf "gan_real_samples_epoch_%A_minibatch_%A.png" epoch (i+1)
              printfn "Saving real samples to %A" realFileName
              x.saveImage(realFileName, normalize=true)
              let fakeFileName = sprintf "gan_fake_samples_epoch_%A_minibatch_%A.png" epoch (i+1)
              printfn "Saving fake samples to %A" fakeFileName
              let goutput = fixedNoise --> generator
              goutput.view([-1;1;28;28]).saveImage(fakeFileName, normalize=true)
  
              let plt = Pyplot()
              plt.plot(glosses |> dsharp.tensor, label="G")
              plt.plot(dlosses |> dsharp.tensor, label="D")
              plt.legend()
              plt.tightLayout()
              plt.savefig (sprintf "gan_loss_epoch_%A_minibatch_%A.pdf" epoch (i+1))
negative.code: open DiffSharp.Util
  
  dsharp.config(backend=Backend.Torch, device=Device.CPU)
  dsharp.seed(4)
  
  let nz = 128
  
  