{"action":"created","issue":{"url":"https://api.github.com/repos/apache/spark/issues/4047","labels_url":"https://api.github.com/repos/apache/spark/issues/4047/labels{/name}","comments_url":"https://api.github.com/repos/apache/spark/issues/4047/comments","events_url":"https://api.github.com/repos/apache/spark/issues/4047/events","html_url":"https://github.com/apache/spark/pull/4047","id":54361128,"number":4047,"title":"[SPARK-1405] [mllib] Latent Dirichlet Allocation (LDA) using EM","user":{"login":"jkbradley","id":5084283,"avatar_url":"https://avatars.githubusercontent.com/u/5084283?v=3","gravatar_id":"","url":"https://api.github.com/users/jkbradley","html_url":"https://github.com/jkbradley","followers_url":"https://api.github.com/users/jkbradley/followers","following_url":"https://api.github.com/users/jkbradley/following{/other_user}","gists_url":"https://api.github.com/users/jkbradley/gists{/gist_id}","starred_url":"https://api.github.com/users/jkbradley/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jkbradley/subscriptions","organizations_url":"https://api.github.com/users/jkbradley/orgs","repos_url":"https://api.github.com/users/jkbradley/repos","events_url":"https://api.github.com/users/jkbradley/events{/privacy}","received_events_url":"https://api.github.com/users/jkbradley/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":35,"created_at":"2015-01-14T18:57:33Z","updated_at":"2015-01-29T00:34:27Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/apache/spark/pulls/4047","html_url":"https://github.com/apache/spark/pull/4047","diff_url":"https://github.com/apache/spark/pull/4047.diff","patch_url":"https://github.com/apache/spark/pull/4047.patch"},"body":"**This PR introduces an API + simple implementation for Latent Dirichlet Allocation (LDA).**\r\n\r\nThe [design doc for this PR](https://docs.google.com/document/d/1kSsDqTeZMEB94Bs4GTd0mvdAmduvZSSkpoSfn-seAzo) has been updated since I initially posted it.  In particular, see the API and Planning for the Future sections.\r\n\r\n## Goals\r\n\r\n* Settle on a public API which may eventually include:\r\n  * more inference algorithms\r\n  * more options / functionality\r\n* Have an initial easy-to-understand implementation which others may improve.\r\n* This is NOT intended to support every topic model out there.  However, if there are suggestions for making this extensible or pluggable in the future, that could be nice, as long as it does not complicate the API or implementation too much.\r\n* This may not be very scalable currently.  It will be important to check and improve accuracy.  For correctness of the implementation, please check against the Asuncion et al. (2009) paper in the design doc.\r\n\r\n## Sketch of contents of this PR\r\n\r\n**Dependency: This makes MLlib depend on GraphX.**\r\n\r\nFiles and classes:\r\n* LDA.scala (441 lines):\r\n  * class LDA (main estimator class)\r\n  * LDA.Document  (text + document ID)\r\n* LDAModel.scala (266 lines)\r\n  * abstract class LDAModel\r\n  * class LocalLDAModel\r\n  * class DistributedLDAModel\r\n* LDAExample.scala (245 lines): script to run LDA + a simple (private) Tokenizer\r\n* LDASuite.scala (144 lines)\r\n\r\nData/model representation and algorithm:\r\n* Data/model: Uses GraphX, with term vertices + document vertices\r\n* Algorithm: EM, following [Asuncion, Welling, Smyth, and Teh.  \"On Smoothing and Inference for Topic Models.\"  UAI, 2009.](http://arxiv-web3.library.cornell.edu/abs/1205.2662v1)\r\n* For more details, please see the description in the “DEVELOPERS NOTE” in LDA.scala\r\n\r\n## Design notes\r\n\r\nPlease refer to the JIRA for more discussion + the [design doc for this PR](https://docs.google.com/document/d/1kSsDqTeZMEB94Bs4GTd0mvdAmduvZSSkpoSfn-seAzo)\r\n\r\nHere, I list the main changes AFTER the design doc was posted.\r\n\r\nDesign decisions:\r\n* logLikelihood() computes the log likelihood of the data and the current point estimate of parameters.  This is different from the likelihood of the data given the hyperparameters, which would be harder to compute.  I’d describe the current approach as more frequentist, whereas the harder approach would be more Bayesian.\r\n* The current API takes Documents as token count vectors.  I believe there should be an extended API taking RDD[String] or RDD[Array[String]] in a future PR.  I have sketched this out in the design doc (as well as handier versions of getTopics returning Strings).\r\n* Hyperparameters should be set differently for different inference/learning algorithms.  See Asuncion et al. (2009) in the design doc for a good demonstration.  I encourage good behavior via defaults and warning messages.\r\n\r\nItems planned for future PRs:\r\n* perplexity\r\n* API taking Strings\r\n\r\n## Questions for reviewers\r\n\r\n* Should LDA be called LatentDirichletAllocation (and LDAModel be LatentDirichletAllocationModel)?\r\n  * Pro: We may someday want LinearDiscriminantAnalysis.\r\n  * Con: Very long names\r\n\r\n* Should LDA reside in clustering?  Or do we want a sub-package?\r\n  * mllib.topicmodel\r\n  * mllib.clustering.topicmodel\r\n\r\n* Does the API seem reasonable and extensible?\r\n\r\n* Unit tests:\r\n  * Should there be a test which checks a clustering results?  E.g., train on a small, fake dataset with 2 very distinct topics/clusters, and ensure LDA finds those 2 topics/clusters.  Does that sound useful or too flaky?\r\n\r\n## Other notes\r\n\r\nThis has not been tested much for scaling.  I have run it on a laptop for 200 iterations on a 5MB dataset with 1000 terms and 5 topics.  Running it for 500 iterations made it fail because of GC problems.  I'm running larger scale tests & will put results here, but future PRs may need to improve the scaling.\r\n\r\n## Thanks to…\r\n\r\n* @dlwh  for the initial implementation\r\n  * + @jegonzal  for some code in the initial implementation\r\n* The many contributors towards topic model implementations in Spark which were referenced as a basis for this PR: @akopich @witgo @yinxusen @dlwh @EntilZha @jegonzal  @IlyaKozlov\r\n  * Note: The plan is to include this full list in the authors if this PR gets merged.  Please notify me if you prefer otherwise.\r\n\r\nCC: @mengxr\r\n"},"comment":{"url":"https://api.github.com/repos/apache/spark/issues/comments/71946931","html_url":"https://github.com/apache/spark/pull/4047#issuecomment-71946931","issue_url":"https://api.github.com/repos/apache/spark/issues/4047","id":71946931,"user":{"login":"EntilZha","id":1382460,"avatar_url":"https://avatars.githubusercontent.com/u/1382460?v=3","gravatar_id":"","url":"https://api.github.com/users/EntilZha","html_url":"https://github.com/EntilZha","followers_url":"https://api.github.com/users/EntilZha/followers","following_url":"https://api.github.com/users/EntilZha/following{/other_user}","gists_url":"https://api.github.com/users/EntilZha/gists{/gist_id}","starred_url":"https://api.github.com/users/EntilZha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EntilZha/subscriptions","organizations_url":"https://api.github.com/users/EntilZha/orgs","repos_url":"https://api.github.com/users/EntilZha/repos","events_url":"https://api.github.com/users/EntilZha/events{/privacy}","received_events_url":"https://api.github.com/users/EntilZha/received_events","type":"User","site_admin":false},"created_at":"2015-01-29T00:34:27Z","updated_at":"2015-01-29T00:34:27Z","body":"@mengxr, correct, its not public, but it would be helpful to at least get a minimal Trait which I can base my PR on (something similar to what I proposed earlier). That being said, I could include the changes in structure to Trait and Gibbs in a PR... seems easier to get it right the first time though."}}