Rcpp::List run(const data_set& data, MODEL& model, SGD& sgd) { unsigned n_samples = data.n_samples; unsigned n_features = data.n_features; unsigned n_passes = sgd.get_n_passes(); bool good_gradient = true; bool good_validity = true; bool averaging = false; if (sgd.name() == "asgd" || sgd.name() == "ai-sgd") { averaging = true; } // TODO these should really be vec's mat theta_new; mat theta_new_ave; mat theta_old = sgd.get_last_estimate(); mat theta_old_ave = theta_old; unsigned max_iters = n_samples*n_passes; bool do_more_iterations = true; bool converged = false; if (sgd.verbose()) { Rcpp::Rcout << "Stochastic gradient method: " << sgd.name() << std::endl; Rcpp::Rcout << "SGD Start!" << std::endl; } for (unsigned t = 1; do_more_iterations; ++t) { theta_new = sgd.update(t, theta_old, data, model, good_gradient); if (averaging) { if (t != 1) { theta_new_ave = (1. - 1./(double)t) * theta_old_ave + 1./((double)t) * theta_new; } else { theta_new_ave = theta_new; } sgd = theta_new_ave; } else { sgd = theta_new; } good_validity = validity_check(data, theta_new, good_gradient, t, model); if (!good_validity) { return Rcpp::List(); } // Check if satisfy convergence threshold. if (averaging) { converged = sgd.check_convergence(theta_new_ave, theta_old_ave); } else { converged = sgd.check_convergence(theta_new, theta_old); } if (converged) { sgd.end_early(); do_more_iterations = false; } // Stop if hit maximum number of iterations. if (t == max_iters) { //if (!sgd.pass()) { // Rcpp::Rcout // << "Informational Message: The maximum number of iterations is " // << "reached! The algorithm has not converged." // << std::endl // << "Estimates from this stochastic gradient descent are not " // << "guaranteed to be meaningful." // << std::endl; //} do_more_iterations = false; } // Set old to new updates and repeat. if (averaging) { theta_old_ave = theta_new_ave; } theta_old = theta_new; } Rcpp::List model_out = post_process(sgd, data, model); return Rcpp::List::create( Rcpp::Named("model") = model.name(), Rcpp::Named("coefficients") = sgd.get_last_estimate(), Rcpp::Named("converged") = converged, Rcpp::Named("estimates") = sgd.get_estimates(), Rcpp::Named("pos") = sgd.get_pos(), Rcpp::Named("times") = sgd.get_times(), Rcpp::Named("model.out") = model_out); }
static int validate_device(const device_class *devclass) { int error = 0; int is_invalid, i; const char *s; INT64 devcount, optcount; char buf[256]; char *s1; char *s2; iodevice_t devtype; int (*validity_check)(const device_class *devclass); /* critical information */ devtype = (iodevice_t) (int) device_get_info_int(devclass, DEVINFO_INT_TYPE); devcount = device_get_info_int(devclass, DEVINFO_INT_COUNT); /* sanity check device type */ if (devtype >= IO_COUNT) { printf("%s: invalid device type %i\n", devclass->gamedrv->name, (int) devtype); error = 1; } /* sanity check device count */ if ((devcount <= 0) || (devcount > MAX_DEV_INSTANCES)) { printf("%s: device type '%s' has an invalid device count %i\n", devclass->gamedrv->name, device_typename(devtype), (int) devcount); error = 1; } /* File Extensions Checks * * Checks the following * * 1. Tests the integrity of the string list * 2. Checks for duplicate extensions * 3. Makes sure that all extensions are either lower case chars or numbers */ s = device_get_info_string(devclass, DEVINFO_STR_FILE_EXTENSIONS); if (!s) { printf("%s: device type '%s' has null file extensions\n", devclass->gamedrv->name, device_typename(devtype)); error = 1; } else { memset(buf, 0, sizeof(buf)); strcpy(buf, s); /* convert to be null delimited */ s1 = buf; while(*s1) { if (*s1 == ',') *s1 = '\0'; s1++; } s1 = buf; while(*s1) { /* check for invalid chars */ is_invalid = 0; for (s2 = s1; *s2; s2++) { if (!isdigit(*s2) && !islower(*s2)) is_invalid = 1; } if (is_invalid) { printf("%s: device type '%s' has an invalid extension '%s'\n", devclass->gamedrv->name, device_typename(devtype), s1); error = 1; } s2++; /* check for dupes */ is_invalid = 0; while(*s2) { if (!strcmp(s1, s2)) is_invalid = 1; s2 += strlen(s2) + 1; } if (is_invalid) { printf("%s: device type '%s' has duplicate extensions '%s'\n", devclass->gamedrv->name, device_typename(devtype), s1); error = 1; } s1 += strlen(s1) + 1; } } /* enforce certain rules for certain device types */ switch(devtype) { case IO_QUICKLOAD: case IO_SNAPSHOT: if (devcount != 1) { printf("%s: there can only be one instance of devices of type '%s'\n", devclass->gamedrv->name, device_typename(devtype)); error = 1; } /* fallthrough */ case IO_CARTSLOT: if (!device_get_info_int(devclass, DEVINFO_INT_READABLE) || device_get_info_int(devclass, DEVINFO_INT_WRITEABLE) || device_get_info_int(devclass, DEVINFO_INT_CREATABLE)) { printf("%s: devices of type '%s' has invalid open modes\n", devclass->gamedrv->name, device_typename(devtype)); error = 1; } break; default: break; } /* check creation options */ optcount = device_get_info_int(devclass, DEVINFO_INT_CREATE_OPTCOUNT); if ((optcount < 0) || (optcount >= DEVINFO_CREATE_OPTMAX)) { printf("%s: device type '%s' has an invalid creation optcount\n", devclass->gamedrv->name, device_typename(devtype)); error = 1; } else { for (i = 0; i < (int) optcount; i++) { if (!device_get_info_string(devclass, DEVINFO_STR_CREATE_OPTNAME + i)) { printf("%s: device type '%s' create option #%d: name not present\n", devclass->gamedrv->name, device_typename(devtype), i); error = 1; } if (!device_get_info_string(devclass, DEVINFO_STR_CREATE_OPTDESC + i)) { printf("%s: device type '%s' create option #%d: description not present\n", devclass->gamedrv->name, device_typename(devtype), i); error = 1; } if (!device_get_info_string(devclass, DEVINFO_STR_CREATE_OPTEXTS + i)) { printf("%s: device type '%s' create option #%d: extensions not present\n", devclass->gamedrv->name, device_typename(devtype), i); error = 1; } } } /* is there a custom validity check? */ validity_check = (int (*)(const device_class *)) device_get_info_fct(devclass, DEVINFO_PTR_VALIDITY_CHECK); if (validity_check) { if (validity_check(devclass)) error = 1; } return error; }