19 using namespace Eigen;
25 malsar_result_t malsar_joint_feature_learning(
26 CDotFeatures* features,
30 const malsar_options& options)
33 int n_feats = features->get_dim_feature_space();
35 int n_vecs = features->get_num_vectors();
37 int n_tasks = options.n_tasks;
44 VectorXd Cs = VectorXd::Zero(n_tasks);
45 MatrixXd Wz=Ws, Wzp=Ws, Wz_old=Ws, delta_Wzp=Ws, gWs=Ws;
46 VectorXd Cz=Cs, Czp=Cs, Cz_old=Cs, delta_Czp=Cs, gCs=Cs;
49 double gamma=1, gamma_inc=2;
50 double obj=0.0, obj_old=0.0;
54 while (!done && iter <= options.max_iter && !CSignal::cancel_computations())
56 double alpha = double(t_old - 1)/t;
59 Ws = (1+alpha)*Wz - alpha*Wz_old;
60 Cs = (1+alpha)*Cz - alpha*Cz_old;
68 for (task=0; task<n_tasks; task++)
70 SGVector<index_t> task_idx = options.tasks_indices[task];
71 int n_task_vecs = task_idx.vlen;
72 for (
int i=0; i<n_task_vecs; i++)
74 double aa = -y[task_idx[i]]*(features->dense_dot(task_idx[i], Ws.col(task).data(), n_feats)+Cs[task]);
78 Fs += (CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb)/n_task_vecs;
79 double b = -y[task_idx[i]]*(1 - 1/(1+CMath::exp(aa)))/n_task_vecs;
82 features->add_to_dense_vec(b, task_idx[i], gWs.col(task).data(), n_feats);
85 gWs.noalias() += 2*rho2*Ws;
88 Fs += Ws.squaredNorm();
98 while (inner_iter <= 1000)
101 for (
int i=0; i<n_feats; i++)
103 Wzp.row(i).noalias() = Ws.row(i) - gWs.row(i)/gamma;
104 double norm = Wzp.row(i).lpNorm<2>();
106 Wzp.row(i).setZero();
109 double threshold = norm - rho1/gamma;
111 Wzp.row(i).setZero();
113 Wzp.row(i) *= threshold/norm;
117 Czp = Cs - gCs/gamma;
121 for (task=0; task<n_tasks; task++)
123 SGVector<index_t> task_idx = options.tasks_indices[task];
124 int n_task_vecs = task_idx.vlen;
125 for (
int i=0; i<n_task_vecs; i++)
127 double aa = -y[task_idx[i]]*(features->dense_dot(task_idx[i], Wzp.col(task).data(), n_feats)+Czp[task]);
130 Fzp += (CMath::log(CMath::exp(-bb) + CMath::exp(aa-bb)) + bb)/n_task_vecs;
133 Fzp += rho2*Wzp.squaredNorm();
136 delta_Wzp = Wzp - Ws;
137 delta_Czp = Czp - Cs;
140 double nrm_delta_Wzp = delta_Wzp.squaredNorm();
141 double nrm_delta_Czp = delta_Czp.squaredNorm();
143 double r_sum = (nrm_delta_Wzp + nrm_delta_Czp)/2;
145 double Fzp_gamma = Fs + (delta_Wzp.transpose()*gWs).trace() +
146 (delta_Czp.transpose()*gCs).trace() +
147 (gamma/2)*nrm_delta_Wzp +
148 (gamma/2)*nrm_delta_Czp;
153 SG_SDEBUG(
"Line search point is too close to search point\n")
159 if (Fzp <= Fzp_gamma)
175 for (
int i=0; i<n_feats; i++)
176 obj += rho1*(Wz.row(i).lpNorm<2>());
182 switch (options.termination)
187 if ( CMath::abs(obj-obj_old) <= options.tolerance )
189 SG_SDEBUG(
"Objective changes less than tolerance\n")
197 if ( CMath::abs(obj-obj_old) <= options.tolerance*CMath::abs(obj_old))
202 if (CMath::abs(obj) <= options.tolerance)
206 if (iter>=options.max_iter)
213 t = 0.5 * (1 + CMath::sqrt(1.0 + 4*t*t));
217 SG_SDEBUG("%d iteration passed, objective = %f\n",iter,obj)
219 SGMatrix<
float64_t> tasks_w(n_feats, n_tasks);
220 for (
int i=0; i<n_feats; i++)
222 for (task=0; task<n_tasks; task++)
223 tasks_w(i,task) = Wzp(i,task);
225 SGVector<float64_t> tasks_c(n_tasks);
226 for (
int i=0; i<n_tasks; i++) tasks_c[i] = Czp[i];
227 return malsar_result_t(tasks_w, tasks_c);
231 #endif //USE_GPL_SHOGUN
all of classes and functions are contained in the shogun namespace
Matrix::Scalar max(Matrix m)