18 using namespace Eigen;
29 const malsar_options& options)
36 int n_tasks = options.n_tasks;
42 MatrixXd Ws = MatrixXd::Zero(n_feats, n_tasks);
43 VectorXd Cs = VectorXd::Zero(n_tasks);
44 MatrixXd Wz=Ws, Wzp=Ws, Wz_old=Ws, delta_Wzp=Ws, gWs=Ws;
45 VectorXd Cz=Cs, Czp=Cs, Cz_old=Cs, delta_Czp=Cs, gCs=Cs;
48 double gamma=1, gamma_inc=2;
49 double obj=0.0, obj_old=0.0;
53 while (!done && iter <= options.max_iter && !CSignal::cancel_computations())
55 double alpha = double(t_old - 1)/t;
58 Ws = (1+alpha)*Wz - alpha*Wz_old;
59 Cs = (1+alpha)*Cz - alpha*Cz_old;
67 for (task=0; task<n_tasks; task++)
70 int n_task_vecs = task_idx.
vlen;
71 for (
int i=0; i<n_task_vecs; i++)
73 double aa = -y[task_idx[i]]*(features->
dense_dot(task_idx[i], Ws.col(task).data(), n_feats)+Cs[task]);
77 Fs += (CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb)/n_task_vecs;
78 double b = -y[task_idx[i]]*(1 - 1/(1+CMath::exp(aa)))/n_task_vecs;
84 gWs.noalias() += 2*rho2*Ws;
87 Fs += Ws.squaredNorm();
97 while (inner_iter <= 1000)
100 for (
int i=0; i<n_feats; i++)
102 Wzp.row(i).noalias() = Ws.row(i) - gWs.row(i)/gamma;
103 double norm = Wzp.row(i).lpNorm<2>();
105 Wzp.row(i).setZero();
108 double threshold = norm - rho1/gamma;
110 Wzp.row(i).setZero();
112 Wzp.row(i) *= threshold/
norm;
116 Czp = Cs - gCs/gamma;
120 for (task=0; task<n_tasks; task++)
123 int n_task_vecs = task_idx.
vlen;
124 for (
int i=0; i<n_task_vecs; i++)
126 double aa = -y[task_idx[i]]*(features->
dense_dot(task_idx[i], Wzp.col(task).
data(), n_feats)+Czp[task]);
129 Fzp += (CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb)/n_task_vecs;
132 Fzp += rho2*Wzp.squaredNorm();
135 delta_Wzp = Wzp - Ws;
136 delta_Czp = Czp - Cs;
139 double nrm_delta_Wzp = delta_Wzp.squaredNorm();
140 double nrm_delta_Czp = delta_Czp.squaredNorm();
142 double r_sum = (nrm_delta_Wzp + nrm_delta_Czp)/2;
144 double Fzp_gamma = Fs + (delta_Wzp.transpose()*gWs).trace() +
145 (delta_Czp.transpose()*gCs).trace() +
146 (gamma/2)*nrm_delta_Wzp +
147 (gamma/2)*nrm_delta_Czp;
152 SG_SDEBUG(
"Line search point is too close to search point\n")
158 if (Fzp <= Fzp_gamma)
174 for (
int i=0; i<n_feats; i++)
175 obj += rho1*(Wz.row(i).lpNorm<2>());
181 switch (options.termination)
186 if ( CMath::abs(obj-obj_old) <= options.tolerance )
188 SG_SDEBUG(
"Objective changes less than tolerance\n")
196 if ( CMath::abs(obj-obj_old) <= options.tolerance*CMath::abs(obj_old))
201 if (CMath::abs(obj) <= options.tolerance)
205 if (iter>=options.max_iter)
212 t = 0.5 * (1 + CMath::sqrt(1.0 + 4*t*t));
216 SG_SDEBUG(
"%d iteration passed, objective = %f\n",iter,obj)
219 for (
int i=0; i<n_feats; i++)
221 for (task=0; task<n_tasks; task++)
222 tasks_w(i,task) = Wzp(i,task);
225 for (
int i=0; i<n_tasks; i++) tasks_c[i] = Czp[i];
226 return malsar_result_t(tasks_w, tasks_c);
double norm(double *v, double p, int n)
virtual float64_t dense_dot(int32_t vec_idx1, const float64_t *vec2, int32_t vec2_len)=0
virtual int32_t get_num_vectors() const =0
virtual void add_to_dense_vec(float64_t alpha, int32_t vec_idx1, float64_t *vec2, int32_t vec2_len, bool abs_val=false)=0
Features that support dot products among other operations.
virtual int32_t get_dim_feature_space() const =0
malsar_result_t malsar_joint_feature_learning(CDotFeatures *features, double *y, double rho1, double rho2, const malsar_options &options)
all of classes and functions are contained in the shogun namespace
Matrix::Scalar max(Matrix m)