PLearn 0.1
|
00001 // -*- C++ -*- 00002 // convolutions.cc 00003 00004 // PLearn (A C++ Machine Learning Library) 00005 // Copyright (C) 1998 Pascal Vincent 00006 // Copyright (C) 1999-2002 Pascal Vincent, Yoshua Bengio and University of 00007 // Montreal 00008 // 00009 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are met: 00012 // 00013 // 1. Redistributions of source code must retain the above copyright 00014 // notice, this list of conditions and the following disclaimer. 00015 // 00016 // 2. Redistributions in binary form must reproduce the above copyright 00017 // notice, this list of conditions and the following disclaimer in the 00018 // documentation and/or other materials provided with the distribution. 00019 // 00020 // 3. The name of the authors may not be used to endorse or promote 00021 // products derived from this software without specific prior written 00022 // permission. 00023 // 00024 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00025 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00026 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00027 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00028 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00029 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00030 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00031 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00032 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00033 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 // 00035 // This file is part of the PLearn library. For more information on the PLearn 00036 // library, go to the PLearn Web site at www.plearn.org 00037 00038 00039 /* ******************************************************* 00040 * $Id$ 00041 * This file is part of the PLearn library. 00042 ******************************************************* */ 00043 00047 #include "convolutions.h" 00048 00049 namespace PLearn { 00050 using namespace std; 00051 00052 void convolve1D(const Vec& source_signal, const Vec& kernel, 00053 const Vec& dest_signal, int step, bool accumulate) 00054 { 00055 int nk=kernel.length(); 00056 int nd=dest_signal.length(); 00057 #ifdef BOUNDCHECK 00058 int ns=source_signal.length(); 00059 if (step<1) 00060 PLERROR("convolve1D: step (%d) should be a positive integer\n",step); 00061 if (ns!=step*(nd-1)+nk) 00062 PLERROR("convolve1D: source_signal.length() (%d) should equal %d:\n" 00063 "step (%d) * (dest_signal.length() (%d) - 1) + kernel.length()" 00064 " (%d)\n", 00065 ns,step*(nd-1)+nk,step,nd,nk); 00066 #endif 00067 if (!accumulate) 00068 dest_signal.clear(); 00069 real* s=source_signal.data(); 00070 real* k=kernel.data(); 00071 real* d=dest_signal.data(); 00072 for (int i=0;i<nd;i++,s+=step) 00073 { 00074 real somme=0; 00075 for (int j=0;j<nk;j++) 00076 somme += s[j]*k[j]; 00077 d[i]+=somme; 00078 } 00079 } 00080 00081 void backConvolve1D(const Vec& source_signal, const Vec& kernel, 00082 const Vec& dest_signal, int step, bool accumulate) 00083 { 00084 int nk=kernel.length(); 00085 int nd=dest_signal.length(); 00086 #ifdef BOUNDCHECK 00087 int ns=source_signal.length(); 00088 if (step<1) 00089 PLERROR("backConvolve1D: step (%d) should be a positive integer\n", 00090 step); 00091 if (ns!=step*(nd-1)+nk) 00092 PLERROR("backConvolve1D: source_signal.length() (%d) should equal %d:\n" 00093 "step (%d) * (dest_signal.length() (%d) - 1) + kernel.length()" 00094 " (%d)\n", 00095 ns,step*(nd-1)+nk,step,nd,nk); 00096 #endif 00097 if (!accumulate) 00098 source_signal.clear(); 00099 real* s=source_signal.data(); 00100 real* k=kernel.data(); 00101 real* d=dest_signal.data(); 00102 for (int i=0;i<nd;i++,s+=step) 00103 { 00107 real di=d[i]; 00108 for (int j=0;j<nk;j++) 00109 s[j] += di*k[j]; 00110 } 00111 } 00112 00113 00114 void convolve1Dbackprop(const Vec& source_signal, const Vec& kernel, 00115 const Vec& dC_ddest_signal, 00116 const Vec& dC_dsource_signal, const Vec& dC_dkernel, 00117 int step, bool accumulate) 00118 { 00119 int nk=kernel.length(); 00120 int nd=dC_ddest_signal.length(); 00121 #ifdef BOUNDCHECK 00122 int ns=source_signal.length(); 00123 if (step<1) 00124 PLERROR("convolve1Dbackprop: step (%d) should be a positive integer\n", 00125 step); 00126 if (ns!=step*(nd-1)+nk) 00127 PLERROR("convolve1Dbackprop: source_signal.length() (%d) should" 00128 " equal %d:\n" 00129 "step (%d) * (dC_ddest_signal.length() (%d) - 1) +" 00130 " kernel.length() (%d)\n", 00131 ns,step*(nd-1)+nk,step,nd,nk); 00132 if (dC_dsource_signal.length()!=ns) 00133 PLERROR("convolve1Dbackprop: source_signal.length() (%d) should" 00134 " equal:\n" 00135 "dC_dsource_signal.length() (%d)\n", 00136 ns,dC_dsource_signal.length()); 00137 if (dC_dkernel.length()!=nk) 00138 PLERROR("convolve1Dbackprop: kernel.length() (%d) should equal:\n" 00139 " dC_dkernel.length() (%d)\n", 00140 nk,dC_dkernel.length()); 00141 #endif 00142 if (!accumulate) 00143 { 00144 dC_dsource_signal.clear(); 00145 dC_dkernel.clear(); 00146 } 00147 real* s=source_signal.data(); 00148 real* dCds=dC_dsource_signal.data(); 00149 real* k=kernel.data(); 00150 real* dCdk=dC_dkernel.data(); 00151 real* dCdd=dC_ddest_signal.data(); 00152 00157 for (int i=0;i<nd;i++,dCds+=step,s+=step) 00158 { 00159 real di=dCdd[i]; 00160 for (int j=0;j<nk;j++) 00161 { 00162 dCds[j] += di*k[j]; 00163 dCdk[j] += di*s[j]; 00164 } 00165 } 00166 } 00167 00168 void convolve1Dbackprop(const Vec& source_signal, 00169 const Vec& dC_ddest_signal, 00170 const Vec& dC_dkernel, 00171 int step, bool accumulate) 00172 { 00173 int nk=dC_dkernel.length(); 00174 int nd=dC_ddest_signal.length(); 00175 #ifdef BOUNDCHECK 00176 int ns=source_signal.length(); 00177 if (step<1) 00178 PLERROR("convolve1Dbackprop: step (%d) should be a positive integer\n", 00179 step); 00180 if (ns!=step*(nd-1)+nk) 00181 PLERROR("convolve1Dbackprop: source_signal.length() (%d) should" 00182 " equal %d:\n" 00183 "step (%d) * (dC_ddest_signal.length() (%d) - 1) +" 00184 " dC_dkernel.length() (%d)\n", 00185 ns,step*(nd-1)+nk,step,nd,nk); 00186 #endif 00187 if (!accumulate) 00188 dC_dkernel.clear(); 00189 00190 real* s=source_signal.data(); 00191 real* dCdk=dC_dkernel.data(); 00192 real* dCdd=dC_ddest_signal.data(); 00193 00197 for (int i=0;i<nd;i++,s+=step) 00198 { 00199 real di=dCdd[i]; 00200 for (int j=0;j<nk;j++) 00201 dCdk[j] += di*s[j]; 00202 } 00203 } 00204 00205 00206 void backConvolve1Dbackprop(const Vec& kernel, const Vec& dest_signal, 00207 const Vec& dC_ddest_signal, 00208 const Vec& dC_dsource_signal, 00209 const Vec& dC_dkernel, 00210 int step, bool accumulate) 00211 { 00212 int nk=kernel.length(); 00213 int nd=dest_signal.length(); 00214 #ifdef BOUNDCHECK 00215 int ns=dC_dsource_signal.length(); 00216 if (step<1) 00217 PLERROR("backConvolve1Dbackprop: step (%d) should be a positive" 00218 " integer\n", 00219 step); 00220 if (ns!=step*(nd-1)+nk) 00221 PLERROR("backConvolve1Dbackprop: dC_dsource_signal.length() (%d)\n" 00222 "should equal %d:\n" 00223 "step (%d) * (dest_signal.length() (%d) - 1) + kernel.length()" 00224 " (%d)\n", 00225 ns,step*(nd-1)+nk,step,nd,nk); 00226 if (dC_ddest_signal.length()!=nd) 00227 PLERROR("backConvolve1Dbackprop: dest_signal.length() (%d) should" 00228 " equal:\n" 00229 "dC_ddest_signal.length() (%d)\n", 00230 nd,dC_ddest_signal.length()); 00231 if (dC_dkernel.length()!=nk) 00232 PLERROR("backConvolve1Dbackprop: kernel.length() (%d) should equal:\n" 00233 " dC_dkernel.length() (%d)\n", 00234 nk,dC_dkernel.length()); 00235 #endif 00236 if (!accumulate) 00237 { 00238 dC_ddest_signal.clear(); 00239 dC_dkernel.clear(); 00240 } 00241 real* k=kernel.data(); 00242 real* dCdk=dC_dkernel.data(); 00243 real* dCdd=dC_ddest_signal.data(); 00244 real* d=dest_signal.data(); 00245 real* dCds=dC_dsource_signal.data(); 00246 00251 for (int i=0;i<nd;i++,dCds+=step) 00252 { 00253 real di = d[i]; 00254 real dCdd_i_sum = 0; 00255 for (int j=0;j<nk;j++) 00256 { 00257 dCdd_i_sum += dCds[j]*k[j]; 00258 dCdk[j] += dCds[j]*di; 00259 } 00260 dCdd[i] += dCdd_i_sum; 00261 } 00262 } 00263 00264 00265 void backConvolve1Dbackprop(const Vec& dest_signal, 00266 const Vec& dC_dsource_signal, 00267 const Vec& dC_dkernel, 00268 int step, bool accumulate) 00269 { 00270 int nk=dC_dkernel.length(); 00271 int nd=dest_signal.length(); 00272 #ifdef BOUNDCHECK 00273 int ns=dC_dsource_signal.length(); 00274 if (step<1) 00275 PLERROR("backConvolve1Dbackprop: step (%d) should be a positive" 00276 " integer\n", 00277 step); 00278 if (ns!=step*(nd-1)+nk) 00279 PLERROR("backConvolve1Dbackprop: dC_dsource_signal.length() (%d)\n" 00280 "should equal %d:\n" 00281 "step (%d) * (dest_signal.length() (%d) - 1) + dC_dkernel.length()" 00282 " (%d)\n", 00283 ns,step*(nd-1)+nk,step,nd,nk); 00284 #endif 00285 if (!accumulate) 00286 dC_dkernel.clear(); 00287 00288 real* dCdk=dC_dkernel.data(); 00289 real* d=dest_signal.data(); 00290 real* dCds=dC_dsource_signal.data(); 00291 00295 for (int i=0;i<nd;i++,dCds+=step) 00296 { 00297 real di = d[i]; 00298 for (int j=0;j<nk;j++) 00299 dCdk[j] += dCds[j]*di; 00300 } 00301 } 00302 00303 00304 void convolve2D(const Mat& source_image, const Mat& kernel, 00305 const Mat& dest_image, 00306 int step1, int step2, bool accumulate) 00307 { 00308 int kl = kernel.length(); 00309 int kw = kernel.width(); 00310 int dl = dest_image.length(); 00311 int dw = dest_image.width(); 00312 00313 #ifdef BOUNDCHECK 00314 int sl = source_image.length(); 00315 int sw = source_image.width(); 00316 00317 if (step1<1) 00318 PLERROR("convolve2D: step1 (%d) should be a positive integer\n",step1); 00319 if (sl != step1*(dl-1)+kl) 00320 PLERROR("convolve2D: source_image.length() (%d) should equal %d:\n" 00321 "step1 (%d) * (dest_image.length() (%d) - 1) + kernel.length()" 00322 " (%d)\n", 00323 sl, step1*(dl-1)+kl, step1, dl, kl); 00324 00325 if (step2<1) 00326 PLERROR("convolve2D: step2 (%d) should be a positive integer\n",step2); 00327 if (sw != step2*(dw-1)+kw) 00328 PLERROR("convolve2D: source_image.width() (%d) should equal %d:\n" 00329 "step2 (%d) * (dest_image.width() (%d) - 1) + kernel.width()" 00330 " (%d)\n", 00331 sw, step2*(dw-1)+kw, step2, dw, kw); 00332 #endif 00333 if (!accumulate) 00334 dest_image.clear(); 00335 int sm = source_image.mod(); 00336 int dm = dest_image.mod(); 00337 int km = kernel.mod(); 00338 real* source_i = source_image.data(); // source_image[i*step1] 00339 real* dest_i = dest_image.data(); // dest_image[i] 00340 for (int i=0; i<dl; i++, source_i+=sm*step1, dest_i+=dm) 00341 { 00342 real* source_i_j = source_i; // source_image[i*step1][j*step2] 00343 for (int j=0; j<dw; j++, source_i_j+=step2) 00344 { 00345 real sum = 0; 00346 real* kernel_k = kernel.data(); // kernel[k] 00347 real* source_ik_j = source_i_j; // source_image[i*step1+k][j*step2] 00348 for (int k=0; k<kl; k++, source_ik_j+=sm, kernel_k+=km) 00349 for (int l=0; l<kw; l++) 00350 sum += source_ik_j[l] * kernel_k[l]; 00351 dest_i[j] += sum; 00352 } 00353 } 00354 } 00355 00356 void backConvolve2D(const Mat& source_image, const Mat& kernel, 00357 const Mat& dest_image, 00358 int step1, int step2, bool accumulate) 00359 { 00360 int n1k=kernel.length(); 00361 int n2k=kernel.width(); 00362 int n1d=dest_image.length(); 00363 int n2d=dest_image.width(); 00364 #ifdef BOUNDCHECK 00365 int n1s=source_image.length(); 00366 int n2s=source_image.width(); 00367 if (step1<1) 00368 PLERROR("backConvolve2D: step1 (%d) should be a positive integer\n", 00369 step1); 00370 if (n1s!=step1*(n1d-1)+n1k) 00371 PLERROR("backConvolve2D: source_image.length() (%d) should equal %d:\n" 00372 "step1 (%d) * (dest_image.length() (%d) - 1) + kernel.length()" 00373 " (%d)\n", 00374 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k); 00375 00376 if (step2<1) 00377 PLERROR("backConvolve2D: step2 (%d) should be a positive integer\n", 00378 step2); 00379 if (n2s!=step2*(n2d-1)+n2k) 00380 PLERROR("backConvolve2D: source_image.width() (%d) should equal %d:\n" 00381 "step2 (%d) * (dest_image.width() (%d) - 1) + kernel.width()" 00382 " (%d)\n", 00383 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k); 00384 #endif 00385 if (!accumulate) 00386 source_image.clear(); 00387 int sm = source_image.mod(); 00388 int dm = dest_image.mod(); 00389 int km = kernel.mod(); 00390 real* s = source_image.data(); 00391 real* d = dest_image.data(); 00392 for (int i=0;i<n1d;i++,s+=sm*step1,d+=dm) 00393 { 00394 real* s1 = s; // copy to iterate over columns 00395 for (int j=0;j<n2d;j++,s1+=step2) 00396 { 00397 real* k = kernel.data(); 00398 real* ss = s1; // copy to iterate over sub-rows 00399 real d_ij=d[j]; 00400 for (int l=0;l<n1k;l++,ss+=sm,k+=km) 00401 { 00402 for (int m=0;m<n2k;m++) 00403 ss[m] += d_ij * k[m]; 00404 } 00405 } 00406 } 00407 } 00408 00409 void convolve2Dbackprop(const Mat& source_image, const Mat& kernel, 00410 const Mat& dC_ddest_image, 00411 const Mat& dC_dsource_image, const Mat& dC_dkernel, 00412 int step1, int step2, bool accumulate) 00413 { 00414 int n1k=kernel.length(); 00415 int n2k=kernel.width(); 00416 int n1d=dC_ddest_image.length(); 00417 int n2d=dC_ddest_image.width(); 00418 #ifdef BOUNDCHECK 00419 int n1s=source_image.length(); 00420 int n2s=source_image.width(); 00421 if (step1<1) 00422 PLERROR("convolve2Dbackprop: step1 (%d) should be a positive integer\n", 00423 step1); 00424 if (n1s!=step1*(n1d-1)+n1k) 00425 PLERROR("convolve2Dbackprop: source_image.length() (%d) should equal" 00426 " %d:\n" 00427 "step1 (%d) * (dest_image.length() (%d) - 1) + kernel.length()" 00428 " (%d)\n", 00429 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k); 00430 if (dC_dsource_image.length()!=n1s) 00431 PLERROR("convolve2Dbackprop: source_image.length() (%d) should" 00432 " equal:\n" 00433 "dC_dsource_image.length() (%d)\n", 00434 n1s,dC_dsource_image.length()); 00435 if (dC_dkernel.length()!=n1k) 00436 PLERROR("convolve2Dbackprop: kernel.length() (%d) should equal:\n" 00437 " dC_dkernel.length() (%d)\n", 00438 n1k,dC_dkernel.length()); 00439 00440 if (step2<1) 00441 PLERROR("convolve2Dbackprop: step2 (%d) should be a positive integer\n", 00442 step2); 00443 if (n2s!=step2*(n2d-1)+n2k) 00444 PLERROR("convolve2Dbackprop: source_image.width() (%d) should equal" 00445 " %d:\n" 00446 "step2 (%d) * (dest_image.width() (%d) - 1) + kernel.width()" 00447 " (%d)\n", 00448 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k); 00449 if (dC_dsource_image.width()!=n2s) 00450 PLERROR("convolve2Dbackprop: source_image.width() (%d) should" 00451 " equal:\n" 00452 "dC_dsource_image.width() (%d)\n", 00453 n2s,dC_dsource_image.width()); 00454 if (dC_dkernel.width()!=n2k) 00455 PLERROR("convolve2Dbackprop: kernel.width() (%d) should equal:\n" 00456 " dC_dkernel.width() (%d)\n", 00457 n2k,dC_dkernel.width()); 00458 #endif 00459 if (!accumulate) 00460 { 00461 dC_dsource_image.clear(); 00462 dC_dkernel.clear(); 00463 } 00464 int sm = source_image.mod(); 00465 int dCdsm = dC_dsource_image.mod(); 00466 int km = kernel.mod(); 00467 int dCdkm = dC_dkernel.mod(); 00468 int dCddm = dC_ddest_image.mod(); 00469 00470 real* s = source_image.data(); 00471 real* dCds = dC_dsource_image.data(); 00472 real* dCdd = dC_ddest_image.data(); 00473 00474 for (int i=0;i<n1d;i++,s+=sm*step1,dCds+=dCdsm*step1,dCdd+=dCddm) 00475 { 00476 real* s1 = s; // copy to iterate over columns 00477 real* dCds1 = dCds; 00478 for (int j=0;j<n2d;j++,s1+=step2,dCds1+=step2) 00479 { 00480 real* k = kernel.data(); 00481 real* dCdk = dC_dkernel.data(); 00482 real* ss = s1; // copy to iterate over sub-rows 00483 real* dCdss = dCds1; 00484 real dCdd_ij=dCdd[j]; 00485 for (int l=0;l<n1k;l++,ss+=sm,dCdss+=dCdsm,k+=km,dCdk+=dCdkm) 00486 { 00487 for (int m=0;m<n2k;m++) 00488 { 00489 dCdss[m] += dCdd_ij * k[m]; 00490 dCdk[m] += dCdd_ij * ss[m]; 00491 } 00492 } 00493 } 00494 } 00495 } 00496 00497 00498 void convolve2Dbackprop(const Mat& source_image, 00499 const Mat& dC_ddest_image, 00500 const Mat& dC_dkernel, 00501 int step1, int step2, bool accumulate) 00502 { 00503 int n1k=dC_dkernel.length(); 00504 int n2k=dC_dkernel.width(); 00505 int n1d=dC_ddest_image.length(); 00506 int n2d=dC_ddest_image.width(); 00507 #ifdef BOUNDCHECK 00508 int n1s=source_image.length(); 00509 int n2s=source_image.width(); 00510 if (step1<1) 00511 PLERROR("convolve2Dbackprop: step1 (%d) should be a positive integer\n", 00512 step1); 00513 if (n1s!=step1*(n1d-1)+n1k) 00514 PLERROR("convolve2Dbackprop: source_image.length() (%d) should equal" 00515 " %d:\n" 00516 "step1 (%d) * (dest_image.length() (%d) - 1) +" 00517 " dC_dkernel.length() (%d)\n", 00518 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k); 00519 00520 if (step2<1) 00521 PLERROR("convolve2Dbackprop: step2 (%d) should be a positive integer\n", 00522 step2); 00523 if (n2s!=step2*(n2d-1)+n2k) 00524 PLERROR("convolve2Dbackprop: source_image.width() (%d) should equal" 00525 " %d:\n" 00526 "step2 (%d) * (dest_image.width() (%d) - 1) +" 00527 " dC_dkernel.width() (%d)\n", 00528 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k); 00529 #endif 00530 if (!accumulate) 00531 dC_dkernel.clear(); 00532 00533 int sm = source_image.mod(); 00534 int dCdkm = dC_dkernel.mod(); 00535 int dCddm = dC_ddest_image.mod(); 00536 00537 real* s = source_image.data(); 00538 real* dCdd = dC_ddest_image.data(); 00539 00540 for (int i=0;i<n1d;i++,s+=sm*step1,dCdd+=dCddm) 00541 { 00542 real* s1 = s; // copy to iterate over columns 00543 for (int j=0;j<n2d;j++,s1+=step2) 00544 { 00545 real* dCdk = dC_dkernel.data(); 00546 real* ss = s1; // copy to iterate over sub-rows 00547 real dCdd_ij=dCdd[j]; 00548 for (int l=0;l<n1k;l++,ss+=sm,dCdk+=dCdkm) 00549 for (int m=0;m<n2k;m++) 00550 dCdk[m] += dCdd_ij * ss[m]; 00551 } 00552 } 00553 } 00554 00555 00556 void backConvolve2Dbackprop(const Mat& kernel, const Mat& dest_image, 00557 const Mat& dC_ddest_image, 00558 const Mat& dC_dsource_image, const Mat& dC_dkernel, 00559 int step1, int step2, bool accumulate) 00560 { 00561 int n1k=kernel.length(); 00562 int n2k=kernel.width(); 00563 int n1d=dest_image.length(); 00564 int n2d=dest_image.width(); 00565 #ifdef BOUNDCHECK 00566 int n1s=dC_dsource_image.length(); 00567 int n2s=dC_dsource_image.width(); 00568 if (step1<1) 00569 PLERROR("backConvolve2Dbackprop: step1 (%d) should be a positive" 00570 " integer\n", 00571 step1); 00572 if (n1s!=step1*(n1d-1)+n1k) 00573 PLERROR("backConvolve2Dbackprop: dC_dsource_image.length() (%d)\n" 00574 "should equal %d:\n" 00575 "step1 (%d) * (dest_image.length() (%d) - 1) + kernel.length()" 00576 " (%d)\n", 00577 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k); 00578 if (dC_ddest_image.length()!=n1d) 00579 PLERROR("backConvolve2Dbackprop: dest_image.length() (%d) should" 00580 " equal:\n" 00581 "dC_ddest_image.length() (%d)\n", 00582 n1d,dC_ddest_image.length()); 00583 if (dC_dkernel.length()!=n1k) 00584 PLERROR("backConvolve2Dbackprop: kernel.length() (%d) should equal:\n" 00585 " dC_dkernel.length() (%d)\n", 00586 n1k,dC_dkernel.length()); 00587 00588 if (step2<1) 00589 PLERROR("backConvolve2Dbackprop: step2 (%d) should be a positive" 00590 " integer\n", 00591 step2); 00592 if (n2s!=step2*(n2d-1)+n2k) 00593 PLERROR("backConvolve2Dbackprop: source_image.width() (%d)\n" 00594 "should equal %d:\n" 00595 "step2 (%d) * (dest_image.width() (%d) - 1) + kernel.width()" 00596 " (%d)\n", 00597 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k); 00598 if (dC_ddest_image.width()!=n2d) 00599 PLERROR("backConvolve2Dbackprop: dest_image.width() (%d) should" 00600 " equal:\n" 00601 "dC_ddest_image.width() (%d)\n", 00602 n2d,dC_ddest_image.width()); 00603 if (dC_dkernel.length()!=n2k) 00604 PLERROR("backConvolve2Dbackprop: kernel.width() (%d) should equal:\n" 00605 " dC_dkernel.width() (%d)\n", 00606 n2k,dC_dkernel.width()); 00607 #endif 00608 if (!accumulate) 00609 { 00610 dC_ddest_image.clear(); 00611 dC_dkernel.clear(); 00612 } 00613 int km = kernel.mod(); 00614 int dCdkm = dC_dkernel.mod(); 00615 int dm = dest_image.mod(); 00616 int dCddm = dC_ddest_image.mod(); 00617 int dCdsm = dC_dsource_image.mod(); 00618 00619 real* d = dest_image.data(); 00620 real* dCdd = dC_ddest_image.data(); 00621 real* dCds = dC_dsource_image.data(); 00622 00623 for (int i=0;i<n1d;i++,d+=dm,dCdd+=dCddm,dCds+=dCdsm*step1) 00624 { 00625 real* dCds1 = dCds; // copy to iterate over columns 00626 for (int j=0;j<n2d;j++,dCds1+=step2) 00627 { 00628 real* k = kernel.data(); 00629 real* dCdk = dC_dkernel.data(); 00630 real* dCdss = dCds1; // copy to iterate over sub-rows 00631 real d_ij=d[j]; 00632 real dCdd_ij_sum = 0; 00633 for (int l=0;l<n1k;l++,dCdss+=dCdsm,k+=km,dCdk+=dCdkm) 00634 { 00635 for (int m=0;m<n2k;m++) 00636 { 00637 dCdd_ij_sum += dCdss[m]*k[m]; 00638 dCdk[m] += dCdss[m]*d_ij; 00639 } 00640 } 00641 dCdd[j] += dCdd_ij_sum; 00642 } 00643 } 00644 } 00645 00646 void backConvolve2Dbackprop(const Mat& dest_image, 00647 const Mat& dC_dsource_image, 00648 const Mat& dC_dkernel, 00649 int step1, int step2, bool accumulate) 00650 { 00651 int n1k=dC_dkernel.length(); 00652 int n2k=dC_dkernel.width(); 00653 int n1d=dest_image.length(); 00654 int n2d=dest_image.width(); 00655 #ifdef BOUNDCHECK 00656 int n1s=dC_dsource_image.length(); 00657 int n2s=dC_dsource_image.width(); 00658 if (step1<1) 00659 PLERROR("backConvolve2Dbackprop: step1 (%d) should be a positive" 00660 " integer\n", 00661 step1); 00662 if (n1s!=step1*(n1d-1)+n1k) 00663 PLERROR("backConvolve2Dbackprop: dC_dsource_image.length() (%d)\n" 00664 "should equal %d:\n" 00665 "step1 (%d) * (dest_image.length() (%d) - 1) +" 00666 " dC_dkernel.length() (%d)\n", 00667 n1s,step1*(n1d-1)+n1k,step1,n1d,n1k); 00668 00669 if (step2<1) 00670 PLERROR("backConvolve2Dbackprop: step2 (%d) should be a positive" 00671 " integer\n", 00672 step2); 00673 if (n2s!=step2*(n2d-1)+n2k) 00674 PLERROR("backConvolve2Dbackprop: source_image.width() (%d)\n" 00675 "should equal %d:\n" 00676 "step2 (%d) * (dest_image.width() (%d) - 1) +" 00677 " dC_dkernel.width() (%d)\n", 00678 n2s,step2*(n2d-1)+n2k,step2,n2d,n2k); 00679 #endif 00680 if (!accumulate) 00681 dC_dkernel.clear(); 00682 00683 int dCdkm = dC_dkernel.mod(); 00684 int dm = dest_image.mod(); 00685 int dCdsm = dC_dsource_image.mod(); 00686 00687 real* d = dest_image.data(); 00688 real* dCds = dC_dsource_image.data(); 00689 00690 for (int i=0;i<n1d;i++,d+=dm,dCds+=dCdsm*step1) 00691 { 00692 real* dCds1 = dCds; // copy to iterate over columns 00693 for (int j=0;j<n2d;j++,dCds1+=step2) 00694 { 00695 real* dCdk = dC_dkernel.data(); 00696 real* dCdss = dCds1; // copy to iterate over sub-rows 00697 real d_ij=d[j]; 00698 for (int l=0;l<n1k;l++,dCdss+=dCdsm,dCdk+=dCdkm) 00699 for (int m=0;m<n2k;m++) 00700 dCdk[m] += dCdss[m]*d_ij; 00701 } 00702 } 00703 } 00704 00705 } // end of namespace PLearn 00706 00707 00708 /* 00709 Local Variables: 00710 mode:c++ 00711 c-basic-offset:4 00712 c-file-style:"stroustrup" 00713 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00714 indent-tabs-mode:nil 00715 fill-column:79 00716 End: 00717 */ 00718 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :