Beispiel #1
0
        private static void UpdateExpectationMatrixPass1(object _args)
        {
            object[] args = (object[])_args;
            SparseMatrix <double> .ReadOnly            trainMtxTr = (SparseMatrix <double> .ReadOnly)args[0];
            IdxDat <SparseVector <double> .ReadOnly>[] rows       = (IdxDat <SparseVector <double> .ReadOnly>[])args[1];
            double[][] mtx      = (double[][])args[2];
            Ref <int>  progress = (Ref <int>)args[3];
            Ref <int>  idx      = (Ref <int>)args[4];
            int        i;

            lock (idx) { i = idx.Val; idx.Val++; }
            while (i < rows.Length)
            {
                IdxDat <SparseVector <double> .ReadOnly> row = rows[i];
                foreach (IdxDat <double> item in row.Dat)
                {
                    if (trainMtxTr.ContainsRowAt(item.Idx))
                    {
                        SparseVector <double> .ReadOnly trainMtxRow = trainMtxTr[item.Idx];
                        foreach (IdxDat <double> trainMtxItem in trainMtxRow)
                        {
                            mtx[row.Idx][trainMtxItem.Idx] += trainMtxItem.Dat * item.Dat;
                        }
                    }
                }
                progress.Val++;
                lock (idx) { i = idx.Val; idx.Val++; }
            }
        }
Beispiel #2
0
        private static void UpdateExpectationMatrixPass2(object _args)
        {
            object[] args = (object[])_args;
            SparseMatrix <double> .ReadOnly   trainMtxTr = (SparseMatrix <double> .ReadOnly)args[0];
            IdxDat <SparseVector <double> >[] rows       = (IdxDat <SparseVector <double> >[])args[1];
            double[][] mtx      = (double[][])args[2];
            double[]   z        = (double[])args[3];
            Ref <int>  progress = (Ref <int>)args[4];
            Ref <int>  idx      = (Ref <int>)args[5];
            int        i;

            lock (idx) { i = idx.Val; idx.Val++; }
            while (i < rows.Length)
            {
                IdxDat <SparseVector <double> > row = rows[i];
                int itemIdx = 0;
                foreach (IdxDat <double> item in row.Dat)
                {
                    SparseVector <double> .ReadOnly pom = trainMtxTr[item.Idx];
                    foreach (IdxDat <double> pomItem in pom)
                    {
                        row.Dat.SetDirect(itemIdx, row.Dat.GetDatDirect(itemIdx) + mtx[row.Idx][pomItem.Idx] / z[pomItem.Idx] * pomItem.Dat);
                    }
                    itemIdx++;
                }
                progress.Val++;
                lock (idx) { i = idx.Val; idx.Val++; }
            }
        }
Beispiel #3
0
        private static void UpdateExpectationMatrixPass1(object _args)
        {
            object[] args     = (object[])_args;
            int      startIdx = (int)args[0];
            int      endIdx   = (int)args[1];

            SparseMatrix <double> .ReadOnly            trainMtxTr = (SparseMatrix <double> .ReadOnly)args[2];
            IdxDat <SparseVector <double> .ReadOnly>[] rows       = (IdxDat <SparseVector <double> .ReadOnly>[])args[3];
            double[][] mtx      = (double[][])args[4];
            Ref <int>  progress = (Ref <int>)args[5];

            for (int i = startIdx; i <= endIdx; i++)
            {
                IdxDat <SparseVector <double> .ReadOnly> row = rows[i];
                foreach (IdxDat <double> item in row.Dat)
                {
                    if (trainMtxTr.ContainsRowAt(item.Idx))
                    {
                        SparseVector <double> .ReadOnly trainMtxRow = trainMtxTr[item.Idx];
                        foreach (IdxDat <double> trainMtxItem in trainMtxRow)
                        {
                            mtx[row.Idx][trainMtxItem.Idx] += trainMtxItem.Dat * item.Dat;
                        }
                    }
                }
                progress.Val++;
            }
        }
