20 using namespace shogun;
28 m_point_index = index;
29 m_distance = specp_distance;
58 void CStochasticProximityEmbedding::init()
63 SG_ADD(&m_tolerance,
"m_tolerance",
"Regularization parameter",
74 SG_ERROR(
"Number of neighbors k must be greater than 0");
86 m_strategy = strategy;
97 SG_ERROR(
"Tolerance regularization parameter must be greater "
100 m_tolerance = tolerance;
111 SG_ERROR(
"The number of updates must be greater than 0");
113 m_nupdates = nupdates;
123 return "StochasticProximityEmbedding";
129 SG_ERROR(
"Features are required to apply SPE\n");
138 if ( m_strategy ==
SPE_LOCAL && m_k >= N )
139 SG_ERROR(
"The number of neighbors (%d) must be less than "
140 "the number of vectors (%d)\n", m_k, N);
142 if ( 2*m_nupdates > N )
143 SG_ERROR(
"The number of vectors (%d) must be at least two times "
144 "the number of updates (%d)\n", N, m_nupdates);
157 int32_t* neighborhood_matrix =
SG_MALLOC(int32_t, N*k);
166 std::vector<SPE_COVERTREE_POINT> neighbors =
168 for (std::size_t m=1; m<unsigned(k+1); m++)
169 neighborhood_matrix[i*k+m-1] = neighbors[m].m_point_index;
180 SG_ERROR(
"Embed distance received no instance of CDistance\n");
183 SG_DEBUG(
"Computing distance matrix\n");
186 SG_ERROR(
"SPE only supports Euclidean distance, %s given\n",
195 for ( i = 0 ; i < N ; ++i )
196 for ( j = i+1 ; j < N ; ++j )
197 if ( ( tmp = distance->
distance(i, j) ) > max )
209 SG_DEBUG(
"Computing neighborhood matrix\n");
210 neighbors_mat = get_neighborhood_matrix(distance, m_k, N, max);
230 index_t idx1 = 0, idx2 = 0, idx = 0;
236 int32_t* ind2 = NULL;
250 for ( i = 0 ; i < max_iter ; ++i )
253 SG_DEBUG(
"SPE's loop, iteration %d of %d\n", i, max_iter);
263 ind2 = J + m_nupdates;
270 for ( j = 0 ; j < m_nupdates ; ++j )
272 for ( k = 0 ; k < m_k ; ++k )
273 ind1Neighbors[k + j*m_k] =
274 neighbors_mat.
matrix[k + ind1[j]*m_k];
278 for ( j = 0 ; j < m_nupdates ; ++j )
285 for ( j = 0 ; j < m_nupdates ; ++j )
286 ind2[j] = ind1Neighbors.
matrix[ J2[j] ];
291 for ( j = 0 ; j < m_nupdates ; ++j )
299 sum +=
CMath::sq(Y.matrix[idx1] - Y.matrix[idx2]);
312 for ( j = 0 ; j < m_nupdates ; ++j )
313 Rt[j] *= distance->
distance( ind1[j], ind2[j] );
318 for ( j = 0 ; j < m_nupdates ; ++j )
319 scale[j] = ( Rt[j] - D[j] ) / ( D[j] + m_tolerance );
322 for ( j = 0 ; j < m_nupdates ; ++j )
329 Yd[idx] = Y[idx1] - Y[idx2];
333 for ( j = 0 ; j < m_nupdates ; ++j )
340 Y[idx1] += lambda / 2 * scale[j] * Yd[idx];
341 Y[idx2] -= lambda / 2 * scale[j] * Yd[idx];
345 lambda = lambda - ( lambda / max_iter );