Скачиваний:
31
Добавлен:
01.05.2014
Размер:
8 Кб
Скачать
unit m_EM;

interface
  uses Classes,Sysutils,Types,Math,Graphics,typeEM;

 type
  TEM = class
   private
   data: TEMList2;

   M: integer;
   N: integer;
   d: integer;

   P: TEMList1;
   u: TEMList2;
   V: TEMList1;
   P_old: TEMList1;
   u_old: TEMList2;
   V_old: TEMList1;

   P_x_a: TEMList1;
   P_x_a_old: TEMList1;

   err: string;
   strf: string;
   Min: TEMList1;
   Max: TEMList1;
   Cntiter: integer;
  public
   constructor create(ldata:TEMList2; MM:integer;CI:integer);overload;
   constructor create();overload;
   destructor destroy;override;

   procedure learn;
   procedure test(ldata: TEMList2);
   procedure setnumofcl(MM: integer);
   procedure setnumofit(CI: integer);
   procedure setdata(ldata: TEMList2);
   procedure setstrf(s: string);

   function getstrf():string;
   function getdata(): TEMList2;
   function getnumofcl(): integer;
   function getnumofit(): integer;

   function getP(j:integer): double;
   function getV(j:integer): double;
   function getU(i,j:integer): double;
   function getN(): integer;
   function getD(i,j:integer): double;
   function get_d():integer;

   function propose(nn,j:integer):double;
   function cluster(i:integer):integer;
  private
   procedure init;
   PROCEDURE new_old;
   function P_x_j(nn,j:integer):double;
   function P_j_x(nn,j:integer):double;
   procedure P_x;
   procedure P_x_old;
   function P_x_j_old(nn,j:integer):double;
   function P_j_x_old(nn,j:integer):double;
   procedure iteration;
   function dist(nn,j:integer):double;


   function pow(c,s:double):double;
   procedure EMerror(s:string);
  end;

