Problem z krzywa logistyczna

dział ogólny

Problem z krzywa logistyczna

Nowy postprzez Matthew » czwartek, 25 wrzeÅ›nia 2008, 20:47

Witam.

Mam problem z wyznaczeniem wartosci krzywej logistycznej.

Kod: Zaznacz cały
fneuron[i] -> Text = (1/(1 + pow(M_E,-2*(fneuron[i]->Text).ToDouble())));


Wartosc x znajduje sie w fneuron[i] -> Text. Dla argumentu 25,59575735 otrzymuje dobra wartosc 1, ale juz dla ujemnego x = -54,59451272 otrzymuje
y = 3,80022024291333E-48.

Wzor na krzywa logistyczna to:
Kod: Zaznacz cały
y = 1/( e^(-2 * x) )


Ktos ma pomysl z czego to moze wynikac?

Dziekuje z gory za wszystkie cenne uwagi i pozdrawiam!
Avatar użytkownika
Matthew
Bladawiec
Bladawiec
 
Posty: 20
Dołączył(a): niedziela, 24 sierpnia 2008, 13:59
PodziÄ™kowaÅ‚ : 0
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
    NieznanyNieznana

Re: Problem z krzywa logistyczna

Nowy postprzez kinio » czwartek, 25 wrzeÅ›nia 2008, 22:11

Cześć
Kod: Zaznacz cały
fneuron[i] -> Text = (1/(1 + pow(M_E,-2*(fneuron[i]->Text).ToDouble())));

Kod: Zaznacz cały
y = 1/( e^(-2 * x) )

Te dwa wzory są różne, w tym pierwszym jest jeszcze "jeden plus" w mianowniku. Zdecyduj się najpierw który jest poprawny, może ten pierwszy jest niepoprawny i dlatego masz problem.

Natomiast jeżeli pierwszy jest na 100% poprawny a wynik na 100% niepoprawny (sugeruję jeszcze sprawdzenie na jakimś kalkulatorze) to zapewne będzie to problem z konwersją.
W swoim pierwszym wyrażeniu stosujesz niejawne konwersje. W teorii to powinno wyglądać pięknie, jednak z doświadczenia wiem, że często teoria nie jest zgodna z praktyką.
Radzę zastosować wartości jednego typu, albo zrobić jawne konwersje:
Zamiast 1 napisać 1. albo (double)1
Jeżeli to nic nie da spróbuj opisać dokładniej swój problem, bo z tego opisu nic więcej nie da się wywnioskować!

PS
Sprawdziłem na kalkulatorze i dla Twojego pierwszego wzoru dla tego argumentu ujemnego rzeczywiście wynik jest taki jak podałeś (czyli jest poprawny). W sumie chyba trzeba by się spodziewać małej wartości to w końcu to prawie odwrotność liczby 3^108!!! To nie może być duże :)
Natomiast dla dodatnich argumentów wartość będzie wychodzić o wiele większa bo przecież wykładnik jest wtedy ujemny czyli liczy się to jako odwrotność wartości dla argumentu dodatniego, a że jeszcze jest niejako odwrotność odwrotności to dla argumentów dodatnich Twój wzór jest równoważny: 1 + pow(M_E, 2*(fneuron[i]->Text).ToDouble())) - co daje duże wartości już dla stosunkowo małych wartości argumentów.

Aha, jeszcze jedna myśl mi przeszła przez głowę, być może Ci chodzi o to że ten wynik jest przedstawiony w notacji wykładniczej, wtedy możesz zastosować np. metodę sprintf. Dla przykładu dwa zestawy kodu:
1.
Kod: Zaznacz cały
double x = 2.;
double y = 444444444444444444434345.;
Memo1->Lines->Add(String(x/y));

2.
double x = 2.;
Kod: Zaznacz cały
double x = 2.;
double y = 444444444444444444434345.;
     AnsiString val;
     val = val.sprintf("%.35f", x/y);
     Memo1->Lines->Add(val);


Jak widzisz w tym drugim przypadku nie ma notacji wykładniczej tylko normalna :)
Jeżeli jednak tego wszystkiego już próbowałeś, a dalej jest coś nie tak to podaj więcej szczegółów problemu.

Pozdr!
Ostatnio edytowano czwartek, 25 września 2008, 22:48 przez kinio, łącznie edytowano 2 razy
If a machine is expected to be infallible, it cannot also be intelligent.
-- A.Turing
Avatar użytkownika
kinio
Homos antropiczny
Homos antropiczny
 
