updates Readme, initializes folder
Vorschlag für Vorgehen
This commit is contained in:
608
BlueJ-Origin/LABOR.java
Normal file
608
BlueJ-Origin/LABOR.java
Normal file
@@ -0,0 +1,608 @@
|
|||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.io.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.text.*;
|
||||||
|
|
||||||
|
public class LABOR
|
||||||
|
{
|
||||||
|
Object Perzeptron;
|
||||||
|
Method methodeLernen;
|
||||||
|
Method methodeBerechne;
|
||||||
|
ArrayList<Datapoint> Trainingset = new ArrayList<Datapoint>();
|
||||||
|
ArrayList<FormVisualization> listener = new ArrayList<FormVisualization>();
|
||||||
|
|
||||||
|
/* Das Labor-Objekt benötigt bei der Objekterzeugung ein Perzeptron, das
|
||||||
|
* vorher schon erzeugt werden musste. Man kann es in BlueJ übergeben,
|
||||||
|
* indem man einfach auf das Objekt klickt.
|
||||||
|
*/
|
||||||
|
public LABOR(Object perzeptron) throws Exception {
|
||||||
|
Perzeptron = perzeptron;
|
||||||
|
Class<?> pClass = Perzeptron.getClass();
|
||||||
|
Method[] methods = pClass.getDeclaredMethods();
|
||||||
|
ArrayList<Method> mlist = new ArrayList<Method>();
|
||||||
|
|
||||||
|
// Auswertemethode finden
|
||||||
|
for(int i=0;i<methods.length;++i){
|
||||||
|
if((methods[i].getReturnType().getName()).equals("double")
|
||||||
|
&& !Modifier.isPrivate( methods[i].getModifiers())
|
||||||
|
&& !Modifier.isProtected( methods[i].getModifiers())
|
||||||
|
&& methods[i].getParameterCount()==2
|
||||||
|
&& methods[i].getParameterTypes()[0].getName().equals("double")
|
||||||
|
&& methods[i].getParameterTypes()[1].getName().equals("double")
|
||||||
|
){
|
||||||
|
mlist.add(methods[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mlist.size()==0){
|
||||||
|
JOptionPane.showMessageDialog(null,"Es wurde keine passende Methode zum Auswerten eines Datenpunktes gefunden.\n" +
|
||||||
|
"Es wird erwartet, dass es eine Methode gibt, die als Parameter zwei double-Werte bekommt und\n"+
|
||||||
|
"einen double-Wert zurückliefert.\n\n"+
|
||||||
|
"Beispiel:\n"+
|
||||||
|
"public double berechneAusgabe(double x, double y)");
|
||||||
|
throw new Exception("Keine Auswertungsmethode für das Perzeptron gefunden");
|
||||||
|
}
|
||||||
|
else if(mlist.size()==1){
|
||||||
|
methodeBerechne=mlist.get(0);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
FormMethodSelector formMS = new FormMethodSelector( mlist.toArray(new Method[0] ), FormMethodSelector.BERECHNE );
|
||||||
|
formMS.setVisible(true);
|
||||||
|
if(formMS.selectedMethodName==null){
|
||||||
|
throw new Exception("Keine Auswertungsmethode für das Perzeptron gewählt");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for(int i=0;i<mlist.size();++i){
|
||||||
|
if(mlist.get(i).getName().equals(formMS.selectedMethodName)){
|
||||||
|
methodeBerechne=mlist.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mlist.clear();
|
||||||
|
// Trainingsmethode finden
|
||||||
|
for(int i=0;i<methods.length;++i){
|
||||||
|
if((methods[i].getReturnType().getName()).equals("void")
|
||||||
|
&& !Modifier.isPrivate( methods[i].getModifiers())
|
||||||
|
&& !Modifier.isProtected( methods[i].getModifiers())
|
||||||
|
&& methods[i].getParameterCount()==3
|
||||||
|
&& methods[i].getParameterTypes()[0].getName().equals("double")
|
||||||
|
&& methods[i].getParameterTypes()[1].getName().equals("double")
|
||||||
|
&& methods[i].getParameterTypes()[1].getName().equals("double")
|
||||||
|
){
|
||||||
|
mlist.add(methods[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mlist.size()==0){
|
||||||
|
JOptionPane.showMessageDialog(null,"Es wurde keine passende Methode zum Lernen eines Traingsdatenpunktes gefunden.\n" +
|
||||||
|
"Es wird erwartet, dass es eine Methode gibt, die als Parameter drei double-Werte bekommt und\n"+
|
||||||
|
"keinen Wert zurückliefert.\n\n"+
|
||||||
|
"Beispiel:\n"+
|
||||||
|
"public void lerne(double x, double y, double label)");
|
||||||
|
throw new Exception("Keine Trainingssmethode für das Perzeptron gefunden");
|
||||||
|
}
|
||||||
|
else if(mlist.size()==1){
|
||||||
|
methodeLernen=mlist.get(0);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
FormMethodSelector formMS = new FormMethodSelector( mlist.toArray(new Method[0] ), FormMethodSelector.TRAINIERE );
|
||||||
|
formMS.setVisible(true);
|
||||||
|
if(formMS.selectedMethodName==null){
|
||||||
|
throw new Exception("Keine Methode zum Training für das Perzeptron gewählt");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for(int i=0;i<mlist.size();++i){
|
||||||
|
if(mlist.get(i).getName().equals(formMS.selectedMethodName)){
|
||||||
|
methodeLernen=mlist.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hier kann man eine Datei öffnen, die Trainingsdaten enthält. Sie endet mit .csv und muss
|
||||||
|
* sich im selben Verzeichnis, wie das BlueJ-Projekt befinden. Oftmals heißt so eine Datei
|
||||||
|
* "daten.csv"
|
||||||
|
*/
|
||||||
|
public void ladeTrainingsdaten(String Dateiname){
|
||||||
|
Trainingset.clear();
|
||||||
|
File file= new File(Dateiname);
|
||||||
|
if(!file.exists()){
|
||||||
|
file= new File(Dateiname + ".csv");
|
||||||
|
if(!file.exists()){
|
||||||
|
JOptionPane.showMessageDialog(null,"Die Datei mit dem Bezeichner " + Dateiname + "\n" +
|
||||||
|
"konnte nicht gefunden werden. Prüfen Sie, ob sich wirklich diese Datei\n" +
|
||||||
|
"in dem Verzeichnis befindet und ob auch die Endung stimmt.\n"+
|
||||||
|
"Üblicherweise lautet die Dateiendung .csv");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try (Scanner scanner = new Scanner(file)) {
|
||||||
|
scanner.nextLine();
|
||||||
|
NumberFormat format = NumberFormat.getInstance(Locale.GERMAN);
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
String line = scanner.nextLine();
|
||||||
|
String[] tokens = line.split(";");
|
||||||
|
Datapoint d = new Datapoint();
|
||||||
|
d.label=tokens[1].equals("1")?1:0;
|
||||||
|
|
||||||
|
Number number = format.parse(tokens[2]);
|
||||||
|
double dv = number.doubleValue();
|
||||||
|
d.x1=dv;
|
||||||
|
number = format.parse(tokens[3]);
|
||||||
|
dv = number.doubleValue();
|
||||||
|
d.x2=dv;
|
||||||
|
Trainingset.add(d);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
JOptionPane.showMessageDialog(null,"Die Datei scheint fehlerhaft zu sein.\n" +
|
||||||
|
"Sie konnte leider nicht gelesen werden.");
|
||||||
|
}
|
||||||
|
UpdateListener();
|
||||||
|
JOptionPane.showMessageDialog(null,"Es wurden Trainingsdaten mit " + Trainingset.size() + " Datenpunkten eingelesen");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Die Delta-Lernregel wird einmal für
|
||||||
|
* alle Trainingsdatenpunkte durchgeführt.
|
||||||
|
*/
|
||||||
|
public void trainiereEinmal(){
|
||||||
|
ArrayList<Datapoint> set = (ArrayList<Datapoint>)Trainingset.clone();
|
||||||
|
Collections.shuffle(set);
|
||||||
|
for (Datapoint dp : set) {
|
||||||
|
Object[] par = new Object[3];
|
||||||
|
par[0]=dp.x1;
|
||||||
|
par[1]=dp.x2;
|
||||||
|
par[2]=dp.label;
|
||||||
|
try{
|
||||||
|
methodeLernen.invoke(Perzeptron, par);
|
||||||
|
}
|
||||||
|
catch(Exception exc){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
private double perzBerechne(double x1, double x2){
|
||||||
|
Object[] par = new Object[2];
|
||||||
|
par[0]=x1;
|
||||||
|
par[1]=x2;
|
||||||
|
double ret = -1;
|
||||||
|
try{
|
||||||
|
ret= (double)methodeBerechne.invoke(Perzeptron,par);
|
||||||
|
}
|
||||||
|
catch(Exception e){}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int testeAnhandTrainingsdaten(){
|
||||||
|
int fehler=0;
|
||||||
|
for(Datapoint dp: Trainingset){
|
||||||
|
Object[] par = new Object[2];
|
||||||
|
par[0]=dp.x1;
|
||||||
|
par[1]=dp.x2;
|
||||||
|
try{
|
||||||
|
double l = (double)methodeBerechne.invoke(Perzeptron,par);
|
||||||
|
if(l!=dp.label)
|
||||||
|
fehler++;
|
||||||
|
}catch(Exception exc){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fehler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Die Methode testet, ob alle Trainingsdaten richtig klassifiziert werden.
|
||||||
|
*/
|
||||||
|
public void überprüfePerzeptron(){
|
||||||
|
int fehler = testeAnhandTrainingsdaten();
|
||||||
|
if(fehler==0){
|
||||||
|
JOptionPane.showMessageDialog(null,"Alle Trainingsdaten wurden richtig klassifiziert.\n" +
|
||||||
|
"Ein weiteres Training ist nicht erforderlich");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
JOptionPane.showMessageDialog(null,"Es wurden " + fehler + " Datenpunkte der Trainingsdaten\n" +
|
||||||
|
"falsch klassifiziert.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Die Delta-Lernregel wird auf alle Trainingsdaten angewendet,
|
||||||
|
* bis entweder alle Trainingsdaten richtig klassifiziert werden,
|
||||||
|
* oder die Anzahl der Wiederholungen den Wert des Übergabeparameters
|
||||||
|
* überschreiten.
|
||||||
|
*/
|
||||||
|
public void trainiere(int maximaleAnzahlAnDurchläufen){
|
||||||
|
for(int i=0;i<maximaleAnzahlAnDurchläufen;++i){
|
||||||
|
trainiereEinmal();
|
||||||
|
if(testeAnhandTrainingsdaten()==0){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ein Fenster öffnet sich, das die Trainingsdaten anzeigt und auch,
|
||||||
|
* wir das Perzeptron die lineare Separierung durchführt.
|
||||||
|
*/
|
||||||
|
public void visualisiere(){
|
||||||
|
FormVisualization f = new FormVisualization(this);
|
||||||
|
listener.add(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateListener(){
|
||||||
|
for(FormVisualization f: listener){
|
||||||
|
f.canvas.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyCanvas extends JComponent
|
||||||
|
{
|
||||||
|
FormVisualization viz;
|
||||||
|
|
||||||
|
public MyCanvas(FormVisualization f){
|
||||||
|
super();
|
||||||
|
viz=f;
|
||||||
|
this.setBackground(Color.WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paintComponent(Graphics g){
|
||||||
|
super.paintComponents(g);
|
||||||
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
|
g2d.clearRect(0, 0, 500, 500);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
double minX1=-0.1;
|
||||||
|
double minX2=-0.1;
|
||||||
|
double maxX1=3;
|
||||||
|
double maxX2=3;
|
||||||
|
|
||||||
|
for(Datapoint d : viz.training){
|
||||||
|
if(d.x1>maxX1) maxX1=d.x1;
|
||||||
|
if(d.x2>maxX2) maxX2=d.x2;
|
||||||
|
if(d.x1<minX1) minX1=d.x1;
|
||||||
|
if(d.x2<minX2) minX2=d.x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color green = new Color(144,238,144);
|
||||||
|
Color red = new Color(240,128,128);
|
||||||
|
|
||||||
|
for(double y=0;y<500;y++){
|
||||||
|
for(double x=0;x<500;x++){
|
||||||
|
Datapoint p = new Datapoint();
|
||||||
|
p.x1=minX1 + (x)/500.0*(maxX1-minX1);
|
||||||
|
p.x2=minX2 + (500.0-y)/500.0*(maxX2-minX2);
|
||||||
|
double label=viz.labor.perzBerechne(p.x1, p.x2);
|
||||||
|
if(label==1){
|
||||||
|
g2d.setColor(green);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
g2d.setColor(red);
|
||||||
|
}
|
||||||
|
g2d.fillRect((int)x, (int)y, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Achsen
|
||||||
|
g2d.setColor(Color.BLACK);
|
||||||
|
g2d.setStroke(new BasicStroke(3));
|
||||||
|
double vaxs = ((0-minX1)/(maxX1-minX1))*500.0;
|
||||||
|
double vays = 500;
|
||||||
|
double vaxe = ((0-minX1)/(maxX1-minX1))*500.0;
|
||||||
|
double vaye = 0;
|
||||||
|
ZeichnePfeil(g2d,(int)vaxs, (int)vays, (int)vaxe, (int)vaye,10,10);
|
||||||
|
|
||||||
|
double haxs = 0;
|
||||||
|
double hays = 500.0-((0-minX2)/(maxX2-minX2))*500.0;
|
||||||
|
double haxe = 500;
|
||||||
|
double haye = 500.0-((0-minX2)/(maxX2-minX2))*500.0;
|
||||||
|
ZeichnePfeil(g2d,(int)haxs, (int)hays, (int)haxe, (int)haye,10,10);
|
||||||
|
|
||||||
|
g2d.setFont(new Font("TimesRoman", Font.PLAIN, 16));
|
||||||
|
g2d.drawString("x", 477, (int)(haye-4));
|
||||||
|
g2d.setFont(new Font("TimesRoman", Font.PLAIN, 10));
|
||||||
|
g2d.drawString("1", 483, (int)(haye-2));
|
||||||
|
|
||||||
|
g2d.setFont(new Font("TimesRoman", Font.PLAIN, 16));
|
||||||
|
g2d.drawString("x", (int)(vaxe+4), 21);
|
||||||
|
g2d.setFont(new Font("TimesRoman", Font.PLAIN, 10));
|
||||||
|
g2d.drawString("2", (int)(vaxe+11), 23);
|
||||||
|
|
||||||
|
// Trainingspunkte
|
||||||
|
g2d.setStroke(new BasicStroke(1));
|
||||||
|
for(Datapoint d : viz.training){
|
||||||
|
if(d.label==0){
|
||||||
|
g2d.setColor(Color.RED);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
g2d.setColor(Color.GREEN);
|
||||||
|
}
|
||||||
|
double px = ((d.x1-minX1)/(maxX1-minX1))*500.0;
|
||||||
|
double py = 500.0-((d.x2-minX2)/(maxX2-minX2))*500.0;
|
||||||
|
|
||||||
|
g.fillOval((int)px-4, (int)py-4, 9, 9);
|
||||||
|
g2d.setColor(Color.BLACK);
|
||||||
|
g.drawOval((int)px-4, (int)py-4, 9, 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ZeichnePfeil(Graphics2D g, int x1, int y1, int x2, int y2, int d, int h) {
|
||||||
|
int dx = x2 - x1, dy = y2 - y1;
|
||||||
|
double D = Math.sqrt(dx*dx + dy*dy);
|
||||||
|
double xm = D - d, xn = xm, ym = h, yn = -h, x;
|
||||||
|
double sin = dy / D, cos = dx / D;
|
||||||
|
|
||||||
|
x = xm*cos - ym*sin + x1;
|
||||||
|
ym = xm*sin + ym*cos + y1;
|
||||||
|
xm = x;
|
||||||
|
|
||||||
|
x = xn*cos - yn*sin + x1;
|
||||||
|
yn = xn*sin + yn*cos + y1;
|
||||||
|
xn = x;
|
||||||
|
|
||||||
|
int[] xpoints = {x2, (int) xm, (int) xn};
|
||||||
|
int[] ypoints = {y2, (int) ym, (int) yn};
|
||||||
|
|
||||||
|
g.drawLine(x1, y1, x2, y2);
|
||||||
|
g.fillPolygon(xpoints, ypoints, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Datapoint isClicked(double x, double y){
|
||||||
|
Datapoint ret = null;
|
||||||
|
|
||||||
|
double minX1=-0.1;
|
||||||
|
double minX2=-0.1;
|
||||||
|
double maxX1=3;
|
||||||
|
double maxX2=3;
|
||||||
|
|
||||||
|
for(Datapoint d : viz.training){
|
||||||
|
if(d.x1>maxX1) maxX1=d.x1;
|
||||||
|
if(d.x2>maxX2) maxX2=d.x2;
|
||||||
|
if(d.x1<minX1) minX1=d.x1;
|
||||||
|
if(d.x2<minX2) minX2=d.x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Datapoint d : viz.training){
|
||||||
|
double px = ((d.x1-minX1)/(maxX1-minX1))*500.0;
|
||||||
|
double py = 500.0-((d.x2-minX2)/(maxX2-minX2))*500.0;
|
||||||
|
if(Math.sqrt((px-x)*(px-x)+(py-y)*(py-y))<=5.0)
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
class Datapoint {
|
||||||
|
public double x1;
|
||||||
|
public double x2;
|
||||||
|
public double label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FormMethodSelector extends javax.swing.JDialog implements ListSelectionListener {
|
||||||
|
Method[] methods;
|
||||||
|
public String selectedMethodName;
|
||||||
|
int type;
|
||||||
|
public static final int BERECHNE=1;
|
||||||
|
public static final int TRAINIERE=2;
|
||||||
|
|
||||||
|
public FormMethodSelector(Method[] methods, int type) {
|
||||||
|
setModal(true);
|
||||||
|
initComponents();
|
||||||
|
this.methods=methods;
|
||||||
|
this.type=type;
|
||||||
|
DefaultListModel listModel = new DefaultListModel();
|
||||||
|
for(int i=0;i<methods.length;++i){
|
||||||
|
listModel.addElement(methods[i].getName());
|
||||||
|
}
|
||||||
|
jListMethods.setModel(listModel);
|
||||||
|
jListMethods.addListSelectionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
jLabel1 = new javax.swing.JLabel();
|
||||||
|
jScrollPane1 = new javax.swing.JScrollPane();
|
||||||
|
jListMethods = new javax.swing.JList<>();
|
||||||
|
jButtonOk = new javax.swing.JButton();
|
||||||
|
|
||||||
|
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||||
|
if(type==BERECHNE)
|
||||||
|
jLabel1.setText("Wählen Sie die Methode aus, die bewirkt, dass das Perzeptron einen Datenpunkt auswertet:");
|
||||||
|
else
|
||||||
|
jLabel1.setText("Wählen Sie die Methode aus, die bewirkt, dass das Perzeptron einen Schritt der Delta-Lernregel durchführt:");
|
||||||
|
|
||||||
|
jListMethods.setModel(new javax.swing.AbstractListModel<String>() {
|
||||||
|
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
|
||||||
|
public int getSize() { return strings.length; }
|
||||||
|
|
||||||
|
public String getElementAt(int i) { return strings[i]; }
|
||||||
|
});
|
||||||
|
jScrollPane1.setViewportView(jListMethods);
|
||||||
|
|
||||||
|
jButtonOk.setText("Weiter");
|
||||||
|
jButtonOk.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
jButtonOkActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||||
|
getContentPane().setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||||
|
.addComponent(jScrollPane1)
|
||||||
|
.addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
|
.addComponent(jButtonOk))
|
||||||
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(jLabel1)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(jButtonOk)
|
||||||
|
.addContainerGap(10, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}// </editor-fold>
|
||||||
|
|
||||||
|
private void jButtonOkActionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
this.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
selectedMethodName = jListMethods.getSelectedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables declaration - do not modify
|
||||||
|
private javax.swing.JButton jButtonOk;
|
||||||
|
private javax.swing.JLabel jLabel1;
|
||||||
|
private javax.swing.JList<String> jListMethods;
|
||||||
|
private javax.swing.JScrollPane jScrollPane1;
|
||||||
|
// End of variables declaration
|
||||||
|
}
|
||||||
|
public class FormVisualization extends javax.swing.JFrame {
|
||||||
|
ArrayList<Datapoint> training;
|
||||||
|
LABOR labor;
|
||||||
|
|
||||||
|
public FormVisualization(){
|
||||||
|
initComponents();
|
||||||
|
training = new ArrayList<Datapoint>();
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FormVisualization(LABOR l) {
|
||||||
|
initComponents();
|
||||||
|
training = l.Trainingset;
|
||||||
|
labor=l;
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
canvas = new MyCanvas(this);
|
||||||
|
jLabel1 = new javax.swing.JLabel();
|
||||||
|
jLabel2 = new javax.swing.JLabel();
|
||||||
|
jLabel3 = new javax.swing.JLabel();
|
||||||
|
jButtonClearDatapoints = new javax.swing.JButton();
|
||||||
|
|
||||||
|
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||||
|
getContentPane().setLayout(null);
|
||||||
|
|
||||||
|
canvas.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||||
|
public void mousePressed(java.awt.event.MouseEvent evt) {
|
||||||
|
canvasMouseClicked(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getContentPane().add(canvas);
|
||||||
|
canvas.setBounds(10,10,500, 500);
|
||||||
|
|
||||||
|
jLabel1.setText("Rechter Mausklick: Datenpunkt mit Label 0 wird hinzugefügt");
|
||||||
|
getContentPane().add(jLabel1);
|
||||||
|
jLabel1.setLocation(20, 540);
|
||||||
|
jLabel1.setSize(500, 20);
|
||||||
|
|
||||||
|
jLabel2.setText("Linker Mausklick: Datenpunkt mit Label 1 wird hinzugefügt");
|
||||||
|
getContentPane().add(jLabel2);
|
||||||
|
jLabel2.setLocation(20,520);
|
||||||
|
jLabel2.setSize(500, 20);
|
||||||
|
|
||||||
|
jLabel3.setText("Klick auf Datenpunkt: Datenpunkt wird entfernt");
|
||||||
|
getContentPane().add(jLabel3);
|
||||||
|
jLabel3.setLocation(20,560);
|
||||||
|
jLabel3.setSize(500, 20);
|
||||||
|
|
||||||
|
jButtonClearDatapoints.setActionCommand("<html><center>Alle Datenpunkte<br>löschen</center></html>");
|
||||||
|
jButtonClearDatapoints.setLabel("<html><div align=\"center\">Alle Datenpunkte<br>löschen</div></html>");
|
||||||
|
jButtonClearDatapoints.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||||
|
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||||
|
jButtonClearDatapointsMouseClicked(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getContentPane().add(jButtonClearDatapoints);
|
||||||
|
jButtonClearDatapoints.setBounds(370, 520, 140, 60);
|
||||||
|
|
||||||
|
addWindowListener(new java.awt.event.WindowAdapter() {
|
||||||
|
public void windowClosing(java.awt.event.WindowEvent e) {
|
||||||
|
CloseHandler();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pack();
|
||||||
|
this.setSize(540, 630);
|
||||||
|
}// </editor-fold>
|
||||||
|
|
||||||
|
private void CloseHandler(){
|
||||||
|
labor.listener.remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void canvasMouseClicked(java.awt.event.MouseEvent evt) {
|
||||||
|
Datapoint clickedPoint=canvas.isClicked(evt.getPoint().getX(), evt.getPoint().getY());
|
||||||
|
if(clickedPoint!=null){
|
||||||
|
training.remove(clickedPoint);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
double l=0;
|
||||||
|
if(SwingUtilities.isLeftMouseButton(evt)) l=1;
|
||||||
|
Datapoint p = new Datapoint();
|
||||||
|
|
||||||
|
double x = evt.getPoint().getX();
|
||||||
|
double y = 500.0-evt.getPoint().getY();
|
||||||
|
double minX1=-0.1;
|
||||||
|
double minX2=-0.1;
|
||||||
|
double maxX1=3;
|
||||||
|
double maxX2=3;
|
||||||
|
for(Datapoint d : training){
|
||||||
|
if(d.x1>maxX1) maxX1=d.x1;
|
||||||
|
if(d.x2>maxX2) maxX2=d.x2;
|
||||||
|
if(d.x1<minX1) minX1=d.x1;
|
||||||
|
if(d.x2<minX2) minX2=d.x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.label=l;
|
||||||
|
p.x1=minX1 + x/500.0*(maxX1-minX1);
|
||||||
|
p.x2=minX2 + y/500.0*(maxX2-minX2);
|
||||||
|
training.add(p);
|
||||||
|
}
|
||||||
|
canvas.repaint();
|
||||||
|
|
||||||
|
labor.UpdateListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void jButtonClearDatapointsMouseClicked(java.awt.event.MouseEvent evt) {
|
||||||
|
training.clear();
|
||||||
|
labor.UpdateListener();
|
||||||
|
canvas.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
MyCanvas canvas;
|
||||||
|
private javax.swing.JButton jButtonClearDatapoints;
|
||||||
|
private javax.swing.JLabel jLabel1;
|
||||||
|
private javax.swing.JLabel jLabel2;
|
||||||
|
private javax.swing.JLabel jLabel3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
BlueJ-Origin/daten.csv
Normal file
25
BlueJ-Origin/daten.csv
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
Beschriftung;Klasse;Kalorien;Eiweiß
|
||||||
|
Erbsen;1;37;3
|
||||||
|
Gurken;1;4;0
|
||||||
|
Karotten;1;29;1
|
||||||
|
Spinat;1;12;2
|
||||||
|
Tomaten;1;16;1
|
||||||
|
Apfel;1;49;0
|
||||||
|
Aprikose;1;49;1
|
||||||
|
Banane;1;70;1
|
||||||
|
Wassermelone;1;12;0
|
||||||
|
Aal;0;204;9
|
||||||
|
Forelle;0;50;10
|
||||||
|
Thunfisch;0;239;22
|
||||||
|
Lachs;0;137;13
|
||||||
|
Makrele;0;124;12
|
||||||
|
Ente;0;192;15
|
||||||
|
Pute;0;122;23
|
||||||
|
Schwein;0;167;18
|
||||||
|
Croissant;0;280;0
|
||||||
|
Donut;0;295;3
|
||||||
|
Semmel;0;276;7
|
||||||
|
Toastbrot;0;326;10
|
||||||
|
Weizenbrot;0;235;8
|
||||||
|
Rührkuchen;0;430;6
|
||||||
|
Roggenbrot;0;243;6
|
||||||
|
16
README.md
16
README.md
@@ -1,3 +1,19 @@
|
|||||||
# PerzeptronLabor
|
# PerzeptronLabor
|
||||||
|
|
||||||
Eine Portierung des Perzeptron Labors von Christoph Gräßl für die Online-IDE, entwickelt unter MIT-Lizenz.
|
Eine Portierung des Perzeptron Labors von Christoph Gräßl für die Online-IDE, entwickelt unter MIT-Lizenz.
|
||||||
|
|
||||||
|
## Vorschlag fürs Vorgehen:
|
||||||
|
|
||||||
|
1. Einlesen der Datenpunkte in der CSV-Datei (`ladeTrainigsdaten`)
|
||||||
|
2. Einrichten eines grafischen Koordinatensystems
|
||||||
|
3. Visualisieren der eingelesenen Datenpunkte
|
||||||
|
4. Visualisieren der kategorisierten Bereiche (rote/grüne Fläche)
|
||||||
|
5. Hinzufügen neuer Datenpunkte durch Mausklick (rechts/links)
|
||||||
|
6. Methode `trainiereEinmal`, mit Button#
|
||||||
|
7. Methode `überprüfePerzeptron`
|
||||||
|
8. Überlegen: wie umsetzen: trainiere n-Mal?
|
||||||
|
|
||||||
|
Entwicklung jedes Schrittes auf eigenem Branch, mergen in main, wenn zwei von uns einverstanden sind.
|
||||||
|
|
||||||
|
Verbesserungsvorschläge sind herzlich willkommen!
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user