ref: 543ee940373ab2b78494a5e502236cd8cac5f8c0
parent: 5be0e59ff0294088db2e584d4c5ea222955d4801
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Fri Feb 15 10:13:14 EST 2019
20-bit VQ
--- /dev/null
+++ b/dnn/ceps_vq_train.c
@@ -1,0 +1,399 @@
+
+#include <valgrind/memcheck.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define COEF 0.75f
+#define MAX_ENTRIES 16384
+
+void compute_weights(const float *x, float *w, int ndim)
+{+ int i;
+ w[0] = MIN(x[0], x[1]-x[0]);
+ for (i=1;i<ndim-1;i++)
+ w[i] = MIN(x[i]-x[i-1], x[i+1]-x[i]);
+ w[ndim-1] = MIN(x[ndim-1]-x[ndim-2], M_PI-x[ndim-1]);
+
+ for (i=0;i<ndim;i++)
+ w[i] = 1./(.01+w[i]);
+ w[0]*=3;
+ w[1]*=2;
+ /*
+ for (i=0;i<ndim;i++)
+ w[i] = 1;*/
+}
+
+int find_nearest(const float *codebook, int nb_entries, const float *x, int ndim, float *dist)
+{+ int i, j;
+ float min_dist = 1e15;
+ int nearest = 0;
+
+ for (i=0;i<nb_entries;i++)
+ {+ float dist=0;
+ for (j=0;j<ndim;j++)
+ dist += (x[j]-codebook[i*ndim+j])*(x[j]-codebook[i*ndim+j]);
+ if (dist<min_dist)
+ {+ min_dist = dist;
+ nearest = i;
+ }
+ }
+ if (dist)
+ *dist = min_dist;
+ return nearest;
+}
+
+int find_nearest_weighted(const float *codebook, int nb_entries, float *x, const float *w, int ndim)
+{+ int i, j;
+ float min_dist = 1e15;
+ int nearest = 0;
+
+ for (i=0;i<nb_entries;i++)
+ {+ float dist=0;
+ for (j=0;j<ndim;j++)
+ dist += w[j]*(x[j]-codebook[i*ndim+j])*(x[j]-codebook[i*ndim+j]);
+ if (dist<min_dist)
+ {+ min_dist = dist;
+ nearest = i;
+ }
+ }
+ return nearest;
+}
+
+int quantize_lsp(const float *x, const float *codebook1, const float *codebook2,
+ const float *codebook3, int nb_entries, float *xq, int ndim)
+{+ int i, n1, n2, n3;
+ float err[ndim], err2[ndim], err3[ndim];
+ float w[ndim], w2[ndim], w3[ndim];
+
+ w[0] = MIN(x[0], x[1]-x[0]);
+ for (i=1;i<ndim-1;i++)
+ w[i] = MIN(x[i]-x[i-1], x[i+1]-x[i]);
+ w[ndim-1] = MIN(x[ndim-1]-x[ndim-2], M_PI-x[ndim-1]);
+
+ /*
+ for (i=0;i<ndim;i++)
+ w[i] = 1./(.003+w[i]);
+ w[0]*=3;
+ w[1]*=2;*/
+ compute_weights(x, w, ndim);
+
+ for (i=0;i<ndim;i++)
+ err[i] = x[i]-COEF*xq[i];
+ n1 = find_nearest(codebook1, nb_entries, err, ndim, NULL);
+
+ for (i=0;i<ndim;i++)
+ {+ xq[i] = COEF*xq[i] + codebook1[ndim*n1+i];
+ err[i] -= codebook1[ndim*n1+i];
+ }
+ for (i=0;i<ndim/2;i++)
+ {+ err2[i] = err[2*i];
+ err3[i] = err[2*i+1];
+ w2[i] = w[2*i];
+ w3[i] = w[2*i+1];
+ }
+ n2 = find_nearest_weighted(codebook2, nb_entries, err2, w2, ndim/2);
+ n3 = find_nearest_weighted(codebook3, nb_entries, err3, w3, ndim/2);
+
+ for (i=0;i<ndim/2;i++)
+ {+ xq[2*i] += codebook2[ndim*n2/2+i];
+ xq[2*i+1] += codebook3[ndim*n3/2+i];
+ }
+ return 0;
+}
+
+void split(float *codebook, int nb_entries, int ndim)
+{+ int i,j;
+ for (i=0;i<nb_entries;i++)
+ {+ for (j=0;j<ndim;j++)
+ {+ float delta = .01*(rand()/(float)RAND_MAX-.5);
+ codebook[i*ndim+j] += delta;
+ codebook[(i+nb_entries)*ndim+j] = codebook[i*ndim+j] - delta;
+ }
+ }
+}
+
+
+void split1(float *codebook, int nb_entries, const float *data, int nb_vectors, int ndim)
+{+ int i,j;
+ int nearest[nb_vectors];
+ float dist[nb_entries];
+ int count[nb_entries];
+ int worst;
+ for (i=0;i<nb_entries;i++)
+ dist[i] = 0;
+ for (i=0;i<nb_entries;i++)
+ count[i]=0;
+ for (i=0;i<nb_vectors;i++)
+ {+ float d;
+ nearest[i] = find_nearest(codebook, nb_entries, data+i*ndim, ndim, &d);
+ dist[nearest[i]] += d;
+ count[nearest[i]]++;
+ }
+
+ worst=0;
+ for (i=1;i<nb_entries;i++)
+ {+ if (dist[i] > dist[worst])
+ worst=i;
+ }
+
+ for (j=0;j<ndim;j++)
+ {+ float delta = .001*(rand()/(float)RAND_MAX-.5);
+ codebook[worst*ndim+j] += delta;
+ codebook[nb_entries*ndim+j] = codebook[worst*ndim+j] - delta;
+ }
+}
+
+
+
+void update(float *data, int nb_vectors, float *codebook, int nb_entries, int ndim)
+{+ int i,j;
+ int count[nb_entries];
+ int nearest[nb_vectors];
+ double err=0;
+
+ for (i=0;i<nb_entries;i++)
+ count[i] = 0;
+
+ for (i=0;i<nb_vectors;i++)
+ {+ float dist;
+ nearest[i] = find_nearest(codebook, nb_entries, data+i*ndim, ndim, &dist);
+ err += dist;
+ }
+ printf("RMS error = %f\n", sqrt(err/nb_vectors/ndim));+ for (i=0;i<nb_entries*ndim;i++)
+ codebook[i] = 0;
+
+ for (i=0;i<nb_vectors;i++)
+ {+ int n = nearest[i];
+ count[n]++;
+ for (j=0;j<ndim;j++)
+ codebook[n*ndim+j] += data[i*ndim+j];
+ }
+
+ float w2=0;
+ for (i=0;i<nb_entries;i++)
+ { + for (j=0;j<ndim;j++)
+ codebook[i*ndim+j] *= (1./count[i]);
+ w2 += (count[i]/(float)nb_vectors)*(count[i]/(float)nb_vectors);
+ }
+ //fprintf(stderr, "%f / %d\n", 1./w2, nb_entries);
+}
+
+void update_weighted(float *data, float *weight, int nb_vectors, float *codebook, int nb_entries, int ndim)
+{+ int i,j;
+ float count[MAX_ENTRIES][ndim];
+ int nearest[nb_vectors];
+
+ for (i=0;i<nb_entries;i++)
+ for (j=0;j<ndim;j++)
+ count[i][j] = 0;
+
+ for (i=0;i<nb_vectors;i++)
+ {+ nearest[i] = find_nearest_weighted(codebook, nb_entries, data+i*ndim, weight+i*ndim, ndim);
+ }
+ for (i=0;i<nb_entries*ndim;i++)
+ codebook[i] = 0;
+
+ for (i=0;i<nb_vectors;i++)
+ {+ int n = nearest[i];
+ for (j=0;j<ndim;j++)
+ {+ float w = sqrt(weight[i*ndim+j]);
+ count[n][j]+=w;
+ codebook[n*ndim+j] += w*data[i*ndim+j];
+ }
+ }
+
+ //float w2=0;
+ for (i=0;i<nb_entries;i++)
+ { + for (j=0;j<ndim;j++)
+ codebook[i*ndim+j] *= (1./count[i][j]);
+ //w2 += (count[i]/(float)nb_vectors)*(count[i]/(float)nb_vectors);
+ }
+ //fprintf(stderr, "%f / %d\n", 1./w2, nb_entries);
+}
+
+void vq_train(float *data, int nb_vectors, float *codebook, int nb_entries, int ndim)
+{+ int i, j, e;
+ e = 1;
+ for (j=0;j<ndim;j++)
+ codebook[j] = 0;
+ for (i=0;i<nb_vectors;i++)
+ for (j=0;j<ndim;j++)
+ codebook[j] += data[i*ndim+j];
+ for (j=0;j<ndim;j++)
+ codebook[j] *= (1./nb_vectors);
+
+
+ while (e< nb_entries)
+ {+#if 1
+ split(codebook, e, ndim);
+ e<<=1;
+#else
+ split1(codebook, e, data, nb_vectors, ndim);
+ e++;
+#endif
+ fprintf(stderr, "%d\n", e);
+ for (j=0;j<4;j++)
+ update(data, nb_vectors, codebook, e, ndim);
+ }
+ for (j=0;j<ndim*2;j++)
+ update(data, nb_vectors, codebook, e, ndim);
+}
+
+void vq_train_weighted(float *data, float *weight, int nb_vectors, float *codebook, int nb_entries, int ndim)
+{+ int i, j, e;
+ e = 1;
+ for (j=0;j<ndim;j++)
+ codebook[j] = 0;
+ for (i=0;i<nb_vectors;i++)
+ for (j=0;j<ndim;j++)
+ codebook[j] += data[i*ndim+j];
+ for (j=0;j<ndim;j++)
+ codebook[j] *= (1./nb_vectors);
+
+
+ while (e< nb_entries)
+ {+#if 0
+ split(codebook, e, ndim);
+ e<<=1;
+#else
+ split1(codebook, e, data, nb_vectors, ndim);
+ e++;
+#endif
+ fprintf(stderr, "%d\n", e);
+ for (j=0;j<ndim;j++)
+ update_weighted(data, weight, nb_vectors, codebook, e, ndim);
+ }
+}
+
+
+int main(int argc, char **argv)
+{+ int i,j;
+ int nb_vectors, nb_entries, ndim, ndim0, total_dim;
+ float *data, *pred, *codebook, *codebook2;
+ float *delta;
+ double err;
+ FILE *fout;
+
+ ndim = atoi(argv[1]);
+ ndim0 = ndim-1;
+ total_dim = atoi(argv[2]);
+ nb_vectors = atoi(argv[3]);
+ nb_entries = 1<<atoi(argv[4]);
+
+ data = malloc((nb_vectors*ndim+total_dim)*sizeof(*data));
+ pred = malloc(nb_vectors*ndim0*sizeof(*pred));
+ codebook = malloc(nb_entries*ndim0*sizeof(*codebook));
+ codebook2 = malloc(nb_entries*ndim0*sizeof(*codebook2));
+
+ for (i=0;i<nb_vectors;i++)
+ {+ fread(&data[i*ndim], sizeof(float), total_dim, stdin);
+ if (feof(stdin))
+ break;
+ }
+ nb_vectors = i;
+ VALGRIND_CHECK_MEM_IS_DEFINED(data, nb_entries*ndim);
+
+ for (i=0;i<4;i++)
+ {+ for (j=0;j<ndim0;j++)
+ pred[i*ndim0+j] = 0;
+ }
+ for (i=4;i<nb_vectors;i++)
+ {+ for (j=0;j<ndim0;j++)
+ pred[i*ndim0+j] = data[i*ndim+j+1] - COEF*data[(i-4)*ndim+j+1];
+ }
+
+ VALGRIND_CHECK_MEM_IS_DEFINED(pred, nb_entries*ndim0);
+ vq_train(pred, nb_vectors, codebook, nb_entries, ndim0);
+
+ delta = malloc(nb_vectors*ndim0*sizeof(*data));
+ err = 0;
+ for (i=0;i<nb_vectors;i++)
+ {+ int nearest = find_nearest(codebook, nb_entries, &pred[i*ndim0], ndim0, NULL);
+ for (j=0;j<ndim0;j++)
+ {+ delta[i*ndim0+j] = pred[i*ndim0+j] - codebook[nearest*ndim0+j];
+ err += delta[i*ndim0+j]*delta[i*ndim0+j];
+ }
+ //printf("\n");+ }
+ fprintf(stderr, "Cepstrum RMS error: %f\n", sqrt(err/nb_vectors/ndim));
+
+ vq_train(delta, nb_vectors, codebook2, nb_entries, ndim0);
+
+ err=0;
+ for (i=0;i<nb_vectors;i++)
+ {+ int n1;
+ n1 = find_nearest(codebook2, nb_entries, &delta[i*ndim0], ndim0, NULL);
+ for (j=0;j<ndim0;j++)
+ {+ delta[i*ndim0+j] = delta[i*ndim0+j] - codebook2[n1*ndim0+j];
+ err += delta[i*ndim0+j]*delta[i*ndim0+j];
+ }
+ }
+ fprintf(stderr, "Cepstrum RMS error after stage 2: %f)\n", sqrt(err/nb_vectors/ndim));
+
+ fout = fopen("ceps_codebooks.c", "w");+ fprintf(fout, "/* This file is automatically generated */\n\n");
+ fprintf(fout, "float ceps_codebook1[%d*%d] = {\n",nb_entries, ndim0);+
+ for (i=0;i<nb_entries;i++)
+ {+ for (j=0;j<ndim0;j++)
+ fprintf(fout, "%f, ", codebook[i*ndim0+j]);
+ fprintf(fout, "\n");
+ }
+ fprintf(fout, "};\n\n");
+
+ fprintf(fout, "float ceps_codebook2[%d*%d] = {\n",nb_entries, ndim0);+
+ for (i=0;i<nb_entries;i++)
+ {+ for (j=0;j<ndim0;j++)
+ fprintf(fout, "%f, ", codebook2[i*ndim0+j]);
+ fprintf(fout, "\n");
+ }
+ fprintf(fout, "};\n\n");
+
+ fclose(fout);
+ return 0;
+}
--- a/dnn/dump_data.c
+++ b/dnn/dump_data.c
@@ -51,7 +51,67 @@
#define NB_FEATURES (2*NB_BANDS+3+LPC_ORDER)
+#include "ceps_codebooks.c"
+int vq_quantize(const float *codebook, int nb_entries, const float *x, int ndim, float *dist)
+{+ int i, j;
+ float min_dist = 1e15;
+ int nearest = 0;
+
+ for (i=0;i<nb_entries;i++)
+ {+ float dist=0;
+ for (j=0;j<ndim;j++)
+ dist += (x[j]-codebook[i*ndim+j])*(x[j]-codebook[i*ndim+j]);
+ if (dist<min_dist)
+ {+ min_dist = dist;
+ nearest = i;
+ }
+ }
+ if (dist)
+ *dist = min_dist;
+ return nearest;
+}
+
+#define NB_BANDS_1 (NB_BANDS - 1)
+float vq_mem[NB_BANDS_1];
+int quantize(float *x, float *mem)
+{+ int i;
+ int id, id2;
+ float ref[NB_BANDS_1];
+ RNN_COPY(ref, x, NB_BANDS_1);
+ for (i=0;i<NB_BANDS_1;i++) {+ x[i] -= 0.0f*mem[i];
+ }
+ id = vq_quantize(ceps_codebook1, 1024, x, NB_BANDS_1, NULL);
+ for (i=0;i<NB_BANDS_1;i++) {+ x[i] -= ceps_codebook1[id*NB_BANDS_1 + i];
+ }
+ id2 = vq_quantize(ceps_codebook2, 1024, x, NB_BANDS_1, NULL);
+ for (i=0;i<NB_BANDS_1;i++) {+ x[i] = ceps_codebook2[id2*NB_BANDS_1 + i];
+ }
+ for (i=0;i<NB_BANDS_1;i++) {+ x[i] += ceps_codebook1[id*NB_BANDS_1 + i];
+ }
+ for (i=0;i<NB_BANDS_1;i++) {+ x[i] += 0.0f*mem[i];
+ mem[i] = x[i];
+ }
+ if (0) {+ float err = 0;
+ for (i=0;i<NB_BANDS_1;i++) {+ err += (x[i]-ref[i])*(x[i]-ref[i]);
+ }
+ printf("%f\n", sqrt(err/NB_BANDS_1));+ }
+
+ return id;
+}
+
typedef struct {float analysis_mem[OVERLAP_SIZE];
float cepstral_mem[CEPS_MEM][NB_BANDS];
@@ -140,6 +200,7 @@
E += Ex[i];
}
dct(st->features[st->pcount], Ly);
+ quantize(&st->features[st->pcount][1], vq_mem);
st->features[st->pcount][0] -= 4;
g = lpc_from_cepstrum(st->lpc, st->features[st->pcount]);
st->features[st->pcount][2*NB_BANDS+2] = log10(g);
--- a/dnn/lpcnet.py
+++ b/dnn/lpcnet.py
@@ -153,6 +153,11 @@
gru_out2, _ = rnn2(Concatenate()([gru_out1, rep(cfeat)]))
ulaw_prob = md(gru_out2)
+ rnn.trainable=False
+ rnn2.trainable=False
+ md.trainable=False
+ embed.Trainable=False
+
model = Model([pcm, feat, pitch], ulaw_prob)
model.rnn_units1 = rnn_units1
model.rnn_units2 = rnn_units2
--- a/dnn/train_lpcnet.py
+++ b/dnn/train_lpcnet.py
@@ -103,8 +103,8 @@
del in_exc
# dump models to disk as we go
-checkpoint = ModelCheckpoint('lpcnet24b_384_10_G16_{epoch:02d}.h5')+checkpoint = ModelCheckpoint('lpcnet24fq_384_10_G16_{epoch:02d}.h5')-#model.load_weights('lpcnet9b_384_10_G16_01.h5')-model.compile(optimizer=Adam(0.001, amsgrad=True, decay=5e-5), loss='sparse_categorical_crossentropy')
-model.fit([in_data, features, periods], out_exc, batch_size=batch_size, epochs=nb_epochs, validation_split=0.0, callbacks=[checkpoint, lpcnet.Sparsify(2000, 40000, 400, (0.05, 0.05, 0.2))])
+model.load_weights('lpcnet24f_384_10_G16_31.h5')+model.compile(optimizer=Adam(0.0005, amsgrad=True, decay=5e-5), loss='sparse_categorical_crossentropy')
+model.fit([in_data, features, periods], out_exc, batch_size=batch_size, epochs=nb_epochs, validation_split=0.0, callbacks=[checkpoint, lpcnet.Sparsify(0, 0, 1, (0.05, 0.05, 0.2))])
--
⑨