package gate.learning.learners; import gate.creole.ResourceInstantiationException; import gate.learning.SparseFeatureVector; import gate.learning.learners.svm.svm_parameter; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; public class SvmForExec extends SupervisedLearner{ /** The uneven margins parameter. */ private float tau = (float)0.4; /** The data file for svm learning.*/ private String svmDat; /** The model file for svm learning.*/ private String modelSVMFile; /** The kernel type. */ private int kernelType =0; //linear kernel as default value /** kernel_type */ public static final int LINEAR = 0; public static final int POLY = 1; public static final int RBF = 2; public static final int SIGMOID = 3; public static final int PRECOMPUTED = 4; /**Parameters in the kernel function.*/ int paramD = 3; double paramG = 1.0; double paramR = 0.0; /**Class constructor without parameter.*/ public SvmForExec() { } /**Class constructor with tau parameter.*/ public SvmForExec(float t) { this.tau = t; } /**Class constructor with tau parameter.*/ public SvmForExec(float t, String command) { this.tau = t; this.commandLine = command; } /** Get the parameters from the command line. * @throws */ public void getParametersFromCommmand() { System.out.println("commandline=*"+commandLine+"*"); if(commandLine == null) { System.out.println("Error: no command for executing!!"); try { throw new Exception("no command to execute"); } catch(Exception e) { e.printStackTrace(); } } else { double coef1=1.0; String [] items = commandLine.split(" "); int len = items.length; modelSVMFile = items[len-1]; svmDat = items[len-2]; kernelType = 0; for(int i=0; i<len-2; ++i) { if(items[i].equals("-t") && i+1<len-2) { kernelType = new Integer(items[i+1]).intValue(); } if(items[i].equals("-d") && i+1<len-2) { this.paramD = new Integer(items[i+1]).intValue(); } if(items[i].equals("-g") && i+1<len-2) { this.paramG = new Double(items[i+1]).doubleValue(); } if(items[i].equals("-r") && i+1<len-2) { this.paramR = new Double(items[i+1]).doubleValue(); } if(items[i].equals("-s") && i+1<len-2) { coef1 = new Double(items[i+1]).doubleValue(); } if(items[i].equals("-tau") && i+1<len-2) { this.tau = new Float(items[i+1]).floatValue(); } } if(coef1!=0) this.paramR /= coef1; } } /** Method for training, by reading from data file for feature vectors, and * with label as input. */ public void trainingWithDataFile(BufferedWriter modelFile, BufferedReader dataFile, int totalNumFeatures, short[] classLabels, int numTraining) { try { //Write the data into the data file for svm learning BufferedWriter svmDataBuff = new BufferedWriter(new FileWriter(new File(svmDat))); for(int iCounter=0; iCounter<numTraining; ++iCounter) { final int i = iCounter; if(classLabels[i]>0) svmDataBuff.append("1 "); else svmDataBuff.append("-1 "); //int [] indexes = dataLearning[i].getIndexes(); //float [] values = dataLearning[i].getValues(); //for(int j=0; j<dataLearning[i].getLen(); ++j) //svmDataBuff.append(" "+dataLearning[i].nodes[j].index+":"+dataLearning[i].nodes[j].value); String line = dataFile.readLine(); svmDataBuff.append(line); svmDataBuff.append("\n"); } svmDataBuff.close(); //Execute the command for the SVM learning //Get the command line for the svm_learn, by getting rid of the tau parameter String commandLineSVM = obtainSVMCommandline(commandLine); //Run the external svm learn exectuable runExternalCommand(commandLineSVM); //runExternalCommandWithRedirect(commandLineSVM); //Read the model from the svm results file and write it into our model file writeSVMModelIntoFile(modelSVMFile, kernelType, modelFile, totalNumFeatures); } catch(IOException e) { e.printStackTrace(); } } public void training(BufferedWriter modelFile, SparseFeatureVector [] dataLearning, int totalNumFeatures, short [] classLabels, int numTraining) { try { //Write the data into the data file for svm learning BufferedWriter svmDataBuff = new BufferedWriter(new FileWriter(new File(svmDat))); for(int iCounter=0; iCounter<numTraining; ++iCounter) { final int i = iCounter; if(classLabels[i]>0) svmDataBuff.append("1"); else svmDataBuff.append("-1"); //int [] indexes = dataLearning[i].getIndexes(); //float [] values = dataLearning[i].getValues(); for(int j=0; j<dataLearning[i].getLen(); ++j) svmDataBuff.append(" "+dataLearning[i].nodes[j].index+":"+dataLearning[i].nodes[j].value); svmDataBuff.append("\n"); } svmDataBuff.close(); //Execute the command for the SVM learning //Get the command line for the svm_learn, by getting rid of the tau parameter String commandLineSVM = obtainSVMCommandline(commandLine); //Run the external svm learn exectuable runExternalCommand(commandLineSVM); //runExternalCommandWithRedirect(commandLineSVM); //Read the model from the svm results file and write it into our model file writeSVMModelIntoFile(modelSVMFile, kernelType, modelFile, totalNumFeatures); } catch(IOException e) { e.printStackTrace(); } } /** Get the command line for the svm_learn, by getting rid of the tau parameter.*/ public static String obtainSVMCommandline(String commandLine) { StringBuffer commandSVM = new StringBuffer(); String [] items = commandLine.split("[ \t]+"); int len=0; commandSVM.append(items[len++]); while(len<items.length) { if(items[len].equalsIgnoreCase("-tau")) { ++len; } else { commandSVM.append(" "+items[len]); } ++len; } return commandSVM.toString(); } public static void writeSVMModelIntoFile(String modelSVMFile, int kernelType, BufferedWriter modelFile, int totalNumFeatures) { //Open the svm model file BufferedReader svmModelBuff; try { svmModelBuff = new BufferedReader(new FileReader(new File(modelSVMFile))); int numSV=0; float b=0; String line; line = svmModelBuff.readLine(); while(!(line.contains("# threshold b,") || line.contains("nr_sv "))) { if(line.contains("# number of support vectors plus 1")) { numSV = new Integer(line.substring(0, line.indexOf(" "))).intValue(); numSV -= 1; //since it's number of SVs plus 1 in svm_light } if(line.contains("rho ")) { //for the model from libsvm b = new Float(line.substring(line.indexOf(" ")+1)).floatValue(); b = -b; } line = svmModelBuff.readLine(); } if(line.contains("# threshold b,")) { b = new Float(line.substring(0, line.indexOf(" "))).floatValue(); b = -b; //since the b in the svm model file is -b } if(line.contains("nr_sv ")) { //for the model from libsvm String [] items = line.split(" "); if(items.length>1) { numSV = new Integer(items[1]).intValue(); if(items.length>2) numSV += new Integer(items[2]).intValue(); } else { System.out.println("Error: no information for num_sv in the model file from libsvm!!"); try { throw new Exception(); } catch(Exception e) { e.printStackTrace(); } } line = svmModelBuff.readLine(); //read in one more line for the libsvm model file } System.out.println("b="+b+", num_sv="+numSV+"*"); //Convert into primal form, if it is linear kernel if(kernelType == 0) { //Define the sparse vectors used for SVs SparseFeatureVector [] svFVs = new SparseFeatureVector[numSV]; double [] alphas = new double[numSV]; SvmLibSVM.readOneSVMModel(svmModelBuff, numSV, svFVs, alphas); //Convert the dual form into primal form float [] w = new float[totalNumFeatures]; for(int i=0; i<numSV; ++i) { //int [] indexes = svFVs[i].getIndexes(); //float [] values = svFVs[i].getValues(); for(int j=0; j<svFVs[i].getLen(); ++j) w[svFVs[i].nodes[j].index] += alphas[i]*svFVs[i].nodes[j].value; } SvmLibSVM.writeLinearModelIntoFile(modelFile, b, w, totalNumFeatures); } else { //just write the all the model into file in dual form modelFile.append(b+"\n"); modelFile.append(numSV+"\n"); for(int i=0; i<numSV; ++i) { line = svmModelBuff.readLine(); modelFile.append(line); } } } catch(FileNotFoundException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } public void applying(BufferedReader modelFile, DataForLearning dataFVinDoc, int totalNumFeatures, int numClasses) { float optB; optB = (1-tau)/(1+tau); svm_parameter svmParam = setSvmParamByCommandline(); SvmLibSVM.svmApplying(modelFile, dataFVinDoc, totalNumFeatures, numClasses, optB, svmParam, this.isUseTauALLCases); } /** Set the svm_parameter.*/ svm_parameter setSvmParamByCommandline() { svm_parameter param = new svm_parameter(); param.kernel_type = kernelType; param.degree = paramD; param.gamma = paramG; param.coef0 = paramR; return param; } //a class used for execute an external command class StreamGobbler extends Thread { InputStream is; String type; StreamGobbler(InputStream is, String type) { this.is = is; this.type = type; } public void run() { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line=null; while ( (line = br.readLine()) != null) System.out.println(type + ">" + line); } catch (IOException ioe) { ioe.printStackTrace(); } } } public void runExternalCommand(String command) { try { String osName = System.getProperty("os.name" ); String[] cmd = new String[3]; boolean isWindows = false; if( osName.equals( "Windows XP") || osName.equals("Windows NT") ) { cmd[0] = "cmd.exe" ; cmd[1] = "/C" ; cmd[2] = command; isWindows = true; } else if( osName.equals( "Windows 95" ) ) { cmd[0] = "command.com" ; cmd[1] = "/C" ; cmd[2] = command; isWindows = true; } else { cmd[0] = " " ; cmd[1] = " " ; cmd[2] = command; } Runtime rt = Runtime.getRuntime(); //System.out.println("Execing " + cmd[0] + " " + cmd[1] // + " " + cmd[2]); Process proc = null; if(isWindows) proc = rt.exec(cmd); else proc = rt.exec(command); //linux cannot run the empty command // any error message? StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR"); // any output? StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT"); // kick them off errorGobbler.start(); outputGobbler.start(); // any error??? int exitVal = proc.waitFor(); //System.out.println("ExitValue: " + exitVal); } catch (Throwable t) { t.printStackTrace(); } } //a class used for execute an external command class StreamGobblerForDirect extends Thread { InputStream is; String type; OutputStream os; StreamGobblerForDirect(InputStream is, String type) { this.is = is; this.type = type; } StreamGobblerForDirect(InputStream is, String type, OutputStream redirect) { this.is = is; this.type = type; this.os = redirect; } public void run() { try { PrintWriter pw = null; if (os != null) pw = new PrintWriter(os); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line=null; while ( (line = br.readLine()) != null) { if (pw != null) pw.println(line); System.out.println(type + ">" + line); } if (pw != null) pw.flush(); } catch (IOException ioe) { ioe.printStackTrace(); } } } public void runExternalCommandWithRedirect(String command) { try { String osName = System.getProperty("os.name" ); String[] cmd = new String[3]; if( osName.equals( "Windows XP") || osName.equals("Windows NT") ) { cmd[0] = "cmd.exe" ; cmd[1] = "/C" ; cmd[2] = command; } else if( osName.equals( "Windows 95" ) ) { cmd[0] = "command.com" ; cmd[1] = "/C" ; cmd[2] = command; } else { cmd[0] = " " ; cmd[1] = " " ; cmd[2] = command; } Runtime rt = Runtime.getRuntime(); System.out.println("Execing " + cmd[0] + " " + cmd[1] + " " + cmd[2]); Process proc = rt.exec(cmd); // any error message? StreamGobblerForDirect errorGobbler = new StreamGobblerForDirect(proc.getErrorStream(), "ERROR"); // any output? String outFileName = command.substring(command.lastIndexOf('>')+1); FileOutputStream fos = new FileOutputStream(outFileName); StreamGobblerForDirect outputGobbler = new StreamGobblerForDirect(proc.getInputStream(), "OUTPUT", fos); // kick them off errorGobbler.start(); outputGobbler.start(); // any error??? int exitVal = proc.waitFor(); System.out.println("ExitValue: " + exitVal); fos.flush(); fos.close(); } catch (Throwable t) { t.printStackTrace(); } } }