Beispiel #4
0
        private static void UpdateExpectationMatrixPass2(object _args)
        {
            object[] args      = (object[])_args;
            int      start_idx = (int)args[0];
            int      end_idx   = (int)args[1];

            SparseMatrix <double> .ReadOnly   train_mtx_tr = (SparseMatrix <double> .ReadOnly)args[2];
            IdxDat <SparseVector <double> >[] rows         = (IdxDat <SparseVector <double> >[])args[3];
            double[][] mtx      = (double[][])args[4];
            double[]   z        = (double[])args[5];
            RefInt     progress = (RefInt)args[6];

            for (int i = start_idx; i <= end_idx; i++)
            {
                IdxDat <SparseVector <double> > row = rows[i];
                int item_idx = 0;
                foreach (IdxDat <double> item in row.Dat)
                {
                    SparseVector <double> .ReadOnly pom = train_mtx_tr[item.Idx];
                    foreach (IdxDat <double> pom_item in pom)
                    {
                        row.Dat.SetDirect(item_idx, row.Dat.GetDatDirect(item_idx) + mtx[row.Idx][pom_item.Idx] / z[pom_item.Idx] * pom_item.Dat);
                    }
                    item_idx++;
                }
                progress.Val++;
            }
        }
Beispiel #5
0
 private static void GetDotProductSimilarity(SparseVector <double> .ReadOnly vec, double[] simVec, SparseMatrix <double> .ReadOnly trMtx, int startIdx)
 {
     foreach (IdxDat <double> item in vec)
     {
         SparseVector <double> .ReadOnly col = trMtx[item.Idx];
         if (col != null)
         {
             int startIdxDirect = col.GetDirectIdx(startIdx);
             if (startIdxDirect < 0)
             {
                 startIdxDirect = ~startIdxDirect;
             }
             for (int i = startIdxDirect; i < col.Count; i++)
             {
                 IdxDat <double> trMtxItem = col.GetDirect(i);
                 simVec[trMtxItem.Idx] += item.Dat * trMtxItem.Dat;
             }
         }
     }
 }
Beispiel #6
0
        private static void UpdateExpectationMatrix(int numClasses, int trainSetSize, SparseMatrix <double> .ReadOnly trainMtxTr, SparseMatrix <double> .ReadOnly lambda, SparseMatrix <double> expectations, int numThreads, Logger logger)
        {
            double[][] mtx = new double[numClasses][];
            for (int j = 0; j < numClasses; j++)
            {
                mtx[j] = new double[trainSetSize];
            }
            double[] z = new double[trainSetSize];
            logger.Info("UpdateExpectationMatrix", "Initiating {0} threads ...", numThreads);
            int lambdaRowCount = lambda.GetRowCount();

            IdxDat <SparseVector <double> .ReadOnly>[] aux = new IdxDat <SparseVector <double> .ReadOnly> [lambdaRowCount];
            int i = 0;

            foreach (IdxDat <SparseVector <double> .ReadOnly> row in lambda)
            {
                aux[i++] = row;
            }
            Thread[]    threads      = new Thread[numThreads];
            Ref <int>[] progressInfo = new Ref <int> [numThreads];
            Ref <int>   idx          = 0;

            for (i = 0; i < numThreads; i++)
            {
                progressInfo[i] = new Ref <int>();
                threads[i]      = new Thread(new ParameterizedThreadStart(UpdateExpectationMatrixPass1));
                threads[i].Start(new object[] { trainMtxTr, aux, mtx, progressInfo[i], idx });
            }
            while (true)
            {
                int aggrProgress = 0;
                foreach (Ref <int> progress in progressInfo)
                {
                    aggrProgress += progress;
                }
                logger.ProgressNormal(Logger.Level.Info, "UpdateExpectationMatrix", "Pass 1: {0} / {1}", aggrProgress, lambdaRowCount);
                if (aggrProgress == lambdaRowCount)
                {
                    break;
                }
                Thread.Sleep(1);
            }
            for (i = 0; i < numClasses; i++)
            {
                for (int j = 0; j < trainSetSize; j++)
                {
                    mtx[i][j] = Math.Exp(mtx[i][j]);
                    z[j]     += mtx[i][j];
                }
            }
            int expeRowCount = expectations.GetRowCount();

            IdxDat <SparseVector <double> >[] aux2 = new IdxDat <SparseVector <double> > [expeRowCount];
            i = 0;
            foreach (IdxDat <SparseVector <double> > row in expectations)
            {
                aux2[i++] = row;
            }
            idx.Val = 0;
            for (i = 0; i < numThreads; i++)
            {
                progressInfo[i] = 0;
                threads[i]      = new Thread(new ParameterizedThreadStart(UpdateExpectationMatrixPass2));
                threads[i].Start(new object[] { trainMtxTr, aux2, mtx, z, progressInfo[i], idx });
            }
            while (true)
            {
                int aggrProgress = 0;
                foreach (Ref <int> progress in progressInfo)
                {
                    aggrProgress += progress;
                }
                logger.ProgressNormal(Logger.Level.Info, "UpdateExpectationMatrix", "Pass 2: {0} / {1}", aggrProgress, expeRowCount);
                if (aggrProgress == expeRowCount)
                {
                    break;
                }
                Thread.Sleep(1);
            }
        }
