[solved] obliczanie regresji wielu zmiennych

0

Witam.

Mam problem. Musze wykonac regresję wielu zmiennych i nie wiem jak. Podam przykałd:

y=a+bx+cx2+dx3+ex^4

Zmienne y oraz x sa dostępne w tablicach, 20 elementowych i policzyć muszę wartości a, b, c, d, e. Prosż euprzejmie o pomoc i podpowiedzenie jak napisac taki algorytm.

Z góry dziękuję bardzo.

Tomek1

0

Poczytaj o metodzie najmniejszych kwadratow i regresji wielomianem.

Podany przez ciebie przyklad sprowadza sie w zasadzie do rozwiazania ukladu 5 rownan liniowych wzgledem wspolczynnikow szukanego wielomianu.

0

Wzór który zastosowałeś jest niezbyt prawidłowy. Regresja liniowa polega na tym, że prowadzisz prostą pomiędzy rozproszonymi punktami. Jak wiadomo prosta ma tylko współczynniki A i B. Kiedyś napisałem w pascalu procedurkę do obliczania regresji liniowej. Jeżeli będziesz miał kłopoty z przetłumaczeniem na C to pomogę.

PROCEDURE RegLin(DBx, DBy :ARRAY OF Double; VAR A, B :Double);
VAR SigX, SigY       :Double; 
    SigXY            :Double;
    SigSqrX          :Double;
    n, i             :Word;  
BEGIN
 n := High(DBx)+1; 
 SigX := 0; SigY := 0;
 SigXY := 0;
 SigSqrX := 0;
 FOR i := 0 TO n-1 DO
  BEGIN
   SigX := SigX + DBx[i];
   SigY := SigY + DBy[i];
   SigXY := SigXY + (DBx[i]*DBy[i]);
   SigSqrX := SigSqrX + Sqr(DBx[i]);
  END;
 A := (n*SigXY - SigX*SigY) / (n*SigSqrX - Sqr(Sigx));
 B := 1/n * (SigY - A*SigX);
END;
0

Wzór który zastosowałeś jest niezbyt prawidłowy.

Alez jak najbardziej prawidlowy, kolego 8-O Po prostu trzeba zrobic regresje wielomianem a nie linia prosta. ;-) Gdybys nie wiedzial, mozemy aproksymowac za pomoca funkcji o dowolnym wzorze.

Tak jak mowilem, metoda najmniejszch kwadratow, liczenie pochodnych czastkowych i w przypadku wielomianow wszystko ladnie sie upraszcza do ukladu rownan liniowych.

BTW: Twoj wzor na regresje liniowa tez dokladnie z tego samego wynika ;-)

Kiedys pisalem taki programik na moj kalkulatorek Casio - liczyl regresje wielomianem 5 stopnia, fajna sprawa, regresja wielomianem niejednkrotnie daje najlepsze wyniki. Lepsza jest tylko metoda funkcji sklejanych (spline w Matlabie).

Polecam zajrzec do jakiejs ksiazki z matematyki/statystyki lub poszukac na google/Wikipedii.

0

Ta regresja to co to właściwie jest?

Aproksymacja średniokwadratowa dyskretna chyba, co?

Co ta regresja ma wspólnego z regresją - zapaścią, kryzysem?

Ekonomiści zawsze próbowali udawać mądrych... a ta ekonomia jak była tylko paplaniną,
tak jest do dzisiaj.

Dwóch profesorów ekonomi = dwie ekonomie, trzech to już wojna,
a czterech to nawet teoria chaosu wysiada... :-D

0

To jest aproksymacja średniokwadratowa dyskretna (inaczej nazywana regresją wielomianową)
Mając zbiór punktów o współrzędnych (xi,yi) poszukujesz funkcji w postaci wielomianu n-tego stopnia
y=a0+a1x+a2x2+a3x3+a4x^4
Algorytm ma za zadanie obliczyć a0,a1..., czyli tworzy funkcję ,która najlepiej odtwarza rzeczywisty rozkład punktów. nadaje im obraz analityczny (funkcyjny).
Korzysta się tutaj z metody najmniejszych kwadratów.

