Adding property to set random seed for noise addition to EntropyMultiVariate estimators (mimicing that for MI/CMI estimators), extending the fix for issue #99 to Entropy estimators

This commit is contained in:
Joseph Lizier 2024-04-20 18:52:10 +10:00
parent 3d1f3fec86
commit a9b6b3e77c
2 changed files with 46 additions and 10 deletions

View File

@ -61,6 +61,26 @@ public interface EntropyCalculatorMultiVariate
* Property name for the number of dimensions
*/
public static final String NUM_DIMENSIONS_PROP_NAME = "NUM_DIMENSIONS";
/**
* Property for whether we normalise the incoming observations to mean 0,
* standard deviation 1.
*/
public static final String NORMALISE_PROP_NAME = "NORMALISE";
/**
* Property name for an amount of random Gaussian noise to be
* added to the data (default is 1e-8, matching the MILCA toolkit).
*/
public static final String PROP_ADD_NOISE = "NOISE_LEVEL_TO_ADD";
/**
* Property name for the seed for the random number generator for noise to be
* added to the data (default is no seed)
*/
public static final String PROP_NOISE_SEED = "NOISE_SEED";
/**
* Property value to indicate no seed for the random number generator for noise to be
* added to the data
*/
public static final String NOISE_NO_SEED_VALUE = "NONE";
/**
* Set properties for the underlying calculator implementation.
@ -84,6 +104,8 @@ public interface EntropyCalculatorMultiVariate
* by Kraskov for the KSG method though, so for the Kozachenko estimator we
* use 1e-8 to match the MILCA toolkit (though note it adds in
* a random amount of noise in [0,noiseLevel) ).</li>
* <li>{@link #PROP_NOISE_SEED} -- a long value seed for the random noise generator or
* the string {@link MutualInfoCalculatorMultiVariate#NOISE_NO_SEED_VALUE} for no seed (default)</li>
* </ul>
*
* <p>Unknown property values are ignored.</p>

View File

@ -64,16 +64,6 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc
* standard deviation 1.
*/
protected boolean normalise = true;
/**
* Property for whether we normalise the incoming observations to mean 0,
* standard deviation 1.
*/
public static final String NORMALISE_PROP_NAME = "NORMALISE";
/**
* Property name for an amount of random Gaussian noise to be
* added to the data (default is 1e-8, matching the MILCA toolkit).
*/
public static final String PROP_ADD_NOISE = "NOISE_LEVEL_TO_ADD";
/**
* Whether to add an amount of random noise to the incoming data
*/
@ -82,6 +72,14 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc
* Amount of random Gaussian noise to add to the incoming data
*/
protected double noiseLevel = (double) 0.0;
/**
* Has the user set a seed for the random noise
*/
protected boolean noiseSeedSet = false;
/**
* Seed that the user set for the random noise
*/
protected long noiseSeed = 0;
/**
* Storage for observations supplied via {@link #addObservations(double[][])}
* type calls
@ -132,6 +130,13 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc
addNoise = true;
noiseLevel = Double.parseDouble(propertyValue);
}
} else if (propertyName.equalsIgnoreCase(PROP_NOISE_SEED)) {
if (propertyValue.equals(NOISE_NO_SEED_VALUE)) {
noiseSeedSet = false;
} else {
noiseSeedSet = true;
noiseSeed = Long.parseLong(propertyValue);
}
} else {
// No property was set
propertySet = false;
@ -150,6 +155,12 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc
return Boolean.toString(normalise);
} else if (propertyName.equalsIgnoreCase(PROP_ADD_NOISE)) {
return Double.toString(noiseLevel);
} else if (propertyName.equalsIgnoreCase(PROP_NOISE_SEED)) {
if (noiseSeedSet) {
return Long.toString(noiseSeed);
} else {
return NOISE_NO_SEED_VALUE;
}
} else {
// No property was set, and no superclass to call:
return null;
@ -188,6 +199,9 @@ public abstract class EntropyCalculatorMultiVariateCommon implements EntropyCalc
if (addNoise) {
Random random = new Random();
if (noiseSeedSet) {
random.setSeed(noiseSeed);
}
// Add Gaussian noise of std dev noiseLevel to the data
for (int r = 0; r < totalObservations; r++) {
for (int c = 0; c < dimensions; c++) {