marytts.tools.dbselection.SelectionFunction Maven / Gradle / Ivy
The newest version!
/**
* Copyright 2007 DFKI GmbH.
* All Rights Reserved. Use is subject to license terms.
*
* This file is part of MARY TTS.
*
* MARY TTS is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*/
package marytts.tools.dbselection;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Set;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import marytts.client.MaryClient;
import marytts.datatypes.MaryData;
import marytts.datatypes.MaryDataType;
import marytts.datatypes.MaryXML;
import marytts.server.Mary;
import marytts.util.dom.MaryDomUtils;
import marytts.util.http.Address;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.traversal.TreeWalker;
import org.xml.sax.SAXException;
/**
* Selects sentences from a given set using the greedy algorithm. At each step, the most useful sentence is added to the set of
* selected sentences. Selection is stopped when the stop criterion is reached. Usefulness of sentences is determined by
* CoverageDefinition.
*
* @author Anna Hunecke
*
*/
public class SelectionFunction {
// maximum number of sentences to select
private int maxNumSents;
// the vectors that are selected next
private byte[] selectedVectors;
// the filename of the sentence that is selected next
// private String selectedBasename;
private int selectedIdSentence;
// the usefulness of the selected sentence
private double selectedUsefulness;
// if true, algorithm stop after maxNumSents are selected
private boolean stopNumSentences;
// if true, algorithm stops when maximum coverage of
// simple diphones is reached
private boolean stopSimpleDiphones;
// if true, algorithm stops when maximum coverage of
// clustered diphones is reached
private boolean stopClusteredDiphones;
// if true, algorithm stops when maximum coverage of
// simple prosody is reached
private boolean stopSimpleProsody;
// if true, algorithm stops when maximum coverage of
// clustered prosody is reached
private boolean stopClusteredProsody;
// if true, print information to command line
private boolean verbose;
/**
* Build a new Selection Function
*
*/
public SelectionFunction() {
}
/**
* Check, if given stop criterion is okay. At the same time, initialise stop criterion as this SelectionFunction's stop
* criterion
*
* @param stopString
* the stop criterion
* @return true if stopString can be parsed, false otherwise
*/
public boolean stopIsOkay(String stopString) {
// set all stop criteria to false
stopNumSentences = false;
stopSimpleDiphones = false;
stopClusteredDiphones = false;
stopSimpleProsody = false;
stopClusteredProsody = false;
// split the stopString
System.out.println("\nChecking stop criterion:");
String[] split = stopString.split(" ");
int i = 0;
while (split.length > i) {
if (split[i].startsWith("numSentences")) {
// criterion is numSentences
stopNumSentences = true;
if (split.length > i + 1) {
// read in the maximum number of sentences
maxNumSents = Integer.parseInt(split[++i]);
} else {
// maximum number of sentences is missing - can not parse
return false;
}
System.out.println("Stop: num sentences " + maxNumSents);
} else {
if (split[i].equals("simpleDiphones")) {
// stop criterion is simpleDiphones
stopSimpleDiphones = true;
System.out.println("Stop: simpleDiphones");
} else {
if (split[i].equals("clusteredDiphones")) {
// stop criterion is clusteredDiphones
stopClusteredDiphones = true;
System.out.println("Stop: clusteredDiphones");
} else {
if (split[i].equals("simpleProsody")) {
// stop criterion is simpleProsody
stopSimpleProsody = true;
System.out.println("Stop: simpleProsody");
} else {
if (split[i].equals("clusteredProsody")) {
// stop criterion is clusteredProsody
stopClusteredProsody = true;
System.out.println("Stop: clusteredProsody");
} else {
// unknown stop criterion - can not parse
return false;
}
}
}
}
}
i++;
}
// everything allright
return true;
}
/**
* Select a set of vectors according to their usefulness which is defined by the coverageDefinition. Stop, when the stop
* criterion is reached
*
* @param selectedIdSents
* the list of selected id sentences
* @param unwantedIdSents
* the list of unwanted id sentences
* @param coverageDefinition
* the coverage definition for the feature vectors
* @param logFile
* the logFile to document the progress
* @param cfProvider
* the list of filenames of the sentences
* @param verboseSelect
* if true, get vectors from coverage definition, if false, read vectors from disk
* @param wikiToDB
* wikiToDB
* @throws Exception
* Exception
*/
public void select(Set selectedIdSents, Set unwantedIdSents, CoverageDefinition coverageDefinition,
PrintWriter logFile, CoverageFeatureProvider cfProvider, boolean verboseSelect, DBHandler wikiToDB) // throws
// IOException
throws Exception {
this.verbose = verboseSelect;
int sentIndex = selectedIdSents.size() + 1;
selectedVectors = null;
DateFormat fullDate = new SimpleDateFormat("HH_mm_ss");
// create the selectedSentences table
// while the stop criterion is not reached
while (!stopCriterionIsReached(selectedIdSents, coverageDefinition)) {
// select the next sentence
// selectNext(coverageDefinition, logFile, sentIndex, basenameList, vectorArray);
boolean haveSelected = selectNext(selectedIdSents, unwantedIdSents, coverageDefinition, cfProvider);
if (haveSelected) {
assert selectedIdSentence >= 0;
selectedIdSents.add(selectedIdSentence);
// print information
String msg = "Sentence " + sentIndex + " (" + selectedIdSentence + "), score: " + selectedUsefulness;
if (verbose) {
System.out.println(msg);
}
logFile.println(msg);
logFile.flush();
} else {
// nothing more to select
// System.out.println("Nothing more to select");
logFile.println("Nothing more to select");
break;
}
// the selected sentences will be marked as selected=true in the DB
Date date = new Date();
System.out.println(" " + sentIndex + " selectedId=" + selectedIdSentence + " " + fullDate.format(date));
// Mark the sentence as selected in dbselection
wikiToDB.setSentenceRecord(selectedIdSentence, "selected", true);
// Insert selected sentence in table
wikiToDB.insertSelectedSentence(selectedIdSentence, false);
// add the selected sentence to the set
// selectedFilenames.add(selectedBasename);
// selectedIdSents.add(selectedIdSentence); already done in selectNext
// update coverageDefinition
coverageDefinition.updateCover(selectedVectors);
sentIndex++;
}
// print out total number of sentences
sentIndex--;
System.out.println("Total number of selected sentences in TABLE: " + wikiToDB.getSelectedSentencesTableName() + " = "
+ sentIndex);
int sel[] = wikiToDB.getIdListOfType("dbselection", "selected=true and unwanted=false");
if (sel != null) {
// saving sentences in a file
System.out.println("Saving selected sentences in ./selected.log");
PrintWriter selectedLog = new PrintWriter(new FileWriter(new File("./selected.log")));
System.out.println("Saving selected sentences and transcriptions in ./selected_text_transcription.log");
PrintWriter selected_tra_Log = new PrintWriter(new FileWriter(new File("./selected_text_transcription.log")));
String str;
for (int i = 0; i < sel.length; i++) {
// not sure if we need to make another table???
// str = wikiToDB.getSentence("selectedSentences", sel[i]);
str = wikiToDB.getDBSelectionSentence(sel[i]);
// System.out.println("id=" + sel[i] + str);
selectedLog.println(sel[i] + " " + str);
selected_tra_Log.println(sel[i] + " " + str);
selected_tra_Log.println(sel[i] + " <" + transcribe(str, "it") + ">");
}
selectedLog.close();
selected_tra_Log.close();
logFile.println("Total number of sentences : " + sentIndex);
} else
System.out.println("No selected sentences to save.");
}
/*
* Utility method for get the Transcription of the selected sentences It makes use of a started builtin MARY TTS
*/
static String transcribe(String ptext, String plocale) throws Exception {
String inputType = "TEXT";
String outputType = "ALLOPHONES";
String audioType = null;
String defaultVoiceName = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Mary.process(ptext, inputType, outputType, plocale, audioType, defaultVoiceName, null, null, null, baos);
// read into mary data object
MaryData maryData = new MaryData(MaryDataType.ALLOPHONES, null);
maryData.readFrom(new ByteArrayInputStream(baos.toByteArray()));
Document doc = maryData.getDocument();
assert doc != null : "null sentence";
TreeWalker phWalker = MaryDomUtils.createTreeWalker(doc, doc, MaryXML.PHONE);
Element ph;
String lTranscription = "";
while ((ph = (Element) phWalker.nextNode()) != null) {
lTranscription = lTranscription + ph.getAttribute("p") + ' ';
}
lTranscription = lTranscription.substring(0, lTranscription.length() - 1);
// System.out.println('<' + lTranscription + '>');
return lTranscription;
}
/**
* Select the next sentence
*
* @param coverageDefinition
* the coverage definition
* @param selectedIdSents
* the index of the next sentence
* @param unwantedIdSents
* the list unwanted sentences
* @param cfProvider
* cf provider
* @throws IOException
* IOException
* @return true if a sentence was selected, false otherwise
*/
private boolean selectNext(Set selectedIdSents, Set unwantedIdSents, CoverageDefinition coverageDefinition,
CoverageFeatureProvider cfProvider) throws IOException {
// TODO: MS, May 2011 -- I have refactored this code but could not test it. Bad me.
selectedIdSentence = -1;
selectedUsefulness = -1;
// Loop over all sentences in the cfProvider to find the most useful one.
// For speed reasons, we need to be a bit smart: if coverage features are not in memory,
// we bulk-load a chunk of them at a time.
if (cfProvider instanceof InMemoryCFProvider) {
// already in memory, can loop through all
determineMostUsefulSentence(selectedIdSents, unwantedIdSents, coverageDefinition, cfProvider);
} else {
assert cfProvider instanceof DatabaseCFProvider;
DatabaseCFProvider dbCfProvider = (DatabaseCFProvider) cfProvider;
int chunkSize = 100000;
for (int c = 0, max = dbCfProvider.getNumSentences(); c < max; c += chunkSize) {
int len = Math.min(chunkSize, max - c);
CoverageFeatureProvider chunk = dbCfProvider.getFeaturesInMemory(c, len);
determineMostUsefulSentence(selectedIdSents, unwantedIdSents, coverageDefinition, chunk);
}
}
return selectedIdSentence >= 0;
}
/**
* @param selectedIdSents
* selectedIdSents
* @param unwantedIdSents
* unwantedIdSents
* @param coverageDefinition
* coverageDefinition
* @param cfProvider
* cfProvider
*/
private void determineMostUsefulSentence(Set selectedIdSents, Set unwantedIdSents,
CoverageDefinition coverageDefinition, CoverageFeatureProvider cfProvider) {
for (int l = 0, num = cfProvider.getNumSentences(); l < num; l++) {
int id = cfProvider.getID(l);
// skip previously selected or excluded sentences:
if (selectedIdSents.contains(id) || unwantedIdSents.contains(id)) {
continue;
}
byte[] nextFeatVects = cfProvider.getCoverageFeatures(l);
// calculate how useful the feature vectors are
double usefulness = coverageDefinition.usefulnessOfFVs(nextFeatVects);
if (usefulness > selectedUsefulness) {
// the current sentence is (currently) the best sentence to add
selectedIdSentence = id;
selectedVectors = nextFeatVects;
selectedUsefulness = usefulness;
}
if (usefulness == -1.0) {
unwantedIdSents.add(id);
// idSentenceList[i] = -1; // Here the sentence should be marked as unwanted?
// System.out.println("unwanted id=" + id);
}
}
}
/**
* Determine if the stop criterion is reached
*
* @param sentences
* the list of selected sentences
* @param covDef
* the coverageDefinition
* @return true, if stop criterion is reached, false otherwise
*/
private boolean stopCriterionIsReached(Set sentences, CoverageDefinition covDef) {
if (stopNumSentences && sentences.size() >= maxNumSents)
// if we have the maximum number of sentences
// stop selecting immediately
return true;
// other stop criteria can be combined
boolean result = false;
if (stopSimpleDiphones && covDef.reachedMaxSimpleDiphones())
result = true;
if (stopSimpleProsody) {
if (covDef.reachedMaxSimpleProsody()) {
if (!stopSimpleDiphones && !stopClusteredDiphones) {
// set result to true only if we do not have to consider
// the simpleDiphones or clusteredDiphones stop criterion
result = true;
}
// else result remains false/true, depending on what the
// test result for simpleDiphones/clusteredDiphones was
} else {
// set the result to false, no matter what the result for
// simpleDiphones/clusteredDiphones was
result = false;
}
}
return result;
}
/**
* Read the feature vectors from disk for a given filename
*
* @param basename
* the file from which to read from
* @return the feature vectors from the file
* @throws IOException
* IOException
*/
private byte[] getNextFeatureVectors1(String basename) throws IOException {
// open the file
FileInputStream fis = new FileInputStream(new File(basename));
// read the first 4 bytes and combine them to get the number
// of feature vectors
byte[] vlength = new byte[4];
fis.read(vlength);
int numFeatVects = (((vlength[0] & 0xff) << 24) | ((vlength[1] & 0xff) << 16) | ((vlength[2] & 0xff) << 8) | (vlength[3] & 0xff));
// read the content of the file into a byte array
byte[] vectorBuf = new byte[4 * numFeatVects];
fis.read(vectorBuf);
fis.close();
// return the feature vectors
return vectorBuf;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy