code: private INDArray calculateBernoulli(INDArray minorityLabels, INDArray labelMask, double targetMinorityDist) {
  
          INDArray minorityClass = minorityLabels.castTo(Nd4j.defaultFloatingPointType()).muli(labelMask);
          INDArray majorityClass = minorityLabels.rsub(1.0).muli(labelMask);      //rsub(1.0) is equivalent to swapping 0s and 1s
  
          //all minorityLabel class, keep masks as is
          //presence of minoriy class and donotmask minority windows set to true return label as is
          if (majorityClass.sumNumber().intValue() == 0
                          || (minorityClass.sumNumber().intValue() > 0 && donotMaskMinorityWindows))
              return labelMask;
          //all majority class and set to not mask all majority windows sample majority class by 1-targetMinorityDist
          if (minorityClass.sumNumber().intValue() == 0 && !maskAllMajorityWindows)
              return labelMask.muli(1 - targetMinorityDist);
  
          //Probabilities to be used for bernoulli sampling
          INDArray minoritymajorityRatio = minorityClass.sum(1).div(majorityClass.sum(1));
          INDArray majorityBernoulliP = minoritymajorityRatio.muli(1 - targetMinorityDist).divi(targetMinorityDist);
          BooleanIndexing.replaceWhere(majorityBernoulliP, 1.0, Conditions.greaterThan(1.0)); //if minority ratio is already met round down to 1.0
          return majorityClass.muliColumnVector(majorityBernoulliP).addi(minorityClass);
      }
docs: /*
  Given a list of labels return the bernoulli prob that the masks
  will be sampled at to meet the target minority label distribution
  
  Masks at time steps where label is the minority class will always be one
  i.e a bernoulli with p = 1
  Masks at time steps where label is the majority class will be sampled from
  a bernoulli dist with p
  = (minorityCount/majorityCount) * ((1-targetDist)/targetDist)