{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/machinelearning/pulls/comments/232105072","pull_request_review_id":173228098,"id":232105072,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzMjEwNTA3Mg==","diff_hunk":"@@ -169,224 +176,668 @@ private sealed class ColInfoEx\n             public readonly int NumBurninIter;\n             public readonly bool ResetRandomGenerator;\n \n-            public ColInfoEx(IExceptionContext ectx, Column item, Arguments args)\n+            /// <summary>\n+            /// Describes how the transformer handles one column pair.\n+            /// </summary>\n+            /// <param name=\"input\">Name of input column.</param>\n+            /// <param name=\"output\">Name of output column.</param>\n+            /// <param name=\"numTopic\">The number of topics in the LDA.</param>\n+            /// <param name=\"alphaSum\">Dirichlet prior on document-topic vectors.</param>\n+            /// <param name=\"beta\">Dirichlet prior on vocab-topic vectors.</param>\n+            /// <param name=\"mhStep\">Number of Metropolis Hasting step.</param>\n+            /// <param name=\"numIter\">Number of iterations.</param>\n+            /// <param name=\"likelihoodInterval\">Compute log likelihood over local dataset on this iteration interval.</param>\n+            /// <param name=\"numThread\">The number of training threads. Default value depends on number of logical processors.</param>\n+            /// <param name=\"numMaxDocToken\">The threshold of maximum count of tokens per doc.</param>\n+            /// <param name=\"numSummaryTermPerTopic\">The number of words to summarize the topic.</param>\n+            /// <param name=\"numBurninIter\">The number of burn-in iterations.</param>\n+            /// <param name=\"resetRandomGenerator\">Reset the random number generator for each document.</param>\n+            public ColumnInfo(string input, string output, int numTopic, Single alphaSum, Single beta, int mhStep, int numIter, int likelihoodInterval,\n+                int numThread, int numMaxDocToken, int numSummaryTermPerTopic, int numBurninIter, bool resetRandomGenerator)\n             {\n-                Contracts.AssertValue(ectx);\n-\n-                NumTopic = item.NumTopic ?? args.NumTopic;\n-                Contracts.CheckUserArg(NumTopic > 0, nameof(item.NumTopic), \"Must be positive.\");\n-\n-                AlphaSum = item.AlphaSum ?? args.AlphaSum;\n-\n-                Beta = item.Beta ?? args.Beta;\n-\n-                MHStep = item.Mhstep ?? args.Mhstep;\n-                ectx.CheckUserArg(MHStep > 0, nameof(item.Mhstep), \"Must be positive.\");\n-\n-                NumIter = item.NumIterations ?? args.NumIterations;\n-                ectx.CheckUserArg(NumIter > 0, nameof(item.NumIterations), \"Must be positive.\");\n-\n-                LikelihoodInterval = item.LikelihoodInterval ?? args.LikelihoodInterval;\n-                ectx.CheckUserArg(LikelihoodInterval > 0, nameof(item.LikelihoodInterval), \"Must be positive.\");\n+                Input = input;\n+                Output = output;\n+                NumTopic = numTopic;\n+                AlphaSum = alphaSum;\n+                Beta = beta;\n+                MHStep = mhStep;\n+                NumIter = numIter;\n+                LikelihoodInterval = likelihoodInterval;\n+                NumThread = numThread;\n+                NumMaxDocToken = numMaxDocToken;\n+                NumSummaryTermPerTopic = numSummaryTermPerTopic;\n+                NumBurninIter = numBurninIter;\n+                ResetRandomGenerator = resetRandomGenerator;\n+            }\n+        }\n \n-                NumThread = item.NumThreads ?? args.NumThreads ?? 0;\n-                ectx.CheckUserArg(NumThread >= 0, nameof(item.NumThreads), \"Must be positive or zero.\");\n+        public sealed class LdaState : IDisposable\n+        {\n+            internal readonly TransformInfo InfoEx;\n+            private readonly int _numVocab;\n+            private readonly object _preparationSyncRoot;\n+            private readonly object _testSyncRoot;\n+            private bool _predictionPreparationDone;\n+            private LdaSingleBox _ldaTrainer;\n \n-                NumMaxDocToken = item.NumMaxDocToken ?? args.NumMaxDocToken;\n-                ectx.CheckUserArg(NumMaxDocToken > 0, nameof(item.NumMaxDocToken), \"Must be positive.\");\n+            private LdaState()\n+            {\n+                _preparationSyncRoot = new object();\n+                _testSyncRoot = new object();\n+            }\n \n-                NumSummaryTermPerTopic = item.NumSummaryTermPerTopic ?? args.NumSummaryTermPerTopic;\n-                ectx.CheckUserArg(NumSummaryTermPerTopic > 0, nameof(item.NumSummaryTermPerTopic), \"Must be positive\");\n+            internal LdaState(IExceptionContext ectx, TransformInfo ex, int numVocab)\n+                : this()\n+            {\n+                Contracts.AssertValue(ectx);\n+                ectx.AssertValue(ex, \"ex\");\n \n-                NumBurninIter = item.NumBurninIterations ?? args.NumBurninIterations;\n-                ectx.CheckUserArg(NumBurninIter >= 0, nameof(item.NumBurninIterations), \"Must be non-negative.\");\n+                ectx.Assert(numVocab >= 0);\n+                InfoEx = ex;\n+                _numVocab = numVocab;\n \n-                ResetRandomGenerator = item.ResetRandomGenerator ?? args.ResetRandomGenerator;\n+                _ldaTrainer = new LdaSingleBox(\n+                    InfoEx.NumTopic,\n+                    numVocab, /* Need to set number of vocabulary here */\n+                    InfoEx.AlphaSum,\n+                    InfoEx.Beta,\n+                    InfoEx.NumIter,\n+                    InfoEx.LikelihoodInterval,\n+                    InfoEx.NumThread,\n+                    InfoEx.MHStep,\n+                    InfoEx.NumSummaryTermPerTopic,\n+                    false,\n+                    InfoEx.NumMaxDocToken);\n             }\n \n-            public ColInfoEx(IExceptionContext ectx, ModelLoadContext ctx)\n+            internal LdaState(IExceptionContext ectx, ModelLoadContext ctx)\n+                : this()\n             {\n-                Contracts.AssertValue(ectx);\n                 ectx.AssertValue(ctx);\n \n                 // *** Binary format ***\n-                // int NumTopic;\n-                // Single AlphaSum;\n-                // Single Beta;\n-                // int MHStep;\n-                // int NumIter;\n-                // int LikelihoodInterval;\n-                // int NumThread;\n-                // int NumMaxDocToken;\n-                // int NumSummaryTermPerTopic;\n-                // int NumBurninIter;\n-                // byte ResetRandomGenerator;\n+                // <ColInfoEx>\n+                // int: vocabnum\n+                // long: memblocksize\n+                // long: aliasMemBlockSize\n+                // (serializing term by term, for one term)\n+                // int: term_id, int: topic_num, KeyValuePair<int, int>[]: termTopicVector\n \n-                NumTopic = ctx.Reader.ReadInt32();\n-                ectx.CheckDecode(NumTopic > 0);\n+                InfoEx = new TransformInfo(ectx, ctx);\n \n-                AlphaSum = ctx.Reader.ReadSingle();\n+                _numVocab = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(_numVocab > 0);\n \n-                Beta = ctx.Reader.ReadSingle();\n+                long memBlockSize = ctx.Reader.ReadInt64();\n+                ectx.CheckDecode(memBlockSize > 0);\n \n-                MHStep = ctx.Reader.ReadInt32();\n-                ectx.CheckDecode(MHStep > 0);\n+                long aliasMemBlockSize = ctx.Reader.ReadInt64();\n+                ectx.CheckDecode(aliasMemBlockSize > 0);\n \n-                NumIter = ctx.Reader.ReadInt32();\n-                ectx.CheckDecode(NumIter > 0);\n+                _ldaTrainer = new LdaSingleBox(\n+                    InfoEx.NumTopic,\n+                    _numVocab, /* Need to set number of vocabulary here */\n+                    InfoEx.AlphaSum,\n+                    InfoEx.Beta,\n+                    InfoEx.NumIter,\n+                    InfoEx.LikelihoodInterval,\n+                    InfoEx.NumThread,\n+                    InfoEx.MHStep,\n+                    InfoEx.NumSummaryTermPerTopic,\n+                    false,\n+                    InfoEx.NumMaxDocToken);\n \n-                LikelihoodInterval = ctx.Reader.ReadInt32();\n-                ectx.CheckDecode(LikelihoodInterval > 0);\n+                _ldaTrainer.AllocateModelMemory(_numVocab, InfoEx.NumTopic, memBlockSize, aliasMemBlockSize);\n \n-                NumThread = ctx.Reader.ReadInt32();\n-                ectx.CheckDecode(NumThread >= 0);\n+                for (int i = 0; i < _numVocab; i++)\n+                {\n+                    int termID = ctx.Reader.ReadInt32();\n+                    ectx.CheckDecode(termID >= 0);\n+                    int termTopicNum = ctx.Reader.ReadInt32();\n+                    ectx.CheckDecode(termTopicNum >= 0);\n \n-                NumMaxDocToken = ctx.Reader.ReadInt32();\n-                ectx.CheckDecode(NumMaxDocToken > 0);\n+                    int[] topicId = new int[termTopicNum];\n+                    int[] topicProb = new int[termTopicNum];\n \n-                NumSummaryTermPerTopic = ctx.Reader.ReadInt32();\n-                ectx.CheckDecode(NumSummaryTermPerTopic > 0);\n+                    for (int j = 0; j < termTopicNum; j++)\n+                    {\n+                        topicId[j] = ctx.Reader.ReadInt32();\n+                        topicProb[j] = ctx.Reader.ReadInt32();\n+                    }\n \n-                NumBurninIter = ctx.Reader.ReadInt32();\n-                ectx.CheckDecode(NumBurninIter >= 0);\n+                    //set the topic into _ldaTrainer inner topic table\n+                    _ldaTrainer.SetModel(termID, topicId, topicProb, termTopicNum);\n+                }\n \n-                ResetRandomGenerator = ctx.Reader.ReadBoolByte();\n+                //do the preparation\n+                if (!_predictionPreparationDone)\n+                {\n+                    _ldaTrainer.InitializeBeforeTest();\n+                    _predictionPreparationDone = true;\n+                }\n             }\n \n             public void Save(ModelSaveContext ctx)\n             {\n                 Contracts.AssertValue(ctx);\n+                long memBlockSize = 0;\n+                long aliasMemBlockSize = 0;\n+                _ldaTrainer.GetModelStat(out memBlockSize, out aliasMemBlockSize);\n \n                 // *** Binary format ***\n-                // int NumTopic;\n-                // Single AlphaSum;\n-                // Single Beta;\n-                // int MHStep;\n-                // int NumIter;\n-                // int LikelihoodInterval;\n-                // int NumThread;\n-                // int NumMaxDocToken;\n-                // int NumSummaryTermPerTopic;\n-                // int NumBurninIter;\n-                // byte ResetRandomGenerator;\n-\n-                ctx.Writer.Write(NumTopic);\n-                ctx.Writer.Write(AlphaSum);\n-                ctx.Writer.Write(Beta);\n-                ctx.Writer.Write(MHStep);\n-                ctx.Writer.Write(NumIter);\n-                ctx.Writer.Write(LikelihoodInterval);\n-                ctx.Writer.Write(NumThread);\n-                ctx.Writer.Write(NumMaxDocToken);\n-                ctx.Writer.Write(NumSummaryTermPerTopic);\n-                ctx.Writer.Write(NumBurninIter);\n-                ctx.Writer.WriteBoolByte(ResetRandomGenerator);\n-            }\n-        }\n+                // <ColInfoEx>\n+                // int: vocabnum\n+                // long: memblocksize\n+                // long: aliasMemBlockSize\n+                // (serializing term by term, for one term)\n+                // int: term_id, int: topic_num, KeyValuePair<int, int>[]: termTopicVector\n \n-        public const string LoaderSignature = \"LdaTransform\";\n-        private static VersionInfo GetVersionInfo()\n-        {\n-            return new VersionInfo(\n-                modelSignature: \"LIGHTLDA\",\n-                verWrittenCur: 0x00010001, // Initial\n-                verReadableCur: 0x00010001,\n-                verWeCanReadBack: 0x00010001,\n-                loaderSignature: LoaderSignature,\n-                loaderAssemblyName: typeof(LdaTransform).Assembly.FullName);\n-        }\n+                InfoEx.Save(ctx);\n+                ctx.Writer.Write(_ldaTrainer.NumVocab);\n+                ctx.Writer.Write(memBlockSize);\n+                ctx.Writer.Write(aliasMemBlockSize);\n \n-        private readonly ColInfoEx[] _exes;\n-        private readonly LdaState[] _ldas;\n-        private readonly ColumnType[] _types;\n-        private readonly bool _saveText;\n+                //save model from this interface\n+                for (int i = 0; i < _ldaTrainer.NumVocab; i++)\n+                {\n+                    KeyValuePair<int, int>[] termTopicVector = _ldaTrainer.GetModel(i);\n \n-        private const string RegistrationName = \"LightLda\";\n-        private const string WordTopicModelFilename = \"word_topic_summary.txt\";\n-        internal const string Summary = \"The LDA transform implements LightLDA, a state-of-the-art implementation of Latent Dirichlet Allocation.\";\n-        internal const string UserName = \"Latent Dirichlet Allocation Transform\";\n-        internal const string ShortName = \"LightLda\";\n+                    //write the topic to disk through ctx\n+                    ctx.Writer.Write(i); //term_id\n+                    ctx.Writer.Write(termTopicVector.Length);\n \n-        public LdaTransform(IHostEnvironment env, Arguments args, IDataView input)\n-            : base(env, RegistrationName, args.Column, input, TestType)\n-        {\n-            Host.CheckValue(args, nameof(args));\n-            Host.CheckUserArg(args.NumTopic > 0, nameof(args.NumTopic), \"Must be positive.\");\n-            Host.CheckValue(input, nameof(input));\n-            Host.CheckUserArg(Utils.Size(args.Column) > 0, nameof(args.Column));\n-            _exes = new ColInfoEx[Infos.Length];\n-            _types = new ColumnType[Infos.Length];\n-            _ldas = new LdaState[Infos.Length];\n-            _saveText = args.OutputTopicWordSummary;\n-            for (int i = 0; i < Infos.Length; i++)\n-            {\n-                var ex = new ColInfoEx(Host, args.Column[i], args);\n-                _exes[i] = ex;\n-                _types[i] = new VectorType(NumberType.Float, ex.NumTopic);\n-            }\n-            using (var ch = Host.Start(\"Train\"))\n-            {\n-                Train(ch, input, _ldas);\n+                    foreach (KeyValuePair<int, int> p in termTopicVector)\n+                    {\n+                        ctx.Writer.Write(p.Key);\n+                        ctx.Writer.Write(p.Value);\n+                    }\n+                }\n             }\n-            Metadata.Seal();\n-        }\n \n-        private void Dispose(bool disposing)\n-        {\n-            if (_ldas != null)\n+            public void AllocateDataMemory(int docNum, long corpusSize)\n             {\n-                foreach (var state in _ldas)\n-                    state?.Dispose();\n+                _ldaTrainer.AllocateDataMemory(docNum, corpusSize);\n             }\n-            if (disposing)\n-                GC.SuppressFinalize(this);\n-        }\n \n-        public void Dispose()\n-        {\n-            Dispose(true);\n-        }\n+            public int FeedTrain(IExceptionContext ectx, in VBuffer<Double> input)\n+            {\n+                Contracts.AssertValue(ectx);\n \n-        ~LdaTransform()\n-        {\n-            Dispose(false);\n-        }\n+                // REVIEW: Input the counts to your trainer here. This\n+                // is called multiple times.\n \n-        private LdaTransform(IHost host, ModelLoadContext ctx, IDataView input)\n-            : base(host, ctx, input, TestType)\n-        {\n-            Host.AssertValue(ctx);\n+                int docSize = 0;\n+                int termNum = 0;\n \n-            // *** Binary format ***\n-            // <prefix handled in static Create method>\n-            // <base>\n-            // ldaState[num infos]: The LDA parameters\n+                for (int i = 0; i < input.Count; i++)\n+                {\n+                    int termFreq = GetFrequency(input.Values[i]);\n+                    if (termFreq < 0)\n+                    {\n+                        // Ignore this row.\n+                        return 0;\n+                    }\n+                    if (docSize >= InfoEx.NumMaxDocToken - termFreq)\n+                        break;\n \n-            // Note: infos.length would be just one in most cases.\n-            _exes = new ColInfoEx[Infos.Length];\n-            _ldas = new LdaState[Infos.Length];\n-            _types = new ColumnType[Infos.Length];\n-            for (int i = 0; i < _ldas.Length; i++)\n-            {\n+                    // If legal then add the term.\n+                    docSize += termFreq;\n+                    termNum++;\n+                }\n+\n+                // Ignore empty doc.\n+                if (docSize == 0)\n+                    return 0;\n+\n+                int actualSize = 0;\n+                if (input.IsDense)\n+                    actualSize = _ldaTrainer.LoadDocDense(input.Values, termNum, input.Length);\n+                else\n+                    actualSize = _ldaTrainer.LoadDoc(input.Indices, input.Values, termNum, input.Length);\n+\n+                ectx.Assert(actualSize == 2 * docSize + 1, string.Format(\"The doc size are distinct. Actual: {0}, Expected: {1}\", actualSize, 2 * docSize + 1));\n+                return actualSize;\n+            }\n+\n+            public void CompleteTrain()\n+            {\n+                //allocate all kinds of in memory sample tables\n+                _ldaTrainer.InitializeBeforeTrain();\n+\n+                //call native lda trainer to perform the multi-thread training\n+                _ldaTrainer.Train(\"\"); /* Need to pass in an empty string */\n+            }\n+\n+            public void Output(in VBuffer<Double> src, ref VBuffer<Float> dst, int numBurninIter, bool reset)\n+            {\n+                // Prediction for a single document.\n+                // LdaSingleBox.InitializeBeforeTest() is NOT thread-safe.\n+                if (!_predictionPreparationDone)\n+                {\n+                    lock (_preparationSyncRoot)\n+                    {\n+                        if (!_predictionPreparationDone)\n+                        {\n+                            //do some preparation for building tables in native c++\n+                            _ldaTrainer.InitializeBeforeTest();\n+                            _predictionPreparationDone = true;\n+                        }\n+                    }\n+                }\n+\n+                int len = InfoEx.NumTopic;\n+                var values = dst.Values;\n+                var indices = dst.Indices;\n+                if (src.Count == 0)\n+                {\n+                    dst = new VBuffer<Float>(len, 0, values, indices);\n+                    return;\n+                }\n+\n+                // Make sure all the frequencies are valid and truncate if the sum gets too large.\n+                int docSize = 0;\n+                int termNum = 0;\n+                for (int i = 0; i < src.Count; i++)\n+                {\n+                    int termFreq = GetFrequency(src.Values[i]);\n+                    if (termFreq < 0)\n+                    {\n+                        // REVIEW: Should this log a warning message? And what should it produce?\n+                        // It currently produces a vbuffer of all NA values.\n+                        // REVIEW: Need a utility method to do this...\n+                        if (Utils.Size(values) < len)\n+                            values = new Float[len];\n+                        for (int k = 0; k < len; k++)\n+                            values[k] = Float.NaN;\n+                        dst = new VBuffer<Float>(len, values, indices);\n+                        return;\n+                    }\n+\n+                    if (docSize >= InfoEx.NumMaxDocToken - termFreq)\n+                        break;\n+\n+                    docSize += termFreq;\n+                    termNum++;\n+                }\n+\n+                // REVIEW: Too much memory allocation here on each prediction.\n+                List<KeyValuePair<int, float>> retTopics;\n+                if (src.IsDense)\n+                    retTopics = _ldaTrainer.TestDocDense(src.Values, termNum, numBurninIter, reset);\n+                else\n+                    retTopics = _ldaTrainer.TestDoc(src.Indices.Take(src.Count).ToArray(), src.Values.Take(src.Count).ToArray(), termNum, numBurninIter, reset);\n+\n+                int count = retTopics.Count;\n+                Contracts.Assert(count <= len);\n+                if (Utils.Size(values) < count)\n+                    values = new Float[count];\n+                if (count < len && Utils.Size(indices) < count)\n+                    indices = new int[count];\n+\n+                double normalizer = 0;\n+                for (int i = 0; i < count; i++)\n+                {\n+                    int index = retTopics[i].Key;\n+                    Float value = retTopics[i].Value;\n+                    Contracts.Assert(value >= 0);\n+                    Contracts.Assert(0 <= index && index < len);\n+                    if (count < len)\n+                    {\n+                        Contracts.Assert(i == 0 || indices[i - 1] < index);\n+                        indices[i] = index;\n+                    }\n+                    else\n+                        Contracts.Assert(index == i);\n+\n+                    values[i] = value;\n+                    normalizer += value;\n+                }\n+\n+                if (normalizer > 0)\n+                {\n+                    for (int i = 0; i < count; i++)\n+                        values[i] = (Float)(values[i] / normalizer);\n+                }\n+                dst = new VBuffer<Float>(len, count, values, indices);\n+            }\n+\n+            public void Dispose()\n+            {\n+                _ldaTrainer.Dispose();\n+            }\n+        }\n+\n+        public sealed class TransformInfo\n+        {\n+            public readonly int NumTopic;\n+            public readonly Single AlphaSum;\n+            public readonly Single Beta;\n+            public readonly int MHStep;\n+            public readonly int NumIter;\n+            public readonly int LikelihoodInterval;\n+            public readonly int NumThread;\n+            public readonly int NumMaxDocToken;\n+            public readonly int NumSummaryTermPerTopic;\n+            public readonly int NumBurninIter;\n+            public readonly bool ResetRandomGenerator;\n+\n+            internal TransformInfo(IExceptionContext ectx, ColumnInfo column)\n+            {\n+                Contracts.AssertValue(ectx);\n+\n+                NumTopic = column.NumTopic;\n+                Contracts.CheckUserArg(NumTopic > 0, nameof(column.NumTopic), \"Must be positive.\");\n+\n+                AlphaSum = column.AlphaSum;\n+\n+                Beta = column.Beta;\n+\n+                MHStep = column.MHStep;\n+                ectx.CheckUserArg(MHStep > 0, nameof(column.MHStep), \"Must be positive.\");\n+\n+                NumIter = column.NumIter;\n+                ectx.CheckUserArg(NumIter > 0, nameof(column.NumIter), \"Must be positive.\");\n+\n+                LikelihoodInterval = column.LikelihoodInterval;\n+                ectx.CheckUserArg(LikelihoodInterval > 0, nameof(column.LikelihoodInterval), \"Must be positive.\");\n+\n+                NumThread = column.NumThread;\n+                ectx.CheckUserArg(NumThread >= 0, nameof(column.NumThread), \"Must be positive or zero.\");\n+\n+                NumMaxDocToken = column.NumMaxDocToken;\n+                ectx.CheckUserArg(NumMaxDocToken > 0, nameof(column.NumMaxDocToken), \"Must be positive.\");\n+\n+                NumSummaryTermPerTopic = column.NumSummaryTermPerTopic;\n+                ectx.CheckUserArg(NumSummaryTermPerTopic > 0, nameof(column.NumSummaryTermPerTopic), \"Must be positive\");\n+\n+                NumBurninIter = column.NumBurninIter;\n+                ectx.CheckUserArg(NumBurninIter >= 0, nameof(column.NumBurninIter), \"Must be non-negative.\");\n+\n+                ResetRandomGenerator = column.ResetRandomGenerator;\n+            }\n+\n+            internal TransformInfo(IExceptionContext ectx, ModelLoadContext ctx)\n+            {\n+                Contracts.AssertValue(ectx);\n+                ectx.AssertValue(ctx);\n+\n+                // *** Binary format ***\n+                // int NumTopic;\n+                // Single AlphaSum;\n+                // Single Beta;\n+                // int MHStep;\n+                // int NumIter;\n+                // int LikelihoodInterval;\n+                // int NumThread;\n+                // int NumMaxDocToken;\n+                // int NumSummaryTermPerTopic;\n+                // int NumBurninIter;\n+                // byte ResetRandomGenerator;\n+\n+                NumTopic = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(NumTopic > 0);\n+\n+                AlphaSum = ctx.Reader.ReadSingle();\n+\n+                Beta = ctx.Reader.ReadSingle();\n+\n+                MHStep = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(MHStep > 0);\n+\n+                NumIter = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(NumIter > 0);\n+\n+                LikelihoodInterval = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(LikelihoodInterval > 0);\n+\n+                NumThread = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(NumThread >= 0);\n+\n+                NumMaxDocToken = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(NumMaxDocToken > 0);\n+\n+                NumSummaryTermPerTopic = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(NumSummaryTermPerTopic > 0);\n+\n+                NumBurninIter = ctx.Reader.ReadInt32();\n+                ectx.CheckDecode(NumBurninIter >= 0);\n+\n+                ResetRandomGenerator = ctx.Reader.ReadBoolByte();\n+            }\n+\n+            public void Save(ModelSaveContext ctx)\n+            {\n+                Contracts.AssertValue(ctx);\n+\n+                // *** Binary format ***\n+                // int NumTopic;\n+                // Single AlphaSum;\n+                // Single Beta;\n+                // int MHStep;\n+                // int NumIter;\n+                // int LikelihoodInterval;\n+                // int NumThread;\n+                // int NumMaxDocToken;\n+                // int NumSummaryTermPerTopic;\n+                // int NumBurninIter;\n+                // byte ResetRandomGenerator;\n+\n+                ctx.Writer.Write(NumTopic);\n+                ctx.Writer.Write(AlphaSum);\n+                ctx.Writer.Write(Beta);\n+                ctx.Writer.Write(MHStep);\n+                ctx.Writer.Write(NumIter);\n+                ctx.Writer.Write(LikelihoodInterval);\n+                ctx.Writer.Write(NumThread);\n+                ctx.Writer.Write(NumMaxDocToken);\n+                ctx.Writer.Write(NumSummaryTermPerTopic);\n+                ctx.Writer.Write(NumBurninIter);\n+                ctx.Writer.WriteBoolByte(ResetRandomGenerator);\n+            }\n+        }\n+\n+        private sealed class Mapper : MapperBase\n+        {\n+            private readonly LdaTransform _parent;\n+            private readonly ColumnType[] _srcTypes;\n+            private readonly int[] _srcCols;\n+\n+            public Mapper(LdaTransform parent, Schema inputSchema)\n+                : base(parent.Host.Register(nameof(Mapper)), parent, inputSchema)\n+            {\n+                _parent = parent;\n+                _srcTypes = new ColumnType[_parent.ColumnPairs.Length];\n+                _srcCols = new int[_parent.ColumnPairs.Length];\n+\n+                for (int i = 0; i < _parent.ColumnPairs.Length; i++)\n+                {\n+                    inputSchema.TryGetColumnIndex(_parent.ColumnPairs[i].input, out _srcCols[i]);\n+                    var srcCol = inputSchema[_srcCols[i]];\n+                    _srcTypes[i] = srcCol.Type;\n+                }\n+            }\n+\n+            public override Schema.Column[] GetOutputColumns()\n+            {\n+                var result = new Schema.Column[_parent.ColumnPairs.Length];\n+                for (int i = 0; i < _parent.ColumnPairs.Length; i++)\n+                    result[i] = new Schema.Column(_parent.ColumnPairs[i].output, _parent._types[i], null);\n+                return result;\n+            }\n+\n+            protected override Delegate MakeGetter(IRow input, int iinfo, out Action disposer)\n+            {\n+                Contracts.AssertValue(input);\n+                Contracts.Assert(0 <= iinfo && iinfo < _parent.ColumnPairs.Length);\n+                disposer = null;\n+\n+                var test = TestType(_srcTypes[iinfo]);","path":"src/Microsoft.ML.Transforms/Text/LdaTransform.cs","position":780,"original_position":780,"commit_id":"ad36d2f3f7d0b357c53e15e1ac57897007904a93","original_commit_id":"ad36d2f3f7d0b357c53e15e1ac57897007904a93","user":{"login":"Ivanidzo4ka","id":1523833,"node_id":"MDQ6VXNlcjE1MjM4MzM=","avatar_url":"https://avatars3.githubusercontent.com/u/1523833?v=4","gravatar_id":"","url":"https://api.github.com/users/Ivanidzo4ka","html_url":"https://github.com/Ivanidzo4ka","followers_url":"https://api.github.com/users/Ivanidzo4ka/followers","following_url":"https://api.github.com/users/Ivanidzo4ka/following{/other_user}","gists_url":"https://api.github.com/users/Ivanidzo4ka/gists{/gist_id}","starred_url":"https://api.github.com/users/Ivanidzo4ka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ivanidzo4ka/subscriptions","organizations_url":"https://api.github.com/users/Ivanidzo4ka/orgs","repos_url":"https://api.github.com/users/Ivanidzo4ka/repos","events_url":"https://api.github.com/users/Ivanidzo4ka/events{/privacy}","received_events_url":"https://api.github.com/users/Ivanidzo4ka/received_events","type":"User","site_admin":false},"body":"It make difference at what point it will fail. I would prefer to test types in constructor.\r\n\r\n\r\n---\r\nIn reply to: [230899143](https://github.com/dotnet/machinelearning/pull/1410#discussion_r230899143) [](ancestors = 230899143)","created_at":"2018-11-09T00:05:37Z","updated_at":"2018-11-09T00:05:37Z","html_url":"https://github.com/dotnet/machinelearning/pull/1410#discussion_r232105072","pull_request_url":"https://api.github.com/repos/dotnet/machinelearning/pulls/1410","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/dotnet/machinelearning/pulls/comments/232105072"},"html":{"href":"https://github.com/dotnet/machinelearning/pull/1410#discussion_r232105072"},"pull_request":{"href":"https://api.github.com/repos/dotnet/machinelearning/pulls/1410"}},"in_reply_to_id":230899143},"pull_request":{"url":"https://api.github.com/repos/dotnet/machinelearning/pulls/1410","id":226266765,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI2MjY2NzY1","html_url":"https://github.com/dotnet/machinelearning/pull/1410","diff_url":"https://github.com/dotnet/machinelearning/pull/1410.diff","patch_url":"https://github.com/dotnet/machinelearning/pull/1410.patch","issue_url":"https://api.github.com/repos/dotnet/machinelearning/issues/1410","number":1410,"state":"open","locked":false,"title":"Convert LdaTransform to IEstimator/ITransformer API","user":{"login":"abgoswam","id":8822956,"node_id":"MDQ6VXNlcjg4MjI5NTY=","avatar_url":"https://avatars1.githubusercontent.com/u/8822956?v=4","gravatar_id":"","url":"https://api.github.com/users/abgoswam","html_url":"https://github.com/abgoswam","followers_url":"https://api.github.com/users/abgoswam/followers","following_url":"https://api.github.com/users/abgoswam/following{/other_user}","gists_url":"https://api.github.com/users/abgoswam/gists{/gist_id}","starred_url":"https://api.github.com/users/abgoswam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abgoswam/subscriptions","organizations_url":"https://api.github.com/users/abgoswam/orgs","repos_url":"https://api.github.com/users/abgoswam/repos","events_url":"https://api.github.com/users/abgoswam/events{/privacy}","received_events_url":"https://api.github.com/users/abgoswam/received_events","type":"User","site_admin":false},"body":"This PR converts LdaTransform to the IEstimator/ITransformer API paradigm (a work item related to #754)\r\n\r\n- LdaTransform is now subclass of OneToOneTransformerBase\r\n- Deleted the previous wrapped version.\r\n- Added pigsty extensions\r\n- Added onFit delegate to return LdaState info to user\r\n\r\nCreated separate issue #1411  for providing a convenient way of providing LDA topic summary info to the user","created_at":"2018-10-27T03:44:13Z","updated_at":"2018-11-09T00:05:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"67c57be4fda2495d9131141eb3e8580cdcd0cda0","assignee":null,"assignees":[],"requested_reviewers":[{"login":"singlis","id":17055319,"node_id":"MDQ6VXNlcjE3MDU1MzE5","avatar_url":"https://avatars2.githubusercontent.com/u/17055319?v=4","gravatar_id":"","url":"https://api.github.com/users/singlis","html_url":"https://github.com/singlis","followers_url":"https://api.github.com/users/singlis/followers","following_url":"https://api.github.com/users/singlis/following{/other_user}","gists_url":"https://api.github.com/users/singlis/gists{/gist_id}","starred_url":"https://api.github.com/users/singlis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/singlis/subscriptions","organizations_url":"https://api.github.com/users/singlis/orgs","repos_url":"https://api.github.com/users/singlis/repos","events_url":"https://api.github.com/users/singlis/events{/privacy}","received_events_url":"https://api.github.com/users/singlis/received_events","type":"User","site_admin":false},{"login":"sfilipi","id":19392467,"node_id":"MDQ6VXNlcjE5MzkyNDY3","avatar_url":"https://avatars1.githubusercontent.com/u/19392467?v=4","gravatar_id":"","url":"https://api.github.com/users/sfilipi","html_url":"https://github.com/sfilipi","followers_url":"https://api.github.com/users/sfilipi/followers","following_url":"https://api.github.com/users/sfilipi/following{/other_user}","gists_url":"https://api.github.com/users/sfilipi/gists{/gist_id}","starred_url":"https://api.github.com/users/sfilipi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sfilipi/subscriptions","organizations_url":"https://api.github.com/users/sfilipi/orgs","repos_url":"https://api.github.com/users/sfilipi/repos","events_url":"https://api.github.com/users/sfilipi/events{/privacy}","received_events_url":"https://api.github.com/users/sfilipi/received_events","type":"User","site_admin":false},{"login":"Zruty0","id":41337831,"node_id":"MDQ6VXNlcjQxMzM3ODMx","avatar_url":"https://avatars1.githubusercontent.com/u/41337831?v=4","gravatar_id":"","url":"https://api.github.com/users/Zruty0","html_url":"https://github.com/Zruty0","followers_url":"https://api.github.com/users/Zruty0/followers","following_url":"https://api.github.com/users/Zruty0/following{/other_user}","gists_url":"https://api.github.com/users/Zruty0/gists{/gist_id}","starred_url":"https://api.github.com/users/Zruty0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Zruty0/subscriptions","organizations_url":"https://api.github.com/users/Zruty0/orgs","repos_url":"https://api.github.com/users/Zruty0/repos","events_url":"https://api.github.com/users/Zruty0/events{/privacy}","received_events_url":"https://api.github.com/users/Zruty0/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/machinelearning/pulls/1410/commits","review_comments_url":"https://api.github.com/repos/dotnet/machinelearning/pulls/1410/comments","review_comment_url":"https://api.github.com/repos/dotnet/machinelearning/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dotnet/machinelearning/issues/1410/comments","statuses_url":"https://api.github.com/repos/dotnet/machinelearning/statuses/ad36d2f3f7d0b357c53e15e1ac57897007904a93","head":{"label":"abgoswam:abgoswam/LDA_conversion","ref":"abgoswam/LDA_conversion","sha":"ad36d2f3f7d0b357c53e15e1ac57897007904a93","user":{"login":"abgoswam","id":8822956,"node_id":"MDQ6VXNlcjg4MjI5NTY=","avatar_url":"https://avatars1.githubusercontent.com/u/8822956?v=4","gravatar_id":"","url":"https://api.github.com/users/abgoswam","html_url":"https://github.com/abgoswam","followers_url":"https://api.github.com/users/abgoswam/followers","following_url":"https://api.github.com/users/abgoswam/following{/other_user}","gists_url":"https://api.github.com/users/abgoswam/gists{/gist_id}","starred_url":"https://api.github.com/users/abgoswam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abgoswam/subscriptions","organizations_url":"https://api.github.com/users/abgoswam/orgs","repos_url":"https://api.github.com/users/abgoswam/repos","events_url":"https://api.github.com/users/abgoswam/events{/privacy}","received_events_url":"https://api.github.com/users/abgoswam/received_events","type":"User","site_admin":false},"repo":{"id":146918126,"node_id":"MDEwOlJlcG9zaXRvcnkxNDY5MTgxMjY=","name":"machinelearning","full_name":"abgoswam/machinelearning","private":false,"owner":{"login":"abgoswam","id":8822956,"node_id":"MDQ6VXNlcjg4MjI5NTY=","avatar_url":"https://avatars1.githubusercontent.com/u/8822956?v=4","gravatar_id":"","url":"https://api.github.com/users/abgoswam","html_url":"https://github.com/abgoswam","followers_url":"https://api.github.com/users/abgoswam/followers","following_url":"https://api.github.com/users/abgoswam/following{/other_user}","gists_url":"https://api.github.com/users/abgoswam/gists{/gist_id}","starred_url":"https://api.github.com/users/abgoswam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abgoswam/subscriptions","organizations_url":"https://api.github.com/users/abgoswam/orgs","repos_url":"https://api.github.com/users/abgoswam/repos","events_url":"https://api.github.com/users/abgoswam/events{/privacy}","received_events_url":"https://api.github.com/users/abgoswam/received_events","type":"User","site_admin":false},"html_url":"https://github.com/abgoswam/machinelearning","description":"ML.NET is an open source and cross-platform machine learning framework for .NET.","fork":true,"url":"https://api.github.com/repos/abgoswam/machinelearning","forks_url":"https://api.github.com/repos/abgoswam/machinelearning/forks","keys_url":"https://api.github.com/repos/abgoswam/machinelearning/keys{/key_id}","collaborators_url":"https://api.github.com/repos/abgoswam/machinelearning/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/abgoswam/machinelearning/teams","hooks_url":"https://api.github.com/repos/abgoswam/machinelearning/hooks","issue_events_url":"https://api.github.com/repos/abgoswam/machinelearning/issues/events{/number}","events_url":"https://api.github.com/repos/abgoswam/machinelearning/events","assignees_url":"https://api.github.com/repos/abgoswam/machinelearning/assignees{/user}","branches_url":"https://api.github.com/repos/abgoswam/machinelearning/branches{/branch}","tags_url":"https://api.github.com/repos/abgoswam/machinelearning/tags","blobs_url":"https://api.github.com/repos/abgoswam/machinelearning/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/abgoswam/machinelearning/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/abgoswam/machinelearning/git/refs{/sha}","trees_url":"https://api.github.com/repos/abgoswam/machinelearning/git/trees{/sha}","statuses_url":"https://api.github.com/repos/abgoswam/machinelearning/statuses/{sha}","languages_url":"https://api.github.com/repos/abgoswam/machinelearning/languages","stargazers_url":"https://api.github.com/repos/abgoswam/machinelearning/stargazers","contributors_url":"https://api.github.com/repos/abgoswam/machinelearning/contributors","subscribers_url":"https://api.github.com/repos/abgoswam/machinelearning/subscribers","subscription_url":"https://api.github.com/repos/abgoswam/machinelearning/subscription","commits_url":"https://api.github.com/repos/abgoswam/machinelearning/commits{/sha}","git_commits_url":"https://api.github.com/repos/abgoswam/machinelearning/git/commits{/sha}","comments_url":"https://api.github.com/repos/abgoswam/machinelearning/comments{/number}","issue_comment_url":"https://api.github.com/repos/abgoswam/machinelearning/issues/comments{/number}","contents_url":"https://api.github.com/repos/abgoswam/machinelearning/contents/{+path}","compare_url":"https://api.github.com/repos/abgoswam/machinelearning/compare/{base}...{head}","merges_url":"https://api.github.com/repos/abgoswam/machinelearning/merges","archive_url":"https://api.github.com/repos/abgoswam/machinelearning/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/abgoswam/machinelearning/downloads","issues_url":"https://api.github.com/repos/abgoswam/machinelearning/issues{/number}","pulls_url":"https://api.github.com/repos/abgoswam/machinelearning/pulls{/number}","milestones_url":"https://api.github.com/repos/abgoswam/machinelearning/milestones{/number}","notifications_url":"https://api.github.com/repos/abgoswam/machinelearning/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/abgoswam/machinelearning/labels{/name}","releases_url":"https://api.github.com/repos/abgoswam/machinelearning/releases{/id}","deployments_url":"https://api.github.com/repos/abgoswam/machinelearning/deployments","created_at":"2018-08-31T16:39:20Z","updated_at":"2018-11-07T21:52:45Z","pushed_at":"2018-11-08T02:57:18Z","git_url":"git://github.com/abgoswam/machinelearning.git","ssh_url":"git@github.com:abgoswam/machinelearning.git","clone_url":"https://github.com/abgoswam/machinelearning.git","svn_url":"https://github.com/abgoswam/machinelearning","homepage":"https://dot.net/ml","size":27124,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dotnet:master","ref":"master","sha":"7fb76b026d0035d6da4d0b46bd3f2a6e3c0ce3f1","user":{"login":"dotnet","id":9141961,"node_id":"MDEyOk9yZ2FuaXphdGlvbjkxNDE5NjE=","avatar_url":"https://avatars0.githubusercontent.com/u/9141961?v=4","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":132021166,"node_id":"MDEwOlJlcG9zaXRvcnkxMzIwMjExNjY=","name":"machinelearning","full_name":"dotnet/machinelearning","private":false,"owner":{"login":"dotnet","id":9141961,"node_id":"MDEyOk9yZ2FuaXphdGlvbjkxNDE5NjE=","avatar_url":"https://avatars0.githubusercontent.com/u/9141961?v=4","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/dotnet/machinelearning","description":"ML.NET is an open source and cross-platform machine learning framework for .NET.","fork":false,"url":"https://api.github.com/repos/dotnet/machinelearning","forks_url":"https://api.github.com/repos/dotnet/machinelearning/forks","keys_url":"https://api.github.com/repos/dotnet/machinelearning/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/machinelearning/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/machinelearning/teams","hooks_url":"https://api.github.com/repos/dotnet/machinelearning/hooks","issue_events_url":"https://api.github.com/repos/dotnet/machinelearning/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/machinelearning/events","assignees_url":"https://api.github.com/repos/dotnet/machinelearning/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/machinelearning/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/machinelearning/tags","blobs_url":"https://api.github.com/repos/dotnet/machinelearning/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/machinelearning/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/machinelearning/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/machinelearning/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/machinelearning/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/machinelearning/languages","stargazers_url":"https://api.github.com/repos/dotnet/machinelearning/stargazers","contributors_url":"https://api.github.com/repos/dotnet/machinelearning/contributors","subscribers_url":"https://api.github.com/repos/dotnet/machinelearning/subscribers","subscription_url":"https://api.github.com/repos/dotnet/machinelearning/subscription","commits_url":"https://api.github.com/repos/dotnet/machinelearning/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/machinelearning/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/machinelearning/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/machinelearning/issues/comments{/number}","contents_url":"https://api.github.com/repos/dotnet/machinelearning/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/machinelearning/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/machinelearning/merges","archive_url":"https://api.github.com/repos/dotnet/machinelearning/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/machinelearning/downloads","issues_url":"https://api.github.com/repos/dotnet/machinelearning/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/machinelearning/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/machinelearning/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/machinelearning/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/machinelearning/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/machinelearning/releases{/id}","deployments_url":"https://api.github.com/repos/dotnet/machinelearning/deployments","created_at":"2018-05-03T16:20:42Z","updated_at":"2018-11-08T23:10:39Z","pushed_at":"2018-11-08T23:50:28Z","git_url":"git://github.com/dotnet/machinelearning.git","ssh_url":"git@github.com:dotnet/machinelearning.git","clone_url":"https://github.com/dotnet/machinelearning.git","svn_url":"https://github.com/dotnet/machinelearning","homepage":"https://dot.net/ml","size":27284,"stargazers_count":4081,"watchers_count":4081,"language":"C#","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":763,"mirror_url":null,"archived":false,"open_issues_count":362,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":763,"open_issues":362,"watchers":4081,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/machinelearning/pulls/1410"},"html":{"href":"https://github.com/dotnet/machinelearning/pull/1410"},"issue":{"href":"https://api.github.com/repos/dotnet/machinelearning/issues/1410"},"comments":{"href":"https://api.github.com/repos/dotnet/machinelearning/issues/1410/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/machinelearning/pulls/1410/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/machinelearning/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dotnet/machinelearning/pulls/1410/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/machinelearning/statuses/ad36d2f3f7d0b357c53e15e1ac57897007904a93"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"Ivanidzo4ka"}}