Beispiel #7
0
 public int Compare(IdxDat <Vector2D> x, IdxDat <Vector2D> y)
 {
     return(x.Dat.Y.CompareTo(y.Dat.Y));
 }
        public override void Run(object[] args)
        {
            // *** ArrayList ***
            Output.WriteLine("*** ArrayList ***");
            Output.WriteLine();
            // create an ArrayList
            Output.WriteLine("Create an ArrayList ...");
            ArrayList <int> list = new ArrayList <int>(new int[] { 1, 2, 3 });

            Output.WriteLine(list);
            // add more items
            Output.WriteLine("Add more items ...");
            list.AddRange(new int[] { 6, 5, 4 });
            Output.WriteLine(list);
            // sort descendingly
            Output.WriteLine("Sort descendingly ...");
            list.Sort(DescSort <int> .Instance);
            Output.WriteLine(list);
            // shuffle
            Output.WriteLine("Shuffle ...");
            list.Shuffle(new Random(1));
            Output.WriteLine(list);
            // convert to array of double
            Output.WriteLine("Convert to array of double ...");
            double[] array = list.ToArray <double>();
            Output.WriteLine(new ArrayList <double>(array));
            // convert to ArrayList of string
            Output.WriteLine("Convert to ArrayList of string ...");
            ArrayList <string> list2 = new ArrayList <string>(list.ToArray <string>());

            Output.WriteLine(list2);
            // get items
            Output.WriteLine("Get items ...");
            Output.WriteLine(list[0]);
            Output.WriteLine(list[1]);
            // set items
            Output.WriteLine("Set items ...");
            list[0] = 3;
            list[1] = 2;
            Output.WriteLine(list);
            // get length
            Output.WriteLine("Get length ...");
            Output.WriteLine(list.Count);
            Output.WriteLine();

            // *** Set ***
            Output.WriteLine("*** Set ***");
            Output.WriteLine();
            // create Set
            Output.WriteLine("Create Set ...");
            Set <int> set = new Set <int>(new int[] { 1, 2, 3 });

            Output.WriteLine(set);
            // check for items
            Output.WriteLine("Check for items ...");
            Output.WriteLine(set.Contains(1));
            Output.WriteLine(set.Contains(4));
            // add more items (note the duplicate)
            Output.WriteLine("Add more items ...");
            set.AddRange(new int[] { 6, 5, 4, 3 });
            Output.WriteLine(set);
            // remove some items
            Output.WriteLine("Remove some items ...");
            set.RemoveRange(new int[] { 1, 3 });
            set.Remove(5);
            Output.WriteLine(set);
            // create another Set
            Output.WriteLine("Create another Set ...");
            Set <int> set2 = new Set <int>(new int[] { 1, 2, 3, 4, 5 });

            Output.WriteLine(set2);
            // compute union
            Output.WriteLine("Compute union ...");
            Output.WriteLine(Set <int> .Union(set, set2));
            // compute difference
            Output.WriteLine("Compute difference ...");
            Output.WriteLine(Set <int> .Difference(set, set2));
            // compute intersection
            Output.WriteLine("Compute intersection ...");
            Output.WriteLine(Set <int> .Intersection(set, set2));
            // compute Jaccard similarity
            Output.WriteLine("Compute Jaccard similarity ...");
            Output.WriteLine(Set <int> .JaccardSimilarity(set, set2));
            // convert to array
            Output.WriteLine("Convert to array ...");
            int[] array2 = set2.ToArray();
            Output.WriteLine(new ArrayList <int>(array2));
            // convert to Set of string
            Output.WriteLine("Convert to Set of string ...");
            Set <string> set3 = new Set <string>(set2.ToArray <string>());

            Output.WriteLine(set3);
            // get length
            Output.WriteLine("Get length ...");
            Output.WriteLine(set3.Count);
            Output.WriteLine();

            /*
             * // *** BinaryVector ***
             * Output.WriteLine("*** BinaryVector ***");
             * Output.WriteLine();
             * // create BinaryVector
             * Output.WriteLine("Create BinaryVector ...");
             * BinaryVector<char> binVec = new BinaryVector<char>(new char[] { 'a', 'b', 'c' });
             * Output.WriteLine((object) binVec);
             * // check for items
             * Output.WriteLine("Check for items ...");
             * Output.WriteLine((bool) binVec.Contains('a'));
             * Output.WriteLine((bool) binVec.Contains('d'));
             * // add more items (note the duplicate)
             * Output.WriteLine("Add more items ...");
             * binVec.AddRange(new char[] { 'f', 'e', 'd', 'c' });
             * Output.WriteLine((object) binVec);
             * // remove some items
             * Output.WriteLine("Remove some items ...");
             * binVec.RemoveRange(new char[] { 'a', 'c' });
             * binVec.Remove('e');
             * Output.WriteLine((object) binVec);
             * // convert to array
             * Output.WriteLine("Convert to array ...");
             * char[] array3 = binVec.ToArray();
             * Output.WriteLine(new ArrayList<char>(array3));
             * // convert to BinaryVector of string
             * Output.WriteLine("Convert to BinaryVector of string ...");
             * BinaryVector<string> binVec2 = new BinaryVector<string>(binVec.ToArray<string>());
             * Output.WriteLine((object) binVec2);
             * // get items
             * Output.WriteLine("Get items ...");
             * Output.WriteLine((int) binVec2[0]);
             * Output.WriteLine((int) binVec2[1]);
             * // get length
             * Output.WriteLine("Get length ...");
             * Output.WriteLine((int) binVec2.Count);
             * Output.WriteLine();
             */

            // *** Pair ***
            Output.WriteLine("*** Pair ***");
            Output.WriteLine();
            // create Pair
            Output.WriteLine("Create Pair ...");
            Pair <int, string> pair = new Pair <int, string>(3, "dogs");

            Output.WriteLine(pair);
            // create another Pair
            Output.WriteLine("Create another Pair ...");
            Pair <int, string> pair2 = new Pair <int, string>(3, "cats");

            Output.WriteLine(pair2);
            // compare
            Output.WriteLine("Compare ...");
            Output.WriteLine(pair == pair2);
            // make a change
            Output.WriteLine("Make a change ...");
            pair.Second = "cats";
            Output.WriteLine(pair);
            // compare again
            Output.WriteLine("Compare again ...");
            Output.WriteLine(pair == pair2);
            Output.WriteLine();

            // *** KeyDat ***
            Output.WriteLine("*** KeyDat ***");
            Output.WriteLine();
            // create KeyDat
            Output.WriteLine("Create KeyDat ...");
            KeyDat <int, string> keyDat = new KeyDat <int, string>(3, "dogs");

            Output.WriteLine(keyDat);
            // create another KeyDat
            Output.WriteLine("Create another KeyDat ...");
            KeyDat <int, string> keyDat2 = new KeyDat <int, string>(3, "cats");

            Output.WriteLine(keyDat2);
            // compare
            Output.WriteLine("Compare ...");
            Output.WriteLine(keyDat == keyDat2);
            // make a change
            Output.WriteLine("Make a change ...");
            keyDat.Key = 4;
            Output.WriteLine(keyDat);
            // compare again
            Output.WriteLine("Compare again ...");
            Output.WriteLine(keyDat == keyDat2);
            Output.WriteLine(keyDat > keyDat2);
            Output.WriteLine();

            // *** IdxDat ***
            Output.WriteLine("*** IdxDat ***");
            Output.WriteLine();
            // create an IdxDat
            Output.WriteLine("Create an IdxDat ...");
            IdxDat <string> idxDat = new IdxDat <string>(3, "dogs");

            Output.WriteLine(idxDat);
            // create another IdxDat
            Output.WriteLine("Create another IdxDat ...");
            IdxDat <string> idxDat2 = new IdxDat <string>(4, "cats");

            Output.WriteLine(idxDat2);
            // compare
            Output.WriteLine("Compare ...");
            Output.WriteLine(idxDat == idxDat2);
            // make a change
            //idxDat.Idx = 4; // not possible to change index
            idxDat.Dat = "cats";
            Output.WriteLine(idxDat);
            // compare again
            Output.WriteLine("Compare again ...");
            Output.WriteLine(idxDat == idxDat2);
            Output.WriteLine(idxDat < idxDat2);
            Output.WriteLine();

            // *** ArrayList of KeyDat ***
            Output.WriteLine("*** ArrayList of KeyDat ***");
            Output.WriteLine();
            // create an ArrayList of KeyDat
            Output.WriteLine("Create an ArrayList of KeyDat ...");
            ArrayList <KeyDat <double, string> > listKeyDat = new ArrayList <KeyDat <double, string> >(new KeyDat <double, string>[] {
                new KeyDat <double, string>(2.4, "cats"),
                new KeyDat <double, string>(3.3, "dogs"),
                new KeyDat <double, string>(4.2, "lizards")
            });

            Output.WriteLine(listKeyDat);
            // sort descendingly
            Output.WriteLine("Sort descendingly ...");
            listKeyDat.Sort(DescSort <KeyDat <double, string> > .Instance);
            Output.WriteLine(listKeyDat);
            // find item with bisection
            Output.WriteLine("Find item with bisection ...");
            int idx = listKeyDat.BinarySearch(new KeyDat <double, string>(3.3), DescSort <KeyDat <double, string> > .Instance);

            Output.WriteLine(idx);
            idx = listKeyDat.BinarySearch(new KeyDat <double, string>(3), DescSort <KeyDat <double, string> > .Instance);
            Output.WriteLine(~idx);
            // remove item
            Output.WriteLine("Remove item ...");
            listKeyDat.Remove(new KeyDat <double, string>(3.3));
            Output.WriteLine(listKeyDat);
            // get first and last item
            Output.WriteLine("Get first and last item ...");
            Output.WriteLine(listKeyDat.First);
            Output.WriteLine(listKeyDat.Last);
        }
