class_docstr: Implements Generative Adversarial Networks.
  
  A Generative Adversarial Network (GAN) is a type of generative model.  It
  consists of two parts called the "generator" and the "discriminator".  The
  generator takes random noise as input and transforms it into an output that
  (hopefully) resembles the training data.  The discriminator takes a set of
  samples as input and tries to distinguish the real training samples from the
  ones created by the generator.  Both of them are trained together.  The
  discriminator tries to get better and better at telling real from false data,
  while the generator tries to get better and better at fooling the discriminator.
  
  In many cases there also are additional inputs to the generator and
  discriminator.  In that case it is known as a Conditional GAN (CGAN), since it
  learns a distribution that is conditional on the values of those inputs.  They
  are referred to as "conditional inputs".
  
  Many variations on this idea have been proposed, and new varieties of GANs are
  constantly being proposed.  This class tries to make it very easy to implement
  straightforward GANs of the most conventional types.  At the same time, it
  tries to be flexible enough that it can be used to implement many (but
  certainly not all) variations on the concept.
  
  To define a GAN, you must create a subclass that provides implementations of
  the following methods:
  
  get_noise_input_shape()
  get_data_input_shapes()
  create_generator()
  create_discriminator()
  
  If you want your GAN to have any conditional inputs you must also implement:
  
  get_conditional_input_shapes()
  
  The following methods have default implementations that are suitable for most
  conventional GANs.  You can override them if you want to customize their
  behavior:
  
  create_generator_loss()
  create_discriminator_loss()
  get_noise_batch()
  
  This class allows a GAN to have multiple generators and discriminators, a model
  known as MIX+GAN.  It is described in [2]
  This can lead to better models, and is especially useful for reducing mode
  collapse, since different generators can learn different parts of the
  distribution.  To use this technique, simply specify the number of generators
  and discriminators when calling the constructor.  You can then tell
  predict_gan_generator() which generator to use for predicting samples.
  
  Examples
  --------
  Importing necessary modules
  
  >>> import deepchem as dc
  >>> from deepchem.models.torch_models.gan import GAN
  >>> import torch
  >>> import torch.nn as nn
  >>> import torch.nn.functional as F
  
  Creating a Generator
  
  >>> class Generator(nn.Module):
  ...     def __init__(self, noise_input_shape, conditional_input_shape):
  ...         super(Generator, self).__init__()
  ...         self.noise_input_shape = noise_input_shape
  ...         self.conditional_input_shape = conditional_input_shape
  ...         self.noise_dim = noise_input_shape[1:]
  ...         self.conditional_dim = conditional_input_shape[1:]
  ...         input_dim = sum(self.noise_dim) + sum(self.conditional_dim)
  ...         self.output = nn.Linear(input_dim, 1)
  ...     def forward(self, input):
  ...         noise_input, conditional_input = input
  ...         inputs = torch.cat((noise_input, conditional_input), dim=1)
  ...         output = self.output(inputs)
  ...         return output
  
  Creating a Discriminator
  
  >>> class Discriminator(nn.Module):
  ...     def __init__(self, data_input_shape, conditional_input_shape):
  ...         super(Discriminator, self).__init__()
  ...         self.data_input_shape = data_input_shape
  ...         self.conditional_input_shape = conditional_input_shape
  ...         # Extracting the actual data dimension
  ...         data_dim = data_input_shape[1:]
  ...         # Extracting the actual conditional dimension
  ...         conditional_dim = conditional_input_shape[1:]
  ...         input_dim = sum(data_dim) + sum(conditional_dim)
  ...         # Define the dense layers
  ...         self.dense1 = nn.Linear(input_dim, 10)
  ...         self.dense2 = nn.Linear(10, 1)
  ...     def forward(self, input):
  ...         data_input, conditional_input = input
  ...         # Concatenate data_input and conditional_input along the second dimension
  ...         discrim_in = torch.cat((data_input, conditional_input), dim=1)
  ...         # Pass the concatenated input through the dense layers
  ...         x = F.relu(self.dense1(discrim_in))
  ...         output = torch.sigmoid(self.dense2(x))
  ...         return output
  
  Defining an Example GAN class
  
  >>> class ExampleGANModel(dc.models.torch_models.GANModel):
  ...    def get_noise_input_shape(self):
  ...        return (100,2,)
  ...    def get_data_input_shapes(self):
  ...        return [(100,1,)]
  ...    def get_conditional_input_shapes(self):
  ...        return [(100,1,)]
  ...    def create_generator(self):
  ...        noise_dim = self.get_noise_input_shape()
  ...        conditional_dim = self.get_conditional_input_shapes()[0]
  ...        return nn.Sequential(Generator(noise_dim, conditional_dim))
  ...    def create_discriminator(self):
  ...        data_input_shape = self.get_data_input_shapes()[0]
  ...        conditional_input_shape = self.get_conditional_input_shapes()[0]
  ...        return nn.Sequential(
  ...            Discriminator(data_input_shape, conditional_input_shape))
  
  Defining a function to generate data
  
  >>> def generate_batch(batch_size):
  ...     means = 10 * np.random.random([batch_size, 1])
  ...     values = np.random.normal(means, scale=2.0)
  ...     return means, values
  
  >>> def generate_data(gan, batches, batch_size):
  ...     for _ in range(batches):
  ...         means, values = generate_batch(batch_size)
  ...         batch = {
  ...             gan.data_input_names[0]: values,
  ...             gan.conditional_input_names[0]: means
  ...         }
  ...         yield batch
  
  Defining the GANModel
  
  >>> batch_size = 100
  >>> noise_shape = (batch_size, 2,)
  >>> data_shape = [(batch_size, 1,)]
  >>> conditional_shape = [(batch_size, 1,)]
  >>> gan = ExampleGANModel(learning_rate=0.01)
  >>> data = generate_data(gan, 500, 100)
  >>> gan.fit_gan(data, generator_steps=0.5, checkpoint_interval=0)
  >>> means = 10 * np.random.random([1000, 1])
  >>> values = gan.predict_gan_generator(conditional_inputs=[means])
  
  References
  ----------
  .. [1] Goodfellow, Ian, et al. "Generative adversarial nets." Advances in
       neural information processing systems. 2014.
  
  .. [2] Arora et al., “Generalization and Equilibrium in Generative
       Adversarial Nets (GANs)” (https://arxiv.org/abs/1703.00573)
class_docstr_tok: ["Implements","Generative","Adversarial","Networks",".","A","Generative","Adversarial","Network","(","GAN",")","is","a","type","of","generative","model",".","It","consists","of","two","parts","called","the","``","generator","''","and","the","``","discriminator","''",".","The","generator","takes","random","noise","as","input","and","transforms","it","into","an","output","that","(","hopefully",")","resembles","the","training","data",".","The","discriminator","takes","a","set","of","samples","as","input","and","tries","to","distinguish","the","real","training","samples","from","the","ones","created","by","the","generator",".","Both","of","them","are","trained","together",".","The","discriminator","tries","to","get","better","and","better","at","telling","real","from","false","data",",","while","the","generator","tries","to","get","better","and","better","at","fooling","the","discriminator",".","In","many","cases","there","also","are","additional","inputs","to","the","generator","and","discriminator",".","In","that","case","it","is","known","as","a","Conditional","GAN","(","CGAN",")",",","since","it","learns","a","distribution","that","is","conditional","on","the","values","of","those","inputs",".","They","are","referred","to","as","``","conditional","inputs","''",".","Many","variations","on","this","idea","have","been","proposed",",","and","new","varieties","of","GANs","are","constantly","being","proposed",".","This","class","tries","to","make","it","very","easy","to","implement","straightforward","GANs","of","the","most","conventional","types",".","At","the","same","time",",","it","tries","to","be","flexible","enough","that","it","can","be","used","to","implement","many","(","but","certainly","not","all",")","variations","on","the","concept",".","To","define","a","GAN",",","you","must","create","a","subclass","that","provides","implementations","of","the","following","methods",":","get_noise_input_shape","(",")","get_data_input_shapes","(",")","create_generator","(",")","create_discriminator","(",")","If","you","want","your","GAN","to","have","any","conditional","inputs","you","must","also","implement",":","get_conditional_input_shapes","(",")","The","following","methods","have","default","implementations","that","are","suitable","for","most","conventional","GANs",".","You","can","override","them","if","you","want","to","customize","their","behavior",":","create_generator_loss","(",")","create_discriminator_loss","(",")","get_noise_batch","(",")","This","class","allows","a","GAN","to","have","multiple","generators","and","discriminators",",","a","model","known","as","MIX+GAN",".","It","is","described","in","[","2","]","This","can","lead","to","better","models",",","and","is","especially","useful","for","reducing","mode","collapse",",","since","different","generators","can","learn","different","parts","of","the","distribution",".","To","use","this","technique",",","simply","specify","the","number","of","generators","and","discriminators","when","calling","the","constructor",".","You","can","then","tell","predict_gan_generator","(",")","which","generator","to","use","for","predicting","samples",".","Examples","--","--","--","--","Importing","necessary","modules",">",">",">","import","deepchem","as","dc",">",">",">","from","deepchem.models.torch_models.gan","import","GAN",">",">",">","import","torch",">",">",">","import","torch.nn","as","nn",">",">",">","import","torch.nn.functional","as","F","Creating","a","Generator",">",">",">","class","Generator","(","nn.Module",")",":","...","def","__init__","(","self",",","noise_input_shape",",","conditional_input_shape",")",":","...","super","(","Generator",",","self",")",".__init__","(",")","...","self.noise_input_shape","=","noise_input_shape","...","self.conditional_input_shape","=","conditional_input_shape","...","self.noise_dim","=","noise_input_shape","[","1",":","]","...","self.conditional_dim","=","conditional_input_shape","[","1",":","]","...","input_dim","=","sum","(","self.noise_dim",")","+","sum","(","self.conditional_dim",")","...","self.output","=","nn.Linear","(","input_dim",",","1",")","...","def","forward","(","self",",","input",")",":","...","noise_input",",","conditional_input","=","input","...","inputs","=","torch.cat","(","(","noise_input",",","conditional_input",")",",","dim=1",")","...","output","=","self.output","(","inputs",")","...","return","output","Creating","a","Discriminator",">",">",">","class","Discriminator","(","nn.Module",")",":","...","def","__init__","(","self",",","data_input_shape",",","conditional_input_shape",")",":","...","super","(","Discriminator",",","self",")",".__init__","(",")","...","self.data_input_shape","=","data_input_shape","...","self.conditional_input_shape","=","conditional_input_shape","...","#","Extracting","the","actual","data","dimension","...","data_dim","=","data_input_shape","[","1",":","]","...","#","Extracting","the","actual","conditional","dimension","...","conditional_dim","=","conditional_input_shape","[","1",":","]","...","input_dim","=","sum","(","data_dim",")","+","sum","(","conditional_dim",")","...","#","Define","the","dense","layers","...","self.dense1","=","nn.Linear","(","input_dim",",","10",")","...","self.dense2","=","nn.Linear","(","10",",","1",")","...","def","forward","(","self",",","input",")",":","...","data_input",",","conditional_input","=","input","...","#","Concatenate","data_input","and","conditional_input","along","the","second","dimension","...","discrim_in","=","torch.cat","(","(","data_input",",","conditional_input",")",",","dim=1",")","...","#","Pass","the","concatenated","input","through","the","dense","layers","...","x","=","F.relu","(","self.dense1","(","discrim_in",")",")","...","output","=","torch.sigmoid","(","self.dense2","(","x",")",")","...","return","output","Defining","an","Example","GAN","class",">",">",">","class","ExampleGANModel","(","dc.models.torch_models.GANModel",")",":","...","def","get_noise_input_shape","(","self",")",":","...","return","(","100,2",",",")","...","def","get_data_input_shapes","(","self",")",":","...","return","[","(","100,1",",",")","]","...","def","get_conditional_input_shapes","(","self",")",":","...","return","[","(","100,1",",",")","]","...","def","create_generator","(","self",")",":","...","noise_dim","=","self.get_noise_input_shape","(",")","...","conditional_dim","=","self.get_conditional_input_shapes","(",")","[","0","]","...","return","nn.Sequential","(","Generator","(","noise_dim",",","conditional_dim",")",")","...","def","create_discriminator","(","self",")",":","...","data_input_shape","=","self.get_data_input_shapes","(",")","[","0","]","...","conditional_input_shape","=","self.get_conditional_input_shapes","(",")","[","0","]","...","return","nn.Sequential","(","...","Discriminator","(","data_input_shape",",","conditional_input_shape",")",")","Defining","a","function","to","generate","data",">",">",">","def","generate_batch","(","batch_size",")",":","...","means","=","10","*","np.random.random","(","[","batch_size",",","1","]",")","...","values","=","np.random.normal","(","means",",","scale=2.0",")","...","return","means",",","values",">",">",">","def","generate_data","(","gan",",","batches",",","batch_size",")",":","...","for","_","in","range","(","batches",")",":","...","means",",","values","=","generate_batch","(","batch_size",")","...","batch","=","{","...","gan.data_input_names","[","0","]",":","values",",","...","gan.conditional_input_names","[","0","]",":","means","...","}","...","yield","batch","Defining","the","GANModel",">",">",">","batch_size","=","100",">",">",">","noise_shape","=","(","batch_size",",","2",",",")",">",">",">","data_shape","=","[","(","batch_size",",","1",",",")","]",">",">",">","conditional_shape","=","[","(","batch_size",",","1",",",")","]",">",">",">","gan","=","ExampleGANModel","(","learning_rate=0.01",")",">",">",">","data","=","generate_data","(","gan",",","500",",","100",")",">",">",">","gan.fit_gan","(","data",",","generator_steps=0.5",",","checkpoint_interval=0",")",">",">",">","means","=","10","*","np.random.random","(","[","1000",",","1","]",")",">",">",">","values","=","gan.predict_gan_generator","(","conditional_inputs=","[","means","]",")","References","--","--","--","--","--","..","[","1","]","Goodfellow",",","Ian",",","et","al",".","``","Generative","adversarial","nets",".","''","Advances","in","neural","information","processing","systems",".","2014",".","..","[","2","]","Arora","et","al.",",","\u201c","Generalization","and","Equilibrium","in","Generative","Adversarial","Nets","(","GANs",")","\u201d","(","https",":","\/\/arxiv.org\/abs\/1703.00573",")"]
docstr: Use the GAN to generate a batch of samples.
  
  Parameters
  ----------
  batch_size: int
      the number of samples to generate.  If either noise_input or
      conditional_inputs is specified, this argument is ignored since the batch
      size is then determined by the size of that argument.
  noise_input: array
      the value to use for the generator's noise input.  If None (the default),
      get_noise_batch() is called to generate a random input, so each call will
      produce a new set of samples.
  conditional_inputs: list of arrays
      the values to use for all conditional inputs.  This must be specified if
      the GAN has any conditional inputs.
  generator_index: int
      the index of the generator (between 0 and n_generators-1) to use for
      generating the samples.
  
  Returns
  -------
  An array (if the generator has only one output) or list of arrays (if it has
  multiple outputs) containing the generated samples.
docstr_tok: ["Use","the","GAN","to","generate","a","batch","of","samples",".","Parameters","--","--","--","--","--","batch_size",":","int","the","number","of","samples","to","generate",".","If","either","noise_input","or","conditional_inputs","is","specified",",","this","argument","is","ignored","since","the","batch","size","is","then","determined","by","the","size","of","that","argument",".","noise_input",":","array","the","value","to","use","for","the","generator","'s","noise","input",".","If","None","(","the","default",")",",","get_noise_batch","(",")","is","called","to","generate","a","random","input",",","so","each","call","will","produce","a","new","set","of","samples",".","conditional_inputs",":","list","of","arrays","the","values","to","use","for","all","conditional","inputs",".","This","must","be","specified","if","the","GAN","has","any","conditional","inputs",".","generator_index",":","int","the","index","of","the","generator","(","between","0","and","n_generators-1",")","to","use","for","generating","the","samples",".","Returns","--","--","--","-","An","array","(","if","the","generator","has","only","one","output",")","or","list","of","arrays","(","if","it","has","multiple","outputs",")","containing","the","generated","samples","."]
code: def predict_gan_generator(
      self,
      batch_size=1,
      noise_input=None,
      conditional_inputs=[],
      generator_index=0,
  ):
      """Use the GAN to generate a batch of samples.
  
      Parameters
      ----------
      batch_size: int
          the number of samples to generate.  If either noise_input or
          conditional_inputs is specified, this argument is ignored since the batch
          size is then determined by the size of that argument.
      noise_input: array
          the value to use for the generator's noise input.  If None (the default),
          get_noise_batch() is called to generate a random input, so each call will
          produce a new set of samples.
      conditional_inputs: list of arrays
          the values to use for all conditional inputs.  This must be specified if
          the GAN has any conditional inputs.
      generator_index: int
          the index of the generator (between 0 and n_generators-1) to use for
          generating the samples.
  
      Returns
      -------
      An array (if the generator has only one output) or list of arrays (if it has
      multiple outputs) containing the generated samples.
      """
      if noise_input is not None:
          batch_size = len(noise_input)
      elif len(conditional_inputs) > 0:
          batch_size = len(conditional_inputs[0])
      if noise_input is None:
          noise_input = self.get_noise_batch(batch_size)
      inputs = [noise_input]
      inputs += conditional_inputs
      inputs = [i.astype(np.float32) for i in inputs]
      inputs = [torch.from_numpy(i) for i in inputs]
      pred = self.generators[generator_index](_list_or_tensor(inputs))
      pred = pred.detach().numpy()
      return pred
  
imports: import numpy
  import time
  from typing import Callable, Any, List, Tuple, Union
  from deepchem.models.torch_models.torch_model import TorchModel
label_desc: Use image node_id 8 for calling the GANModel obj's underlying member method code with example usage: obj.predict_gan_generator(batch_size, noise_input, conditional_inputs, generator_index) and returns: pred