code: def _outer_init_full_values(self):
          
          retd = dict(dL_dKmm=np.zeros((self.Z.shape[0], self.Z.shape[0])))
          if self.has_uncertain_inputs():
              retd.update(dict(dL_dpsi0=np.zeros(self.X.shape[0]),
                               dL_dpsi1=np.zeros((self.X.shape[0], self.Z.shape[0])),
                               dL_dpsi2=np.zeros((self.X.shape[0], self.Z.shape[0], self.Z.shape[0]))))
          else:
              retd.update({'dL_dKdiag': np.zeros(self.X.shape[0]),
                           'dL_dKnm': np.zeros((self.X.shape[0], self.Z.shape[0]))})
          return retd
docs: If full_values has indices in values_indices, we might want to initialize
          the full_values differently, so that subsetting is possible.
  
          Here you can initialize the full_values for the values needed.
  
          Keep in mind, that if a key does not exist in full_values when updating
          values, it will be set (so e.g. for Z there is no need to initialize Zgrad,
          as there is no subsetting needed. For X in BGPLVM on the other hand we probably need
          to initialize the gradients for the mean and the variance in order to
          have the full gradient for indexing)