inline float compute_quadratic_cubic_approximate_error(fastuidraw::c_array<const fastuidraw::vec2> p) { /* This is derivied fromt the article at * http://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html * * The derivation for the error comes from the following: * * Let p(t) = (1-t)^3 p0 + 3t(1-t)^2 p1 + 3t^2(1-t) p2 + t^3 p3 * * Set A = 3p1 - p0, B = 3p2 - p1 * q0 = p0, q1 = (A + B) / 4 and q2 = p2 * * then, after lots of algebra, * * p(t) - q(t) = (A - B) (t^3 - 1.5t^2 + 0.5t) * * then the maximum error in each coordinate occurs when * the polynomial Z(t) = t^3 - 1.5t^2 + 0.5t has maixmal * absolute value the critical points; thus we need to only * check the critical points which are when Z'(t) = 0 which * are t1 = 0.5 * (1 - sqrt(3)) and t2 = 0.5 * (1 + sqrt(3)). * Z(t1) = sqrt(3) / 36 and Z(t2) = -sqrt(3) / 36. Hence, * the maximal error of max ||p(t) - q(t) || over 0 <= t < 1 * is ||A - B|| * sqrt(3) / 36 */ const float error_coeff(0.04811252243f); fastuidraw::vec2 error_vec(p[3] - 3.0f * p[2] + 3.0f * p[1] - p[0]); float error(error_coeff * error_vec.magnitude()); return error; }
void line_trainer_path::train_path(int mode, int *node_lst, real alpha, real *_error_vec, real *_error_p, real *_error_q, double (*func_rand_num)(), unsigned long long &rand_index, int model) { int target, label, u, v, vector_size, trans_id; real f, g; std::string path_type = std::string(); int step_bg = 0, step_ed = 0, pst_bg = 0, pst_ed = 0; line_node *node_u = phin->node_u, *node_v = phin->node_v; vector_size = node_u->vector_size; Eigen::Map<BLPVector> error_vec(_error_vec, vector_size); Eigen::Map<BLPVector> error_p(_error_p, vector_size); Eigen::Map<BLPVector> error_q(_error_q, vector_size); error_vec.setZero(); error_p.setZero(); error_q.setZero(); sample_path(node_lst, func_rand_num); if (model == 0) { step_bg = path_size - 1; step_ed = path_size; pst_bg = 0; pst_ed = 1; } else if (model == 1) { step_bg = 1; step_ed = 2; pst_bg = 0; pst_ed = path_size - 1; } else if (model == 2) { step_bg = 1; step_ed = path_size; pst_bg = 0; pst_ed = path_size - 1; } for (int step = step_bg; step != step_ed; step++) for (int pst = pst_bg; pst != pst_ed; pst++) { if (pst + step >= path_size) continue; path_type = path.substr(pst * 2, step * 2 + 1); trans_id = map_trans[path_type]; if (trans_id == 0) { printf("ERROR: trans id error!\n"); exit(1); } trans_id--; u = node_lst[pst]; v = node_lst[pst + step]; error_vec.setZero(); error_p.setZero(); error_q.setZero(); for (int d = 0; d < neg_samples + 1; d++) { if (d == 0) { target = v; label = 1; } else { rand_index = rand_index * (unsigned long long)25214903917 + 11; target = neg_table[pst + step][(rand_index >> 16) % neg_table_size]; if (target == v) continue; label = 0; } f = 0; f += node_u->vec.row(u) * node_v->vec.row(target).transpose(); if (mode == 1 || mode == 2 || mode == 3) { f += (node_u->vec.row(u)) * (vec_trans[trans_id]->P.transpose()); f += (node_v->vec.row(target)) * (vec_trans[trans_id]->Q.transpose()); f += vec_trans[trans_id]->bias; } if (f > MAX_EXP) g = (label - 1) * alpha; else if (f < -MAX_EXP) g = (label - 0) * alpha; else g = (label - expTable[(int)((f + MAX_EXP) * (EXP_TABLE_SIZE / MAX_EXP / 2))]) * alpha; if (mode == 2 || mode == 3) { error_p += g * (node_u->vec.row(u)); error_q += g * (node_v->vec.row(target)); } if (mode == 1 || mode == 3) { error_vec += g * ((node_v->vec.row(target))); error_vec += g * (vec_trans[trans_id]->P); node_v->vec.row(target) += g * ((node_u->vec.row(u))); node_v->vec.row(target) += g * (vec_trans[trans_id]->Q); } if (mode == 0) { error_vec += g * node_v->vec.row(target); node_v->vec.row(target) += g * node_u->vec.row(u); } } if (mode == 0 || mode == 1 || mode == 3) node_u->vec.row(u) += error_vec; if (mode == 2 || mode == 3) { vec_trans[trans_id]->P += error_p; vec_trans[trans_id]->Q += error_q; } } new (&error_vec) Eigen::Map<BLPMatrix>(NULL, 0, 0); new (&error_p) Eigen::Map<BLPMatrix>(NULL, 0, 0); new (&error_q) Eigen::Map<BLPMatrix>(NULL, 0, 0); }
void line_trainer_edge::train_sample_randwalk(int mode, real alpha, real restart, real *_error_vec, real *_error_p, real *_error_q, double (*func_rand_num)(), unsigned long long &rand_index) { int target, label, u, v, node, index, vector_size, trans_id; real f, g; std::string edge_type = std::string(); line_node *node_u = phin->node_u, *node_v = phin->node_v; std::vector<int> node_lst; int node_cnt = 0; vector_size = node_u->vector_size; Eigen::Map<BLPVector> error_vec(_error_vec, vector_size); Eigen::Map<BLPVector> error_p(_error_p, vector_size); Eigen::Map<BLPVector> error_q(_error_q, vector_size); error_vec.setZero(); error_p.setZero(); error_q.setZero(); edge_type += edge_tp; trans_id = map_trans[edge_type]; if (trans_id == 0) { printf("ERROR: trans id error!\n"); exit(1); } trans_id--; node_lst.clear(); node = (int)(ransampl_draw(smp_u, func_rand_num(), func_rand_num())); node_lst.push_back(node); node_cnt = 0; while(1) { if (func_rand_num() < restart) break; if (u_nb_cnt[node_lst[node_cnt]] == 0) break; index = (int)(ransampl_draw(smp_u_nb[node_lst[node_cnt]], func_rand_num(), func_rand_num())); node = u_nb_id[node_lst[node_cnt]][index]; node_lst.push_back(node); node_cnt++; } for (int k = 1; k <= node_cnt; k++) { u = node_lst[0]; v = node_lst[k]; error_vec.setZero(); error_p.setZero(); error_q.setZero(); for (int d = 0; d < neg_samples + 1; d++) { if (d == 0) { target = v; label = 1; } else { rand_index = rand_index * (unsigned long long)25214903917 + 11; target = neg_table[(rand_index >> 16) % neg_table_size]; if (target == v) continue; label = 0; } f = 0; f += node_u->vec.row(u) * node_v->vec.row(target).transpose(); if (mode == 1 || mode == 2 || mode == 3) { f += (node_u->vec.row(u)) * (vec_trans[trans_id]->P.transpose()); f += (node_v->vec.row(target)) * (vec_trans[trans_id]->Q.transpose()); f += vec_trans[trans_id]->bias; } if (f > MAX_EXP) g = (label - 1) * alpha; else if (f < -MAX_EXP) g = (label - 0) * alpha; else g = (label - expTable[(int)((f + MAX_EXP) * (EXP_TABLE_SIZE / MAX_EXP / 2))]) * alpha; if (mode == 2 || mode == 3) { error_p += g * (node_u->vec.row(u)); error_q += g * (node_v->vec.row(target)); } if (mode == 1 || mode == 3) { error_vec += g * ((node_v->vec.row(target))); error_vec += g * (vec_trans[trans_id]->P); node_v->vec.row(target) += g * ((node_u->vec.row(u))); node_v->vec.row(target) += g * (vec_trans[trans_id]->Q); } if (mode == 0) { error_vec += g * node_v->vec.row(target); node_v->vec.row(target) += g * node_u->vec.row(u); } } if (mode == 0 || mode == 1 || mode == 3) node_u->vec.row(u) += error_vec; if (mode == 2 || mode == 3) { vec_trans[trans_id]->P += error_p; vec_trans[trans_id]->Q += error_q; } } new (&error_vec) Eigen::Map<BLPMatrix>(NULL, 0, 0); new (&error_p) Eigen::Map<BLPMatrix>(NULL, 0, 0); new (&error_q) Eigen::Map<BLPMatrix>(NULL, 0, 0); }