Implementation of a homogeneous Markov model of order 0 based on AbstractModel
From Jstacs
Jump to navigationJump to search
import java.util.Arrays;
import de.jstacs.NonParsableException;
import de.jstacs.NotTrainedException;
import de.jstacs.data.AlphabetContainer;
import de.jstacs.data.Sample;
import de.jstacs.data.Sequence;
import de.jstacs.io.XMLParser;
import de.jstacs.models.AbstractModel;
import de.jstacs.results.NumericalResult;
import de.jstacs.results.NumericalResultSet;
public class HomogeneousMarkovModel extends AbstractModel {
//array for the parameters, i.e. the probabilities for each symbol
private double[] probs;
//stores if the model has been trained
private boolean isTrained;
public HomogeneousMarkovModel( AlphabetContainer alphabets ) throws Exception {
//we have a homogeneous Model, hence the length is set to 0
super( alphabets, 0 );
//a homogeneous Model can only handle simple alphabets
if(! (alphabets.isSimple() && alphabets.isDiscrete()) ){
throw new Exception("Only simple and discrete alphabets allowed");
}
//initialize parameter array
this.probs = new double[(int) alphabets.getAlphabetLengthAt( 0 )];
//we have not trained the model, yet
isTrained = false;
}
public HomogeneousMarkovModel( StringBuffer stringBuff ) throws NonParsableException {
super( stringBuff );
}
@Override
protected void fromXML( StringBuffer xml ) throws NonParsableException {
//extract our XML-code
xml = XMLParser.extractForTag( xml, "homogeneousMarkovModel" );
//extract all the variables using XMLParser
alphabets = (AlphabetContainer) XMLParser.extractStorableForTag( xml, "alphabets" );
length = XMLParser.extractIntForTag( xml, "length" );
probs = XMLParser.extractDoubleArrayForTag( xml, "probs" );
isTrained = XMLParser.extractBooleanForTag( xml, "isTrained" );
}
public StringBuffer toXML() {
StringBuffer buf = new StringBuffer();
//pack all the variables using XMLParser
XMLParser.appendStorableWithTags( buf, alphabets, "alphabets" );
XMLParser.appendIntWithTags( buf, length, "length" );
XMLParser.appendDoubleArrayWithTags( buf, probs, "probs" );
XMLParser.appendBooleanWithTags( buf, isTrained, "isTrained" );
//add our own tag
XMLParser.addTags( buf, "homogeneousMarkovModel" );
return buf;
}
public String getInstanceName() {
return "Homogeneous Markov model of order 0";
}
public double getLogPriorTerm() throws Exception {
//we use ML-estimation, hence no prior term
return 0;
}
public NumericalResultSet getNumericalCharacteristics() throws Exception {
//we do not have much to tell here
return new NumericalResultSet(new NumericalResult("Number of parameters","The number of parameters this model uses",probs.length));
}
public double getProbFor( Sequence sequence, int startpos, int endpos ) throws NotTrainedException, Exception {
double seqProb = 1.0;
//compute the probability of the sequence between startpos and endpos (inclusive)
//as product of the single symbol probabilities
for(int i=startpos;i<=endpos;i++){
//directly access the array by the numerical representation of the symbols
seqProb *= probs[sequence.discreteVal( i )];
}
return seqProb;
}
public boolean isTrained() {
return isTrained;
}
public void train( Sample data, double[] weights ) throws Exception {
//reset the parameter array
Arrays.fill( probs, 0.0 );
//default sequence weight
double w = 1;
//for each sequence in the data set
for(int i=0;i<data.getNumberOfElements();i++){
//retrieve sequence
Sequence seq = data.getElementAt( i );
//if we do have any weights, use them
if(weights != null){
w = weights[i]
}
//for each position in the sequence
for(int j=0;j<seq.getLength();j++){
//count symbols, weighted by weights
probs[ seq.discreteVal( j ) ] += w;
}
}
//compute normalization
double norm = 0.0;
for(int i=0;i<probs.length;i++){
norm += probs[i];
}
//normalize probs to obtain proper probabilities
for(int i=0;i<probs.length;i++){
probs[i] /= norm;
}
//now the model is trained
isTrained = true;
}
}