SHOGUN  v2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
KernelLocalTangentSpaceAlignment.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 2011 Sergey Lisitsyn
8  * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
9  */
10 
12 #ifdef HAVE_LAPACK
15 #include <shogun/lib/Time.h>
16 #include <shogun/lib/common.h>
17 #include <shogun/lib/SGMatrix.h>
19 #include <shogun/io/SGIO.h>
21 #include <shogun/lib/Signal.h>
22 #include <shogun/base/Parallel.h>
23 
24 #ifdef HAVE_PTHREAD
25 #include <pthread.h>
26 #endif
27 
28 using namespace shogun;
29 
30 #ifndef DOXYGEN_SHOULD_SKIP_THIS
31 struct KLTSA_THREAD_PARAM
32 {
34  int32_t idx_start;
36  int32_t idx_step;
38  int32_t idx_stop;
40  int32_t m_k;
42  int32_t target_dim;
44  int32_t N;
46  const int32_t* neighborhood_matrix;
48  const float64_t* kernel_matrix;
50  float64_t* local_gram_matrix;
52  float64_t* ev_vector;
54  float64_t* G_matrix;
56  float64_t* W_matrix;
57 #ifdef HAVE_PTHREAD
58 
59  PTHREAD_LOCK_T* W_matrix_lock;
60 #endif
61 };
62 #endif
63 
66 {
67 }
68 
71 {
72 }
73 
75 {
76 }
77 
79 {
80  return "KernelLocalTangentSpaceAlignment";
81 };
82 
84  SGMatrix<int32_t> neighborhood_matrix)
85 {
86  int32_t N = kernel_matrix.num_cols;
87  int32_t t;
88 #ifdef HAVE_PTHREAD
89  int32_t num_threads = parallel->get_num_threads();
90  ASSERT(num_threads>0);
91  // allocate threads and params
92  pthread_t* threads = SG_MALLOC(pthread_t, num_threads);
93  KLTSA_THREAD_PARAM* parameters = SG_MALLOC(KLTSA_THREAD_PARAM, num_threads);
94 #else
95  int32_t num_threads = 1;
96 #endif
97 
98  // init matrices and norm factor to be used
99  float64_t* local_gram_matrix = SG_MALLOC(float64_t, m_k*m_k*num_threads);
100  float64_t* G_matrix = SG_MALLOC(float64_t, m_k*(1+m_target_dim)*num_threads);
101  float64_t* W_matrix = SG_CALLOC(float64_t, N*N);
102  float64_t* ev_vector = SG_MALLOC(float64_t, m_k*num_threads);
103 
104 #ifdef HAVE_PTHREAD
105  PTHREAD_LOCK_T W_matrix_lock;
106  pthread_attr_t attr;
107  PTHREAD_LOCK_INIT(&W_matrix_lock);
108  pthread_attr_init(&attr);
109  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
110 
111  for (t=0; t<num_threads; t++)
112  {
113  KLTSA_THREAD_PARAM params = {t,num_threads,N,m_k,m_target_dim,N,neighborhood_matrix.matrix,
114  kernel_matrix.matrix,local_gram_matrix+(m_k*m_k)*t,ev_vector+m_k*t,
115  G_matrix+(m_k*(1+m_target_dim))*t,W_matrix,&W_matrix_lock};
116  parameters[t] = params;
117  pthread_create(&threads[t], &attr, run_kltsa_thread, (void*)&parameters[t]);
118  }
119  for (t=0; t<num_threads; t++)
120  pthread_join(threads[t], NULL);
121  PTHREAD_LOCK_DESTROY(&W_matrix_lock);
122  SG_FREE(parameters);
123  SG_FREE(threads);
124 #else
125  KLTSA_THREAD_PARAM single_thread_param = {0,1,N,m_k,m_target_dim,N,neighborhood_matrix.matrix,
126  kernel_matrix.matrix,local_gram_matrix,ev_vector,
127  G_matrix,W_matrix};
128  run_kltsa_thread((void*)&single_thread_param);
129 #endif
130 
131  // clean
132  SG_FREE(local_gram_matrix);
133  SG_FREE(ev_vector);
134  SG_FREE(G_matrix);
135 
136  for (int32_t i=0; i<N; i++)
137  {
138  for (int32_t j=0; j<m_k; j++)
139  W_matrix[N*neighborhood_matrix[i*m_k+j]+neighborhood_matrix[i*m_k+j]] += 1.0;
140  }
141 
142  return SGMatrix<float64_t>(W_matrix,N,N);
143 }
144 
146 {
147  KLTSA_THREAD_PARAM* parameters = (KLTSA_THREAD_PARAM*)p;
148  int32_t idx_start = parameters->idx_start;
149  int32_t idx_step = parameters->idx_step;
150  int32_t idx_stop = parameters->idx_stop;
151  int32_t m_k = parameters->m_k;
152  int32_t target_dim = parameters->target_dim;
153  int32_t N = parameters->N;
154  const int32_t* neighborhood_matrix = parameters->neighborhood_matrix;
155  const float64_t* kernel_matrix = parameters->kernel_matrix;
156  float64_t* ev_vector = parameters->ev_vector;
157  float64_t* G_matrix = parameters->G_matrix;
158  float64_t* local_gram_matrix = parameters->local_gram_matrix;
159  float64_t* W_matrix = parameters->W_matrix;
160 #ifdef HAVE_PTHREAD
161  PTHREAD_LOCK_T* W_matrix_lock = parameters->W_matrix_lock;
162 #endif
163 
164  int32_t i,j,k;
165 
166  for (j=0; j<m_k; j++)
167  G_matrix[j] = 1.0/CMath::sqrt((float64_t)m_k);
168 
169  for (i=idx_start; i<idx_stop; i+=idx_step)
170  {
171  for (j=0; j<m_k; j++)
172  {
173  for (k=0; k<m_k; k++)
174  local_gram_matrix[j*m_k+k] = kernel_matrix[neighborhood_matrix[i*m_k+j]*N+neighborhood_matrix[i*m_k+k]];
175  }
176 
177  SGMatrix<float64_t>::center_matrix(local_gram_matrix,m_k,m_k);
178 
179  int32_t info = 0;
180  wrap_dsyevr('V','U',m_k,local_gram_matrix,m_k,m_k-target_dim+1,m_k,ev_vector,G_matrix+m_k,&info);
181  ASSERT(info==0);
182 
183  cblas_dgemm(CblasColMajor,CblasNoTrans,CblasTrans,
184  m_k,m_k,1+target_dim,
185  1.0,G_matrix,m_k,
186  G_matrix,m_k,
187  0.0,local_gram_matrix,m_k);
188 
189 #ifdef HAVE_PTHREAD
190  PTHREAD_LOCK(W_matrix_lock);
191 #endif
192  for (j=0; j<m_k; j++)
193  {
194  for (k=0; k<m_k; k++)
195  W_matrix[N*neighborhood_matrix[i*m_k+k]+neighborhood_matrix[i*m_k+j]] -= local_gram_matrix[j*m_k+k];
196  }
197 #ifdef HAVE_PTHREAD
198  PTHREAD_UNLOCK(W_matrix_lock);
199 #endif
200  }
201  return NULL;
202 }
203 
204 #endif /* HAVE_LAPACK */

SHOGUN Machine Learning Toolbox - Documentation