├── .gitignore ├── ascii-diagramm.txt ├── src └── dsv2 │ ├── Distance.java │ ├── PointsDouble.java │ ├── MahalanobisDistance.java │ ├── VectorsDoubleArray.java │ ├── NormalDistributionDistance.java │ ├── SimplifiedNormalDistributionDistance.java │ ├── LogarithmisedNormalDistributionDistance.java │ ├── EuclideanDistance2.java │ ├── HMM.java │ ├── Input.java │ ├── Viterbi.java │ ├── ViterbiHMM.java │ ├── Util.java │ ├── Vector.java │ ├── ViterbiTraining.java │ ├── DSV2.java │ └── ViterbiTrainingHMM.java ├── daten.txt └── daten2.txt /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | nbproject 3 | test 4 | build.xml 5 | manifest.mf 6 | /dist/ -------------------------------------------------------------------------------- /ascii-diagramm.txt: -------------------------------------------------------------------------------- 1 | a 2 | 3| x 3 | 2| / 4 | 1| x-x-x 5 | 0|x 6 | -+---------x 7 | |0 1 2 3 4 -------------------------------------------------------------------------------- /src/dsv2/Distance.java: -------------------------------------------------------------------------------- 1 | package dsv2; 2 | 3 | /** 4 | * 5 | * @author ns130291 6 | */ 7 | public interface Distance { 8 | public double calcDistance(Vector x, Vector mu, Vector sigma2) throws RuntimeException; 9 | } 10 | -------------------------------------------------------------------------------- /daten.txt: -------------------------------------------------------------------------------- 1 | 3 2 | 5 3 | 6 3 5 4 4 4 | 5 | 9 1 1 9 1 2 8 2 1 6 3 4 7 2 6 2 0 7 6 | 8 2 1 4 2 4 2 1 8 7 | 8 1 3 7 1 2 12 3 1 3 3 5 2 1 9 8 | 9 2 1 6 1 2 11 2 5 2 3 8 9 | 9 2 1 6 2 3 4 2 5 2 1 6 10 | -------------------------------------------------------------------------------- /daten2.txt: -------------------------------------------------------------------------------- 1 | 3 2 | 7 3 | 6 3 5 4 4 11 9 4 | 5 | 9 1 1 9 1 2 8 2 1 6 3 4 7 2 6 2 0 7 6 | 8 2 1 4 2 4 2 1 8 7 | 8 1 3 7 1 2 12 3 1 3 3 5 2 1 9 8 | 9 2 1 6 1 2 11 2 5 2 3 8 9 | 9 2 1 6 2 3 4 2 5 2 1 6 10 | 9 1 1 9 2 1 10 1 2 7 2 1 9 1 2 10 2 1 6 3 4 4 2 6 2 0 7 2 0 7 2 0 7 11 | 7 1 1 3 2 4 1 1 5 2 2 3 3 3 7 2 2 6 2 1 7 2 0 7 3 1 7 12 | -------------------------------------------------------------------------------- /src/dsv2/PointsDouble.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package dsv2; 8 | 9 | import java.awt.Point; 10 | 11 | /** 12 | * 13 | * @author ns130291 14 | */ 15 | public class PointsDouble { 16 | Point[] points; 17 | double doub; 18 | 19 | public PointsDouble(Point[] points, double doub) { 20 | this.points = points; 21 | this.doub = doub; 22 | } 23 | 24 | public Point[] getPoints() { 25 | return points; 26 | } 27 | 28 | public double getDouble() { 29 | return doub; 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/dsv2/MahalanobisDistance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package dsv2; 8 | 9 | /** 10 | * 11 | * @author ns130291 12 | */ 13 | public class MahalanobisDistance implements Distance{ 14 | 15 | @Override 16 | public double calcDistance(Vector x, Vector mu, Vector sigma2) throws RuntimeException { 17 | if(x.getSize() != mu.getSize() && x.getSize() != sigma2.getSize()){ 18 | throw new RuntimeException("Vectors have different sizes"); 19 | }else{ 20 | double[] xs = x.getValues(); 21 | double[] mus = mu.getValues(); 22 | double[] sigmas2 = sigma2.getValues(); 23 | 24 | double distance = 0; 25 | 26 | for(int i = 0; i < xs.length; i++){ 27 | distance += Math.pow(xs[i]-mus[i], 2) / sigmas2[i]; 28 | } 29 | return distance; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/dsv2/VectorsDoubleArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package dsv2; 8 | 9 | /** 10 | * 11 | * @author ns130291 12 | */ 13 | public class VectorsDoubleArray { 14 | private Vector[] vectors1; 15 | private Vector[] vectors2; 16 | private double doub; 17 | private double[][] array; 18 | 19 | public VectorsDoubleArray(Vector[] vectors1, Vector[] vectors2, double doub, double[][] array) { 20 | this.vectors1 = vectors1; 21 | this.vectors2 = vectors2; 22 | this.doub = doub; 23 | this.array = array; 24 | } 25 | 26 | public Vector[] getVectors1() { 27 | return vectors1; 28 | } 29 | 30 | public Vector[] getVectors2() { 31 | return vectors2; 32 | } 33 | 34 | public double getDouble() { 35 | return doub; 36 | } 37 | 38 | public double[][] getArray() { 39 | return array; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/dsv2/NormalDistributionDistance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package dsv2; 8 | 9 | /** 10 | * 11 | * @author ns130291 12 | */ 13 | public class NormalDistributionDistance implements Distance{ 14 | 15 | @Override 16 | public double calcDistance(Vector x, Vector mu, Vector sigma2) throws RuntimeException { 17 | if(x.getSize() != mu.getSize() && x.getSize() != sigma2.getSize()){ 18 | throw new RuntimeException("Vectors have different sizes"); 19 | }else{ 20 | double[] xs = x.getValues(); 21 | double[] mus = mu.getValues(); 22 | double[] sigmas2 = sigma2.getValues(); 23 | 24 | double distance = 0; 25 | 26 | for(int i = 0; i < xs.length; i++){ 27 | distance += 0.5 * (Math.log(2 * Math.PI * sigmas2[i]) + Math.pow(xs[i]-mus[i], 2) / sigmas2[i]); 28 | } 29 | return distance; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/dsv2/SimplifiedNormalDistributionDistance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package dsv2; 8 | 9 | /** 10 | * 11 | * @author ns130291 12 | */ 13 | public class SimplifiedNormalDistributionDistance implements Distance{ 14 | 15 | @Override 16 | public double calcDistance(Vector x, Vector mu, Vector sigma2) throws RuntimeException { 17 | if(x.getSize() != mu.getSize() && x.getSize() != sigma2.getSize()){ 18 | throw new RuntimeException("Vectors have different sizes"); 19 | }else{ 20 | double[] xs = x.getValues(); 21 | double[] mus = mu.getValues(); 22 | double[] sigmas2 = sigma2.getValues(); 23 | 24 | double distance = 0; 25 | 26 | for(int i = 0; i < xs.length; i++){ 27 | distance += Math.log(sigmas2[i]) + Math.pow(xs[i]-mus[i], 2) / sigmas2[i]; 28 | } 29 | return distance; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/dsv2/LogarithmisedNormalDistributionDistance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package dsv2; 8 | 9 | /** 10 | * 11 | * @author ns130291 12 | */ 13 | public class LogarithmisedNormalDistributionDistance implements Distance{ 14 | 15 | @Override 16 | public double calcDistance(Vector x, Vector mu, Vector sigma2) throws RuntimeException { 17 | if(x.getSize() != mu.getSize() && x.getSize() != sigma2.getSize()){ 18 | throw new RuntimeException("Vectors have different sizes"); 19 | }else{ 20 | double[] xs = x.getValues(); 21 | double[] mus = mu.getValues(); 22 | double[] sigmas2 = sigma2.getValues(); 23 | 24 | double distance = 0; 25 | 26 | for(int i = 0; i < xs.length; i++){ 27 | distance += Math.log(2 * Math.PI * sigmas2[i]) + Math.pow(xs[i]-mus[i], 2) / sigmas2[i]; 28 | } 29 | return 0.5 * distance; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/dsv2/EuclideanDistance2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | 7 | package dsv2; 8 | 9 | /** 10 | * 11 | * @author ns130291 12 | */ 13 | public class EuclideanDistance2 implements Distance{ 14 | 15 | /** 16 | * 17 | * @param x 18 | * @param mu µ(Mittelwert) des Modells 19 | * @param sigma2 20 | * @return 21 | * @throws RuntimeException 22 | */ 23 | @Override 24 | public double calcDistance(Vector x, Vector mu, Vector sigma2) throws RuntimeException { 25 | if(x.getSize() != mu.getSize()){ 26 | throw new RuntimeException("Vectors have different sizes"); 27 | }else{ 28 | double[] xs = x.getValues(); 29 | double[] mus = mu.getValues(); 30 | 31 | double distance = 0; 32 | 33 | for(int i = 0; i < xs.length; i++){ 34 | distance += Math.pow(xs[i]-mus[i], 2); 35 | } 36 | return distance; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/dsv2/HMM.java: -------------------------------------------------------------------------------- 1 | package dsv2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Random; 5 | 6 | /** 7 | * 8 | * @author ns130291 9 | */ 10 | public class HMM { 11 | 12 | public Vector[] generate(int modelLength, long seed, Vector[] mus, Vector[] sigmas) { 13 | Random rand = new Random(seed); 14 | ArrayList refs = new ArrayList<>(); 15 | int zustand = 0; 16 | 17 | while (zustand < modelLength) { 18 | 19 | double[] mu = mus[zustand].getValues(); 20 | double[] sigma = sigmas[zustand].getValues(); 21 | 22 | double[] ref = new double[mu.length]; 23 | 24 | for (int i = 0; i < mu.length; i++) { 25 | ref[i] = rand.nextGaussian() * Math.sqrt(sigma[i]) + mu[i]; 26 | } 27 | 28 | refs.add(new Vector(ref)); 29 | 30 | if (zustand < modelLength - 2) { 31 | if (rand.nextDouble() <= (1.0 / 3.0)) { 32 | zustand++; 33 | } else if (rand.nextDouble() <= (2.0 / 3.0)) { 34 | zustand += 2; 35 | } 36 | } else { 37 | if (rand.nextDouble() <= 0.5) { 38 | zustand++; 39 | } 40 | } 41 | } 42 | 43 | for(Vector x:refs){ 44 | System.out.println(x); 45 | } 46 | System.out.println(""); 47 | 48 | //Umwandlung in Array 49 | return refs.toArray(new Vector[1]); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/dsv2/Input.java: -------------------------------------------------------------------------------- 1 | package dsv2; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileReader; 6 | import java.io.IOException; 7 | import java.util.ArrayList; 8 | import java.util.logging.Level; 9 | import java.util.logging.Logger; 10 | 11 | /** 12 | * 13 | * @author ns130291 14 | */ 15 | public class Input { 16 | public ArrayList fromFile(String path){ 17 | BufferedReader br = null; 18 | try { 19 | br = new BufferedReader(new FileReader(path)); 20 | 21 | br.readLine(); 22 | 23 | String temp = br.readLine(); 24 | int numReferences = Integer.parseInt(temp); 25 | 26 | br.readLine(); 27 | br.readLine(); 28 | 29 | ArrayList references = new ArrayList<>(); 30 | for(int i = 0; i < numReferences; i++){ 31 | temp = br.readLine(); 32 | if(temp != null){ 33 | String[] vector = temp.split(" ");//Anpassen falls zwischen den Vektorfolgen weniger als 4 Leerzeichen sind 34 | Vector[] x = new Vector[vector.length]; 35 | for(int j = 0; j < vector.length; j++){ 36 | String[] values = vector[j].split(" "); 37 | x[j] = new Vector(stringArrayToDoubleArray(values)); 38 | } 39 | references.add(x); 40 | } 41 | } 42 | return references; 43 | 44 | } catch (FileNotFoundException ex) { 45 | Logger.getLogger(Input.class.getName()).log(Level.SEVERE, null, ex); 46 | } catch (IOException ex) { 47 | Logger.getLogger(Input.class.getName()).log(Level.SEVERE, null, ex); 48 | } finally { 49 | try { 50 | br.close(); 51 | } catch (IOException ex) { 52 | Logger.getLogger(Input.class.getName()).log(Level.SEVERE, null, ex); 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | private double[] stringArrayToDoubleArray(String[] array){ 59 | double[] doubles = new double[array.length]; 60 | for(int i = 0; i < array.length; i++){ 61 | doubles[i] = Double.parseDouble(array[i]); 62 | } 63 | return doubles; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/dsv2/Viterbi.java: -------------------------------------------------------------------------------- 1 | package dsv2; 2 | 3 | import java.awt.Point; 4 | 5 | /** 6 | * 7 | * @author ns130291 8 | */ 9 | public class Viterbi { 10 | 11 | private Distance d; 12 | 13 | public Viterbi(Distance d) { 14 | this.d = d; 15 | } 16 | 17 | public PointsDouble calc(Vector[] x, Vector[] mu, Vector[] sigma2){ 18 | double[][] s = new double[x.length][mu.length]; 19 | int[][] r = new int[x.length][mu.length]; 20 | 21 | //---Erste Spalte--- 22 | s[0][0] = d.calcDistance(mu[0], x[0], sigma2[0]); 23 | for(int j = 1; j < mu.length; j++){ 24 | s[0][j] = Double.POSITIVE_INFINITY; 25 | } 26 | 27 | //---Iteriere über Spalten--- 28 | for(int i = 1; i < x.length; i++){ 29 | for(int j = 0; j < mu.length; j++){ 30 | // k=0 31 | double distance = s[i-1][j]; 32 | int k = 0; 33 | // k=1 34 | if(j > 0){ 35 | if(s[i-1][j-1] < distance){ 36 | distance = s[i-1][j-1]; 37 | k=1; 38 | } 39 | } 40 | // k=2 41 | if(j > 1){ 42 | if(s[i-1][j-2] < distance){ 43 | k=2; 44 | distance = s[i-1][j-2]; 45 | } 46 | } 47 | 48 | r[i][j] = k; 49 | s[i][j] = distance + d.calcDistance(x[i], mu[j], sigma2[j]); 50 | } 51 | } 52 | 53 | //---Rückwärtszeiger verfolgen--- 54 | Point[] p = new Point[x.length]; 55 | int j = mu.length - 1; 56 | for(int i = x.length - 1; i >= 0; i--){ 57 | p[i] = new Point(i, j); 58 | j -= r[i][j]; 59 | } 60 | 61 | /*System.out.println("a x"); 62 | for (Point p1 : p) { 63 | System.out.println(p1.x + " " + p1.y); 64 | } 65 | System.out.println("");*/ 66 | 67 | //todo: Überprüfung ob n-1 m-1 Knoten Minimum ist??? Vermutlich nicht, man nimmt einfach den n-1 m-1 Knoten? 68 | /*for (j = model.length - 1; j >= 0; j--) { 69 | for (int i = 0; i < x.length; i++) { 70 | System.out.print(s[i][j] + " "); 71 | } 72 | System.out.println(""); 73 | }*/ 74 | 75 | return new PointsDouble(p, s[x.length - 1][mu.length - 1]); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/dsv2/ViterbiHMM.java: -------------------------------------------------------------------------------- 1 | package dsv2; 2 | 3 | import java.awt.Point; 4 | 5 | /** 6 | * 7 | * @author ns130291 8 | */ 9 | public class ViterbiHMM { 10 | 11 | private Distance d; 12 | 13 | public ViterbiHMM(Distance d) { 14 | this.d = d; 15 | } 16 | 17 | public PointsDouble calc(Vector[] x, Vector[] mu, Vector[] sigma2, double[][] uebergangsw){ 18 | double[][] s = new double[x.length][mu.length]; 19 | int[][] r = new int[x.length][mu.length]; 20 | 21 | //---Erste Spalte--- 22 | s[0][0] = 1;//d.calcDistance(mu[0], x[0], sigma2[0]); 23 | for(int j = 1; j < mu.length; j++){ 24 | s[0][j] = Double.POSITIVE_INFINITY; 25 | } 26 | 27 | //---Iteriere über Spalten--- 28 | for(int i = 1; i < x.length; i++){ 29 | for(int j = 0; j < mu.length; j++){ 30 | 31 | // k=0 32 | //System.out.println("i-1 " + (i-1) + " j " + j); 33 | double min = s[i-1][j] + uebergangsw[j][j]; 34 | //double distance = s[i-1][j]; 35 | int k = j; 36 | // k=1 37 | if(j > 0){ 38 | if(s[i-1][j-1] + uebergangsw[j-1][j] < min){ 39 | min = s[i-1][j-1] + uebergangsw[j-1][j]; 40 | k=j-1; 41 | } 42 | } 43 | // k=2 44 | if(j > 1){ 45 | if(s[i-1][j-2] + uebergangsw[j-2][j] < min){ 46 | min = s[i-1][j-2] + uebergangsw[j-2][j]; 47 | k=j-2; 48 | } 49 | } 50 | 51 | r[i][j] = k; 52 | s[i][j] = min + d.calcDistance(x[i], mu[j], sigma2[j]); 53 | } 54 | } 55 | 56 | /*System.out.println("\nRückwärtszeiger"); 57 | for(int i = 0; i < r.length; i++){ 58 | for(int j = 0; j < r[i].length; j++){ 59 | System.out.print(r[i][j] + " "); 60 | } 61 | System.out.println(""); 62 | } 63 | System.out.println("");*/ 64 | 65 | //---Rückwärtszeiger verfolgen--- 66 | //TODO: hier 67 | Point[] p = new Point[x.length]; 68 | int j = mu.length - 1;//Endzustand 69 | for(int i = x.length - 1; i >= 0; i--){ 70 | p[i] = new Point(i, j); 71 | //j -= r[i][j]; 72 | j = r[i][j]; 73 | } 74 | 75 | /*System.out.println("a x"); 76 | for (Point p1 : p) { 77 | System.out.println(p1.x + " " + p1.y); 78 | } 79 | System.out.println("");*/ 80 | 81 | //todo: Überprüfung ob n-1 m-1 Knoten Minimum ist??? Vermutlich nicht, man nimmt einfach den n-1 m-1 Knoten? 82 | /*for (j = model.length - 1; j >= 0; j--) { 83 | for (int i = 0; i < x.length; i++) { 84 | System.out.print(s[i][j] + " "); 85 | } 86 | System.out.println(""); 87 | }*/ 88 | 89 | return new PointsDouble(p, s[x.length - 1][mu.length - 1]); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/dsv2/Util.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package dsv2; 7 | 8 | import java.awt.Point; 9 | 10 | /** 11 | * 12 | * @author ns130291 13 | */ 14 | public class Util { 15 | 16 | /** 17 | * Rounds doubles to two decimal points 18 | * @param in double value to round 19 | * @return rounded double value 20 | */ 21 | public static double r2d(double in) { 22 | return Math.round(in * 100) / 100.0; 23 | } 24 | 25 | public static void drawDiagram(Point[] points) { 26 | int max = 0; 27 | for (int i = 0; i < points.length; i++) { 28 | if (points[i].y > max) { 29 | max = points[i].y; 30 | } 31 | } 32 | String[] lines = new String[max + 1]; 33 | for (int i = 0; i < lines.length; i++) { 34 | lines[i] = new String(); 35 | } 36 | for (int i = 0; i < points.length; i++) { 37 | int leerzeichen = points[i].x * 2; 38 | if (i > 0) { 39 | leerzeichen--; 40 | } 41 | leerzeichen = leerzeichen - lines[points[i].y].length(); 42 | for (int j = 0; j < leerzeichen; j++) { 43 | lines[points[i].y] += " "; 44 | 45 | } 46 | if (i > 0) { 47 | if (points[i - 1].y == points[i].y) { 48 | lines[points[i].y] += "-"; 49 | } else { 50 | if (points[i].y - points[i - 1].y == 2) { 51 | leerzeichen = points[i].x * 2 - 1; 52 | for (int j = 0; j < leerzeichen; j++) { 53 | lines[points[i].y - 1] += " "; 54 | 55 | } 56 | lines[points[i].y - 1] += "/"; 57 | } 58 | lines[points[i].y] += " "; 59 | 60 | } 61 | } 62 | lines[points[i].y] += "x"; 63 | } 64 | 65 | //Ausgeben 66 | System.out.println("\nDiagramm"); 67 | System.out.println(" a"); 68 | for (int i = lines.length - 1; i >= 0; i--) { 69 | System.out.println(i + "|" + lines[i]); 70 | } 71 | System.out.print("-+"); 72 | for (int i = 0; i < points.length * 2 - 1; i++) { 73 | System.out.print("-"); 74 | } 75 | System.out.println("x"); 76 | System.out.print(" |"); 77 | for (int i = 0; i < points.length; i++) { 78 | System.out.print(i + " "); 79 | } 80 | System.out.println(""); 81 | } 82 | 83 | public static void muSigma(double[] values) { 84 | double sum = 0; 85 | double sumquad = 0; 86 | for (int i = 0; i < values.length; i++) { 87 | sum += values[i]; 88 | sumquad += values[i] * values[i]; 89 | } 90 | 91 | double mu = sum / values.length; 92 | double varianz = sumquad / values.length - mu * mu; 93 | System.out.println("Müüühh = " + mu + " Sigma = " + varianz); 94 | } 95 | 96 | public static Vector arithmeticMean(Vector[] model){ 97 | Vector mu = new Vector(new double[]{0, 0, 0}); 98 | for(Vector m:model){ 99 | mu = Vector.add(mu, m); 100 | } 101 | mu.divide(model.length); 102 | return mu; 103 | } 104 | 105 | public static Vector variance(Vector[] model, Vector mu){ 106 | Vector sigma = new Vector(new double[]{0, 0, 0}); 107 | for(Vector m:model){ 108 | sigma = Vector.add(sigma, Vector.multiply(m, m)); 109 | } 110 | sigma.divide(model.length); 111 | sigma = Vector.subtract(sigma, Vector.multiply(mu, mu)); 112 | double[] vals = sigma.getValues(); 113 | for(int i = 0; i < vals.length; i++){ 114 | if(vals[i] < 0.01){ 115 | vals[i] = 0.01; 116 | } 117 | } 118 | sigma.setValues(vals); 119 | return sigma; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/dsv2/Vector.java: -------------------------------------------------------------------------------- 1 | package dsv2; 2 | 3 | /** 4 | * 5 | * @author ns130291 6 | */ 7 | public class Vector { 8 | 9 | private double values[]; 10 | private int size; 11 | 12 | public Vector(int size) { 13 | this.size = size; 14 | } 15 | 16 | public Vector(double[] values) { 17 | this.size = values.length; 18 | this.values = values; 19 | } 20 | 21 | public double[] getValues() { 22 | return values; 23 | } 24 | 25 | public void setValues(double[] values) throws RuntimeException { 26 | if (size == values.length) { 27 | this.values = values; 28 | } else { 29 | throw new RuntimeException("Wrong array length"); 30 | } 31 | } 32 | 33 | public int getSize() { 34 | return size; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | String out = "("; 40 | for (int i = 0; i < size; i++) { 41 | out += Util.r2d(values[i]); 42 | if (i != size - 1) { 43 | out += ", "; 44 | } 45 | } 46 | out += ")"; 47 | return out; 48 | } 49 | 50 | public static Vector add(Vector v1, Vector v2) throws RuntimeException { 51 | if (v1 == null && v2 == null) { 52 | return null; 53 | } 54 | if (v1 == null) { 55 | return v2; 56 | } 57 | if (v2 == null) { 58 | return v1; 59 | } 60 | if (v1.getSize() != v2.getSize()) { 61 | throw new RuntimeException("Vectors have different sizes"); 62 | } else { 63 | double[] values1 = v1.getValues(); 64 | double[] values2 = v2.getValues(); 65 | 66 | double[] values = new double[values1.length]; 67 | 68 | for (int i = 0; i < values1.length; i++) { 69 | values[i] = values1[i] + values2[i]; 70 | } 71 | 72 | return new Vector(values); 73 | } 74 | } 75 | 76 | public void divide(int divisor) { 77 | if (divisor == 0) { 78 | return; 79 | } 80 | 81 | for (int i = 0; i < size; i++) { 82 | values[i] = values[i] / divisor; 83 | } 84 | } 85 | 86 | public void multiply(int multiplier) { 87 | for (int i = 0; i < size; i++) { 88 | values[i] = values[i] * multiplier; 89 | } 90 | } 91 | 92 | public static Vector multiply(Vector v1, Vector v2) throws RuntimeException { 93 | if (v1 == null && v2 == null) { 94 | return null; 95 | } 96 | if (v1 == null) { 97 | return v2; 98 | } 99 | if (v2 == null) { 100 | return v1; 101 | } 102 | if (v1.getSize() != v2.getSize()) { 103 | throw new RuntimeException("Vectors have different sizes"); 104 | } else { 105 | double[] values1 = v1.getValues(); 106 | double[] values2 = v2.getValues(); 107 | 108 | double[] values = new double[values1.length]; 109 | 110 | for (int i = 0; i < values1.length; i++) { 111 | values[i] = values1[i] * values2[i]; 112 | } 113 | 114 | return new Vector(values); 115 | } 116 | } 117 | 118 | public static Vector subtract(Vector v1, Vector v2) throws RuntimeException { 119 | if (v1 == null && v2 == null) { 120 | return null; 121 | } 122 | if (v1 == null) { 123 | return v2; 124 | } 125 | if (v2 == null) { 126 | return v1; 127 | } 128 | if (v1.getSize() != v2.getSize()) { 129 | throw new RuntimeException("Vectors have different sizes"); 130 | } else { 131 | double[] values1 = v1.getValues(); 132 | double[] values2 = v2.getValues(); 133 | 134 | double[] values = new double[values1.length]; 135 | 136 | for (int i = 0; i < values1.length; i++) { 137 | values[i] = values1[i] - values2[i]; 138 | } 139 | 140 | return new Vector(values); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/dsv2/ViterbiTraining.java: -------------------------------------------------------------------------------- 1 | package dsv2; 2 | 3 | import java.awt.Point; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | 7 | /** 8 | * 9 | * @author ns130291 10 | */ 11 | public class ViterbiTraining { 12 | 13 | public void train(ArrayList references) { 14 | System.out.println("Viterbi Training\n================"); 15 | int[] lengths = new int[references.size()]; 16 | for (int i = 0; i < lengths.length; i++) { 17 | lengths[i] = references.get(i).length; 18 | } 19 | 20 | //TODO: min length of array == 1 21 | Arrays.sort(lengths); 22 | int median; 23 | if (lengths.length % 2 == 1) { 24 | median = lengths[lengths.length / 2]; 25 | } else { 26 | median = (lengths[lengths.length / 2] + lengths[lengths.length / 2 - 1]) / 2; 27 | } 28 | //Aufgabenstellung sagt 4! 29 | median = 4; 30 | System.out.println("Median: " + median); 31 | int modelLength = median;// / 2; 32 | 33 | ArrayList points = new ArrayList<>(); 34 | for (Vector[] reference : references) { 35 | Point[] p = new Point[reference.length]; 36 | double slope = (double) (modelLength - 1) / (double) (reference.length - 1); 37 | for (int i = 0; i < reference.length; i++) { 38 | p[i] = new Point(i, (int) Math.round(slope * i)); 39 | } 40 | points.add(p); 41 | 42 | //print matching 43 | System.out.println("a x"); 44 | for (int i = 0; i < p.length; i++) { 45 | System.out.println(p[i].x + " " + p[i].y); 46 | } 47 | Util.drawDiagram(p); 48 | System.out.println(""); 49 | } 50 | 51 | //Sammeln der jeweiligen Zuordnungen 52 | ArrayList> models = new ArrayList<>(modelLength); 53 | for (int i = 0; i < modelLength; i++) { 54 | models.add(new ArrayList()); 55 | } 56 | for (int i = 0; i < references.size(); i++) { 57 | for (Point matching : points.get(i)) { 58 | models.get(matching.y).add(references.get(i)[matching.x]); 59 | } 60 | } 61 | 62 | Vector[] mus = new Vector[modelLength]; 63 | Vector[] sigmas = new Vector[modelLength]; 64 | for (int i = 0; i < models.size(); i++) { 65 | Vector mu = Util.arithmeticMean(models.get(i).toArray(new Vector[models.get(i).size()])); 66 | System.out.print("µ = "); 67 | System.out.println(mu); 68 | Vector sigma = Util.variance(models.get(i).toArray(new Vector[models.get(i).size()]), mu); 69 | System.out.print("σ² = "); 70 | System.out.println(sigma); 71 | System.out.println(""); 72 | mus[i] = mu; 73 | sigmas[i] = sigma; 74 | } 75 | 76 | System.out.println("\nIterieren\n============="); 77 | 78 | double sum = Double.POSITIVE_INFINITY; 79 | double newSum = Double.MAX_VALUE; 80 | int i = 1; 81 | while (sum - newSum != 0) { 82 | sum = newSum; 83 | System.out.println("Schritt " + i); 84 | System.out.println("------------"); 85 | i++; 86 | VectorsDoubleArray vd = iterate(mus, sigmas, references); 87 | mus = vd.getVectors1(); 88 | sigmas = vd.getVectors2(); 89 | newSum = vd.getDouble(); 90 | System.out.println(""); 91 | } 92 | 93 | } 94 | 95 | private VectorsDoubleArray iterate(Vector[] mus, Vector[] sigmas, ArrayList references) { 96 | 97 | Viterbi viterbi = new Viterbi(new SimplifiedNormalDistributionDistance()); 98 | 99 | double sum = 0; 100 | ArrayList points = new ArrayList<>(); 101 | for (Vector[] reference : references) { 102 | PointsDouble pd = viterbi.calc(reference, mus, sigmas); 103 | points.add(pd.getPoints()); 104 | sum += pd.getDouble(); 105 | 106 | //print matching 107 | Point[] p = pd.getPoints(); 108 | /*System.out.println("Viterbi Punkte"); 109 | for (int i = 0; i < p.length; i++) { 110 | System.out.println(p[i].x + " " + p[i].y); 111 | }*/ 112 | Util.drawDiagram(p); 113 | System.out.println("Summe " + Util.r2d(pd.getDouble()) + "\n"); 114 | 115 | } 116 | 117 | //Sammeln der jeweiligen Zuordnungen 118 | ArrayList> models = new ArrayList<>(mus.length); 119 | for (int i = 0; i < mus.length; i++) { 120 | models.add(new ArrayList()); 121 | } 122 | for (int i = 0; i < references.size(); i++) { 123 | for (Point matching : points.get(i)) { 124 | models.get(matching.y).add(references.get(i)[matching.x]); 125 | } 126 | } 127 | 128 | mus = new Vector[mus.length]; 129 | sigmas = new Vector[sigmas.length]; 130 | for (int i = 0; i < models.size(); i++) { 131 | Vector mu = Util.arithmeticMean(models.get(i).toArray(new Vector[models.get(i).size()])); 132 | System.out.print("µ = "); 133 | System.out.println(mu); 134 | Vector sigma = Util.variance(models.get(i).toArray(new Vector[models.get(i).size()]), mu); 135 | System.out.print("σ² = "); 136 | System.out.println(sigma); 137 | System.out.println(""); 138 | mus[i] = mu; 139 | sigmas[i] = sigma; 140 | } 141 | System.out.println("Sum " + Util.r2d(sum) + "\n"); 142 | 143 | return new VectorsDoubleArray(mus, sigmas, sum, null); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/dsv2/DSV2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package dsv2; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Random; 10 | 11 | /** 12 | * 13 | * @author ns130291 14 | */ 15 | public class DSV2 { 16 | 17 | /** 18 | * @param args the command line arguments 19 | */ 20 | public static void main(String[] args) { 21 | /*Vector eins = new Vector(new double[]{4, 1, -2}); 22 | Vector zwei = new Vector(new double[]{2, 3, -1}); 23 | 24 | Distance d = new EuclideanDistance2(); 25 | double dis = -1; 26 | 27 | dis = d.calcDistance(eins, zwei, null); 28 | 29 | //System.out.println("Distanz: " + dis); 30 | System.out.println(""); 31 | 32 | 33 | Vector[] a = new Vector[]{new Vector(new double[]{9, 0 ,1}), new Vector(new double[]{6, 2, 1}), new Vector(new double[]{4, 2, 1}), new Vector(new double[]{1, 0 ,2})}; 34 | Vector[] x = new Vector[]{new Vector(new double[]{9, 1, 1}), new Vector(new double[]{8, 1, 0}), new Vector(new double[]{4, 2, 1}), new Vector(new double[]{4, 3, 1}), new Vector(new double[]{3, 2, 0}), new Vector(new double[]{2, 0, 1})}; 35 | 36 | Viterbi viterbi = new Viterbi(new EuclideanDistance2()); 37 | PointsDouble matching = viterbi.calc(x, a, null); 38 | 39 | /*System.out.println("Zuordnung"); 40 | for(Point p1:matching.getPoints()){ 41 | System.out.println(p1.x + " " + p1.y); 42 | } 43 | System.out.println("");*/ 44 | 45 | //Aufgabe 2 46 | /*System.out.println("Aufgabe 2"); 47 | 48 | String path = "C:\\Users\\ns130291\\Desktop\\Java\\DSV2\\daten.txt"; 49 | 50 | Input i = new Input(); 51 | ArrayList references = i.fromFile(path); 52 | 53 | for(Vector[] xx:references){ 54 | for(Vector xxx:xx){ 55 | System.out.println(xxx); 56 | } 57 | System.out.println(""); 58 | } 59 | 60 | ViterbiTraining viterbiTraining = new ViterbiTraining(); 61 | viterbiTraining.train(references);*/ 62 | /*System.out.println("Aufgabe 4"); 63 | 64 | String path2 = "C:\\Users\\ns130291\\Desktop\\Java\\DSV2\\daten2.txt"; 65 | Input i2 = new Input(); 66 | ArrayList references2 = i2.fromFile(path2); 67 | 68 | for(Vector[] xx:references2){ 69 | for(Vector xxx:xx){ 70 | System.out.println(xxx); 71 | } 72 | System.out.println(""); 73 | } 74 | ViterbiTrainingHMM viterbiTraining2 = new ViterbiTrainingHMM(); 75 | viterbiTraining2.train(references2, 4);*/ 76 | Random rand = new Random(42); 77 | HMM hmm = new HMM(); 78 | int modelLength = 7; 79 | 80 | Vector[] mus1 = { 81 | new Vector(new double[]{2, 5, 3}), 82 | new Vector(new double[]{1, 2, 5}), 83 | new Vector(new double[]{4, 2, 3}), 84 | new Vector(new double[]{1, 4, 3}), 85 | new Vector(new double[]{6, 10, 10}), 86 | new Vector(new double[]{8, 2, 3}), 87 | new Vector(new double[]{8, 9, 3}),}; 88 | 89 | Vector[] sigmas1 = { 90 | new Vector(new double[]{3, 10, 5}), 91 | new Vector(new double[]{11, 2, 3}), 92 | new Vector(new double[]{1, 1, 4}), 93 | new Vector(new double[]{9, 2, 1}), 94 | new Vector(new double[]{2, 1, 3}), 95 | new Vector(new double[]{8, 1, 4}), 96 | new Vector(new double[]{3, 3, 3}),}; 97 | 98 | // 100 Merkmalvektorfolgen für HMM1 generieren 99 | ArrayList refs1 = new ArrayList<>(); 100 | for (int i = 0; i < 100; i++) { 101 | refs1.add(hmm.generate(modelLength, rand.nextLong(), mus1, sigmas1)); 102 | } 103 | // 100 Merkmalvektorfolgen für HMM2 generieren 104 | ArrayList refs2 = new ArrayList<>(); 105 | for (int i = 0; i < 100; i++) { 106 | refs2.add(hmm.generate(modelLength, rand.nextLong(), sigmas1, mus1)); 107 | } 108 | 109 | System.out.println("refs1 size " + refs1.size()); 110 | System.out.println("refs2 size " + refs2.size()); 111 | 112 | // Aus Merkmalvektorfolgen trainieren 113 | // Hier Modellänge verändern bei Bedarf 114 | ViterbiTrainingHMM viterbiTrainingHMM = new ViterbiTrainingHMM(); 115 | VectorsDoubleArray hmm1 = viterbiTrainingHMM.train(refs1, modelLength); 116 | VectorsDoubleArray hmm2 = viterbiTrainingHMM.train(refs2, modelLength); 117 | 118 | // 100 Merkmalvektorfolgen von HMM1 generieren zum Testen der trainierten HMMs 119 | ArrayList refs11 = new ArrayList<>(); 120 | for (int i = 0; i < 100; i++) { 121 | refs11.add(hmm.generate(modelLength, rand.nextLong(), mus1, sigmas1)); 122 | } 123 | // 100 Merkmalvektorfolgen von HMM2 generieren zum Testen der trainierten HMMs 124 | ArrayList refs22 = new ArrayList<>(); 125 | for (int i = 0; i < 100; i++) { 126 | refs22.add(hmm.generate(modelLength, rand.nextLong(), sigmas1, mus1)); 127 | } 128 | 129 | ViterbiHMM viterbiHMM = new ViterbiHMM(new LogarithmisedNormalDistributionDistance()); 130 | 131 | //Klassifizieren der neuen 100 Merkmalvektorfolgen von HMM1 132 | ArrayList resultHMM1refs11 = new ArrayList<>(); 133 | ArrayList resultHMM2refs11 = new ArrayList<>(); 134 | //Jede Merkmalvektorfolge klassifizieren mit den beiden trainierten HMMs 135 | for (Vector[] x : refs11) { 136 | PointsDouble result1 = viterbiHMM.calc(x, hmm1.getVectors1(), hmm1.getVectors2(), hmm1.getArray()); 137 | PointsDouble result2 = viterbiHMM.calc(x, hmm2.getVectors1(), hmm2.getVectors2(), hmm2.getArray()); 138 | System.out.print("HMM1 " + Util.r2d(result1.getDouble()) + " HMM2 " + Util.r2d(result2.getDouble())); 139 | if (result1.getDouble() < result2.getDouble()) { 140 | System.out.println(" r = 1"); 141 | } else { 142 | System.out.println(" r = 2"); 143 | } 144 | resultHMM1refs11.add(result1); 145 | resultHMM2refs11.add(result2); 146 | } 147 | 148 | System.out.println(""); 149 | System.out.println(""); 150 | System.out.println(""); 151 | 152 | //Klassifizieren der neuen 100 Merkmalvektorfolgen von HMM2 153 | ArrayList resultHMM1refs22 = new ArrayList<>(); 154 | ArrayList resultHMM2refs22 = new ArrayList<>(); 155 | for (Vector[] x : refs22) { 156 | PointsDouble result1 = viterbiHMM.calc(x, hmm1.getVectors1(), hmm1.getVectors2(), hmm1.getArray()); 157 | PointsDouble result2 = viterbiHMM.calc(x, hmm2.getVectors1(), hmm2.getVectors2(), hmm2.getArray()); 158 | System.out.print("HMM1 " + Util.r2d(result1.getDouble()) + " HMM2 " + Util.r2d(result2.getDouble())); 159 | if (result1.getDouble() < result2.getDouble()) { 160 | System.out.println(" r = 1"); 161 | } else { 162 | System.out.println(" r = 2"); 163 | } 164 | resultHMM1refs22.add(result1); 165 | resultHMM2refs22.add(result2); 166 | } 167 | 168 | 169 | 170 | System.out.println(""); 171 | System.out.println(""); 172 | System.out.println(""); 173 | 174 | /* 175 | 176 | // 3 Merkmalvektorfolgen für HMM1 generieren 177 | ArrayList refs111 = new ArrayList<>(); 178 | for (int i = 0; i < 3; i++) { 179 | refs111.add(hmm.generate(modelLength, rand.nextLong(), mus1, sigmas1)); 180 | } 181 | // 3 Merkmalvektorfolgen für HMM2 generieren 182 | ArrayList refs222 = new ArrayList<>(); 183 | for (int i = 0; i < 3; i++) { 184 | refs222.add(hmm.generate(modelLength, rand.nextLong(), sigmas1, mus1)); 185 | } 186 | 187 | // Aus Merkmalvektorfolgen trainieren 188 | VectorsDoubleArray hmm11 = viterbiTrainingHMM.train(refs111, modelLength); 189 | VectorsDoubleArray hmm22 = viterbiTrainingHMM.train(refs222, modelLength); 190 | 191 | //Klassifizieren der neuen 100 Merkmalvektorfolgen von HMM11 192 | ArrayList resultHMM1refs11_ = new ArrayList<>(); 193 | ArrayList resultHMM2refs11_ = new ArrayList<>(); 194 | for (Vector[] x : refs11) { 195 | PointsDouble result1 = viterbiHMM.calc(x, hmm11.getVectors1(), hmm11.getVectors2(), hmm11.getArray()); 196 | PointsDouble result2 = viterbiHMM.calc(x, hmm22.getVectors1(), hmm22.getVectors2(), hmm22.getArray()); 197 | System.out.print("HMM11 " + Util.r2d(result1.getDouble()) + " HMM22 " + Util.r2d(result2.getDouble())); 198 | if (result1.getDouble() < result2.getDouble()) { 199 | System.out.println(" r = 1"); 200 | } else { 201 | System.out.println(" r = 2"); 202 | } 203 | resultHMM1refs11_.add(result1); 204 | resultHMM2refs11_.add(result2); 205 | } 206 | 207 | System.out.println(""); 208 | System.out.println(""); 209 | System.out.println(""); 210 | 211 | //Klassifizieren der neuen 100 Merkmalvektorfolgen von HMM22 212 | ArrayList resultHMM1refs22_ = new ArrayList<>(); 213 | ArrayList resultHMM2refs22_ = new ArrayList<>(); 214 | for (Vector[] x : refs22) { 215 | PointsDouble result1 = viterbiHMM.calc(x, hmm11.getVectors1(), hmm11.getVectors2(), hmm11.getArray()); 216 | PointsDouble result2 = viterbiHMM.calc(x, hmm22.getVectors1(), hmm22.getVectors2(), hmm22.getArray()); 217 | System.out.print("HMM11 " + Util.r2d(result1.getDouble()) + " HMM22 " + Util.r2d(result2.getDouble())); 218 | if (result1.getDouble() < result2.getDouble()) { 219 | System.out.println(" r = 1"); 220 | } else { 221 | System.out.println(" r = 2"); 222 | } 223 | resultHMM1refs22_.add(result1); 224 | resultHMM2refs22_.add(result2); 225 | } 226 | */ 227 | //Util.muSigma(new double[]{2, 6, 1, 5, 7}); 228 | } 229 | 230 | } 231 | -------------------------------------------------------------------------------- /src/dsv2/ViterbiTrainingHMM.java: -------------------------------------------------------------------------------- 1 | package dsv2; 2 | 3 | import java.awt.Point; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | 7 | /** 8 | * 9 | * @author ns130291 10 | */ 11 | public class ViterbiTrainingHMM { 12 | 13 | public VectorsDoubleArray train(ArrayList references, int modelLength) { 14 | System.out.println("Viterbi Training HMM\n================"); 15 | //Lineare Zuordnung der Merkmalvektorfolgen zu den Zuständen des Modells 16 | ArrayList points = new ArrayList<>(); 17 | int[][] uebergaenge = new int[modelLength][modelLength]; 18 | 19 | //Für jede Merkmalvektorfolge 20 | for (Vector[] reference : references) { 21 | Point[] p = new Point[reference.length]; 22 | //Steigung berechnen 23 | double slope = (double) (modelLength) / (double) (reference.length); 24 | System.out.println("Slope " + slope); 25 | 26 | //Für jeden Merkmalvektor in einer Merkmalvektorfolge 27 | for (int i = 0; i < reference.length; i++) { 28 | //int point = (int) Math.round(slope * i); 29 | //int point = ((int) Math.round(slope * (i + 1))) - 1; 30 | //int point = ((int) Math.round(slope * (i + 2))) - 1; 31 | //int point = (int) Math.round(slope * (i + 1) - 1); 32 | int point = (int) (slope * i); 33 | if (point > (modelLength - 1)) { 34 | point = modelLength - 1; 35 | } 36 | if (point < 0) { 37 | point = 0; 38 | } 39 | p[i] = new Point(i, point); 40 | if (i > 0) { 41 | //TODO vereinfachen 42 | uebergaenge[p[i - 1].y][p[i].y - p[i - 1].y + p[i - 1].y]++; 43 | } 44 | } 45 | points.add(p); 46 | 47 | Util.drawDiagram(p); 48 | System.out.println(""); 49 | } 50 | 51 | System.out.println("\nÜbergänge"); 52 | for (int i = 0; i < uebergaenge.length; i++) { 53 | for (int j = 0; j < uebergaenge[i].length; j++) { 54 | System.out.print(uebergaenge[i][j] + " "); 55 | } 56 | System.out.println(""); 57 | } 58 | System.out.println(""); 59 | //--> Übergangswahrscheinlichkeiten darauß berechnen 60 | double[][] uebergangsw = new double[modelLength][modelLength]; 61 | for (int i = 0; i < uebergaenge.length; i++) { 62 | //Zählen der Übergänge 63 | int num = 0; 64 | for (int j = 0; j < uebergaenge[i].length; j++) { 65 | num += uebergaenge[i][j]; 66 | } 67 | for (int j = 0; j < uebergaenge[i].length; j++) { 68 | if (num == 0) {//Falls keine Übergänge 69 | uebergangsw[i][j] = 0.01; 70 | } else { 71 | uebergangsw[i][j] = (double) uebergaenge[i][j] / (double) num; 72 | } 73 | if (uebergangsw[i][j] <= 0) { 74 | uebergangsw[i][j] = 0.01; 75 | } 76 | //Negativ Logarithmieren 77 | uebergangsw[i][j] = -1.0 * Math.log(uebergangsw[i][j]); 78 | if (uebergangsw[i][j] <= 0) { 79 | uebergangsw[i][j] = 0.01; 80 | } 81 | } 82 | } 83 | System.out.println("\nÜbergangswahrscheinlichkeiten"); 84 | for (int i = 0; i < uebergangsw.length; i++) { 85 | for (int j = 0; j < uebergangsw[i].length; j++) { 86 | System.out.print(uebergangsw[i][j] + " "); 87 | } 88 | System.out.println(""); 89 | } 90 | System.out.println(""); 91 | 92 | ArrayList> models = new ArrayList<>(modelLength); 93 | for (int i = 0; i < modelLength; i++) { 94 | models.add(new ArrayList()); 95 | } 96 | //Sammeln der jeweiligen Zuordnungen 97 | for (int i = 0; i < references.size(); i++) { 98 | for (Point matching : points.get(i)) { 99 | models.get(matching.y).add(references.get(i)[matching.x]); 100 | } 101 | } 102 | 103 | //Kenndaten für jeden Zustand ausrechnen 104 | Vector[] mus = new Vector[modelLength]; 105 | Vector[] sigmas = new Vector[modelLength]; 106 | for (int i = 0; i < models.size(); i++) { 107 | Vector mu = Util.arithmeticMean(models.get(i).toArray(new Vector[models.get(i).size()])); 108 | System.out.print("µ = "); 109 | System.out.println(mu); 110 | Vector sigma = Util.variance(models.get(i).toArray(new Vector[models.get(i).size()]), mu); 111 | System.out.print("σ² = "); 112 | System.out.println(sigma); 113 | System.out.println(""); 114 | mus[i] = mu; 115 | sigmas[i] = sigma; 116 | } 117 | 118 | System.out.println("\nIterieren\n============="); 119 | 120 | double sum = Double.POSITIVE_INFINITY; 121 | double newSum = Double.MAX_VALUE; 122 | VectorsDoubleArray result = null; 123 | int i = 1; 124 | while (sum - newSum != 0) { 125 | sum = newSum; 126 | /*if (i > 100) { 127 | throw new RuntimeException("Wahrscheinlich gabs nen Fehler..."); 128 | }*/ 129 | System.out.println("Schritt " + i); 130 | System.out.println("------------"); 131 | i++; 132 | VectorsDoubleArray vd = iterationStep(mus, sigmas, references, uebergangsw); 133 | mus = vd.getVectors1(); 134 | sigmas = vd.getVectors2(); 135 | newSum = vd.getDouble(); 136 | result = vd; 137 | System.out.println(""); 138 | } 139 | 140 | //µ, σ², Summe, Übergangswahrscheinlichkeiten 141 | return result; 142 | } 143 | 144 | private VectorsDoubleArray iterationStep(Vector[] mus, Vector[] sigmas, ArrayList references, double[][] uebergangsw) { 145 | 146 | //Initialisierung des Viterbi-Algorithmus mit passender Distanzfunktion 147 | ViterbiHMM viterbi = new ViterbiHMM(new MahalanobisDistance()); 148 | 149 | double sum = 0; 150 | ArrayList points = new ArrayList<>(); 151 | int[][] uebergaenge = new int[mus.length][mus.length]; 152 | for (Vector[] reference : references) { 153 | PointsDouble pd = viterbi.calc(reference, mus, sigmas, uebergangsw); 154 | //Sammeln der Zuordnungen 155 | points.add(pd.getPoints()); 156 | 157 | //Gesamtsumme erhöhen 158 | sum += pd.getDouble(); 159 | 160 | //print matching 161 | Point[] p = pd.getPoints(); 162 | 163 | for (int i = 1; i < reference.length; i++) { 164 | uebergaenge[p[i - 1].y][p[i].y - p[i - 1].y + p[i - 1].y]++; 165 | } 166 | 167 | Util.drawDiagram(p); 168 | } 169 | 170 | System.out.println("\nÜbergänge"); 171 | for (int i = 0; i < uebergaenge.length; i++) { 172 | for (int j = 0; j < uebergaenge[i].length; j++) { 173 | System.out.print(uebergaenge[i][j] + " "); 174 | } 175 | System.out.println(""); 176 | } 177 | System.out.println(""); 178 | 179 | //--> Übergangswahrscheinlichkeiten darauß berechnen 180 | uebergangsw = new double[mus.length][mus.length]; 181 | for (int i = 0; i < uebergaenge.length; i++) { 182 | int num = 0; 183 | for (int j = 0; j < uebergaenge[i].length; j++) { 184 | num += uebergaenge[i][j]; 185 | } 186 | for (int j = 0; j < uebergaenge[i].length; j++) { 187 | if (num == 0) { 188 | uebergangsw[i][j] = 0.01; 189 | } else { 190 | uebergangsw[i][j] = (double) uebergaenge[i][j] / (double) num; 191 | } 192 | if (uebergangsw[i][j] <= 0) { 193 | uebergangsw[i][j] = 0.01; 194 | } 195 | /*uebergangsw[i][j] = -1.0 * Math.log(uebergangsw[i][j]); 196 | if (uebergangsw[i][j] <= 0) { 197 | uebergangsw[i][j] = 0.01; 198 | }*/ 199 | } 200 | } 201 | //TODO: Vermutlich noch die neuen Übergangswahrscheinlichkeiten ausrechnen 202 | //beim letzten Iterationsschritt muss vermutlich nicht mehr logarithmiert 203 | //werden! (Angaben können dann mit der Lösung überprüft werden) 204 | System.out.println("\nÜbergangswahrscheinlichkeiten"); 205 | for (int i = 0; i < uebergangsw.length; i++) { 206 | for (int j = 0; j < uebergangsw[i].length; j++) { 207 | System.out.print(uebergangsw[i][j] + " "); 208 | } 209 | System.out.println(""); 210 | } 211 | System.out.println(""); 212 | 213 | //TEST 214 | for (int i = 0; i < uebergaenge.length; i++) { 215 | for (int j = 0; j < uebergaenge[i].length; j++) { 216 | uebergangsw[i][j] = -1.0 * Math.log(uebergangsw[i][j]); 217 | if (uebergangsw[i][j] <= 0) { 218 | uebergangsw[i][j] = 0.01; 219 | } 220 | } 221 | } 222 | //TEST 223 | 224 | ArrayList> models = new ArrayList<>(mus.length); 225 | for (int i = 0; i < mus.length; i++) { 226 | models.add(new ArrayList()); 227 | } 228 | //Sammeln der jeweiligen Zuordnungen 229 | for (int i = 0; i < references.size(); i++) { 230 | for (Point matching : points.get(i)) { 231 | models.get(matching.y).add(references.get(i)[matching.x]); 232 | } 233 | } 234 | 235 | //Kenndaten berechnen 236 | mus = new Vector[mus.length]; 237 | sigmas = new Vector[sigmas.length]; 238 | for (int i = 0; i < models.size(); i++) { 239 | Vector mu = Util.arithmeticMean(models.get(i).toArray(new Vector[models.get(i).size()])); 240 | System.out.print("µ = "); 241 | System.out.println(mu); 242 | Vector sigma = Util.variance(models.get(i).toArray(new Vector[models.get(i).size()]), mu); 243 | System.out.print("σ² = "); 244 | System.out.println(sigma); 245 | System.out.println(""); 246 | mus[i] = mu; 247 | sigmas[i] = sigma; 248 | } 249 | System.out.println("Sum " + Util.r2d(sum) + "\n"); 250 | 251 | return new VectorsDoubleArray(mus, sigmas, sum, uebergangsw); 252 | } 253 | } 254 | --------------------------------------------------------------------------------