00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <shogun/preprocessor/LocalTangentSpaceAlignment.h>
00012 #ifdef HAVE_LAPACK
00013 #include <shogun/mathematics/arpack.h>
00014 #include <shogun/mathematics/lapack.h>
00015 #include <shogun/lib/Time.h>
00016 #include <shogun/lib/common.h>
00017 #include <shogun/mathematics/Math.h>
00018 #include <shogun/io/SGIO.h>
00019 #include <shogun/distance/EuclidianDistance.h>
00020 #include <shogun/lib/Signal.h>
00021
00022 #ifdef HAVE_PTHREAD
00023 #include <pthread.h>
00024 #endif
00025
00026 using namespace shogun;
00027
00028 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00029 struct LTSA_THREAD_PARAM
00030 {
00032 int32_t idx_start;
00034 int32_t idx_step;
00036 int32_t idx_stop;
00038 int32_t m_k;
00040 int32_t m_target_dim;
00042 int32_t dim;
00044 int32_t N;
00046 const int32_t* neighborhood_matrix;
00048 float64_t* G_matrix;
00050 float64_t* mean_vector;
00052 float64_t* local_feature_matrix;
00054 const float64_t* feature_matrix;
00056 float64_t* s_values_vector;
00058 float64_t* q_matrix;
00060 float64_t* W_matrix;
00061 #ifdef HAVE_PTHREAD
00062
00063 PTHREAD_LOCK_T* W_matrix_lock;
00064 #endif
00065 };
00066 #endif
00067
00068 CLocalTangentSpaceAlignment::CLocalTangentSpaceAlignment() :
00069 CLocallyLinearEmbedding()
00070 {
00071 }
00072
00073 CLocalTangentSpaceAlignment::~CLocalTangentSpaceAlignment()
00074 {
00075 }
00076
00077 bool CLocalTangentSpaceAlignment::init(CFeatures* features)
00078 {
00079 return true;
00080 }
00081
00082 void CLocalTangentSpaceAlignment::cleanup()
00083 {
00084 }
00085
00086 SGMatrix<float64_t> CLocalTangentSpaceAlignment::apply_to_feature_matrix(CFeatures* features)
00087 {
00088 ASSERT(features);
00089 if (!(features->get_feature_class()==C_SIMPLE &&
00090 features->get_feature_type()==F_DREAL))
00091 {
00092 SG_ERROR("Given features are not of SimpleRealFeatures type.\n");
00093 }
00094
00095
00096 CSimpleFeatures<float64_t>* simple_features = (CSimpleFeatures<float64_t>*) features;
00097 SG_REF(features);
00098
00099
00100 int32_t dim = simple_features->get_num_features();
00101 if (m_target_dim>dim)
00102 SG_ERROR("Cannot increase dimensionality: target dimensionality is %d while given features dimensionality is %d.\n",
00103 m_target_dim, dim);
00104
00105 int32_t N = simple_features->get_num_vectors();
00106 if (m_k>=N)
00107 SG_ERROR("Number of neighbors (%d) should be less than number of objects (%d).\n",
00108 m_k, N);
00109
00110
00111 int32_t t;
00112
00113
00114 CDistance* distance = new CEuclidianDistance(simple_features,simple_features);
00115 SG_UNREF(distance->parallel);
00116 distance->parallel = this->parallel;
00117 SGMatrix<int32_t> neighborhood_matrix = get_neighborhood_matrix(distance);
00118
00119
00120 float64_t* W_matrix = SG_CALLOC(float64_t, N*N);
00121
00122 #ifdef HAVE_PTHREAD
00123 int32_t num_threads = parallel->get_num_threads();
00124 ASSERT(num_threads>0);
00125
00126 pthread_t* threads = SG_MALLOC(pthread_t, num_threads);
00127 LTSA_THREAD_PARAM* parameters = SG_MALLOC(LTSA_THREAD_PARAM, num_threads);
00128 #else
00129 int32_t num_threads = 1;
00130 #endif
00131
00132
00133 float64_t* local_feature_matrix = SG_MALLOC(float64_t, m_k*dim*num_threads);
00134 float64_t* mean_vector = SG_MALLOC(float64_t, dim*num_threads);
00135 float64_t* q_matrix = SG_MALLOC(float64_t, m_k*m_k*num_threads);
00136 float64_t* s_values_vector = SG_MALLOC(float64_t, dim*num_threads);
00137 float64_t* G_matrix = SG_MALLOC(float64_t, m_k*(1+m_target_dim)*num_threads);
00138
00139
00140 SGMatrix<float64_t> feature_matrix = simple_features->get_feature_matrix();
00141
00142 #ifdef HAVE_PTHREAD
00143 PTHREAD_LOCK_T W_matrix_lock;
00144 pthread_attr_t attr;
00145 PTHREAD_LOCK_INIT(&W_matrix_lock);
00146 pthread_attr_init(&attr);
00147 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00148
00149 for (t=0; t<num_threads; t++)
00150 {
00151 parameters[t].idx_start = t;
00152 parameters[t].idx_step = num_threads;
00153 parameters[t].idx_stop = N;
00154 parameters[t].m_k = m_k;
00155 parameters[t].m_target_dim = m_target_dim;
00156 parameters[t].dim = dim;
00157 parameters[t].N = N;
00158 parameters[t].neighborhood_matrix = neighborhood_matrix.matrix;
00159 parameters[t].G_matrix = G_matrix + (m_k*(1+m_target_dim))*t;
00160 parameters[t].mean_vector = mean_vector + dim*t;
00161 parameters[t].local_feature_matrix = local_feature_matrix + (m_k*dim)*t;
00162 parameters[t].feature_matrix = feature_matrix.matrix;
00163 parameters[t].s_values_vector = s_values_vector + dim*t;
00164 parameters[t].q_matrix = q_matrix + (m_k*m_k)*t;
00165 parameters[t].W_matrix = W_matrix;
00166 parameters[t].W_matrix_lock = &W_matrix_lock;
00167 pthread_create(&threads[t], &attr, run_ltsa_thread, (void*)¶meters[t]);
00168 }
00169 for (t=0; t<num_threads; t++)
00170 pthread_join(threads[t], NULL);
00171 PTHREAD_LOCK_DESTROY(&W_matrix_lock);
00172 SG_FREE(parameters);
00173 SG_FREE(threads);
00174 #else
00175 LTSA_THREAD_PARAM single_thread_param;
00176 single_thread_param.idx_start = 0;
00177 single_thread_param.idx_step = 1;
00178 single_thread_param.idx_stop = N;
00179 single_thread_param.m_k = m_k;
00180 single_thread_param.m_target_dim = m_target_dim;
00181 single_thread_param.dim = dim;
00182 single_thread_param.N = N;
00183 single_thread_param.neighborhood_matrix = neighborhood_matrix.matrix;
00184 single_thread_param.G_matrix = G_matrix;
00185 single_thread_param.mean_vector = mean_vector;
00186 single_thread_param.local_feature_matrix = local_feature_matrix;
00187 single_thread_param.feature_matrix = feature_matrix.matrix;
00188 single_thread_param.s_values_vector = s_values_vector;
00189 single_thread_param.q_matrix = q_matrix;
00190 single_thread_param.W_matrix = W_matrix;
00191 run_ltsa_thread((void*)&single_thread_param);
00192 #endif
00193
00194
00195 SG_FREE(G_matrix);
00196 SG_FREE(s_values_vector);
00197 SG_FREE(mean_vector);
00198 neighborhood_matrix.destroy_matrix();
00199 SG_FREE(local_feature_matrix);
00200 SG_FREE(q_matrix);
00201
00202
00203 SGMatrix<float64_t> W_sgmatrix(W_matrix,N,N);
00204 simple_features->set_feature_matrix(find_null_space(W_sgmatrix,m_target_dim,false));
00205 W_sgmatrix.destroy_matrix();
00206
00207 SG_UNREF(features);
00208 return simple_features->get_feature_matrix();
00209 }
00210
00211 SGVector<float64_t> CLocalTangentSpaceAlignment::apply_to_feature_vector(SGVector<float64_t> vector)
00212 {
00213 SG_NOTIMPLEMENTED;
00214 return vector;
00215 }
00216
00217 void* CLocalTangentSpaceAlignment::run_ltsa_thread(void* p)
00218 {
00219 LTSA_THREAD_PARAM* parameters = (LTSA_THREAD_PARAM*)p;
00220 int32_t idx_start = parameters->idx_start;
00221 int32_t idx_step = parameters->idx_step;
00222 int32_t idx_stop = parameters->idx_stop;
00223 int32_t m_k = parameters->m_k;
00224 int32_t m_target_dim = parameters->m_target_dim;
00225 int32_t dim = parameters->dim;
00226 int32_t N = parameters->N;
00227 const int32_t* neighborhood_matrix = parameters->neighborhood_matrix;
00228 float64_t* G_matrix = parameters->G_matrix;
00229 float64_t* mean_vector = parameters->mean_vector;
00230 float64_t* local_feature_matrix = parameters->local_feature_matrix;
00231 const float64_t* feature_matrix = parameters->feature_matrix;
00232 float64_t* s_values_vector = parameters->s_values_vector;
00233 float64_t* q_matrix = parameters->q_matrix;
00234 float64_t* W_matrix = parameters->W_matrix;
00235 #ifdef HAVE_PTHREAD
00236 PTHREAD_LOCK_T* W_matrix_lock = parameters->W_matrix_lock;
00237 #endif
00238
00239 int i,j,k;
00240
00241 for (i=idx_start; i<idx_stop; i+=idx_step)
00242 {
00243 for (j=0; j<m_k; j++)
00244 G_matrix[j] = 1.0/CMath::sqrt((float64_t)m_k);
00245
00246
00247 for (j=0; j<dim; j++)
00248 mean_vector[j] = 0.0;
00249
00250
00251 for (j=0; j<m_k; j++)
00252 {
00253 for (k=0; k<dim; k++)
00254 {
00255 local_feature_matrix[j*dim+k] = feature_matrix[neighborhood_matrix[j*N+i]*dim+k];
00256 mean_vector[k] += local_feature_matrix[j*dim+k];
00257 }
00258 }
00259
00260
00261 for (j=0; j<dim; j++)
00262 mean_vector[j] /= m_k;
00263
00264
00265 for (j=0; j<m_k; j++)
00266 {
00267 for (k=0; k<dim; k++)
00268 local_feature_matrix[j*dim+k] -= mean_vector[k];
00269 }
00270
00271 int32_t info = 0;
00272
00273 wrap_dgesvd('N','O', dim,m_k,local_feature_matrix,dim,
00274 s_values_vector,
00275 NULL,1, NULL,1, &info);
00276 ASSERT(info==0);
00277
00278 for (j=0; j<m_target_dim; j++)
00279 {
00280 for (k=0; k<m_k; k++)
00281 G_matrix[(j+1)*m_k+k] = local_feature_matrix[k*dim+j];
00282 }
00283
00284
00285 cblas_dgemm(CblasColMajor,CblasNoTrans,CblasTrans,
00286 m_k,m_k,1+m_target_dim,
00287 1.0,G_matrix,m_k,
00288 G_matrix,m_k,
00289 0.0,q_matrix,m_k);
00290
00291
00292 #ifdef HAVE_PTHREAD
00293 PTHREAD_LOCK(W_matrix_lock);
00294 #endif
00295 for (j=0; j<m_k; j++)
00296 {
00297 W_matrix[N*neighborhood_matrix[j*N+i]+neighborhood_matrix[j*N+i]] += 1.0;
00298
00299 for (k=0; k<m_k; k++)
00300 W_matrix[N*neighborhood_matrix[k*N+i]+neighborhood_matrix[j*N+i]] -= q_matrix[j*m_k+k];
00301 }
00302 #ifdef HAVE_PTHREAD
00303 PTHREAD_UNLOCK(W_matrix_lock);
00304 #endif
00305 }
00306 return NULL;
00307 }
00308
00309 #endif