Repository /Rseslib/rseslib-3.0.2.jar:rseslib.processing.classification.neural.VNNPanel


Back

No file description

Source code

/*
 * $RCSfile: VNNPanel.java,v $
 * $Revision: 1.3 $
 * $Date: 2007/08/18 10:44:06 $
 * $Author: wojna $
 * 
 * Copyright (C) 2002 - 2007 Logic Group, Institute of Mathematics, Warsaw University
 * 
 *  This file is part of Rseslib.
 *
 *  Rseslib is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Rseslib 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


package rseslib.processing.classification.neural;

import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.Image;
import java.util.*;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.awt.Color;
import java.awt.geom.*;
import javax.swing.JButton;
import javax.swing.ImageIcon;

import java.awt.Graphics;
import java.awt.geom.Line2D;
import java.awt.Rectangle;

import rseslib.structure.attribute.NominalAttribute;
import rseslib.structure.data.DoubleData;
import rseslib.structure.table.DoubleDataTable;

/**
 * Klasa reprezentujaca panel z siecia neuronowa
 * 
 * @author Damian Wojcik
 * 
 */
public class VNNPanel extends JComponent implements
		MouseListener {

    /** Serialization version. */
	private static final long serialVersionUID = 1L;

	static int IMAGEX = 20;

	static int IMAGEY = 20;

	static int FIRSTX = IMAGEX;

	static int FIRSTY = IMAGEY / 2;

	static int SECONDX = 0;

	static int SECONDY = IMAGEY / 2;

	static int ROW_DISTANCE = 20;
	
	static int LEFT_MARGIN = 120;
	
	static int RIGHT_MARGIN = 240;

	private int DimensionX = 800;

	private int DimensionY = 600;

	private Image blueImg[] = null;

	private double blueImgBrackets[] = null;

	private Image orangeImg = null;
	
	private Image inputImage = null;

	private Perceptron zoomedPerceptron = null;

	private int[] networkStructure;
	
	private List<Layer> layers;

	private Map<Integer, List<PPair>> paths = new HashMap<Integer, List<PPair>>();

	private Map<Perceptron, Rectangle> points = new HashMap<Perceptron, Rectangle>();

	private Map<Perceptron, Image> pictures = new HashMap<Perceptron, Image>();

	private double minWeight, maxWeight;

	private DoubleDataTable table;

	private Layer inputFoo;
	
	public JButton TrainButton;

	public JButton AddNodes;
	
	public boolean validShapes = false;

	public boolean showClassification;

	/**
	 * Konstruktor VNNPanel
	 * 
	 * @param newSizes
	 *            lista rozmiarow kolejnych warstw sieci - tez z wejsciem i
	 *            zakonczeniem
	 * @param newLayers
	 *            lista perceptronow w kolejnych warstwach - bez wejscia
	 */
	public VNNPanel(int[] newSizes, List<Layer> newLayers, DoubleDataTable tab, boolean addButtons) {
		/* inicjalizacja jako podklasy JPanel */
		super();

		int i;
		/* pobranie argumentow */
		if ((newSizes == null) || (newLayers == null)) {
			System.out.print("Jeden z parametrow konstruktora klasy NUpperPanel jest bledny");
			System.exit(1);
		} else {
			networkStructure = newSizes;
			layers = newLayers;
		}

		/* wczytanie obrazkow dla perceptronow */

			blueImg = new Image[6];
			blueImg[0] = new ImageIcon(rseslib.processing.classification.neural.VNNPanel.class.getResource("perceptron1.png")).getImage();
			blueImg[1] = new ImageIcon(rseslib.processing.classification.neural.VNNPanel.class.getResource("perceptron2.png")).getImage();
			blueImg[2] = new ImageIcon(rseslib.processing.classification.neural.VNNPanel.class.getResource("perceptron3.png")).getImage();
			blueImg[3] = new ImageIcon(rseslib.processing.classification.neural.VNNPanel.class.getResource("perceptron4.png")).getImage();
			blueImg[4] = new ImageIcon(rseslib.processing.classification.neural.VNNPanel.class.getResource("perceptron5.png")).getImage();
			blueImg[5] = new ImageIcon(rseslib.processing.classification.neural.VNNPanel.class.getResource("perceptron6.png")).getImage();
			orangeImg = new ImageIcon(rseslib.processing.classification.neural.VNNPanel.class.getResource("perceptronZaznaczony.png")).getImage();
			inputImage = new ImageIcon(rseslib.processing.classification.neural.VNNPanel.class.getResource("input.png")).getImage();
			blueImgBrackets = new double[6];
			for (i = 0; i < 6; i++)
				blueImgBrackets[i] = 0;


		inputFoo = new Layer(networkStructure[0]);

		/* inicjacja skojarzen pomiecdzy perceptronami a obrazkami */
		pictures.clear();

		// dodanie opisu okna
		setToolTipText("Visualisation of classification with neuron network classifier");

		if (addButtons)
		{
			TrainButton = new JButton("Train");
			this.add(TrainButton);
			TrainButton.setLocation(20, getHeight() - 30);
			TrainButton.setSize(new Dimension(100, 30));
			TrainButton.setVisible(true);

			AddNodes = new JButton("Add Perceptrons");
			this.add(AddNodes);
			AddNodes.setLocation(120, getHeight() - 30);
			AddNodes.setSize(new Dimension(160, 30));
			AddNodes.setVisible(true);
		}
		
		setLayout(null);
		setPreferredSize(new Dimension(DimensionX, DimensionY));
		addMouseListener(this);
		table = tab;
		showClassification = false;

		repaint();
	}

	public void setNotValidShapes() {
		validShapes = false;
		repaint();
	}
	
	/**
	 *  Zmiana rozmiaru okna - dezaktualizacja ulozenia elementow 
	 */
	public void setBounds(int x, int y, int width, int height) {
		validShapes = false;
		super.setBounds(x, y, width, height);
	}

	/**
	 *  Zmiana rozmiaru okna - dezaktualizacja ulozenia elementow 
	 */
	public void setBounds(Rectangle r) {
		validShapes = false;
		super.setBounds(r);
	}

	/**
	 * Uaktualnienie informacji o strukturze sieci neuronowej
	 * 
	 * @param newSizes
	 * @param newLayers
	 */
	public void updateModel(int[] newSizes, List<Layer> newLayers) {
		networkStructure = newSizes;
		layers = newLayers;
		pictures.clear();
		setNotValidShapes();
	}

	/**
	 * Rysowanie sieci neuronowej
	 */
	public void paint(Graphics g) {
		Graphics2D gg = (Graphics2D) g;
		Color baseColor = gg.getColor();

		super.paint(g);

		/* wyrysowanie perceptronow */
		Perceptron p1;		
		if (!validShapes) {
			points.clear();
			calculate();
		}	
		Iterator<Perceptron> it = points.keySet().iterator();
		while (it.hasNext()) {
			p1 = it.next();
			if (inputFoo.includesPercetron(p1)) {
				drawInput(g, points.get(p1));
			} else
				drawPerceptron(g, points.get(p1), p1);
		}

		/* wyskalowanie kolorow linii */
		if (!validShapes) {
			double pom1, pom2;
			minWeight = layers.get(0).getMinWeight();
			maxWeight = layers.get(0).getMaxWeight();
			for (Layer present : layers) {
				if (layers.get(0) != present) {
					pom1 = present.getMinWeight();
					pom2 = present.getMaxWeight();
					if (pom1 < minWeight)
						minWeight = pom1;
					if (pom2 > maxWeight)
						maxWeight = pom2;
				}
			}
		}

		/* wyliczenie prostych reprezentujacych linie pomiedzy perceptronami */
		if (!validShapes) {
			Perceptron p2;
			ListIterator<Perceptron> it1, it2;
			Layer previousl = null;
			Line2D.Float newLine;

			paths.clear();
			for (Layer present : layers) {
				if (previousl == null) {
					previousl = inputFoo;
				}
				it1 = previousl.perceptrons.listIterator();
				int i1 = -1;
				it2 = present.perceptrons.listIterator();
				while (it1.hasNext()) {
					p1 = it1.next();
					i1++;
					while (it2.hasNext()) {
						p2 = it2.next();
						newLine = new Line2D.Float(points.get(p1).x + FIRSTX,
								points.get(p1).y + FIRSTY, points.get(p2).x
										+ SECONDX, points.get(p2).y + SECONDY);
						if (paths.containsKey(i1)) {
							paths.get(i1).add(new PPair(p1, p2, newLine));
						} else {
							List<PPair> l = new ArrayList<PPair>();
							l.add(new PPair(p1, p2, newLine));
							paths.put(i1, l);
						}
					}
					it2 = present.perceptrons();
				}
				previousl = present;
			}
			validShapes = true;
		}
		List<PPair> lista;

		/* wyrysowanie linii pomiedzy perceptronami */
		for (Integer klucz : paths.keySet()) {
			lista = paths.get(klucz);
			for (PPair element : lista) {
				gg.setColor(ColorChooser.getColor(element.getSPerceptron()
						.getWeight(klucz), minWeight, maxWeight));
				gg.draw(element.getLine());
			}
		}

		/* dodanie legendy kolorow */
		int i;
		Point2D.Float corner = new Point2D.Float(getWidth() - RIGHT_MARGIN, 20);
		gg.setColor(Color.black);
		gg.drawString("Legend", (int) corner.getX(), (int) corner.getY());
		for (i = 0; i < ColorChooser.COLOR_NO; i++) {
			corner.y = corner.y + ROW_DISTANCE;
			gg.setColor(ColorChooser.COLORS[i]);
			Rectangle rec = new Rectangle((int) (corner.x), (int) (corner.y),
					40, 20);
			gg.draw(rec);
			gg.fill(rec);
			gg.setColor(Color.black);
			gg.drawString(ColorChooser.getBounds(i, minWeight, maxWeight),
					corner.x + 60, corner.y + 15);
		}

		/* dodanie opisu do zaznaczonego neuronu */
		if (zoomedPerceptron != null) {
			gg.setColor(Color.black);
			corner.y = corner.y + 45;
			if (showClassification) {
				gg.drawString("Output: " + zoomedPerceptron.getOutput(), corner.x, corner.y);
				corner.y = corner.y + 2*ROW_DISTANCE;
			}
			gg.drawString("Treshold: " + zoomedPerceptron.getWeight(zoomedPerceptron.getWeightLength() - 1), corner.x, corner.y);
			corner.y = corner.y + ROW_DISTANCE;
			gg.drawString("Weight values: ", corner.x, corner.y);
			corner.y = corner.y + ROW_DISTANCE;
			for (i = 0; i < (zoomedPerceptron.getWeightLength() - 1); i++) {
				gg.drawString(i + " : " + zoomedPerceptron.getWeight(i), corner.x, corner.y);
				corner.y = corner.y + ROW_DISTANCE;
			}
		}
		
		/* dodanie opisu do neuronow wejsciowych - z lewej strony obrazka neuronu */
		StringBuffer text = new StringBuffer();
		Set<Double> valueSet = new HashSet<Double>();
		Iterator vSIterator = valueSet.iterator();
		Rectangle ElementPosition, stringPosition;
		int attr_no = 0;		
		for (Perceptron p : inputFoo.perceptrons) {
			ElementPosition = points.get(p);
			stringPosition = (Rectangle) ElementPosition.clone();
			if (stringPosition.x - LEFT_MARGIN > 0)
				stringPosition.setLocation(stringPosition.x - LEFT_MARGIN,
						stringPosition.y + 12);
			else
				stringPosition.setLocation(0, stringPosition.y + 12);
			text.setLength(0);
			text.append(table.attributes().name(attr_no));
			if (text.length() > 15)
				text.setLength(15);
			if (table.attributes().isNumeric(attr_no)) {
				attr_no++;
			} else {
				if (table.attributes().attribute(attr_no).isNominal()) {
					if (table.attributes().attribute(attr_no).isDecision()) {
						attr_no++;
						text.setLength(0);
						text.append(table.attributes().name(attr_no));
					}
					if (!vSIterator.hasNext()) {
						valueSet = new HashSet<Double>();
						for (DoubleData dd : table.getDataObjects()) {
							valueSet.add(new Double(dd.get(attr_no)));
						}
						vSIterator = valueSet.iterator();
					}
					// dopisanie kolejnej wartosci
					text.append(" "+ (NominalAttribute.stringValue((Double) vSIterator.next())));
					// sprawdzenie czy moge sknczyc iterowanie
					if (!vSIterator.hasNext())
						attr_no++;
				}
			}
			gg.drawString(text.toString(), stringPosition.x, stringPosition.y);
		}

		/* dodanie opisu do neuronow wyjsciowych - z prawej strony obrazka neuronu*/
		attr_no = 0;
		while (! table.attributes().attribute(attr_no).isDecision())
			attr_no++;
		valueSet = new HashSet<Double>();
		for (DoubleData dd : table.getDataObjects()) {
			valueSet.add(new Double(dd.get(attr_no)));
		}
		vSIterator = valueSet.iterator();
		
		for (Perceptron p : layers.get(layers.size() - 1).perceptrons) {
			ElementPosition = points.get(p);
			stringPosition = (Rectangle) ElementPosition.clone();
			stringPosition.setLocation(stringPosition.x + 40,
					stringPosition.y + 12);
			gg.drawString(NominalAttribute.stringValue((Double) vSIterator.next()), stringPosition.x, stringPosition.y);
		}

		/* dodanie przyciskow */
		if (TrainButton!=null)
		{
			TrainButton.setLocation(20, getHeight() - 30);
			TrainButton.setVisible(true);
		}
		
		if (TrainButton!=null)
		{
			AddNodes.setLocation(120, getHeight() - 30);
			AddNodes.setVisible(true);
		}
		
		/* inne */
		gg.setColor(baseColor);
	}

	/**
	 * Rysowanie perceptronu w okreslonej lokalizacji
	 * @param g Graphics
	 * @param rec Rectangle
	 * @param p Perceptron
	 */
	private void drawPerceptron(Graphics g, Rectangle rec, Perceptron p) {
		if (pictures.containsKey(p)) {
			g.drawImage(pictures.get(p), rec.x, rec.y, null);
		} else {
			if (!showClassification) {
				g.drawImage(blueImg[3], rec.x, rec.y, null);
			} else {
				double pom = p.getOutput();
				int i = 0;
				while ((i < blueImgBrackets.length)
						&& (blueImgBrackets[i] < pom))
					i++;
				if (i >= blueImgBrackets.length)
					i = blueImgBrackets.length - 1;
				g.drawImage(blueImg[i], rec.x, rec.y, null);
			}
		}
	}

	/**
	 * Rysowanie obrazka wejscia z okreslonej lokalizacji
	 * @param g Graphics
	 * @param rec Rectangle
	 */
	private void drawInput(Graphics g, Rectangle rec) {
		g.drawImage(inputImage, rec.x, rec.y, null);
	}

	/**
	 * Wyjcie z trybu klasyfikacji wiersza
	 *
	 */
	public void setNotShowClassification() {

		showClassification = false;
		repaint();
	}

	/** wejscie do trybu klasyfikacji wiersza*/
	public void setShowClassification() {
		double min, max, pom;
		double distance;

		showClassification = true;
		min = layers.get(0).getMinOutput();
		max = layers.get(0).getMaxOutput();
		for (Layer o : layers) {
			pom = o.getMinOutput();
			if (pom < min)
				min = pom;
			pom = o.getMaxOutput();
			if (pom > max)
				max = pom;

		}
		distance = (max - min) / (6);
		if (distance < 0)
			distance = -distance;
		int i;
		for (i = 0; i < 6; i++) {
			if (i == 0)
				blueImgBrackets[i] = min + distance;
			else
				blueImgBrackets[i] = blueImgBrackets[i - 1] + distance;
		}
	}

	/**
	 *  Policzenie rozmieszczenia perceptronow na panelu
	 */
	private void calculate() {
		Perceptron p;
		ListIterator<Perceptron> it;
		int i, j;
		/* przesuniecia(w pikslach) przy przechodzeniu miedzy wierszami i kolumnami*/
		int stepRow, stepColumn; 
		/* wspolrzedne(pikslowe) reozpoczecia przechodzenia miedzy wierszami lub kolumnami*/
		int zeroRow, zeroColumn; 
		/*biezace wspolrzedne*/
		int currentX, currentY;

		/* w wypadku gdy perceptrono w pierwszej warstwie ejst za duzo - powiekszenie panelu*/
		if ((inputFoo.perceptrons.size() * IMAGEY + 100) > getHeight()) {
			setPreferredSize(new Dimension(DimensionX, inputFoo.perceptrons.size() * IMAGEY + 100));
		}
		/*rozmiary panelu*/
		int sizeX = getWidth();
		int sizeY = getHeight();
		
		/*incjalizacja zmiennych*/
		i = 0; 
		j = 0;
		zeroRow = LEFT_MARGIN;
		stepRow = (sizeX - zeroRow) / (networkStructure.length + 1);
		stepColumn = (sizeY - 50) / (networkStructure[i] + 2);
		zeroColumn = (sizeY - 50) / 2 - stepColumn * (networkStructure[i] / 2);


		
		/* obliczenia dla warstwy wejsciowej*/
		it = inputFoo.perceptrons();
		currentX = zeroRow;
		currentY = zeroColumn;	
		while (it.hasNext()) {
			p = it.next();
			points.put(p, new Rectangle(currentX, currentY, IMAGEX, IMAGEY));
			j = j + 1;
			currentY += stepColumn;
		}
		currentX += stepRow;
		i++;
		
		/*obliczenia dla neuronow wlasciwych*/
		for (Layer o : layers) {
			it = o.perceptrons();
			j = 0;
			stepColumn = (sizeY - 50) / (networkStructure[i] + 2);
			zeroColumn = (sizeY - 50) / 2 - stepColumn * (networkStructure[i] / 2);
			currentY = zeroColumn;
			while (it.hasNext()) {
				p = it.next();
				points.put(p, new Rectangle(currentX, currentY, IMAGEX, IMAGEY));
				j = j + 1;
				currentY += stepColumn;
			}
			currentX += stepRow;
			i = i + 1;
		}
	}

	public void mouseClicked(MouseEvent e) {
		;
	}

	public void mouseEntered(MouseEvent e) {
		;
	}

	public void mouseExited(MouseEvent e) {
		/* opuszczenie obszaru panelu */
		zoomedPerceptron = null;
		pictures.clear();
		repaint();
	}

	public void mousePressed(MouseEvent e) {
		/* sprawdzene czy wybrano neuron */
		pictures.clear();
		for (Perceptron p : points.keySet()) {
			if (points.get(p).contains(e.getPoint())) {
				if (inputFoo.perceptrons.contains(p))
					zoomedPerceptron = null;
				else {
					pictures.put(p, orangeImg);
					/* dac info o obrazku */
					zoomedPerceptron = p;
					repaint();
				}
				return;
			}
		}
	}

	public void mouseReleased(MouseEvent e) {
		;
	}

}

Copyright © 2008-2011 by TunedIT
Design by luksite