#include <conio.h>
#include <iostream.h>
//aproksymacja średniokwadratowa na zbiorze dyskretnym
//za pomocą wielomianu stopnia 4-tego
//inaczej regresja wielomianowa
 int i,j,n,k,h;
 float x,y,sa,t;
 double s[8],sum[8],p[5],xa[5];
 float aij[5][6];
 void UkrLin();
int main()
{
 cout<<"Aproksymacja sredniokwadratowa na zbiorze dyskretnym\n";
 cout<<"przy pomocy wielomianu stopnia 4-go\n";
 cout<<"Baza={1,x,x^2,x^3,x^4} F(x)=a0+a1x+a2x^2+a3x^3+a4x^4\n";	  
 for(j=1;j<=5;j++)
  {
   xa[j]=0;
   p[j]=0;
    for(k=1;k<=6;k++)
    aij[j][k]=0;
  }
 for(j=1;j<=8;j++)
  {
    s[j]=0;
    sum[j]=0;
  }
 cout<<"podaj liczbe wezlow n>=3\n";
 cin>>n;
 cout<<"podaj wartosci x i y dla kolenego wezla\n";
 for(j=1;j<=n;j++)
  {
   cout<<j<<"\t";
   cout<<"x=";
   cin>>x;
   cout<<"\t"<<"y=";
   cin>>y;
   s[1]=x;

    for(i=2;i<=8;i++)
     s[i]=x*s[i-1];
    for(i=1;i<=8;i++)
     sum[i]+=s[i];

     p[1]=p[1]+y;
      for(i=2;i<=5;i++)
       p[i]=p[i]+y*s[i-1];
  }
   aij[1][1]=n;
   for(i=1;i<=5;i++)
      {
        aij[i][6]=p[i];
         for(j=1;j<=5;j++)
          {
            k=i+j;
             if(k!=2)
              aij[i][j]=sum[k-2];
          }
       }
   UkrLin();    
   for(h=1;h<=5;h++)
   {
    cout<<"i="<<h-1<<"\tai="<<xa[h]<<"\n";
   }
  cout<<"F(x)="<<xa[1]<<"+"<<xa[2]<<"x+"<<xa[3]<<"x^2+"<<xa[4]<<"x^3+"<<xa[5]<<"x^4";
 getch();
}
void UkrLin()
{
 for(h=1;h<=5;h++)
    {
     sa=aij[h][h];

      for(j=h+1;j<=6;j++)
       {
        t=aij[h][j];
        t=t/sa;
        aij[h][j]=t;
         for(i=h+1;i<=5;i++)
          aij[i][j]=aij[i][j]-aij[i][h]*t;
       }
    }
  for(h=5;h>=1;h--)
   {
    sa=aij[h][6];
     for(j=h+1;j<=5;j++)
       sa=sa-aij[h][j]*xa[j];
    xa[h]=sa;
   }
}   	
 		
0

Odświerze temat. Mam do napisania program ktory liczy aproksymacje sredniokwadrowa dyskretretna 2 stopnia dla podanych n wezlow xi,yi,zi (Czyli trojwymiarowa). Nie moge sobie poradzic z rozpisaniem ukladu rownan do rozwiazania tego zadania. Dla wezlow xi,yi jestem wstanie program napisac problem jest gdy dochodzi zmienna z. Glowny problem to rozpisnie tych rownan. Moze ktos bedzie mial o tym pojecie i p0omoze mi. Prosze sie skontaktowac ze mna mailowo na [email protected] lub na gadu 3771643. Zalezy mi na czasie musze sie z tym uwinac do konca nadchodzacego tygodnia. Pozdrawiam

0

@StPan .
Program jest na pewno do kitu bo zawiera przekroczenia indeksów tablic

double s[8],sum[8],p[5],xa[5];