Beispiel #9
0
        private static void UpdateExpectationMatrix(int numClasses, int trainSetSize, SparseMatrix <double> .ReadOnly trainMtxTr, SparseMatrix <double> .ReadOnly lambda, SparseMatrix <double> expectations, int numThreads)
        {
            double[][] mtx = new double[numClasses][];
            for (int j = 0; j < numClasses; j++)
            {
                mtx[j] = new double[trainSetSize];
            }
            double[] z = new double[trainSetSize];
            mLogger.Info("UpdateExpectationMatrix", "Initiating {0} threads ...", numThreads);
            int lambdaRowCount = lambda.GetRowCount();

            IdxDat <SparseVector <double> .ReadOnly>[] aux = new IdxDat <SparseVector <double> .ReadOnly> [lambdaRowCount];
            int i = 0;

            foreach (IdxDat <SparseVector <double> .ReadOnly> row in lambda)
            {
                aux[i++] = row;
            }
            int chunkSz = (int)Math.Round((double)lambdaRowCount / (double)numThreads); // *** this load balancing is not so good; should I count values instead of rows?

            Thread[]    threads      = new Thread[numThreads];
            Ref <int>[] progressInfo = new Ref <int> [numThreads];
            int         startIdx     = 0;

            for (i = 0; i < numThreads; i++)
            {
                int endIdx = startIdx + chunkSz - 1;
                if (i == numThreads - 1)
                {
                    endIdx = aux.Length - 1;
                }
                progressInfo[i] = new Ref <int>();
                threads[i]      = new Thread(new ParameterizedThreadStart(UpdateExpectationMatrixPass1));
                threads[i].Start(new object[] { startIdx, endIdx, trainMtxTr, aux, mtx, progressInfo[i] });
                startIdx += chunkSz;
            }
            object id           = new object();
            bool   isAlive      = true;
            int    aggrProgress = 0;

            while (isAlive)
            {
                aggrProgress = 0;
                foreach (Ref <int> progress in progressInfo)
                {
                    aggrProgress += progress;
                }
                mLogger.ProgressNormal(id, "UpdateExpectationMatrix", "Pass 1: {0} / {1}", aggrProgress, lambdaRowCount);
                isAlive = false;
                foreach (Thread thread in threads)
                {
                    isAlive = isAlive || thread.IsAlive;
                }
                Thread.Sleep(100);
            }
            if (aggrProgress != lambdaRowCount)
            {
                mLogger.ProgressNormal(id, "UpdateExpectationMatrix", "Pass 1: {0} / {0}", lambdaRowCount, lambdaRowCount);
            }
            for (i = 0; i < numClasses; i++)
            {
                for (int j = 0; j < trainSetSize; j++)
                {
                    mtx[i][j] = Math.Exp(mtx[i][j]);
                    z[j]     += mtx[i][j];
                }
            }
            int expeRowCount = expectations.GetRowCount();

            IdxDat <SparseVector <double> >[] aux2 = new IdxDat <SparseVector <double> > [expeRowCount];
            i = 0;
            foreach (IdxDat <SparseVector <double> > row in expectations)
            {
                aux2[i++] = row;
            }
            startIdx = 0;
            for (i = 0; i < numThreads; i++)
            {
                int endIdx = startIdx + chunkSz - 1;
                if (i == numThreads - 1)
                {
                    endIdx = aux.Length - 1;
                }
                progressInfo[i] = 0;
                threads[i]      = new Thread(new ParameterizedThreadStart(UpdateExpectationMatrixPass2));
                threads[i].Start(new object[] { startIdx, endIdx, trainMtxTr, aux2, mtx, z, progressInfo[i] });
                startIdx += chunkSz;
            }
            isAlive = true;
            while (isAlive)
            {
                aggrProgress = 0;
                foreach (Ref <int> progress in progressInfo)
                {
                    aggrProgress += progress;
                }
                mLogger.ProgressNormal(id, "UpdateExpectationMatrix", "Pass 2: {0} / {1}", aggrProgress, expeRowCount);
                isAlive = false;
                foreach (Thread thread in threads)
                {
                    isAlive = isAlive || thread.IsAlive;
                }
                Thread.Sleep(100);
            }
            if (aggrProgress != expeRowCount)
            {
                mLogger.ProgressNormal(id, "UpdateExpectationMatrix", "Pass 2: {0} / {0}", expeRowCount, expeRowCount);
            }
        }
