I have this method where I find the distances with an Euclidean algorithm and save the values as double in an array of doubles. Now I need to find the minimum value of each test and return the value indexed.
public static double distance() {
for (int i = 0; i < GetFile.testMatrix.length;) {
double[] distances = new double[4000];
double minDistance = 999999;
for (int j = 0; j < GetFile.trainingMatrix.length; j++) {
distances[j] = EuclideanDistance.findED(GetFile.trainingMatrix[j], GetFile.testMatrix[i]);
}
return minDistance;
}
return 0;
}
I would appreciate any help. Thanks in advance
It doesn't look as though you need to store the result in an array at all, since that's being discarded. You should consider tracking the result in minDistance every time you get a result from findED.
This also looks like the kind of thing that would be a lot easier to understand if you used java's streams, if you're using a version of java that has access to them.
There are several ways to do so.
One way would be iterating over the values and taking always the smallest:
double minDistance = distances[0];
for(int j =1 ;j < GetFile.trainingMatrix.length; j++){
if(distances[j]<minDistance)
minDistance=distances[j];
}
or alternatively
double minDistance = distances[0];
for(int j =1 ;j < GetFile.trainingMatrix.length; j++){
minDistance = Math.min(minDistance, distances[j];
}
or using streams (with distances as List):
double minDistance = distances.stream().mapToDouble(e -> e).min().getAsDouble();
or even nicer (with your for-loop completely implemented):
double minDistance = Stream.iterate(0,j -> j+1)
.limit(GetFile.trainingMatrix.length)
.mapToDouble(j->EuclideanDistance.findED(GetFile.trainingMatrix[j], GetFile.testMatrix[i]))
.min().orElse(-1);
Another way along with your code:
public static double distance() {
for (int i = 0; i < GetFile.testMatrix.length;) {
double[] distances = new double[4000];
for (int j = 0; j < GetFile.trainingMatrix.length; j++) {
distances[j] = EuclideanDistance.findED(GetFile.trainingMatrix[j], GetFile.testMatrix[i]);
}
return getMinDistance(distances);
}
return 0;
}
static double getMinDistance(double[] distances) {
double minDistance = Double.MAX_VALUE;
for (double distance : distances) {
minDistance = Math.min(distance, minDistance);
}
return minDistance;
}
Assign the minDistance to distances[0] unless you are very sure about the maximum value that distances array will contain.
public static double distance() {
for (int i = 0; i < GetFile.testMatrix.length;) {
double[] distances = new double[4000];
double minDistance;
for (int j = 0; j < GetFile.trainingMatrix.length; j++) {
distances[j] = EuclideanDistance.findED(GetFile.trainingMatrix[j], GetFile.testMatrix[i]);
}
minDistance = distances[0];
for(int i = 1 ; i < distances.length; i++) {
if(minDistance > distances[i]) {
minDistance = distances[i];
}
}
return minDistance;
}
Related
I have been trying to understand the correct implementation of Bellman-Ford by following these resources: 1 & 2
If we already know that the given weighted digraph doesn't contain a cycle (hence no negative cycle either), is following a correct implementation of Bellman-Ford algorithm?
int src = 0;
int V = nodes.length; // 0 to n-1 nodes
int E = edges.length;
double[] distTo = new double[V];
for (int i = 0; i < V; i++) {
distTo[i] = Double.POSITIVE_INFINITY;
}
int[] edgeTo = new int[V];
distTo[src] = 0.0;
for (int i = 1; i < V - 1; i++) {
double[] distToLocal = new double[V];
for (int j = 0; j < V; j++) {
distToLocal[j] = Double.POSITIVE_INFINITY;
}
for (int j = 0; j < E; j++) {
int to = edges[i].to;
int from = edges[i].from;
int weight = edges[i].weight;
if (distToLocal[to] > distTo[to] && distToLocal[to] > distTo[from] + weight) {
distToLocal[to] = distTo[from] + weight;
edgeTo[to] = from;
}
distToLocal[to] = Math.min(distToLocal[to],distTo[to]);
}
distTo = distToLocal;
}
The first issue that I am having with above implementation is that, if there are only 2 nodes in the graph with a directed edge from source node to destination node, then the first for loop needs to be modified to start with 0 instead of 1 as follows:
for (int i = 0; i < V - 1; i++) {
If I make the above change, is it still a correct implementation?
Variation in implementation
If there is no need to find the shortest distance of a node from src with maximum of K edges where K is [0,V-1], then following variation also seem to give correct result.
int src = 0;
int V = nodes.length; // 0 to n-1 nodes
int E = edges.length;
double[] distTo = new double[V];
for (int i = 0; i < V; i++) {
distTo[i] = Double.POSITIVE_INFINITY;
}
int[] edgeTo = new int[V];
distTo[src] = 0.0;
for (int i = 1; i < V - 1; i++) {
/*double[] distToLocal = new double[V];
for (int j = 0; j < V; j++) {
distToLocal[j] = Double.POSITIVE_INFINITY;
}*/
for (int j = 0; j < E; j++) {
int to = edges[i].to;
int from = edges[i].from;
int weight = edges[i].weight;
if (distTo[to] > distTo[from] + weight) {
distTo[to] = distTo[from] + weight;
edgeTo[to] = from;
}
}
//distTo = distToLocal;
}
I think I understand why the variation works, however I am curious why resource 1 doesn't mention this.
Are there any downsides to implementing this variation? Clearly, the variation has better memory requirement.
Note: I know that I can use topological sort SPT algorithm when there are no cycles in the weighted digraph, but I am trying to understand the correctness of Bellman-Ford.
Bellman-Ford algorithm states that after V-1 phases of relaxation of every edge would calculate the minimum distance between source to any destination. In your implementation, you run V-2 iterations of each phase. Actually, two of implementations are the same, you can just reuse the old array of distances.
In an effort to learn and use hidden markov models, I am writing my own code to implement them. I am using this wiki article to help with my work. I do not wish to resort to pre-written libraries, because I have found I can achieve a better understanding if I write it myself. And no, this isn't a school assignment! :)
Unfortunately, my highest level of education consists of high school computer science and statistics. I have no background in Machine Learning besides the casual poking around with ANN libraries and TensorFlow. I am therefore having a bit of trouble translating mathematical equations into code. Specifically, I'm worried my implementations of the alpha and beta functions aren't functionally correct. If anyone can assist in describing where I messed up and how to correct my mistakes to have a functioning HMM implementation, it'd be greatly appreciated.
Here are my class-wide globals:
public int n; //number of states
public int t; //number of observations
public int time; //iteration holder
public double[][] emitprob; //Emission parameter
public double[][] stprob; //State transition parameter
public ArrayList<String> states, observations, x, y;
My constructor:
public Model(ArrayList<String> sts, ArrayList<String> obs)
{
//the most important algorithm we need right now is
//unsupervised learning through BM. Supervised is
//pretty easy.
//need hashtable of count objects... Aya...
//perhaps a learner...?
states = sts;
observations = obs;
n = states.size();
t = observations.size();
x = new ArrayList();
y = new ArrayList();
time = 0;
stprob = new double[n][n];
emitprob = new double[n][t];
stprob = newDistro(n,n);
emitprob = newDistro(n,t);
}
The newDistro method is for creating a new, uniform, normal distribution:
public double[][] newDistro(int x, int y)
{
Random r = new Random(System.currentTimeMillis());
double[][] returnme = new double[x][y];
double sum = 0;
for(int i = 0; i < x; i++)
{
for(int j = 0; j < y; j++)
{
returnme[i][j] = Math.abs(r.nextInt());
sum += returnme[i][j];
}
}
for(int i = 0; i < x; i++)
{
for(int j = 0; j < y; j++)
{
returnme[i][j] /= sum;
}
}
return returnme;
}
My viterbi algorithm implementation:
public ArrayList<String> viterbi(ArrayList<String> obs)
{
//K means states
//T means observations
//T arrays should be constructed as K * T (N * T)
ArrayList<String> path = new ArrayList();
String firstObservation = obs.get(0);
int firstObsIndex = observations.indexOf(firstObservation);
double[] pi = new double[n]; //initial probs of first obs for each st
int ts = obs.size();
double[][] t1 = new double[n][ts];
double[][] t2 = new double[n][ts];
int[] y = new int[obs.size()];
for(int i = 0; i < obs.size(); i++)
{
y[i] = observations.indexOf(obs.get(i));
}
for(int i = 0; i < n; i++)
{
pi[i] = emitprob[i][firstObsIndex];
}
for(int i = 0; i < n; i++)
{
t1[i][0] = pi[i] * emitprob[i][y[0]];
t2[i][0] = 0;
}
for(int i = 1; i < ts; i++)
{
for(int j = 0; j < n; j++)
{
double maxValue = 0;
int maxIndex = 0;
//first we compute the max value
for(int q = 0; q < n; q++)
{
double value = t1[q][i-1] * stprob[q][j];
if(value > maxValue)
{
maxValue = value; //the max
maxIndex = q; //the argmax
}
}
t1[j][i] = emitprob[j][y[i]] * maxValue;
t2[j][i] = maxIndex;
}
}
int[] z = new int[ts];
int maxIndex = 0;
double maxValue = 0.0d;
for(int k = 0; k < n; k++)
{
double myValue = t1[k][ts-1];
if(myValue > maxValue)
{
myValue = maxValue;
maxIndex = k;
}
}
path.add(states.get(maxIndex));
for(int i = ts-1; i >= 2; i--)
{
z[i-1] = (int)t2[z[i]][i];
path.add(states.get(z[i-1]));
}
System.out.println(path.size());
for(String s: path)
{
System.out.println(s);
}
return path;
}
My forward algorithm, which takes place of the alpha function as described later:
public double forward(ArrayList<String> obs)
{
double result = 0;
int length = obs.size()-1;
for(int i = 0; i < n; i++)
{
result += alpha(i, length, obs);
}
return result;
}
The remaining functions are for implementing the Baum-Welch Algorithm.
The alpha function is what I'm afraid I'm doing wrong of the most on here. I had trouble understanding which "direction" it needs to iterate over the sequence - Do I start from the last element (size-1) or the first (at index zero) ?
public double alpha(int j, int t, ArrayList<String> obs)
{
double sum = 0;
if(t == 0)
{
return stprob[0][j];
}
else
{
String lastObs = obs.get(t);
int obsIndex = observations.indexOf(lastObs);
for(int i = 0; i < n; i++)
{
sum += alpha(i, t-1, obs) * stprob[i][j] * emitprob[j][obsIndex];
}
}
return sum;
}
I'm having similar "correctness" issues with my beta function:
public double beta(int i, int t, ArrayList<String> obs)
{
double result = 0;
int obsSize = obs.size()-1;
if(t == obsSize)
{
return 1;
}
else
{
String lastObs = obs.get(t+1);
int obsIndex = observations.indexOf(lastObs);
for(int j = 0; j < n; j++)
{
result += beta(j, t+1, obs) * stprob[i][j] * emitprob[j][obsIndex];
}
}
return result;
}
I'm more confident in my gamma function; However, since it explicitly requires use of alpha and beta, obviously I'm worried it'll be "off" somehow.
public double gamma(int i, int t, ArrayList<String> obs)
{
double top = alpha(i, t, obs) * beta(i, t, obs);
double bottom = 0;
for(int j = 0; j < n; j++)
{
bottom += alpha(j, t, obs) * beta(j, t, obs);
}
return top / bottom;
}
Same for my "squiggle" function - I do apologize for naming; Not sure of the actual name for the symbol.
public double squiggle(int i, int j, int t, ArrayList<String> obs)
{
String lastObs = obs.get(t+1);
int obsIndex = observations.indexOf(lastObs);
double top = alpha(i, t, obs) * stprob[i][j] * beta(j, t+1, obs) * emitprob[j][obsIndex];
double bottom = 0;
double innerSum = 0;
double outterSum = 0;
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
innerSum += alpha(i, t, obs) * stprob[i][j] * beta(j, t+1, obs) * emitprob[j][obsIndex];
}
outterSum += innerSum;
}
return top / bottom;
}
Lastly, to update my state transition and emission probability arrays, I have implemented these functions as aStar and bStar.
public double aStar(int i, int j, ArrayList<String> obs)
{
double squiggleSum = 0;
double gammaSum = 0;
int T = obs.size()-1;
for(int t = 0; t < T; t++)
{
squiggleSum += squiggle(i, j, t, obs);
gammaSum += gamma(i, t, obs);
}
return squiggleSum / gammaSum;
}
public double bStar(int i, String v, ArrayList<String> obs)
{
double top = 0;
double bottom = 0;
for(int t = 0; t < obs.size()-1; t++)
{
if(obs.get(t).equals(v))
{
top += gamma(i, t, obs);
}
bottom += gamma(i, t, obs);
}
return top / bottom;
}
In my understanding, since the b* function includes a piecewise function that returns either 1 or 0, I think implementing it in an "if" statement and only adding the result if the string is equal to the observation history is the same as what is described, since the function would render the call to gamma 0, thus saving a little computation time. Is this correct?
In summation, I want to get my math right, to ensure a successful (albeit simple) HMM implementation. As for the Baum-Welch algorithm, I am having trouble understanding how to implment the complete function - would it be as simple as running aStar over all states (as an n * n FOR loop) and bStar for all observations, inside a loop with a convergence function? Also, what would be a best-practice function for checking for convergence without overfitting?
Please let me know of everything I need to do in order to get this right.
Thank you heavily for any help you can give me!
To avoid underflow, one should use a scaling factor in the forward and backward algorithms. To get the correct result, one uses nested for loops and the steps are forward in the forward method.
The backward method is similar to the forward function.
You invoke them from the method of the Baum-Welch algorithm.
I'm trying to write a method that calculates the exponential of a square matrix. In this instance, the matrix is a square array of value:
[1 0]
[0 10]
and the method should return a value of:
[e 0]
[0 e^10]
However, when I run my code, I get a range of values depending on what bits I've rearranged, non particularly close to the expected value.
The way the method works is to utilise the power series for the matrix, so basically for a matrix A, n steps and an identity matrix I:
exp(A) = I + A + 1/2!*AA + 1/3!*AAA + ... +1/n!*AAA..
The code follows here. The method where I'm having the issue is the method exponential(Matrix A, int nSteps). The methods involved are enclosed, and the Matrix objects take the arguments (int m, int n) to create an array of size double[m][n].
public static Matrix multiply(Matrix m1, Matrix m2){
if(m1.getN()!=m2.getM()) return null;
Matrix res = new Matrix(m1.getM(), m2.getN());
for(int i = 0; i < m1.getM(); i++){
for(int j = 0; j < m2.getN(); j++){
res.getArray()[i][j] = 0;
for(int k = 0; k < m1.getN(); k++){
res.getArray()[i][j] = res.getArray()[i][j] + m1.getArray()[i][k]*m2.getArray()[k][j];
}
}
}
return res;
}
public static Matrix identityMatrix(int M){
Matrix id = new Matrix(M, M);
for(int i = 0; i < id.getM(); i++){
for(int j = 0; j < id.getN(); j++){
if(i==j) id.getArray()[i][j] = 1;
else id.getArray()[i][j] = 0;
}
}
return id;
}
public static Matrix addMatrix(Matrix m1, Matrix m2){
Matrix m3 = new Matrix(m1.getM(), m2.getN());
for(int i = 0; i < m3.getM(); i++){
for(int j = 0; j < m3.getN(); j++){
m3.getArray()[i][j] = m1.getArray()[i][j] + m2.getArray()[i][j];
}
}
return m3;
}
public static Matrix scaleMatrix(Matrix m, double scale){
Matrix res = new Matrix(m.getM(), m.getN());
for(int i = 0; i < res.getM(); i++){
for(int j = 0; j < res.getN(); j++){
res.getArray()[i][j] = m.getArray()[i][j]*scale;
}
}
return res;
}
public static Matrix exponential(Matrix A, int nSteps){
Matrix runtot = identityMatrix(A.getM());
Matrix sum = identityMatrix(A.getM());
double factorial = 1.0;
for(int i = 1; i <= nSteps; i++){
sum = Matrix.multiply(Matrix.scaleMatrix(sum, factorial), A);
runtot = Matrix.addMatrix(runtot, sum);
factorial /= (double)i;
}
return runtot;
}
So my question is, how should I modify my code, so that I can input a matrix and a number of timesteps to calculate the exponential of said matrix after said timesteps?
My way to go would be to keep two accumulators :
the sum, which is your approximation of exp(A)
the nth term of the series M_n, that is A^n/n!
Note that there is a nice recursive relationship with M_n: M_{n+1} = M_n * A / (n+1)
Which yields :
public static Matrix exponential(Matrix A, int nSteps){
Matrix seriesTerm = identityMatrix(A.getM());
Matrix sum = identityMatrix(A.getM());
for(int i = 1; i <= nSteps; i++){
seriesTerm = Matrix.scaleMatrix(Matrix.multiply(seriesTerm,A),1.0/i);
sum = Matrix.addMatrix(seriesTerm, sum);
}
return sum;
}
I totally understand the sort of thrill that implementing such algorithms can give you. But if this is not a hobby project, I concur that you should that you should use a library for this kind of stuff. Making such computations precise and efficient is really not a trivial matter, and a huge wheel to reinvent.
I have figured out how to create an array of integers and create a method to find the most frequent value in the array. Creating this method by creating another array used as a counter for each value. but how would I go about creating a method used to find the most frequent double in an array of DOUBLES.. without using hashmaps or sorting?
-this is my code for the method using integers, but will not work with double values/double array
public static int findMostFrequentValue(int[] array) {
int i;
int[] numberCount = new int[100];
for (i = 0; i < array.length; i++)
++numberCount[array[i]];
int max = 0;
int j;
for (j = 0; j < numberCount.length; j++) {
if (numberCount[j] > max) max = j;
}
return max;
}
Here's a quick blurb, sticking to your requirement of no hashmaps or sorting. Note, as coded, if there's a tie it returns the last match. Also note this is exponential O(n^2) time with the inner loop, so poor for large arrays.
public class Frequency {
public static void main(String args[]) {
double[] array = {3.4, 6.8, 1.1, 2.4, 3.8, 6.8, 7.0, 5.0};
double result = findMostFrequentValue(array);
System.out.println("Most frequent value: " + result);
}
public static double findMostFrequentValue(double[] array) {
int[] count = new int[array.length];
for (int i = 0; i < array.length; i++) {
count[i] = 0;
for (int j = 0; j < array.length; j++) {
if (approxEquals(array[i], array[j], .0001)) {
count[i]++;
}
}
}
int index = 0;
int max = 0;
for (int i = 0; i < count.length; i++) {
if (count[i] > max) {
max = count[i];
index = i;
}
}
return array[index];
}
private static boolean approxEquals(double val1, double val2, double tolerance) {
return Math.abs(val1 - val2) < tolerance;
}
}
I have two dimensional float array as below
{0.2,0.0,0.3,0.0,0.0}
{0.4,0.1,0.0,0.0,0.9}
{0.0,0.0,0.0,0.3,0.6}
I want to get the following output
{0.6,0.0,0.3,0.0,0.0}
{0.6,0.1,0.0,0.0,1.5}
{0.0,0.0,0.0,0.3,1.5}
If you analyse, I sum each column's non zero value and update all non zero values with that sum value. For example, in first column I sum (0.2+0.4=0.4) and updated both value position with 0.6.
I am using Java, how can I perform this? Its a simple example, in real time I have really big arrays.
This works assuming they're all the same length. Special cases are exercise to the reader.
class MatTest {
static void makeSums(float[][] floats) {
// we wouldn't be doing any operations on these inputs anyway, so return
if(floats == null || floats.length == 0 || floats.length == 1) return;
// check to make sure it's retangular
for(float[] arr : floats) {
if(arr.length != floats[0].length) {
throw new IllegalArgumentException("makeSums() requires rectangular array");
}
}
for(int i = 0; i < floats[0].length; i++) {
// do each column
float sum = 0f;
for(int j = 0; j < floats.length; j++) {
sum += floats[j][i];
}
for(int j = 0; j < floats.length; j++) {
if(floats[j][i] != 0) floats[j][i] = sum;
}
}
}
public static void main(String[] args) {
float[][] floats = new float[3][5];
floats[0] = new float[] {0.2f,0.0f,0.3f,0.0f,0.0f};
floats[1] = new float[] {0.4f,0.1f,0.0f,0.0f,0.9f};
floats[2] = new float[] {0.0f,0.0f,0.0f,0.3f,0.6f};
makeSums(floats);
for(int i = 0; i < floats.length; i++) {
for(int j = 0; j < floats[0].length; j++) {
System.out.print(floats[i][j]);
System.out.print(" ");
}
System.out.println(" ");
}
}
}
And here's its result:
C:\Documents and Settings\glow\My Documents>javac MatTest.java
C:\Documents and Settings\glow\My Documents>java MatTest
0.6 0.0 0.3 0.0 0.0
0.6 0.1 0.0 0.0 1.5
0.0 0.0 0.0 0.3 1.5
Let's call your input array float[][] a and parallel output array b initialized to all zeroes.
float curSum = 0.0;
first = true;
for(int i = 0; i < a[0].length; i++)
{
for(int j = 0; j < a.length; j++)
{
if(a[i][j] != 0)
{
if (first)
{
for(int k = j; k < a.length; k++)
curSum += a[i][k];
first = false;
}
b[i][j] = curSum;
}
}
curSum = 0.0;
first = true;
}
There might be some finer points you have to change, such as comparison of the floats and stuff, but i think the idea is all there
I think it runs in O(n*m), andwhich doesnt seem great, but I tried to keep the iterations as short as possible. I dont see any faster way to do it. Even tho there are three for loops, the one with k will only run once for every j loop so asymptotically it doesnt increase complexity at all.