Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SYSTEMDS-3549] Hidden Markov model builtin #1838

Open
wants to merge 28 commits into
base: main
Choose a base branch
from

Conversation

cluelesprogrammer
Copy link

No description provided.

@Baunsgaard
Copy link
Contributor

Hi @cluelesprogrammer ,

Yes the files are located correctly.

Next steps are to (as we texted about before):

  1. Take a bit of inspiration from the other files, to define an interface of these methods such that you take an input X that you want to train on for the hmm.dml and a input X that you want to predict on for the hmmPredict.dml. As a starting point just make the methods call stop("NotImplemented").
  2. You can integrate these into the system by adding them in /src/main/java/org/apache/sysds/common/Builtins.java, again look at how other builtin functions are done.
  3. Then try to call it from a new file that is not in the repository, perhaps make a /temp directory can a file called test.dml that calls your new builtin.
  4. Add a test that verifies that the builtin is working/throwing the not implemented in src/test/java/org/apache/sysds/test/functions/builtin either part1 or 2, again find some inspiration from other tests.

Once the above is done start making the HMM implementation.

I suggest you just do the work on top of this PR.

@Baunsgaard Baunsgaard changed the title added empty files [SYSTEMDS-3549] Hidden Markov model builtin Jun 7, 2023
@Baunsgaard Baunsgaard marked this pull request as draft June 7, 2023 19:39
# P Probability of the set of outputs
# --------------------------------------------------------------------------------------------

hmm = function(Matrix[Double] X)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since you are allowed to define more than one function in these files, we require you to mark the main function with: m_ , aka here it become m_hmm

Copy link
Contributor

@Baunsgaard Baunsgaard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good so far you just have to write the test matrix to disk and verify that the test executes correctly with the correct output.

writeInputMatrixWithMTD("X", X, true);
"""

runTest(true, false, null, -1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this only runs your code. it does not verify something happened.

you can alternatively call it like

String stdout = runTest(null).toString()

then you get the output from the experiment if you also call before setOutputBuffering(true);

Copy link
Contributor

@Baunsgaard Baunsgaard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @cluelesprogrammer

To Finish the submission i expect at least:

  1. A test that verify behavior not just that your method is running.
  2. If it is impossible to implement the HMM itself, then at least test the HMM predict in accordance to what you think it should do, and make clear indications where in the code elements are missing for a full implementation. Otherwise a full simple version of HMM would be required, it does not have to be efficient.

Best regards
Sebastian

iteration, break.
*/
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new lines in end of files.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand this. Could you please clarify?

Copy link
Contributor

@Baunsgaard Baunsgaard Jul 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simple, GitHub indicate with a big red mark that there is no newline. The code does work, but we try to make it consistent across files.

image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I add or remove a newline?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add

@cluelesprogrammer cluelesprogrammer marked this pull request as ready for review July 23, 2023 20:01
Copy link
Contributor

@Baunsgaard Baunsgaard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @cluelesprogrammer

I went through the code again.
It looks okay, so i would say it is a passed AMLS project.
But i did leave some coding comments, that we need to look into before we merge it.

Thanks for the PR and help (but do not feel forced to do it.)


#X should have the size of 1 * ncols
#should be transposed for the unique function
unique_X = matrix(X, rows=ncol(X), cols=1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to transpose call t(X)


search = TRUE
nr_states = 2
seed = 42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make seed an argument initially

#X should have the size of 1 * ncols
#should be transposed for the unique function
unique_X = matrix(X, rows=ncol(X), cols=1)
nr_outputs = unique_vals(unique_X)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have a builtin function to calculate the number of unique values:
countDistinct()

you can give it an direction if you want to know the number of distinct in columns, rows or entirety.

seed = seed+1
B = col_normalize(matrix(1/nr_outputs,rows=nr_states, cols=nr_outputs) + rand(rows=nr_states, cols=nr_outputs, seed=seed))
seed = seed+1
ip = matrix(1/nr_states, rows=nr_states, cols=1) + rand(rows=nr_states, cols=1, seed=seed)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, each call to random have to have a unique seed. A suggestion for this is to make each rand call with seed += 1. (+= is not supported so you have to assign back the seed with seed = seed + 1, between the lines.)

#initialize state transition and emmission matrices uniformly
A = col_normalize(matrix(1/nr_states, rows=nr_states, cols=nr_states) + rand(rows=nr_states, cols=nr_states, seed=seed))
seed = seed+1
B = col_normalize(matrix(1/nr_outputs,rows=nr_states, cols=nr_outputs) + rand(rows=nr_states, cols=nr_outputs, seed=seed))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Values contained in the matrix is equivalent in each cell for both calls.
perhaps the value to put into the matrix can be calculated once and then assigned into a matrix?
And even better if this is something we can assign into the arguments of the rand call, then we would reduce the current calls from 3 matrices materialized to only 1 per line of (98, 100, and 102)

[i, j] = index(trans_id, nr_states)
for (t in 1:(T-1)) {
#indices for alpha and beta
ot1 = output_t(X, t+1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the method output_t and call the extraction here. It should automatically know it is a scalar.
Do you cast to int because you want to round? if so then call round()

nr_states = nrow(alpha)
T = ncol(alpha)

gamma = rand(rows=nr_states, cols=T)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rand call seems to be done just to materialize a matrix?
If so we could consider changing it to a matrix(rows...) call.
But it might not be the best solution.

den_it = sum(alpha[,t] * beta[,t])
gamma[i, t] = num_it / den_it
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these parfors can be rewritten as:

num_it_M = alpha * beta
den_it_M =  rowsum(num_it_M)
gamma = num_it_M / den_it_M

This is because we support direct matrix and vector operations.
And i think this nicely maps to it. (But i might have an error here.)

for (t in 2:T) {
ot = output_t(X, t)
for (i in 1:nr_states) {
alpha[i, t] = B[i, ot] * sum(alpha[,t-1]* A[ ,i])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move alpha[,t-1] to outer loop

for (t in (T-1):1) {
ot = output_t(X, t)
for (i in 1:nr_states) {
beta[i, t] = sum(beta[, t+1] * t(A[i, ]) * B[ , ot])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move beta[,t+1] to outer loop if possible

@j143
Copy link
Contributor

j143 commented Dec 17, 2023

Hi @cluelesprogrammer , thanks a lot for contributing to SystemDS. Do you need some help with addressing the review comments.

Your PR looks good as is. Let me know if you would like to address the comments.

Kindly let us know, if there is any assistance we could provide.

Regards,
Janardhan

@j143 j143 added this to the next-release milestone Feb 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

3 participants