Beispiel #10
0
        private static void UpdateExpectationMatrix(int num_classes, int train_set_size, SparseMatrix <double> .ReadOnly train_mtx_tr, SparseMatrix <double> .ReadOnly lambda, SparseMatrix <double> expectations, int num_threads)
        {
            double[][] mtx = new double[num_classes][];
            for (int j = 0; j < num_classes; j++)
            {
                mtx[j] = new double[train_set_size];
            }
            double[] z = new double[train_set_size];
            Utils.VerboseLine("Initiating {0} threads ...", num_threads);
            int lambda_row_count = lambda.GetRowCount();

            IdxDat <SparseVector <double> .ReadOnly>[] aux = new IdxDat <SparseVector <double> .ReadOnly> [lambda_row_count];
            int i = 0;

            foreach (IdxDat <SparseVector <double> .ReadOnly> row in lambda)
            {
                aux[i++] = row;
            }
            int chunk_sz = (int)Math.Round((double)lambda_row_count / (double)num_threads); // *** this load balancing is not so good; should I count values instead of rows?

            Thread[] threads       = new Thread[num_threads];
            RefInt[] progress_info = new RefInt[num_threads];
            int      start_idx     = 0;

            for (i = 0; i < num_threads; i++)
            {
                int end_idx = start_idx + chunk_sz - 1;
                if (i == num_threads - 1)
                {
                    end_idx = aux.Length - 1;
                }
                progress_info[i] = new RefInt();
                threads[i]       = new Thread(new ParameterizedThreadStart(UpdateExpectationMatrixPass1));
                threads[i].Start(new object[] { start_idx, end_idx, train_mtx_tr, aux, mtx, progress_info[i] });
                //Console.WriteLine("{0}-{1}", start_idx, end_idx);
                start_idx += chunk_sz;
            }
            bool is_alive = true;

            while (is_alive)
            {
                int aggr_progress = 0;
                foreach (RefInt progress in progress_info)
                {
                    aggr_progress += progress.Val;
                }
                Utils.Verbose("Pass 1: {0} / {1}\r", aggr_progress, lambda_row_count);
                is_alive = false;
                foreach (Thread thread in threads)
                {
                    is_alive = is_alive || thread.IsAlive;
                }
                Thread.Sleep(100);
            }
            Utils.VerboseLine("Pass 1: {0} / {0}\r", lambda_row_count);
            for (i = 0; i < num_classes; i++)
            {
                for (int j = 0; j < train_set_size; j++)
                {
                    mtx[i][j] = Math.Exp(mtx[i][j]);
                    z[j]     += mtx[i][j];
                }
            }
            int expe_row_count = expectations.GetRowCount();

            IdxDat <SparseVector <double> >[] aux2 = new IdxDat <SparseVector <double> > [expe_row_count];
            i = 0;
            foreach (IdxDat <SparseVector <double> > row in expectations)
            {
                aux2[i++] = row;
            }
            start_idx = 0;
            for (i = 0; i < num_threads; i++)
            {
                int end_idx = start_idx + chunk_sz - 1;
                if (i == num_threads - 1)
                {
                    end_idx = aux.Length - 1;
                }
                progress_info[i].Val = 0;
                threads[i]           = new Thread(new ParameterizedThreadStart(UpdateExpectationMatrixPass2));
                threads[i].Start(new object[] { start_idx, end_idx, train_mtx_tr, aux2, mtx, z, progress_info[i] });
                start_idx += chunk_sz;
            }
            is_alive = true;
            while (is_alive)
            {
                int aggr_progress = 0;
                foreach (RefInt progress in progress_info)
                {
                    aggr_progress += progress.Val;
                }
                Utils.Verbose("Pass 2: {0} / {1}\r", aggr_progress, expe_row_count);
                is_alive = false;
                foreach (Thread thread in threads)
                {
                    is_alive = is_alive || thread.IsAlive;
                }
                Thread.Sleep(100);
            }
            Utils.VerboseLine("Pass 2: {0} / {0}\r", expe_row_count);
        }