annotate dsp/segmentation/cluster_melt.c @ 84:e5907ae6de17

* Add GPL and README; some tidying
author Chris Cannam
date Mon, 13 Dec 2010 14:55:28 +0000
parents 8e90a56b4b5f
children e4a57215ddee
rev   line source
cannam@18 1 /*
cannam@18 2 * cluster.c
cannam@18 3 * cluster_melt
cannam@18 4 *
cannam@18 5 * Created by Mark Levy on 21/02/2006.
Chris@84 6 * Copyright 2006 Centre for Digital Music, Queen Mary, University of London.
Chris@84 7
Chris@84 8 This program is free software; you can redistribute it and/or
Chris@84 9 modify it under the terms of the GNU General Public License as
Chris@84 10 published by the Free Software Foundation; either version 2 of the
Chris@84 11 License, or (at your option) any later version. See the file
Chris@84 12 COPYING included with this distribution for more information.
cannam@18 13 *
cannam@18 14 */
cannam@18 15
cannam@18 16 #include <stdlib.h>
cannam@18 17
cannam@18 18 #include "cluster_melt.h"
cannam@18 19
cannam@18 20 #define DEFAULT_LAMBDA 0.02;
cannam@18 21 #define DEFAULT_LIMIT 20;
cannam@18 22
cannam@18 23 double kldist(double* a, double* b, int n) {
cannam@18 24 /* NB assume that all a[i], b[i] are non-negative
cannam@18 25 because a, b represent probability distributions */
cannam@18 26 double q, d;
cannam@18 27 int i;
cannam@18 28
cannam@18 29 d = 0;
cannam@18 30 for (i = 0; i < n; i++)
cannam@18 31 {
cannam@18 32 q = (a[i] + b[i]) / 2.0;
cannam@18 33 if (q > 0)
cannam@18 34 {
cannam@18 35 if (a[i] > 0)
cannam@18 36 d += a[i] * log(a[i] / q);
cannam@18 37 if (b[i] > 0)
cannam@18 38 d += b[i] * log(b[i] / q);
cannam@18 39 }
cannam@18 40 }
cannam@18 41 return d;
cannam@18 42 }
cannam@18 43
cannam@18 44 void cluster_melt(double *h, int m, int n, double *Bsched, int t, int k, int l, int *c) {
cannam@18 45 double lambda, sum, beta, logsumexp, maxlp;
cannam@18 46 int i, j, a, b, b0, b1, limit, B, it, maxiter, maxiter0, maxiter1;
cannam@18 47 double** cl; /* reference histograms for each cluster */
cannam@18 48 int** nc; /* neighbour counts for each histogram */
cannam@18 49 double** lp; /* soft assignment probs for each histogram */
cannam@18 50 int* oldc; /* previous hard assignments (to check convergence) */
cannam@18 51
cannam@18 52 /* NB h is passed as a 1d row major array */
cannam@18 53
cannam@18 54 /* parameter values */
cannam@18 55 lambda = DEFAULT_LAMBDA;
cannam@18 56 if (l > 0)
cannam@18 57 limit = l;
cannam@18 58 else
cannam@18 59 limit = DEFAULT_LIMIT; /* use default if no valid neighbourhood limit supplied */
cannam@18 60 B = 2 * limit + 1;
cannam@18 61 maxiter0 = 20; /* number of iterations at initial temperature */
cannam@18 62 maxiter1 = 5; /* number of iterations at subsequent temperatures */
cannam@18 63
cannam@18 64 /* allocate memory */
cannam@18 65 cl = (double**) malloc(k*sizeof(double*));
cannam@18 66 for (i= 0; i < k; i++)
cannam@18 67 cl[i] = (double*) malloc(m*sizeof(double));
cannam@18 68
cannam@18 69 nc = (int**) malloc(n*sizeof(int*));
cannam@18 70 for (i= 0; i < n; i++)
cannam@18 71 nc[i] = (int*) malloc(k*sizeof(int));
cannam@18 72
cannam@18 73 lp = (double**) malloc(n*sizeof(double*));
cannam@18 74 for (i= 0; i < n; i++)
cannam@18 75 lp[i] = (double*) malloc(k*sizeof(double));
cannam@18 76
cannam@18 77 oldc = (int*) malloc(n * sizeof(int));
cannam@18 78
cannam@18 79 /* initialise */
cannam@18 80 for (i = 0; i < k; i++)
cannam@18 81 {
cannam@18 82 sum = 0;
cannam@18 83 for (j = 0; j < m; j++)
cannam@18 84 {
cannam@18 85 cl[i][j] = rand(); /* random initial reference histograms */
cannam@18 86 sum += cl[i][j] * cl[i][j];
cannam@18 87 }
cannam@18 88 sum = sqrt(sum);
cannam@18 89 for (j = 0; j < m; j++)
cannam@18 90 {
cannam@18 91 cl[i][j] /= sum; /* normalise */
cannam@18 92 }
cannam@18 93 }
cannam@18 94 //print_array(cl, k, m);
cannam@18 95
cannam@18 96 for (i = 0; i < n; i++)
cannam@18 97 c[i] = 1; /* initially assign all histograms to cluster 1 */
cannam@18 98
cannam@18 99 for (a = 0; a < t; a++)
cannam@18 100 {
cannam@18 101 beta = Bsched[a];
cannam@18 102
cannam@18 103 if (a == 0)
cannam@18 104 maxiter = maxiter0;
cannam@18 105 else
cannam@18 106 maxiter = maxiter1;
cannam@18 107
cannam@18 108 for (it = 0; it < maxiter; it++)
cannam@18 109 {
cannam@18 110 //if (it == maxiter - 1)
cannam@18 111 // mexPrintf("hasn't converged after %d iterations\n", maxiter);
cannam@18 112
cannam@18 113 for (i = 0; i < n; i++)
cannam@18 114 {
cannam@18 115 /* save current hard assignments */
cannam@18 116 oldc[i] = c[i];
cannam@18 117
cannam@18 118 /* calculate soft assignment logprobs for each cluster */
cannam@18 119 sum = 0;
cannam@18 120 for (j = 0; j < k; j++)
cannam@18 121 {
cannam@18 122 lp[i][ j] = -beta * kldist(cl[j], &h[i*m], m);
cannam@18 123
cannam@18 124 /* update matching neighbour counts for this histogram, based on current hard assignments */
cannam@18 125 /* old version:
cannam@18 126 nc[i][j] = 0;
cannam@18 127 if (i >= limit && i <= n - 1 - limit)
cannam@18 128 {
cannam@18 129 for (b = i - limit; b <= i + limit; b++)
cannam@18 130 {
cannam@18 131 if (c[b] == j+1)
cannam@18 132 nc[i][j]++;
cannam@18 133 }
cannam@18 134 nc[i][j] = B - nc[i][j];
cannam@18 135 }
cannam@18 136 */
cannam@18 137 b0 = i - limit;
cannam@18 138 if (b0 < 0)
cannam@18 139 b0 = 0;
cannam@18 140 b1 = i + limit;
cannam@18 141 if (b1 >= n)
cannam@18 142 b1 = n - 1;
cannam@18 143 nc[i][j] = b1 - b0 + 1; /* = B except at edges */
cannam@18 144 for (b = b0; b <= b1; b++)
cannam@18 145 if (c[b] == j+1)
cannam@18 146 nc[i][j]--;
cannam@18 147
cannam@18 148 sum += exp(lp[i][j]);
cannam@18 149 }
cannam@18 150
cannam@18 151 /* normalise responsibilities and add duration logprior */
cannam@18 152 logsumexp = log(sum);
cannam@18 153 for (j = 0; j < k; j++)
cannam@18 154 lp[i][j] -= logsumexp + lambda * nc[i][j];
cannam@18 155 }
cannam@18 156 //print_array(lp, n, k);
cannam@18 157 /*
cannam@18 158 for (i = 0; i < n; i++)
cannam@18 159 {
cannam@18 160 for (j = 0; j < k; j++)
cannam@18 161 mexPrintf("%d ", nc[i][j]);
cannam@18 162 mexPrintf("\n");
cannam@18 163 }
cannam@18 164 */
cannam@18 165
cannam@18 166
cannam@18 167 /* update the assignments now that we know the duration priors
cannam@18 168 based on the current assignments */
cannam@18 169 for (i = 0; i < n; i++)
cannam@18 170 {
cannam@18 171 maxlp = lp[i][0];
cannam@18 172 c[i] = 1;
cannam@18 173 for (j = 1; j < k; j++)
cannam@18 174 if (lp[i][j] > maxlp)
cannam@18 175 {
cannam@18 176 maxlp = lp[i][j];
cannam@18 177 c[i] = j+1;
cannam@18 178 }
cannam@18 179 }
cannam@18 180
cannam@18 181 /* break if assignments haven't changed */
cannam@18 182 i = 0;
cannam@18 183 while (i < n && oldc[i] == c[i])
cannam@18 184 i++;
cannam@18 185 if (i == n)
cannam@18 186 break;
cannam@18 187
cannam@18 188 /* update reference histograms now we know new responsibilities */
cannam@18 189 for (j = 0; j < k; j++)
cannam@18 190 {
cannam@18 191 for (b = 0; b < m; b++)
cannam@18 192 {
cannam@18 193 cl[j][b] = 0;
cannam@18 194 for (i = 0; i < n; i++)
cannam@18 195 {
cannam@18 196 cl[j][b] += exp(lp[i][j]) * h[i*m+b];
cannam@18 197 }
cannam@18 198 }
cannam@18 199
cannam@18 200 sum = 0;
cannam@18 201 for (i = 0; i < n; i++)
cannam@18 202 sum += exp(lp[i][j]);
cannam@18 203 for (b = 0; b < m; b++)
cannam@18 204 cl[j][b] /= sum; /* normalise */
cannam@18 205 }
cannam@18 206
cannam@18 207 //print_array(cl, k, m);
cannam@18 208 //mexPrintf("\n\n");
cannam@18 209 }
cannam@18 210 }
cannam@18 211
cannam@18 212 /* free memory */
cannam@18 213 for (i = 0; i < k; i++)
cannam@18 214 free(cl[i]);
cannam@18 215 free(cl);
cannam@18 216 for (i = 0; i < n; i++)
cannam@18 217 free(nc[i]);
cannam@18 218 free(nc);
cannam@18 219 for (i = 0; i < n; i++)
cannam@18 220 free(lp[i]);
cannam@18 221 free(lp);
cannam@18 222 free(oldc);
cannam@18 223 }
cannam@18 224
cannam@18 225