Posty: 67
Dołączył(a): poniedziałek, 14 lipca 2008, 08:51
PodziÄ™kowaÅ‚ : 0
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
    NieznanyNieznana

Re: Problem z krzywa logistyczna

Nowy postprzez Cyfrowy Baron » czwartek, 25 wrzeÅ›nia 2008, 22:22

Wynik nie mieści się w zmiennych, pewnie dlatego, że używasz zmiennych 8 bitowych.
Pozostawiasz zbyt wiele przypadkowi. Nie definiujesz konkretnych zmiennych o określonej pojemności, lecz piszesz kod jak leci, na skróty, w efekcie kompilator używa domyślnej własnej konwersji, nie tak jak oczekujesz lecz idzie po najmniejszej linii oporu.

Właściwość Text obiektu fneuron[i] oczekuje wartości typu AnsiString, a Twój wzór zwraca wartość liczbową, którą kompilator oczywiście konwertuje na łańcuch znaków, ale robi to po swojemu.
Mieszasz zmienne całkowite ze zmiennymi zmiennopozycyjnymi (ułamki), w efekcie znów kompilatora wykonuje obliczenia jak mu pasuje, raz na zmiennych całkowitych innym razem na ułamkach, sam zaokrągla sobie, nie określiłeś jawnie kolejności wykonywania działań, wiec kompilator najpier wykona to co jest w nawiasach, mnożenie - dzielenie, dodawanie - odejmowanie

Prawidłowy zapis powinien wyglądać tak:

Kod: Zaznacz cały
  double x = fneuron[i]->Text.ToDouble();
  long double wynik = 1.0 / (1.0 + pow(M_E, -2.0 * x) ); // używam tylko zmiennych zmiennopozycyjnych
  fneuron[i]->Text = (AnsiString)wynik;


funkcja pow powinna zwracać jako wynik wartość typu double, a nie np. Integer.

To tylko przykład jak to powinno wyglądać, nie wiem co próbujesz osiągnąć, ale przy dużych liczbach nie można polegać tylko na zmiennych typu int, float, double, gdyż mają zbyt małe pojemności na przechowywanie dużych liczb, poszukaj w pomocy do BCB, a zobaczysz jakie bogactwo zmiennych oferuje ten język.

► 
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Problem z krzywa logistyczna

Nowy postprzez Matthew » czwartek, 25 wrzeÅ›nia 2008, 23:52

kinio napisał(a):Te dwa wzory są różne, w tym pierwszym jest jeszcze "jeden plus" w mianowniku. Zdecyduj się najpierw który jest poprawny, może ten pierwszy jest niepoprawny i dlatego masz problem.


Pomylilem sie przy przepsiywaniu tego drugiego :[
Poprawny to oczywiscie:

Kod: Zaznacz cały
y = 1/(1+ e^(-2 * x) )


Sorry za blad.

kinio napisał(a):Jeżeli to nic nie da spróbuj opisać dokładniej swój problem, bo z tego opisu nic więcej nie da się wywnioskować!

Ok, pomecze to troche jak nie wyjdzie, na pewno dam znac i podam wiecej szczegolow. Gdy pisalem posta te wydawaly mi sie najwazniejsze :) ale chyba faktycznie problem jest z zakresem typow danych. Myslalem, ze kiedy wyjde poza double'a to dostane jakis stosowny komunikat.

Cyfrowy Baron napisał(a):nie określiłeś jawnie kolejności wykonywania działań, wiec kompilator najpier wykona to co jest w nawiasach, mnożenie - dzielenie, dodawanie - odejmowanie

To zle? Wykonaja sie chyba tak jak powinny.

Cyfrowy Baron napisał(a): double x = fneuron[i]->Text.ToDouble();
long double wynik = 1.0 / (1.0 + pow(M_E, -2.0 * x) ); // używam tylko zmiennych zmiennopozycyjnych

Tutaj pytanie. Moge mieszac double z long double? Nic sie nie stanie zlego?


Edit:
kinio napisał(a):PS
Sprawdziłem na kalkulatorze i dla Twojego pierwszego wzoru dla tego argumentu ujemnego rzeczywiście wynik jest taki jak podałeś (czyli jest poprawny). W sumie chyba trzeba by się spodziewać małej wartości to w końcu to prawie odwrotność liczby 3^108!!! To nie może być duże :)
Natomiast dla dodatnich argumentów wartość będzie wychodzić o wiele większa bo przecież wykładnik jest wtedy ujemny czyli liczy się to jako odwrotność wartości dla argumentu dodatniego, a że jeszcze jest niejako odwrotność odwrotności to dla argumentów dodatnich Twój wzór jest równoważny: 1 + pow(M_E, 2*(fneuron[i]->Text).ToDouble())) - co daje duże wartości już dla stosunkowo małych wartości argumentów.

