dyv *mk_lr_XtWz_dyv( const lr_train *lrt) { /* XtWz = Xt v = [ r_i ], v = w * z, elementwise, r_i = dyv_partial_sum( v, posrows_i) */ double cterm; dyv *Wz, *XtWz; /* [1t] Compute [--] W z [Xt] */ /* Compute Wz. */ Wz = mk_dyv_mult( lrt_w_ref(lrt), lrt_z_ref(lrt)); /* Compute XtWz. */ if (lrt->X != NULL) XtWz = mk_spardat_transpose_times_dyv( lrt->X, Wz); else XtWz = mk_dym_transpose_times_dyv( lrt->M, Wz); /* Insert 1t Wz at beginning of XtWz. */ cterm = dyv_sum( Wz); dyv_insert( XtWz, 0, cterm); free_dyv( Wz); return XtWz; }
dyv *mk_lr_XtWXv_dyv( const lr_train *lrt, const dyv *v) { /* Compute [1t] [--] W [1|X] v [Xt] */ double v0, cterm; dyv *subv, *Xv, *XtWXv; /* Split v into v0=v[0] and subv=v[1:] */ v0 = dyv_ref( v, 0); subv = mk_dyv_slice( v, 1, dyv_size( v)); /* Compute [1|X] v. */ if (lrt->X != NULL) Xv = mk_spardat_times_dyv( lrt->X, subv); else Xv = mk_dym_times_dyv( lrt->M, subv); dyv_scalar_add( Xv, v0, Xv); free_dyv( subv); /* Compute W [1|X] v. */ dyv_mult( Xv, lrt_w_ref(lrt), Xv); /* Xv now stores WXv. */ /* Compute Xt W [1|X] v and 1t W [1|X] v separately. Both get stored in XtWXv. */ if (lrt->X != NULL) XtWXv = mk_spardat_transpose_times_dyv( lrt->X, Xv); else XtWXv = mk_dym_transpose_times_dyv( lrt->M, Xv); cterm = dyv_sum( Xv); dyv_insert( XtWXv, 0, cterm); free_dyv( Xv); return XtWXv; }
double dym_sum_row(dym *x,int row) { dyv *dv = mk_dyv_from_dym_row(x,row); double result = dyv_sum(dv); free_dyv(dv); return result; }
void diag_precond( const dyv *v, dyv *result, void *userdata) { /* Get diagonal ( [1t] ) diag( [--] W [1|X] ) = [ m_ii = Sum(x_ki^2 * w_k over k) ] ( [Xt] ) In the sparse case, X is binary and x_ki^2 == x_ki, and the diagonal is [ m_ii = Sum(w_k over posrows_i) ]. Preconditioning matrix is the diagonal matrix. Multiply inverse of this matrix time v, which is an element-wise product. */ int colidx; double divisor, val; ivec *posrows; dyv *w; lr_train *lrt; lrt = (lr_train *) userdata; if (lrt->X == NULL) { my_error( "diag_precond: dense problems not yet supported."); } w = lrt_w_ref( lrt); val = dyv_ref( v, 0); dyv_set( result, 0, val / dyv_sum( w)); for (colidx=1; colidx < lrt->numatts; ++colidx) { posrows = spardat_attnum_to_posrows( lrt->X, colidx-1); divisor = dyv_partial_sum( w, posrows); val = dyv_ref( v, colidx); dyv_set( result, colidx, val / divisor); } return; }