bool runCRF(EncoderTagger[] x, ModelWritter modelWritter, bool orthant, EncoderArgs args) { double old_obj = double.MaxValue; int converge = 0; LBFGS lbfgs = new LBFGS(args.threads_num); lbfgs.expected = new double[modelWritter.feature_size() + 1]; List <CRFEncoderThread> processList = new List <CRFEncoderThread>(); #if NO_SUPPORT_PARALLEL_LIB #else ParallelOptions parallelOption = new ParallelOptions(); parallelOption.MaxDegreeOfParallelism = args.threads_num; #endif //Initialize encoding threads for (int i = 0; i < args.threads_num; i++) { CRFEncoderThread thread = new CRFEncoderThread(); thread.start_i = i; thread.thread_num = args.threads_num; thread.x = x; thread.lbfgs = lbfgs; thread.Init(); processList.Add(thread); } //Statistic term and result tags frequency int termNum = 0; int[] yfreq; yfreq = new int[modelWritter.y_.Count]; foreach (EncoderTagger tagger in x) { termNum += tagger.word_num; for (int j = 0; j < tagger.word_num; j++) { yfreq[tagger.answer_[j]]++; } } //Iterative training DateTime startDT = DateTime.Now; double dMinErrRecord = 1.0; for (int itr = 0; itr < args.max_iter; ++itr) { //Clear result container lbfgs.obj = 0.0f; lbfgs.err = 0; lbfgs.zeroone = 0; Array.Clear(lbfgs.expected, 0, lbfgs.expected.Length); List <Thread> threadList = new List <Thread>(); for (int i = 0; i < args.threads_num; i++) { Thread thread = new Thread(new ThreadStart(processList[i].Run)); thread.Start(); threadList.Add(thread); } int[,] merr; merr = new int[modelWritter.y_.Count, modelWritter.y_.Count]; for (int i = 0; i < args.threads_num; ++i) { threadList[i].Join(); lbfgs.obj += processList[i].obj; lbfgs.err += processList[i].err; lbfgs.zeroone += processList[i].zeroone; //Calculate error for (int j = 0; j < modelWritter.y_.Count; j++) { for (int k = 0; k < modelWritter.y_.Count; k++) { merr[j, k] += processList[i].merr[j, k]; } } } long num_nonzero = 0; long fsize = modelWritter.feature_size(); double[] alpha = modelWritter.alpha_; if (orthant == true) { //L1 regularization #if NO_SUPPORT_PARALLEL_LIB for (long k = 1; k < fsize + 1; k++) { lbfgs.obj += Math.Abs(alpha[k] / modelWritter.cost_factor_); if (alpha[k] != 0.0) { num_nonzero++; } } #else Parallel.For <double>(1, fsize + 1, parallelOption, () => 0, (k, loop, subtotal) => { subtotal += Math.Abs(alpha[k] / modelWritter.cost_factor_); if (alpha[k] != 0.0) { Interlocked.Increment(ref num_nonzero); } return(subtotal); }, (subtotal) => // lock free accumulator { double initialValue; double newValue; do { initialValue = lbfgs.obj; // read current value newValue = initialValue + subtotal; //calculate new value }while (initialValue != Interlocked.CompareExchange(ref lbfgs.obj, newValue, initialValue)); } ); #endif } else { //L2 regularization num_nonzero = fsize; #if NO_SUPPORT_PARALLEL_LIB for (long k = 1; k < fsize + 1; k++) { lbfgs.obj += (alpha[k] * alpha[k] / (2.0 * modelWritter.cost_factor_)); lbfgs.expected[k] += (alpha[k] / modelWritter.cost_factor_); } #else Parallel.For <double>(1, fsize + 1, parallelOption, () => 0, (k, loop, subtotal) => { subtotal += (alpha[k] * alpha[k] / (2.0 * modelWritter.cost_factor_)); lbfgs.expected[k] += (alpha[k] / modelWritter.cost_factor_); return(subtotal); }, (subtotal) => // lock free accumulator { double initialValue; double newValue; do { initialValue = lbfgs.obj; // read current value newValue = initialValue + subtotal; //calculate new value }while (initialValue != Interlocked.CompareExchange(ref lbfgs.obj, newValue, initialValue)); } ); #endif } //Show each iteration result double diff = (itr == 0 ? 1.0f : Math.Abs(old_obj - lbfgs.obj) / old_obj); old_obj = lbfgs.obj; ShowEvaluation(x.Length, modelWritter, lbfgs, termNum, itr, merr, yfreq, diff, startDT, num_nonzero, args); if (diff < args.min_diff) { converge++; } else { converge = 0; } if (itr > args.max_iter || converge == 3) { break; // 3 is ad-hoc } if (args.debugLevel > 0 && (double)lbfgs.zeroone / (double)x.Length < dMinErrRecord) { ConsoleColor cc = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.Write("[Debug Mode] "); Console.ForegroundColor = cc; Console.Write("Saving intermediate feature weights at current directory..."); //Save current best feature weight into file dMinErrRecord = (double)lbfgs.zeroone / (double)x.Length; modelWritter.SaveFeatureWeight("feature_weight_tmp"); Console.WriteLine("Done."); } int iret; iret = lbfgs.optimize(alpha, modelWritter.cost_factor_, orthant); if (iret <= 0) { return(false); } } return(true); }
bool runCRF(EncoderTagger[] x, ModelWritter modelWritter, bool orthant, EncoderArgs args) { var old_obj = double.MaxValue; var converge = 0; var lbfgs = new LBFGS(args.threads_num); lbfgs.expected = new double[modelWritter.feature_size() + 1]; var processList = new List<CRFEncoderThread>(); #if NO_SUPPORT_PARALLEL_LIB #else var parallelOption = new ParallelOptions(); parallelOption.MaxDegreeOfParallelism = args.threads_num; #endif //Initialize encoding threads for (var i = 0; i < args.threads_num; i++) { var thread = new CRFEncoderThread(); thread.start_i = i; thread.thread_num = args.threads_num; thread.x = x; thread.lbfgs = lbfgs; thread.Init(); processList.Add(thread); } //Statistic term and result tags frequency var termNum = 0; int[] yfreq; yfreq = new int[modelWritter.y_.Count]; for (int index = 0; index < x.Length; index++) { var tagger = x[index]; termNum += tagger.word_num; for (var j = 0; j < tagger.word_num; j++) { yfreq[tagger.answer_[j]]++; } } //Iterative training var startDT = DateTime.Now; var dMinErrRecord = 1.0; for (var itr = 0; itr < args.max_iter; ++itr) { //Clear result container lbfgs.obj = 0.0f; lbfgs.err = 0; lbfgs.zeroone = 0; Array.Clear(lbfgs.expected, 0, lbfgs.expected.Length); var threadList = new List<Thread>(); for (var i = 0; i < args.threads_num; i++) { var thread = new Thread(processList[i].Run); thread.Start(); threadList.Add(thread); } int[,] merr; merr = new int[modelWritter.y_.Count, modelWritter.y_.Count]; for (var i = 0; i < args.threads_num; ++i) { threadList[i].Join(); lbfgs.obj += processList[i].obj; lbfgs.err += processList[i].err; lbfgs.zeroone += processList[i].zeroone; //Calculate error for (var j = 0; j < modelWritter.y_.Count; j++) { for (var k = 0; k < modelWritter.y_.Count; k++) { merr[j, k] += processList[i].merr[j, k]; } } } long num_nonzero = 0; var fsize = modelWritter.feature_size(); var alpha = modelWritter.alpha_; if (orthant == true) { //L1 regularization #if NO_SUPPORT_PARALLEL_LIB for (long k = 1; k < fsize + 1; k++) { lbfgs.obj += Math.Abs(alpha[k] / modelWritter.cost_factor_); if (alpha[k] != 0.0) { num_nonzero++; } } #else Parallel.For<double>(1, fsize + 1, parallelOption, () => 0, (k, loop, subtotal) => { subtotal += Math.Abs(alpha[k] / modelWritter.cost_factor_); if (alpha[k] != 0.0) { Interlocked.Increment(ref num_nonzero); } return subtotal; }, (subtotal) => // lock free accumulator { double initialValue; double newValue; do { initialValue = lbfgs.obj; // read current value newValue = initialValue + subtotal; //calculate new value } while (initialValue != Interlocked.CompareExchange(ref lbfgs.obj, newValue, initialValue)); } ); #endif } else { //L2 regularization num_nonzero = fsize; #if NO_SUPPORT_PARALLEL_LIB for (long k = 1; k < fsize + 1; k++) { lbfgs.obj += (alpha[k] * alpha[k] / (2.0 * modelWritter.cost_factor_)); lbfgs.expected[k] += (alpha[k] / modelWritter.cost_factor_); } #else Parallel.For<double>(1, fsize + 1, parallelOption, () => 0, (k, loop, subtotal) => { subtotal += (alpha[k] * alpha[k] / (2.0 * modelWritter.cost_factor_)); lbfgs.expected[k] += (alpha[k] / modelWritter.cost_factor_); return subtotal; }, (subtotal) => // lock free accumulator { double initialValue; double newValue; do { initialValue = lbfgs.obj; // read current value newValue = initialValue + subtotal; //calculate new value } while (initialValue != Interlocked.CompareExchange(ref lbfgs.obj, newValue, initialValue)); } ); #endif } //Show each iteration result var diff = (itr == 0 ? 1.0f : Math.Abs(old_obj - lbfgs.obj) / old_obj); old_obj = lbfgs.obj; ShowEvaluation(x.Length, modelWritter, lbfgs, termNum, itr, merr, yfreq, diff, startDT, num_nonzero, args); if (diff < args.min_diff) { converge++; } else { converge = 0; } if (itr > args.max_iter || converge == 3) { break; // 3 is ad-hoc } if (args.debugLevel > 0 && (double)lbfgs.zeroone / (double)x.Length < dMinErrRecord) { var cc = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.Write("[Debug Mode] "); Console.ForegroundColor = cc; Console.Write("Saving intermediate feature weights at current directory..."); //Save current best feature weight into file dMinErrRecord = (double)lbfgs.zeroone / (double)x.Length; modelWritter.SaveFeatureWeight("feature_weight_tmp"); Console.WriteLine("Done."); } int iret; iret = lbfgs.optimize(alpha, modelWritter.cost_factor_, orthant); if (iret <= 0) { return false; } } return true; }