void bof_compute_subsets(int k, int d, const float *centroids, int n, const float *v, int n_subset, const int *subset_indexes, const int *subset_ends, float *desc) { int *assign=ivec_new(n); nn (n, k, d, centroids, v, assign); fvec_0 (desc, k * n_subset); int ss, ss_begin = 0; for (ss = 0 ; ss < n_subset ; ss++) { float *descss = desc + ss * k; int ss_end = subset_ends[ss], ii; for (ii = ss_begin ; ii < ss_end ; ii++) { int i = subset_indexes[ii]; descss[assign[i]] ++; } ss_begin = ss_end; } free (assign); }
void vlad_compute_subsets(int k, int d, const float *centroids, int n, const float *v, int n_subset, const int *subset_indexes, const int *subset_ends, float *desc) { int j; int *assign = ivec_new(n); nn (n, k, d, centroids, v, assign); fvec_0 (desc, k * d * n_subset); int ss, ss_begin = 0; for (ss = 0 ; ss < n_subset ; ss++) { float *descss = desc + ss * k * d; int ss_end = subset_ends[ss], ii; for (ii = ss_begin ; ii < ss_end ; ii++) { int i = subset_indexes[ii]; for (j = 0 ; j < d ; j++) descss[assign[i]*d+j] += v[i*d+j] - centroids[assign[i]*d+j]; } ss_begin = ss_end; } free(assign); }
float *fmat_new_covariance (int d, int n, const float *v, float *avg, int assume_centered) { long i, j; float *cov = fvec_new_0 (d * d); if(!assume_centered) { float *sums = avg ? avg : fvec_new(d); fvec_0(sums,d); for (i = 0; i < n; i++) for (j = 0; j < d; j++) sums[j] += v[i * d + j]; for (i = 0; i < d; i++) for (j = 0; j < d; j++) cov[i + j * d] = sums[i] * sums[j]; if(avg) for(i=0;i<d;i++) avg[i]/=n; else free (sums); } FINTEGER di=d,ni=n; if(0) { float alpha = 1.0 / n, beta = -1.0 / (n * n); sgemm_ ("N", "T", &di, &di, &ni, &alpha, v, &di, v, &di, &beta, cov, &di); } else if(1) { /* transpose input matrix */ float *vt=fvec_new(n*d); for(i=0;i<d;i++) for(j=0;j<n;j++) vt[i*n+j]=v[j*d+i]; float alpha = 1.0 / n, beta = -1.0 / (n * n); sgemm_ ("T", "N", &di, &di, &ni, &alpha, vt, &ni, vt, &ni, &beta, cov, &di); free(vt); } else { float alpha = 1.0 / n, beta = -1.0 / (n * n); ssyrk_("L","N", &di, &ni, &alpha,(float*)v,&di,&beta,cov,&di); /* copy lower triangle to upper */ for(i=0;i<d;i++) for(j=i+1;j<d;j++) cov[i+j*d]=cov[j+i*d]; } return cov; }
void fmat_sum_rows (const float * a, int nrow, int ncol, float * sums) { long i, j; fvec_0 (sums, nrow); for(j=0 ; j<ncol ; j++) for (i=0 ; i<nrow ; i++) sums[i] += a[nrow*j+i]; }
void vlad_compute(int k, int d, const float *centroids, int n, const float *v, float *desc) { int i,j; int *assign = ivec_new (n); nn (n, k, d, centroids, v, assign); fvec_0 (desc, k * d); for (i = 0 ; i < n ; i++) { for (j = 0 ; j < d ; j++) desc[assign[i]*d+j] += v[i*d+j] - centroids[assign[i]*d+j]; } free(assign); }
void vlad_compute_weighted(int k, int d, const float *centroids, int n, const float *v, const float *weights, float *desc) { int i,j; int *assign=ivec_new(n); nn(n,k,d,centroids,v,assign,NULL,NULL); fvec_0(desc,k*d); for(i=0;i<n;i++) { float w=weights[i]; for(j=0;j<d;j++) desc[assign[i]*d+j] += (v[i*d+j]-centroids[assign[i]*d+j])*w; } free(assign); }
/* estimate the GMM parameters */ static void gmm_compute_params (int n, const float * v, const float * p, gmm_t * g, int flags, int n_thread) { long i, j; long d=g->d, k=g->k; float * vtmp = fvec_new (d); float * mu_old = fvec_new_cpy (g->mu, k * d); float * w_old = fvec_new_cpy (g->w, k); fvec_0 (g->w, k); fvec_0 (g->mu, k * d); fvec_0 (g->sigma, k * d); if(0) { /* slow and simple */ for (j = 0 ; j < k ; j++) { double dtmp = 0; for (i = 0 ; i < n ; i++) { /* contribution to the gaussian weight */ dtmp += p[i * k + j]; /* contribution to mu */ fvec_cpy (vtmp, v + i * d, d); fvec_mul_by (vtmp, d, p[i * k + j]); fvec_add (g->mu + j * d, vtmp, d); /* contribution to the variance */ fvec_cpy (vtmp, v + i * d, d); fvec_sub (vtmp, mu_old + j * d, d); fvec_sqr (vtmp, d); fvec_mul_by (vtmp, d, p[i * k + j]); fvec_add (g->sigma + j * d, vtmp, d); } g->w[j] = dtmp; } } else { /* fast and complicated */ if(n_thread<=1) compute_sum_dcov(n,k,d,v,mu_old,p,g->mu,g->sigma,g->w); else compute_sum_dcov_thread(n,k,d,v,mu_old,p,g->mu,g->sigma,g->w,n_thread); } if(flags & GMM_FLAGS_1SIGMA) { for (j = 0 ; j < k ; j++) { float *sigma_j=g->sigma+j*d; double var=fvec_sum(sigma_j,d)/d; fvec_set(sigma_j,d,var); } } long nz=0; for(i=0; i<k*d; i++) if(g->sigma[i]<min_sigma) { g->sigma[i]=min_sigma; nz++; } if(nz) printf("WARN %ld sigma diagonals are too small (set to %g)\n",nz,min_sigma); for (j = 0 ; j < k ; j++) { fvec_div_by (g->mu + j * d, d, g->w[j]); fvec_div_by (g->sigma + j * d, d, g->w[j]); } assert(finite(fvec_sum(g->mu, k*d))); fvec_normalize (g->w, k, 1); printf ("w = "); fvec_print (g->w, k); double imfac = k * fvec_sum_sqr (g->w, k); printf (" imfac = %.3f\n", imfac); free (vtmp); free (w_old); free (mu_old); }
void vlad_compute(int k, int d, const float *centroids, int n, const float *v,int flags, float *desc) { int i,j,l,n_quantile,i0,i1,ai,a,ma,ni; int *perm ; float un , diff; float *tab,*u,*avg,*sum,*mom2,*dists; int *hist,*assign; if(flags<11 || flags>=13) { assign=ivec_new(n); nn(n,k,d,centroids,v,assign,NULL,NULL); if(flags==6 || flags==7) { n_quantile = flags==6 ? 3 : 1; fvec_0(desc,k*d*n_quantile); perm = ivec_new(n); tab = fvec_new(n); ivec_sort_index(assign,n,perm); i0=0; for(i=0;i<k;i++) { i1=i0; while(i1<n && assign[perm[i1]]==i) { i1++; } if(i1==i0) continue; for(j=0;j<d;j++) { for(l=i0;l<i1;l++) { tab[l-i0]=v[perm[l]*d+j]; } ni=i1-i0; fvec_sort(tab,ni); for(l=0;l<n_quantile;l++) { desc[(i*d+j)*n_quantile+l]=(tab[(l*ni+ni/2)/n_quantile]-centroids[i*d+j])*ni; } } i0=i1; } free(perm); free(tab); } else if(flags==5) { fvec_0(desc,k*d); for(i=0;i<n;i++) { for(j=0;j<d;j++) { desc[assign[i]*d+j]+=v[i*d+j]; } } } else if(flags==8 || flags==9) { fvec_0(desc,k*d); u = fvec_new(d); for(i=0;i<n;i++) { fvec_cpy(u,v+i*d,d); fvec_sub(u,centroids+assign[i]*d,d); un=(float)sqrt(fvec_norm2sqr(u,d)); if(un==0) continue; if(flags==8) { fvec_div_by(u,d,un); } else if(flags==9) { fvec_div_by(u,d,sqrt(un)); } fvec_add(desc+assign[i]*d,u,d); } free(u); } else if(flags==10) { fvec_0(desc,k*d); for(i=0;i<n;i++) { for(j=0;j<d;j++) { desc[assign[i]*d+j]+=v[i*d+j]; } } for(i=0;i<k;i++) { fvec_normalize(desc+i*d,d,2.0); } } else if(flags==13) { fvec_0(desc,k*d); for(i=0;i<n;i++) { for(j=0;j<d;j++) { desc[assign[i]*d+j]+=(float)sqr(v[i*d+j]-centroids[assign[i]*d+j]); } } } else if(flags==14) { avg = fvec_new_0(k*d); for(i=0;i<n;i++) { for(j=0;j<d;j++) { avg[assign[i]*d+j]+=v[i*d+j]-centroids[assign[i]*d+j]; } } hist=ivec_new_histogram(k,assign,n); for(i=0;i<k;i++) { if(hist[i]>0) { for(j=0;j<d;j++) { avg[i*d+j]/=hist[i]; } } } free(hist); fvec_0(desc,k*d); for(i=0;i<n;i++) { for(j=0;j<d;j++) { desc[assign[i]*d+j]+=(float)(sqr(v[i*d+j]-centroids[assign[i]*d+j]-avg[assign[i]*d+j])); } } fvec_sqrt(desc,k*d); free(avg); } else if(flags==15) { fvec_0(desc,k*d*2); sum = desc; for(i=0;i<n;i++) { for(j=0;j<d;j++) { sum[assign[i]*d+j]+=v[i*d+j]-centroids[assign[i]*d+j]; } } hist = ivec_new_histogram(k,assign,n); mom2 = desc+k*d; for(i=0;i<n;i++) { ai=assign[i]; for(j=0;j<d;j++) { mom2[ai*d+j]+=(float)(sqr(v[i*d+j]-centroids[ai*d+j]-sum[ai*d+j]/hist[ai])); } } fvec_sqrt(mom2,k*d); free(hist); } else if(flags==17) { fvec_0(desc,k*d*2); for(i=0;i<n;i++) { for(j=0;j<d;j++) { diff=v[i*d+j]-centroids[assign[i]*d+j]; if(diff>0) { desc[assign[i]*d+j]+=diff; } else { desc[assign[i]*d+j+k*d]-=diff; } } } } else { fvec_0(desc,k*d); for(i=0;i<n;i++) { for(j=0;j<d;j++) { desc[assign[i]*d+j]+=v[i*d+j]-centroids[assign[i]*d+j]; } } if(flags==1) { hist=ivec_new_histogram(k,assign,n); /* printf("unbalance factor=%g\n",ivec_unbalanced_factor(hist,k)); */ for(i=0;i<k;i++) { for(j=0;j<d;j++) { desc[i*d+j]/=hist[i]; } } free(hist); } if(flags==2) { for(i=0;i<k;i++) { fvec_normalize(desc+i*d,d,2.0); } } if(flags==3 || flags==4) { assert(!"not implemented"); } if(flags==16) { hist=ivec_new_histogram(k,assign,n); for(i=0;i<k;i++) { if(hist[i]>0) { fvec_norm(desc+i*d,d,2); fvec_mul_by(desc+i*d,d,sqrt(hist[i])); } } free(hist); } } free(assign); } else if(flags==11 || flags==12) { ma=flags==11 ? 4 : 2; assign=ivec_new(n*ma); dists=knn(n,k,d,ma,centroids,v,assign,NULL,NULL); fvec_0(desc,k*d); for(i=0;i<n;i++) { for(j=0;j<d;j++) { for(a=0;a<ma;a++) { desc[assign[ma*i+a]*d+j]+=v[i*d+j]-centroids[assign[ma*i+a]*d+j]; } } } free(dists); free(assign); } }