Aha, jeszcze jedna myśl mi przeszła przez głowę, być może Ci chodzi o to że ten wynik jest przedstawiony w notacji wykładniczej, wtedy możesz zastosować np. metodę sprintf. Dla przykładu dwa zestawy kodu:
1.
Kod: Zaznacz cały
double x = 2.;
double y = 444444444444444444434345.;
Memo1->Lines->Add(String(x/y));

2.
double x = 2.;
Kod: Zaznacz cały
double x = 2.;
double y = 444444444444444444434345.;
     AnsiString val;
     val = val.sprintf("%.35f", x/y);
     Memo1->Lines->Add(val);


Jak widzisz w tym drugim przypadku nie ma notacji wykładniczej tylko normalna :)
Jeżeli jednak tego wszystkiego już próbowałeś, a dalej jest coś nie tak to podaj więcej szczegółów problemu.

Pozdr!


Masz racje! Ale to dziwne, bo wszystkie wyniki operialem o program FNGraph i on dla argumentu -5 na przyklad, pokazywal wartosc 0, czyli taka, jaka chce uzyskac, nawet mi nie przyszlo do glowy zeby sprawdzic to na kalkulatorze. Teraz jednak faktycznie, dla -5 wartosc 0 nie istnieje. Odbije symetycznie ta funkcje i to chyba bedzie najprostsze i najlatwiejsze rozwiazanie tego problemu.

Dziekuje wam za pomoc!
Avatar użytkownika
Matthew
Bladawiec
Bladawiec
 
Posty: 20
Dołączył(a): niedziela, 24 sierpnia 2008, 13:59
PodziÄ™kowaÅ‚ : 0
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
    NieznanyNieznana

Re: Problem z krzywa logistyczna

Nowy postprzez kinio » piÄ…tek, 26 wrzeÅ›nia 2008, 00:38

Cześć!!!

Ale to dziwne, bo wszystkie wyniki operialem o program FNGraph i on dla argumentu -5 na przyklad, pokazywal wartosc 0, czyli taka, jaka chce uzyskac

Po pierwsze jak chcesz uzyskać zero w takiej funkcji, gdzie ona ma miejsca zerowe? Chyba nigdzie, bo aby takie wyrażenie niewymierne mogło się zerować, to licznik musi być zero a on jest cały czas stały i równy 1. Jedyne miejsce zerowe jakie może mieć ta funkcja znajduje się w minus nieskończoności, kiedy to TeX: \lim_{x \rightarrow -\infty}\frac{1}{1+e^{-2x}} = 0 natomiast w TeX: \infty wartość wyrażenia będzie dążyć do jeden: TeX: \lim_{x \rightarrow \infty}\frac{1}{1+e^{-2x}} = 1
Po drugie. Nie wieżę żeby ten program miał tak słabą dokładność, więc pewnie da się gdzieś ustawić dokładność obiliczeń i pewnie podczas twoich obliczeń była ona za mała, bo jak widzisz wynik y = 3,80022024291333E-48.
jest bardzo mały, być może zbyt mała jest to wartość. Zobacz czy da się zwiększyć dokładność obliczeń.

Odbije symetycznie ta funkcje i to chyba bedzie najprostsze i najlatwiejsze rozwiazanie tego problemu.

Co to znaczy odbiję symetrycznie, co chcesz zrobić? Chyba mi nie powiesz że chcesz odbić zwględem osi OY, czy przekształcić przez jednokładność względem środka układu!!
Po pierwsze funckja ani jest pażysta ani nie pażysta więc nie możesz wykonać takich operacji.
Pażystość zachodzi gdy: f(x) = f(-x), czyli dla Twojego przypadku: TeX: f(x) = \frac{1}{1+e^{-2x}}, natomiast TeX: f(-x) = \frac{1}{1+e^{(-2)(-x)}} = \frac{1}{1+e^{2x}} \neq f(x) - więc funckja nie jest pażysta, w ten sam sposób zobaczysz że też nie jest nieparzysta. Więc nie możesz jej odbijać (chyba że co innego rozumiesz przez to pojęcie).

Pozdr!
Ostatnio edytowano piątek, 26 września 2008, 01:22 przez kinio, łącznie edytowano 5 razy
If a machine is expected to be infallible, it cannot also be intelligent.
-- A.Turing
Avatar użytkownika
kinio
Homos antropiczny
Homos antropiczny
 
