Jannis (0.1preAlpha) | ||
Frames | No Frames |
1: /* NeuralNet.java - Copyright (c) 2005 by Stefan Thesing 2: <p>This file is part of Jannis.</p> 3: <p>Jannis is free software; you can redistribute it and/or modify 4: it under the terms of the GNU General Public License as published by 5: the Free Software Foundation; either version 2 of the License, or 6: (at your option) any later version.</p> 7: <p>Jannis is distributed in the hope that it will be useful, 8: but WITHOUT ANY WARRANTY; without even the implied warranty of 9: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10: GNU General Public License for more details.</p> 11: <p>You should have received a copy of the GNU General Public License 12: along with Jannis; if not, write to the<br> 13: Free Software Foundation, Inc.,<br> 14: 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA<br> 15: */ 16: package de.webdings.jannis.neuralnet; 17: 18: import java.io.IOException; 19: 20: import de.webdings.jannis.exceptions.BadArgumentException; 21: import de.webdings.jannis.exceptions.LowerLayersEmptyException; 22: import de.webdings.jannis.exceptions.NeuronTypeMismatchException; 23: import de.webdings.jannis.neuralnet.nnml.BiNetToNNML; 24: import de.webdings.tools.StringSearch; 25: import de.webdings.tools.files.TextFiles; 26: /** 27: * NeuralNet is a wrapper for the actual neural net that is 28: * represented in {@link #layers layers}.<br> 29: * It provides functionality for setting up, using, training 30: * and reconfiguring the net easily as well as saving it 31: * to an NNML file.</p> 32: * <p>The net can consist of all known neuron types that are 33: * a subclass of the abstract 34: * {@link de.webdings.jannis.neuralnet.Neuron}. It accepts 35: * only one such type at a time. So you can't mix different 36: * neuron types in one net.</p> 37: * <p>Currently only one neuron type is supported:</p> 38: * <ul> 39: * <li>{@link de.webdings.jannis.neuralnet.BiNeuron BiNeuron}</li> 40: * </ul> 41: * 42: * @author Stefan Thesing<br> 43: * Website: <a href="http://www.webdings.de">http://www.webdings.de</a> 44: * @version 0.1 10.08.2005 45: */ 46: public class NeuralNet { 47: //attributes 48: /** 49: * <code>layers</code> is an array containing layers 50: * of neurons. Each layer is an array containing neurons. 51: * So <code>layers</code> is the actual neural net 52: * wrapped by this class. 53: */ 54: protected Neuron[][] layers; 55: /** 56: * <code>type</code> represents the type of neurons 57: * of which this net consists. For example, if a net 58: * consists of 59: * {@link de.webdings.jannis.neuralnet.BiNeuron BiNeuron}s 60: * <code>type</code> reads 61: * "de.webdings.jannis.neuralnet.BiNeuron"</p> 62: * <p>Mixing different neuron types is not allowed. 63: * 64: */ 65: protected String type; 66: //constructors 67: /** 68: * Constructs an empty NeuralNet of the specified type. 69: * @param type 70: * @throws NeuronTypeMismatchException 71: */ 72: public NeuralNet(String type) throws NeuronTypeMismatchException { 73: if(type.equals("de.webdings.jannis.neuralnet.BiNeuron")) { 74: this.layers = new BiNeuron[0][]; 75: this.type = type; 76: } else { 77: throw new NeuronTypeMismatchException("Unknown neuron type!"); 78: } 79: } 80: /** 81: * Constructs an empty NeuralNet of the specified type. 82: * @param type 83: * @throws NeuronTypeMismatchException 84: */ 85: public NeuralNet(Class type) throws NeuronTypeMismatchException { 86: this(new String(type.getName())); 87: } 88: /** 89: * Constructs a NeuralNet using a specified array containing layers 90: * of neurons. This constructor automatically determines the type of 91: * the neurons that the specified layers contain and rejects layers 92: * that contain neurons of unsupported types as well as layers that 93: * contain neurons of mixed types. 94: * @param layers 95: * @throws NeuronTypeMismatchException 96: */ 97: public NeuralNet(Neuron[][] layers) throws NeuronTypeMismatchException { 98: if(areNeuronTypesConsistent(layers)) { 99: this.type = new String(layers[0][0].getClass().getName()); 100: this.layers = layers; 101: } else { 102: throw new NeuronTypeMismatchException 103: ("Couldn't create neural net. There " + 104: "are gaps in the specified layers " + 105: "or they contain different neuron " + 106: "types!"); 107: } 108: } 109: /** 110: * Constructs a NeuralNet starting with a single specified neuron and automatically 111: * determines the type of this neuron. It rejects unsupported neuron types. 112: * @param aFirstInputNeuron 113: * @throws NeuronTypeMismatchException 114: */ 115: public NeuralNet(Neuron aFirstInputNeuron) throws NeuronTypeMismatchException { 116: if(aFirstInputNeuron.getClass().getName().equals 117: ("de.webdings.jannis.neuralNet.BiNeuron")){ 118: this.layers = new BiNeuron[1][]; 119: layers[0] = new BiNeuron[1]; 120: layers[0][0]= aFirstInputNeuron; 121: this.type = new String(aFirstInputNeuron.getClass().getName()); 122: } else { 123: throw new NeuronTypeMismatchException("Unsupported neuron type: " 124: + aFirstInputNeuron.getClass().getName() + "!"); 125: } 126: } 127: 128: /** 129: * This static method is called by other methods and constructors 130: * to ensure that the neuron types used in this net are consistent. 131: * @param layers The layers of the net that is checked for consistency. 132: * @return <code>true</code> if only one type of Neurons is used in this 133: * net, <code>false</code> if there are mixed types. 134: * @throws NeuronTypeMismatchException if the specified layers are empty. 135: */ 136: public static boolean areNeuronTypesConsistent(Neuron[][] layers) 137: throws NeuronTypeMismatchException { 138: String sType; 139: //Check if the first neuron exists 140: if(layers.length>0 141: && layers[0].length>0 142: && layers[0][0] != null) { 143: //use the type of the first neuron for comparison 144: sType = new String(layers[0][0].getClass().getName()); 145: //Check if the other neurons are the same type 146: for(int i=0;i<layers.length;++i) { 147: for(int j=0;j<layers[i].length;++j) { 148: if(layers[i][j]==null 149: ||!(layers[i][j].getClass().getName(). 150: equals(sType))) { 151: return false; 152: } 153: } 154: } 155: //If all is well we can use the specified layers 156: return true; 157: } else { 158: throw new NeuronTypeMismatchException("Could not determine " + 159: "neuron type! Specified layers are empty."); 160: } 161: 162: } 163: //setters and getters 164: /** 165: * @return Returns the layers. 166: */ 167: public Neuron[][] getLayers() { 168: return layers; 169: } 170: /** 171: * This methods replaces the actual neural net wrapped 172: * by this class with the specified array. It does 173: * essentially the same as the constructor with the same 174: * parameter. 175: * @param layers The layers to set. 176: * @throws NeuronTypeMismatchException 177: */ 178: public void setLayers(Neuron[][] layers) throws NeuronTypeMismatchException { 179: if(areNeuronTypesConsistent(layers)) { 180: this.type = new String(layers[0][0].getClass().getName()); 181: this.layers = layers; 182: } else { 183: throw new NeuronTypeMismatchException 184: ("Couldn't create neural net. There " + 185: "are gaps in the specified layers " + 186: "or they contain different neuron " + 187: "types!"); 188: } 189: } 190: /** 191: * @return Returns the neuron type of this net. 192: */ 193: public String getType() { 194: return type; 195: } 196: //other 197: /** 198: * Adds a neuron to the specified layer 199: * @param neuron 200: * @param targetLayerID 201: * @throws LowerLayersEmptyException 202: * @throws NeuronTypeMismatchException 203: * @throws BadArgumentException 204: */ 205: public void addNeuron(Neuron neuron, int targetLayerID) 206: throws LowerLayersEmptyException, 207: NeuronTypeMismatchException, BadArgumentException { 208: //check if the neuron is the same type as this net 209: if(!neuron.getClass().getName().equals(this.type)) { 210: throw new NeuronTypeMismatchException("The " + 211: "specified neuron doesn't match the type " + 212: "of this net!"); 213: } 214: //Does targetLayerID fit into the netsize? 215: if(targetLayerID>=layers.length) { 216: throw new BadArgumentException("The target layer " + 217: "you specified does not exist!"); 218: } 219: //If the layer with the specified ID hasn't been 220: //initialized yet, do it now... 221: if(layers[targetLayerID]==null) { 222: layers[targetLayerID] = new Neuron[0]; 223: } 224: //check if the layers before targetLayerID are 225: //empty. If yes throw an exception 226: for(int i=0;i<targetLayerID;++i) { 227: if(layers[i].length<1) { 228: throw new LowerLayersEmptyException(); 229: } 230: } 231: //if everything's ok add the new neuron to the 232: //specified layer 233: Neuron[] tempLayer = new Neuron[layers[targetLayerID].length+1]; 234: for(int i=0; i<layers[targetLayerID].length; ++i) { 235: tempLayer[i] = layers[targetLayerID][i]; 236: } 237: tempLayer[layers[targetLayerID].length] = neuron; 238: layers[targetLayerID] = tempLayer; 239: } 240: 241: /** 242: * Adds a new empty layer to the net. 243: * @throws NeuronTypeMismatchException 244: */ 245: public void addLayer() throws NeuronTypeMismatchException { 246: if(this.getType().equals 247: ("de.webdings.jannis.neuralnet.BiNeuron")) { 248: this.addLayer(new BiNeuron[0]); 249: } else { 250: throw new NeuronTypeMismatchException("Unsupported neuron type: " 251: + this.getClass().getName() + "!"); 252: 253: } 254: } 255: 256: /** 257: * Adds a specified number of empty layers to the net. 258: * @param numberOfLayersToAdd 259: * @throws NeuronTypeMismatchException 260: */ 261: public void addLayers(int numberOfLayersToAdd) throws NeuronTypeMismatchException { 262: for(int i=0;i<numberOfLayersToAdd;++i) { 263: this.addLayer(); 264: } 265: } 266: 267: /** 268: * Adds the specified layer to the net. 269: * @param l 270: * @throws NeuronTypeMismatchException 271: */ 272: public void addLayer(Neuron[] l) throws NeuronTypeMismatchException { 273: this.addLayer(l, this.layers.length); 274: } 275: 276: 277: /** 278: * Adds the specified layer to the net using the 279: * specified layerID. If the net already contains 280: * a layer with this ID it (and the following layers) 281: * will be moved one step farther.<br> 282: * So the ID number of these layers will be increased 283: * by one.<br> 284: * If you don't want that, but want to replace the 285: * existing layer use the method replaceLayer. 286: * @param l 287: * @param layerID 288: * @throws NeuronTypeMismatchException 289: */ 290: public void addLayer(Neuron[] l, int layerID) throws NeuronTypeMismatchException { 291: if(StringSearch.stringContainsCaseSensitive 292: (l.getClass().getName(), 293: "de.webdings.jannis.neuralnet.BiNeuron")) { 294: Neuron[][] temp = new Neuron[layers.length+1][]; 295: for(int i=0;i<layerID;++i) { 296: temp[i] = layers[i]; 297: } 298: temp[layerID] = l; 299: for(int i=layerID+1;i<temp.length;++i) { 300: temp[i] = layers[i-1]; 301: } 302: layers = temp; 303: } else { 304: throw new NeuronTypeMismatchException(); 305: } 306: 307: } 308: 309: /** 310: * Replaces the layer of the specified layerID with the 311: * specified layer l. 312: * @param l 313: * @param layerID 314: * @throws NeuronTypeMismatchException 315: */ 316: public void replaceLayer(Neuron[] l, int layerID) throws NeuronTypeMismatchException { 317: if(StringSearch.stringContainsCaseSensitive 318: (l.getClass().getName(), 319: "de.webdings.jannis.neuralnet.BiNeuron")) { 320: Neuron[][] temp = new Neuron[layers.length][]; 321: for(int i=0;i<layerID;++i) { 322: temp[i] = layers[i]; 323: } 324: temp[layerID] = l; 325: for(int i=layerID+1;i<layers.length;++i) { 326: temp[i] = layers[i]; 327: } 328: layers = temp; 329: } else { 330: throw new NeuronTypeMismatchException(); 331: } 332: } 333: 334: /** 335: * Saves a NNML representation of the net to a file 336: * of the specified filename. 337: * @param fileName 338: * @throws NeuronTypeMismatchException if the neuron type 339: * of the net is not supported. 340: * @throws IOException 341: */ 342: public void toFile(String fileName) throws NeuronTypeMismatchException, IOException { 343: if(this.getType().equals 344: ("de.webdings.jannis.neuralnet.BiNeuron")) { 345: BiNetToNNML konverter = new BiNetToNNML(); 346: try { 347: TextFiles.writeToFile(fileName, konverter.generateString(layers)); 348: } catch (Exception e) { 349: // TODO Auto-generated catch block 350: System.out.print(e.getClass()); 351: System.out.print(e.getMessage()); 352: //e.printStackTrace();; 353: } 354: } else { 355: throw new NeuronTypeMismatchException("Saving of " 356: + "nets of this neuron type is not yet supported."); 357: } 358: 359: }
Jannis (0.1preAlpha) |
© 2005 by Stefan Thesing;
Verbatim copying and redistribution of this entire page are permitted provided this notice is preserved.