........
........
 for(j=1;j<=5;j++)
  {
   xa[j]=0;
   p[j]=0;

itd.........  jeszcze w kilku miejscach 

Ale jak by się dało poprawić ... [green] To :

Pytanie :
Czy algorytm jest prawidłowy ?

0

Kurde, moze zamiast pisac na forum, lepiej czasami zajrzec do pierwszej lepszej ksiazki z analizy matematycznej albo chociaz na google poszukac - to nie jest zaden specyficzny problem do rozwiazania - po prostu kawalek teorii - wystarczylo uwazac na zajeciach albo chociaz zajrzec do ksiazek :-[

Bede dobry dzisiaj: http://aproks.republika.pl/#aproksymacja%20%B6redniokwadratowa

Ale nie jestem zwolennikiem takiego podejscia do sprawy

0

OMG :-[ , pisze bo chyba już szukałem wzorów na necie i wypożyczałem książki z metod numerycznych w których cały dział jest poświęcony aproksymacji ale o 3D nie ma tam wzmianki. Tak samo piszesz mi że nie chodze na wykłady chciałbym zauważyć że mam kompletne notatki z tego przedmiotu a egzamin zaliczyłem w pierwszym terminie. Niestety na wykładzie się tym nie zajmowaliśmy. Ja nie mam kurde 12 lat żeby pisać na forum wcześniej nie robiąc nic :-[ . Dzięki za strone ale widzisz problem w tym że z tych wzorów nie przekształce tak żeby mieć ogólny sposób na budowanie macierzy do obliczenia aproksymacji 3D. Wszystkie wzory są oparte o aproksymacje na płaszczyźnie. Nie zauważyłeś że masz tam zmienne X,Y a dochodzi jeszcze Z i teraz sobie poradź jak jesteś taki cwany :-[

0

Zastanawiam się nad tą regresją 3D. Google milczy. A czy nie możesz obliczyć regresji zdla rzutów prostokątnych w układzie XY, ZY ?

//@Dopisane: Zobacz ten link. Więcej nie mam.

0
Oleksy_Adam napisał(a)

Wzór który zastosowałeś jest niezbyt prawidłowy. Regresja liniowa polega na tym, że prowadzisz prostą pomiędzy rozproszonymi punktami. Jak wiadomo prosta ma tylko współczynniki A i B. Kiedyś napisałem w pascalu procedurkę do obliczania regresji liniowej. Jeżeli będziesz miał kłopoty z przetłumaczeniem na C to pomogę.

PROCEDURE RegLin(DBx, DBy :ARRAY OF Double; VAR A, B :Double);
VAR SigX, SigY       :Double; 
    SigXY            :Double;
    SigSqrX          :Double;
    n, i             :Word;  
BEGIN
 n := High(DBx)+1; 
 SigX := 0; SigY := 0;
 SigXY := 0;
 SigSqrX := 0;
 FOR i := 0 TO n-1 DO
  BEGIN
   SigX := SigX + DBx[i];
   SigY := SigY + DBy[i];
   SigXY := SigXY + (DBx[i]*DBy[i]);
   SigSqrX := SigSqrX + Sqr(DBx[i]);
  END;
 A := (n*SigXY - SigX*SigY) / (n*SigSqrX - Sqr(Sigx));
 B := 1/n * (SigY - A*SigX);
END;

W linijce SigSqrX := SigSqrX + Sqr(DBx[i]); powinna być potęga...

poniżej funkcja w Qt - może się komuś przyda....

QPair<float,float> interpolacja(const QPolygonF polygon)
{

QPair<float,float> wsp;

 int n=polygon.size();

 float SigX = 0., SigY = 0.;
 float SigXY = 0.;
 float SigSqrX = 0.;
 float A,B;
 for(int i=0;i<n;i++)
 {

   SigX = SigX + polygon[i].x();
   SigY = SigY + polygon[i].y();
   SigXY = SigXY + (polygon[i].x()*polygon[i].y());
   SigSqrX = SigSqrX + pow(polygon[i].x(),2);
   A = ((n*SigXY) - (SigX*SigY)) / ((n*SigSqrX) - sqrt(SigX));
   B = 1./n * (SigY - (A*SigX));
}

wsp.first=A;
wsp.second=B;
    return wsp;
}

<i>//q: nie no, nie przeginajmny. Co to ma wspolnego z QT? to że pair<>/polygon używa? eh.. std::pair, sturct{x,y}, QT tutaj masz jeden promil max</i>

1 użytkowników online, w tym zalogowanych: 0, gości: 1