implementation

  function TEM.getP(j:integer):double;
   begin
    getP:=P[j];
   end;

  function TEM.getV(j:integer):double;
   begin
    getV:=v[j];
   end;

  function TEM.getU(i,j:integer):double;
   begin
    getU:=u[i,j];
   end;
  function TEM.getN():integer;
   begin
    getN:=N;
   end;

  function TEM.get_d():integer;
   begin
    get_d:=d;
   end;

  function TEM.getD(i,j:integer):double;
   begin
    getD:=data[i,j];
   end;

  constructor TEM.create(ldata:TEMList2; MM:integer; CI:integer);
   begin
    inherited create();
    setdata(ldata);
    setnumofcl(MM);
    setnumofit(CI);
   end;

   constructor TEM.create();
    begin
     inherited create();
    end;

   destructor TEM.destroy;
    begin
     setlength(Data,0,0);
     setlength(Min,0);
     setlength(Max,0);
     setlength(P,0);
     setlength(u,0,0);
     setlength(v,0);
     setlength(P_old,0);
     setlength(u_old,0,0);
     setlength(v_old,0);
     setlength(P_x_a,0);
     setlength(P_x_a_old,0);
     inherited destroy();
    end;

   procedure TEM.learn;
    var
     i:integer;
    begin
     init;
    for i:=0 to Cntiter do
     begin
      iteration;
     end;
   end;

   procedure TEM.test(ldata:TEMList2);
    begin
     if d=high(ldata[0])+1 then
      begin
       data:=copy(ldata);
       N:=high(ldata)+1;
       {display(); }
      end
     else EMerror('ERROR# Size of learn and test data is not equal');
    end;

   procedure TEM.init;
    var
     i,j,nn:integer;
     vvar:double;
    begin
      vvar:=0.0;
      setlength(Min,d);
      setlength(Max,d);
      setlength(P,M);
      setlength(u,M,d);
      setlength(v,M);
      setlength(P_old,M);
      setlength(u_old,M,d);
      setlength(v_old,M);
      setlength(P_x_a,N);
      setlength(P_x_a_old,N);
      for i:=0 to d-1 do
      begin
       Min[i]:=data[0,i];
       Max[i]:=data[0,i];
       for nn:=1 to N-1 do
       begin
        if Min[i] > data[nn,i] then min[i]:=data[nn,i]
        else if max[i] < data[nn,i] then max[i]:=data[nn,i];
       end;
      end;
      for i:=0 to d-1 do vvar:=vvar+(Max[i]-Min[i])*(Max[i]-Min[i])/12/d;
      for j:=0 to M-1 do
       begin
        P[j]:=1.0/M;
        v[j]:=vvar/4+random*vvar/4;
        for i:=0 to d-1 do u[j,i]:=(Max[i]-Min[i])/2+(random-0.5)*(Max[i]-Min[i])/2;
       end;
    end;

    procedure TEM.setdata(ldata:TEMList2);
     begin
      data:=copy(ldata);
      N:=high(ldata)+1;
      d:=high(ldata[0])+1;
     end;

    procedure TEM.setnumofcl( MM:integer);
     begin
      M:=MM;
     end;

    procedure TEM.setnumofit( CI:integer);
     begin
      cntiter:=CI;
     end;

    procedure TEM.setstrf(s: string);
     begin
      strf:=s;
     end;

    function TEM.getstrf():string;
     begin
      getstrf:=strf;
     end;

    function TEM.getdata():TEMList2;
     begin
      getdata:=data;
     end;

    function TEM.getnumofcl():integer;
     begin
      getnumofcl:=M;
     end;

    function TEM.getnumofit():integer;
     begin
      getnumofit:=cntiter;
     end;

    procedure TEM.new_old;
     Var
      i,j:integer;
     begin
      for j:=0 to M-1 do
      begin
       P_old[j]:=P[j];
       v_old[j]:=v[j];
       for i:=0 to d-1 do u_old[j,i]:=u[j,i];
      end;
     end;

    function TEM.P_x_j(nn,j:integer):double;
     var
      i:integer;
      e:double;
     begin
      e:=0.0;
      for i:=0 to d-1 do e:=e+(data[nn,i]-u[j,i])*(data[nn,i]-u[j,i]);
      e:=e/(-2*v[j]*v[j]);
      if e<-1000 then P_x_j:=1E-12
      else P_x_j:=exp(e)/pow(2*Pi*v[j]*v[j],d/2.0);
     end;

    function TEM.P_j_x(nn,j:integer):double;
     begin
      P_j_x:=P_x_j(nn,j)*P[j]/P_x_a[nn];
     end;

    procedure TEM.P_x;
     var
      nn,j:integer;
      temp:double;
     begin
      for nn:=0 to N-1 do
      begin
       temp:=0.0;
       for j:=0 to M-1 do temp:=temp+P_x_j(nn,j)*P[j];
       P_x_a[nn]:=temp;
      end;
     end;

    function TEM.P_x_j_old(nn,j:integer):double;
     var
      i:integer;
      e:double;
     begin
      e:=0.0;
      for i:=0 to d-1 do e:=e+(data[nn,i]-u_old[j,i])*(data[nn,i]-u_old[j,i]);
      e:=e/(-2*v_old[j]*v_old[j]);
      if e<-1000 then P_x_j_old:=1E-12
      else P_x_j_old:=exp(e)/pow(2*Pi*v_old[j]*v_old[j],d/2.0);
     end;

    function TEM.P_j_x_old(nn,j:integer):double;
     begin
      P_j_x_old:=P_x_j_old(nn,j)*P_old[j]/P_x_a_old[nn];
     end;

   procedure TEM.P_x_old;
    var
     nn,j:integer;
     temp:double;
    begin
     for nn:=0 to N-1 do
      begin
       temp:=0.0;
       for j:=0 to M-1 do temp:=temp+(P_x_j_old(nn,j))*(P_old[j]);
       P_x_a_old[nn]:=temp;
      end;
    end;

    procedure TEM.iteration;
     var
      nn,j,i:integer;
      denom: double;
      sum:double;
     begin
      new_old;
      P_x;
      P_x_old;
      for j:=0 to M-1 do
       begin
        denom:=0.0;
        for nn:=0 to N-1 do denom:=denom+P_j_x_old(nn,j);
        for i:=0 to d-1 do
         begin
          u[j,i]:=0.0;
          for nn:=0 to N-1 do u[j,i]:=u[j,i]+P_j_x_old(nn,j)*data[nn,i];
          u[j,i]:=u[j,i]/denom;
         end;
        v[j]:=0.0;
        for nn:=0 to N-1 do
         begin
          sum:=0.0;
          for i:=0 to d-1 do sum:=sum+pow(Data[nn,i]-u[j,i],2);
          v[j]:=v[j]+sum*P_j_x_old(nn,j);
         end;
        v[j]:=sqrt(v[j]/(denom*d));
        P[j]:=denom/N;
       end;
     end;

    function TEM.dist(nn,j:integer):double;
     var
      sum:double;
      i:integer;
     begin
      sum:=0.0;
      for i:=0 to d-1 do
       sum:= sum+pow(u[j,i]-data[nn,i],2);
      dist:=sqrt(sum);
     end;

   function TEM.propose(nn,j:integer):double;
    var
     sum: double;
     i: integer;
    begin
     sum:=0.0;
     for i:=0 to M-1 do sum:=sum+dist(nn,i);
     if M<=1 then propose:=1
     else propose:=(sum-dist(nn,j))/((M-1)*sum);
    end;

   function TEM.cluster(i:integer):integer;
    var
     j,k:integer;
     maxp,prp:double;
    begin
     maxp:=0;
     k:=0;
     for j:=0 to M-1 do
     begin
      prp:=propose(i,j);
      if(maxp<prp)then
      begin
       maxp:=prp;
       k:=j;
      end;
     end;
     cluster:=k;
    end;


   function TEM.pow(c,s:double):double;
    begin
     if c=0 then pow:=0
     else pow:=exp(s*ln(abs(c)));
    end;

   procedure TEM.EMerror(s:string);
    begin
      err:=s;
    end;
  end.



Соседние файлы в папке MyEM