Forum: Offtopic Max-Lloyd-Algorithmus


von Rüdiger K. (sleipnir)


Lesenswert?

Hiho! Ich wollte den Max-Lloyd-Algorithmus zur Optimalquantisierung in 
C++ implementieren.

Allerdings wollte ich nicht über die Integration der 
Wahrscheinlichkeitsdichteverteilung gehen sondern habe den Algorithmus 
wie folgt abgewandelt:
 Wiederhole:
   * ordne jedem Trainigssample den Rekonstruktionswert zu, der ihm am 
nächsten liegt.
   * berechne die Rekonstruktionswerte als Mittelwert der ihnen 
zugeordneten Samples.

Die Ergebnisse sehen für laplaceverteilte Daten schon ganz gut aus, 
allerdings nicht mehr für einen Sinus als Eingangssignal. Dort müßten 
sich die Rekonstruktionswerte eigentlich im Bereich der großen 
Amplituden konzentrieren, was sie aber nicht wirklich tun.
1
template<class T>  bool MaxLloydQuantizer<T>::train(const itpp::Vec<T> &trainingdata,double epsilon,unsigned int max_iter)
2
{
3
#ifdef DEBUG
4
  if(!initialized) cerr << "MaxLloydQuantizer<T>::train() called before initializing the quantizer!" << endl;
5
#endif
6
  if(trainingdata.length()==0) return false;
7
  T minv,maxv;
8
  minv=maxv=trainingdata(0);
9
  for(const T* ptr=trainingdata._data();ptr < trainingdata._data()+trainingdata.length();ptr++)
10
  {
11
    register T val = *ptr;
12
    minv = ((val < minv) ? val : minv);
13
    maxv = ((val > maxv) ? val : maxv);
14
  }
15
16
  // berechne nun die Intervallgrenzen eines gleichverteilten Quantisierers
17
  T step=(maxv-minv)/N;
18
  T w=minv;
19
  for(unsigned int k=0;k<=N;k++,w+=step) d(k)=w;
20
  w=minv+step/2;
21
  for(unsigned int k=0;k<N;k++,w+=step) r(k)=w;
22
23
  itpp::Vec<T> r_neu(N);
24
  itpp::Vec<unsigned int> r_anz(N);
25
26
  unsigned int iteration=0;
27
  for(;iteration < max_iter;iteration++)
28
  {
29
    // ordne jedem Trainingswert einen Rekonstruktionswert zu
30
    for(int k=0;k<trainingdata.length();k++)
31
    {
32
      T val=trainingdata(k);
33
      T min_dist=std::abs(r(0)-val);
34
      unsigned min_index=0;
35
      for(unsigned int l=1;l<N;l++)
36
      {
37
        T dist=std::abs(T(r(l)-val));
38
        if(dist < min_dist)
39
        {
40
          min_dist=dist;
41
          min_index=l;
42
        }
43
      }
44
      r_neu(min_index)+=val;
45
      r_anz(min_index)++;
46
    }
47
    double change=0.0;
48
    for(unsigned int k=0;k<N;k++)
49
    {
50
      double r_neuw = (r_anz(k) != 0 ? r_neu(k)/r_anz(k) : r(k));
51
      double tmp=r_neuw-r(k);
52
      change+=tmp*tmp;
53
      r(k)=r_neuw;
54
    }
55
56
    if(change/N <= epsilon) break;
57
    r_neu.clear();
58
    r_anz.clear();
59
  }
60
  // berechne Intervallgrenzen neu
61
62
  for(unsigned int i=1;i<N;i++)
63
  {
64
    T di_neu=(r(i-1)+r(i))/2;
65
66
    d(i)=di_neu;
67
  }
68
  trained=true;
69
  return (iteration!=max_iter);
70
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.