Posty: 67
Dołączył(a): poniedziałek, 14 lipca 2008, 08:51
PodziÄ™kowaÅ‚ : 0
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
    NieznanyNieznana

Re: Problem z krzywa logistyczna

Nowy postprzez Matthew » piÄ…tek, 26 wrzeÅ›nia 2008, 00:54

Chce uzyskac funkcje, ktora osiaga dla dodatnich argumentow wartosc 1, a dla ujemnych wartosc 0 i zeby miala ona ksztalt podobny do tej:
Obrazek
Dla x=0, y=1/2, wiec usune czesc po lewej stronie OY i 'przekopiuje' tam prawa, odpowiednia odwracajac. O to mi chodzilo. Przepraszam, jesli cos co napisalem bylo zbyt malo precyzyjne :)

Ten program dla argumentu -20 pokazuje error ;] Ustawilem precyzje na 0.0001, wyniki te same, a prog malo co sie nie zwiesil.
Avatar użytkownika
Matthew
Bladawiec
Bladawiec
 
Posty: 20
Dołączył(a): niedziela, 24 sierpnia 2008, 13:59
PodziÄ™kowaÅ‚ : 0
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
    NieznanyNieznana

Re: Problem z krzywa logistyczna

Nowy postprzez kinio » piÄ…tek, 26 wrzeÅ›nia 2008, 01:02

Ten program dla argumentu -20 pokazuje error ;] Ustawilem precyzje na 0.0001, wyniki te same, a prog malo co sie nie zwiesil.

W moim przykładzie pierwsze znaczące liczby pojawiły się ok. 30-setgo miejsca po przecinku więc nawet w takim razie nie próbuj zwiększać dokładności bo się zawiesi na amen :)

Jeżeli chcesz mieć funkcję, która dla wartości x mniejszych od 0 przyjmuje zero a dla dodatnich jeden to i proponuję funckję postaci: TeX: f(x) = \frac{sgn(x)+1}{2} która w 100% spełnia Twoje wymaganie!
Natomiast nie wiem o co chodzi żeby była podobna? Czy masz na myśli żeby była różniczkowalna w całej dziedzinie tzn. TeX: \forall_{x \in D} zachodzi TeX: \lim_{x \rightarrow a^{-}}f(x) = \lim_{x \rightarrow a^{+}}f(x)?
If a machine is expected to be infallible, it cannot also be intelligent.
-- A.Turing
Avatar użytkownika
kinio
Homos antropiczny
Homos antropiczny
 
Posty: 67
Dołączył(a): poniedziałek, 14 lipca 2008, 08:51
PodziÄ™kowaÅ‚ : 0
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
    NieznanyNieznana

Re: Problem z krzywa logistyczna

Nowy postprzez Matthew » piÄ…tek, 26 wrzeÅ›nia 2008, 09:08

kinio napisał(a):W moim przykładzie pierwsze znaczące liczby pojawiły się ok. 30-setgo miejsca po przecinku więc nawet w takim razie nie próbuj zwiększać dokładności bo się zawiesi na amen

Nie udaloby mi sie go zawiesic chyba, bo juz przy wpisaniu dokladniosci 0.000001 program wyrzuca inteligentny komunikat, ze wartosc musi sie zawierac miedzy 0 a 1 :P Zwyczajnie w zle towarzystwo trafilem :]

kinio napisał(a):
Jeżeli chcesz mieć funkcję, która dla wartości x mniejszych od 0 przyjmuje zero a dla dodatnich jeden to i proponuję funckję postaci: TeX: f(x) = \frac{sgn(x)+1}{2} która w 100% spełnia Twoje wymaganie!

Nie wiem jak to napisac, ale chodzi mi o to, zeby w okolicach argumentu zero przybierala ksztalt paraboliczny, sinusoidalny, no cos takiego... Ta ktora podales, niestety taka nie jest.

No ale nic, zrobie tak jak napisalem w poscie wyzej i bedzie git.

Jeszcze raz wielkie dzieki za zainteresowanie i pomoc!
Avatar użytkownika
Matthew
Bladawiec
Bladawiec
 
Posty: 20
Dołączył(a): niedziela, 24 sierpnia 2008, 13:59
PodziÄ™kowaÅ‚ : 0
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
    NieznanyNieznana


Powrót do Ogólne problemy z programowaniem

Kto przeglÄ…da forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 5 gości