You are on page 1of 74

AKADEMIA GÓRNICZO-HUTNICZA

Wydział Zarządzania

Praca magisterska
Hybrydowy system wspomagania decyzji inwestycyjnych
Piotr Szwabowski

Nr albumu: 91088

Opiekun pracy:
dr inż. Adam Stawowy

Kraków, 2002
Spis treści
Spis treści...................................................................................................................................2
1. Główne kierunki rozwoju systemów wspomagania decyzji...................................................3
1.1. Wstęp...............................................................................................................................3
1.2. Rola sztucznej inteligencji w systemach ekspertowych i predykcyjnych.......................4
1.3. Teoria chaosu, a współczesne podejście do analizy danych...........................................7
1.4. Cel i zakres pracy............................................................................................................8
2. Systemy wspomagania decyzji inwestycyjnych.....................................................................9
2.1. Wstęp...............................................................................................................................9
2.2. Sieć neuronowa jako narzędzie wspomagania decyzji inwestycyjnych.......................12
2.2.1. Model I..................................................................................................................14
2.2.2. Model II.................................................................................................................19
2.3. Rozmyto neuronowy system wspomagania decyzji inwestycyjnych............................30
3. Wnioski.................................................................................................................................50
4. Literatura...............................................................................................................................52
5. Aneks....................................................................................................................................53
1. Programy do importowania notowań, przenoszenia danych do środowiska Matlab i
weryfikacji danych...................................................................................53
2. Funkcje do nauki i testów klasyfikujących sieci neuronowych
(rozdział 2.2.2).........................................................................................59
3. Wyniki testów sieci klasyfikujących (rozdział 2.2.2).................................................63
4. Funkcje do nauki sieci rozmyto neuronowych (rozdział 2.3).....................................65
5. Wyniki testów sieci rozmyto neuronowych (rozdział 2.3)..........................................69

2
1. Główne kierunki rozwoju systemów
wspomagania decyzji

1.1. Wstęp
Metody przewidywania przyszłości od starożytności zaprzątały umysły ludzkie. W
historii zaobserwować możemy ich ewolucję, od szklanych kul i zwierciadeł, aż po ekrany
komputerów. Jeszcze nie tak dawno w analizie danych korzystano z ołówków, stert papieru i
suwaków logarytmicznych. Obecnie komputery i zaawansowana technologia stały się
wystarczająco wydajne, abyśmy mogli analizować wielkie ilości danych. Wszystkie dziedziny
związane z szeroko pojętą analizą danych są połączone z rozwojem technik informatycznych.
Niesłychany rozwój w dziedzinie komputerów w ostatnim dziesięcioleciu spowodował, że
możemy w domach wykorzystywać maszyny o potężnej mocy obliczeniowej. Dzięki temu,
przeciętni ludzie zyskali możliwość rozpoznawania obrazu i dźwięku, korzystania z
inteligentnych pomocników, a nawet dialogu z komputerem. Wymienione systemy
inteligentne są jedynie niewielkim ułamkiem wszystkich, powszechnie używanych do analizy
i obróbki danych. Stworzenie inteligentnych maszyn, które z minimalną ingerencją człowieka
będą się zajmowały rozlicznymi problemami zaczyna być realne. Jedną z dziedzin, gdzie
takie narzędzie znalazłoby zastosowanie jest z pewnością analiza finansowych szeregów
czasowych. Pomocnik, który sam konstruuje portfel papierów wartościowych i modyfikuje
jego skład zgodnie z tendencjami na rynku, jest marzeniem każdego inwestora giełdowego.
Nie każdego jednak stać na opłacenie prywatnego doradcy. Z drugiej strony, jeżeli
pomocnikiem tym okazałby się niedrogi w eksploatacji komputer wyposażony w
odpowiednie oprogramowanie, wówczas wiele osób zdecydowałoby się na jego zakup.

3
Analiza finansowych szeregów czasowych zaliczana jest do metod ilościowych,
opisowo prognostycznych. Główną przyczyną rozwoju tych technik była chęć uzyskania
ponadprzeciętnych zysków w wyniku trafnych decyzji inwestycyjnych. W tym celu nasi
przodkowie analizowali wykresy i zachowanie rynku, próbowali wychwytywać zależności
rządzące tym złożonym systemem. Z czasem metody zostały połączone w całość o nazwie
„Analiza techniczna”. Współcześnie, oprócz tej wysoce zawodnej techniki, mamy do wyboru
wiele innych, takich jak:
• modele ekonometryczne,
• metody oparte na teorii procesów stochastycznych,
• teoria chaosu,
• sztuczna inteligencja – sieci neuronowe, algorytmy genetyczne oraz systemy
rozmyte. 4
Dwie ostatnie grupy są szczególnie interesujące ze względu na nowe możliwości,
które przed nami otwierają.

1.2. Rola sztucznej inteligencji w systemach


ekspertowych i predykcyjnych
Sztuczna inteligencja, jak wszystkie zaawansowane numeryczne metody
obliczeniowe, rozwinęła się dopiero w drugiej połowie ubiegłego stulecia. Od tamtej pory
dzięki metodom z nią związanym udało się rozwiązać wiele niezwykle trudnych problemów,
a zapotrzebowanie na rozwiązania w tej dziedzinie ciągle rośnie.
Sztuczna inteligencja niezwykłe zainteresowanie zawdzięcza swoim specyficznym
własnościom. Techniki z nią związane posiadają zdolność do modelowania niezwykle
skomplikowanych zjawisk i systemów na podstawie dotyczących ich historycznych
wiadomości. Bez nich analiza niektórych klasycznych problemów nieliniowych, takich jak
stabilizacja wahadła odwróconego bądź zagadnienie parkowania ciężarówki, byłaby
niezwykle utrudniona. Istnieje wiele dziedzin, w których wykorzystanie tych metod jest nie
tylko wygodne, lecz konieczne, jak ma to miejsce w predykcji chaotycznych szeregów
czasowych. Jest to niezwykle istotny problem spotykany w dziedzinach ekonomii,
planowania finansowego, przewidywania pogody, przetwarzania sygnałów, sterowania i
wielu, wielu innych.
Kolejną niezwykle istotną zaletą tych metod jest możliwość przetwarzania wielkich
ilości danych. Ograniczeniem jakie stawia przed nami rzeczywistość, jest w tym przypadku

4
szybkość wykorzystywanego komputera. Metody SI znajdują również zastosowanie w
skomplikowanych problemach optymalizacyjnych. Algorytmy genetyczne służą nam jako
metody optymalizacji globalnej.
Oprócz rozlicznych zalet techniki te posiadają również wady. Jedną z nich jest długi
czas przetwarzania danych. Widać to wyraźnie na przykładzie sieci neuronowych. Czasami
niewielka poprawa wyników okupiona jest niezwykle długim okresem nauki. Choć sieć
neuronowa składa się z niezwykle prostych elementów, jakimi są neurony, to w efekcie
otrzymujemy wyjątkowo skomplikowaną strukturę z setkami połączeń. Obróbka dużej ilości
danych z wykorzystaniem takiego narzędzia jest niezwykle czasochłonna. Również algorytmy
ewolucyjne są pod tym względem podobne. Wyniki dzięki nim uzyskane przekraczają
możliwości innych metod obliczeniowych, jednak czas dotarcia do odpowiedzi nie jest znany.
Posiadając dużo informacji na temat badanego zjawiska, możemy jedynie szacować
prawdopodobny czas obliczeń. Z systemami rozmytymi sytuacja wygląda bardzo podobnie
jak w przypadku sieci neuronowych. Składający się z neuronów system jest jednak
wyposażony w znacznie większą ich liczbę. Suma połączeń w strukturach rozmytych jest
astronomiczna, a dodanie choćby jednej zmiennej powoduje często niemożność
przeprowadzenia obliczeń.
Inną niekorzystną cechą tych metod jest ich skłonność do przeuczenia, narażone są na
to sieci neuronowe i rozmyto neuronowe. Przeuczenie następuje, gdy proces nauki jest zbyt
długi. Wiedza zgromadzona w danych nie zostaje wówczas uogólniona, a jedynie wyuczona
przez daną strukturę, przez co traci ona elastyczność. Przeuczone sieci neuronowe uzyskują
świetne rezultaty w obszarze danych służących do nauki, ale prezentacja każdego innego
zbioru testowego nie daje efektów. Algorytmy zapobiegające temu zjawisku często zawodzą,
a wówczas poszukiwana odpowiedź jest obarczona błędem znacznie wyższym od
zakładanego.
Ostatnim problemem, kto wie czy nie najpoważniejszym, jest zawartość informacyjna
danych. Zazwyczaj nie jesteśmy w stanie ocenić czy posiadane przez nas dane są rzetelne, czy
nie są obarczone zbyt dużym błędem, i czy niosą ze sobą jakąkolwiek wiedzę na temat
badanego zjawiska, wiedzę, którą dałoby się uogólnić. Sieć neuronowa bądź rozmyto
neuronowa zawsze udzieli nam odpowiedzi, bez względu na to, co zaprezentujemy na jej
wejściu. Jeżeli uogólniona w tej strukturze wiedza na dany temat nie obejmuje danych
prezentowanych na wejściu wówczas odpowiedź będzie prawdopodobnie błędna. Zatem
najtrudniejszym zadaniem przy konstruowaniu sieci jest odpowiedni wybór i przygotowanie
danych wzorcowych, tak aby uzyskane później wyniki były jak najtrafniejsze.

5
Ogromna różnorodność algorytmów wchodzących w skład dziedziny zwanej sztuczną
inteligencją, i ich skuteczność powodują, iż coraz częściej znajdują one zastosowanie w życiu.
We współczesnym świecie przetwarzanie danych oraz wyciąganie z nich odpowiednich
wniosków powoli stają się odrębną gałęzią przemysłu. „Data Mining” jest często najtańszą i
wyjątkowo skuteczną metodą ograniczania kosztów lub maksymalizowania korzyści. Jest to
oczywiście pojęcie znacznie szersze i nie obejmuje jedynie metod wywodzących się ze
sztucznej inteligencji, jednak sieci neuronowe i rozmyto neuronowe oraz algorytmy
genetyczne w połączeniu z nimi uzyskują nadspodziewanie dobre wyniki. Wiele
zaawansowanych aplikacji służących do „Data Mining” umożliwia integrację kilku metod i
wspólne wnioskowanie na podstawie uzyskanych z nich wyników. W zakresie tych metod
szczególne zainteresowanie wzbudzają dwie:
• drzewa decyzyjne,
• segmentacja danych.
Z ich pomocą można wstępnie przeanalizować dane pod względem zawartości
informacyjnej ograniczając w ten sposób błędy wynikające ze złego doboru danych.
Segmentacja danych jest również używana w systemach rozmyto neuronowych w celu
określenia liczby reguł rządzących danym zjawiskiem. Proces ten wielokrotnie ogranicza czas
trwania nauki dowolnego systemu.
Współczesny światowy system gospodarczy to niezwykle skomplikowany organizm,
w którym większość zależności wciąż pozostaje ukryta. Wyznaczenie podstawowych
zmiennych, na których powinniśmy opierać nasze wnioskowanie jest wręcz niemożliwe.
Dlatego też osoby zajmujące się tą dziedziną wiedzy świadomie ograniczają ich liczbę, tak,
aby przeprowadzenie obliczeń było w ogóle możliwe. Problemem jest nie tylko liczba
dostępnych zmiennych, lecz również ich struktura. Wprowadzenie danych określających
nastroje giełdowe z pewnością poszerzyłoby naszą wiedzę na temat zjawiska, ale sposób
wykonania tego zadania nie jest znany. Podobnie jak każdy system naturalny gospodarka
pozostaje w ciągłym ruchu. Kolejne zachodzące w niej zmiany mogą mieć unikalny charakter
i nie mieć swoich odpowiedników w historii. Większość systemów wspomagania decyzji
staje się wówczas bezużyteczna, ale nie zawsze.
Na początku dwudziestego wieku na giełdach światowych pojawiły się indeksy. Te
niezwykle proste wskaźniki były kolejnym krokiem na drodze do poznania mechanizmów
związanych z rynkami kapitałowymi. Do dnia dzisiejszego stanowią podstawę globalnych
analiz giełdowych ze względu na swój ogólny charakter. Dzięki nim możliwe staje się

6
określenie ogólnej sytuacji rynkowej, bez konieczności koncentrowania się na wszystkich
papierach wartościowych. Poza tym indeksy giełdowe jako wskaźniki syntetyczne przenoszą
znacznie więcej informacji niż wynikałoby to ze sposobu ich obliczania. Są również
odzwierciedleniem sytuacji gospodarczej danego regionu, kraju czy całego globu. Jedynym
problemem jest wydobycie tych informacji i wyeliminowanie wpływu szumu, który może
skutecznie uniemożliwić przeprowadzenie analiz. Sieci neuronowe i rozmyto neuronowe
znajdują swoje zastosowanie właśnie w tego rodzaju skomplikowanych i wymagających
nietypowego podejścia problemach.

1.3. Teoria chaosu, a współczesne podejście do analizy


danych
Teoria chaosu to stosunkowo młoda dziedzina wiedzy. Fakt ten zaskakuje ze względu
na to , że chaos nie jest niczym wyjątkowym w naszym codziennym życiu. Niemal wszystkie
systemy naturalne podlegają prawom chaosu i pomimo swojej cykliczności dalej pozostają
nieprzewidywalne. Większość modeli, liniowych bądź nieliniowych, stworzonych na
potrzeby nauki ma niewielki związek z rzeczywistością. Są one zazwyczaj niezwykle
uproszczone i nie oddają całej istoty zjawisk.
Po raz pierwszy konieczność zastosowania teorii chaosu zauważono w meteorologii.
Przewidywanie pogody z wyprzedzeniem kilku dni jeszcze niedawno pozostawało poza
zasięgiem ludzkich możliwości. Niezwykle chaotyczny charakter tych zjawisk wymagał
nowego podejścia i zerwania z dotychczasowymi przyzwyczajeniami. Analiza pogody i
innych systemów naturalnych stała się podstawą do stworzenia koncepcji deterministycznego
chaosu. Ostatnio coraz częściej mówi się o chaotycznym charakterze globalnego systemu
gospodarczego. Podstawą tego założenia jest, podobnie jak w przypadku pogody,
nieprzewidywalny, choć cykliczny charakter zmian zachodzących w tym systemie. Jeżeli
przyjmiemy założenie, iż gospodarka, podobnie jak pogoda, istotnie jest systemem
naturalnym, to w takim wypadków zerwanie z dotychczasowymi przyzwyczajeniami również
może okazać się koniecznością. Wszystkie analizy trendów i cykli giełdowych będzie trzeba
wyrzucić do kosza i rozpocząć nowe badania z wykorzystaniem metod wchodzących w skład
teorii chaosu.
Duże zastosowanie znajdują algorytmy, o których wspomniano w poprzednim
rozdziale, gdyż świetnie nadają się do modelowania, przeprowadzając je na podstawie danych
doświadczalnych. Nowe możliwości otwiera przed nami również Analiza R/S. Na podstawie

7
tej metody można określić czy dany chaotyczny szereg czasowy jest persystentny, a jeżeli tak
to jak daleko w przeszłość sięga jego „pamięć”. Niestety wykonanie analizy przeskalowanego
zakresu wymaga dużych ilości danych, z tego względu nie da się jej przeprowadzić dla
polskich indeksów giełdowych.

1.4. Cel i zakres pracy


Niniejsza praca poświęcona jest dwóm z wymienionych technik, sieciom neuronowym
i rozmyto neuronowym. Na podstawie tych technik postaram się stworzyć system
predykcyjny, który pozwoli przewidywać przyszłe wartości indeksu giełdowego WIG20.
Wybór indeksu nie jest przypadkowy. Jako instrument, który opisuje największe polskie
spółki giełdowe, jest z pewnością najlepszym wskaźnikiem obrazującym ogólną sytuację
polskiego rynku finansowego. Postaram się zatem odpowiedzieć na pytanie: Czy
przewidywanie zachowania uczestników rynku na podstawie ograniczonych danych
historycznych jest możliwe?
Podstawowym narzędziem wykorzystywanym w pracy jest środowisko „Matlab 6.0”
wyposażone w kilka dodatkowych bibliotek. Szczegółowy opis tego pakietu przedstawiono w
dalszej części pracy.

8
2. Systemy wspomagania decyzji inwestycyjnych

2.1. Wstęp
Analiza dowolnego zjawiska nie może obejść się bez danych. Jest to oczywiste, jednak
bardzo często stanowi ogromny problem, często znacznie większy niż wszystkie dalsze etapy
pracy. Posiadanie rzetelnych i odpowiednio przygotowanych danych jest warunkiem
koniecznym do stworzenia skutecznego systemu predykcyjnego.
W pracy skupiono się na przewidywaniu zmian wartości indeksu WIG20 w
najbliższym tygodniu. We wszystkich wariantach sieci wielkość ta występuje jako zmienna
zależna. Wykładnicze zmiany wartości papierów i indeksów mogą okazać się niebezpieczne
dla systemu, w którym przewidywane są inne wielkości, na przykład średnia wartość WIG20
w przyszłym tygodniu. Rozwiązania polegające na przewidywaniu konkretnych wartości
dowolnego waloru istnieją w wielu komercyjnych aplikacjach, a uzyskiwane przez nie wyniki
są w zupełności zadowalające. Mimo to zrezygnowałem z tego podejścia, właśnie ze względu
na duże niebezpieczeństwo błędów, które znacznie wzrasta, gdy następują gwałtowne zmiany
na rynku. Dodatkową przewagą przewidywania wielkości związanych z indeksami
giełdowymi jest ich względna stabilność w krótkich okresach czasu. Predykcja ceny
konkretnego papieru wartościowego wydaje się niemożliwa nawet w sytuacji zastosowania
ogromnej ilości danych. Wynika to ze znacznych wahań tych cen spowodowanych często
plotkami i niepotwierdzonymi informacjami. We wskaźnikach giełdowych takich jak WIG
lub WIG20 wartości te są uśredniane i dzięki temu nie stanowią tak dużego zagrożenia.
Za najmniejszą jednostkę czasu, stosowaną do określania wszystkich zmiennych,
przyjęto 1 tydzień. Przyjęcie takiego okresu podstawowego wydaje się najbezpieczniejsze w
sytuacji, gdy na polskim rynku istnieje kilka wariantów notowań różnych papierów
wartościowych. Dzięki temu uniknięto również niezgodności wynikających z
okolicznościowych bądź losowych przestojów w działalności giełdy.
Do stworzenia modeli sieci neuronowych wykorzystano „Neural Network Toolbox”,
pakiet funkcji środowiska Matlab. Jest to niezwykle obszerny zbiór skryptów zawierających
algorytmy tworzenia i nauki różnorodnych struktur neuronowych.
Za zmienne niezależne przyjęto historyczne zmiany wartości tego samego indeksu w
różnych okresach. Żadne z poważniejszych wydarzeń gospodarczych, politycznych bądź
społecznych nie pozostaje bez wpływu na jego zmiany. Zatem stosowanie innych

9
wskaźników gospodarczych bądź demograficznych wcale nie musi znacząco poprawiać
wyników systemu predykcyjnego. Znacząco natomiast komplikuje strukturę tego systemu i
wydłuża czas trwania obliczeń. Często też zawartość informacyjna zmiennej jest duplikowana
poprzez wprowadzenie innej zmiennej. Sytuacji tej należy się wystrzegać nawet w przypadku
prostych modeli regresji liniowej, nie wspominając o sieciach neuronowych i rozmyto
neuronowych. Ilość możliwych do wykorzystania zmiennych jest nieograniczona, lecz
niestety ich wpływ na badane zjawisko nie jest jednakowy. Zastosowanie nieodpowiednich
zmiennych może nawet pogorszyć przyszłe wyniki projektowanego systemu. Z tych właśnie
powodów zdecydowano się na użycie zmian wartości indeksu giełdowego WIG20 w różnych
okresach jako jedynych zmiennych niezależnych, pomimo, iż początkowo może to
przypominać prostą analizę jednowymiarową.
Informacje o wartościach indeksu giełdowego WIG20 pozyskano ze zbiorczych
tekstowych plików notowań dostępnych na stornach internetowych Domu Maklerskiego
Banku Ochrony Środowiska S.A.. Informacje te wymagały następnie przeniesienia do
środowiska Matlab. W tym celu stworzono podstawowe elementy systemu służące do
formatowania posiadanych plików tekstowych i importowania ich. Pierwszy z nich to arkusz
kalkulacyjny o nazwie aktualizacja.xls wyposażony w krótki moduł Visual Basic. Moduł ten
wraz z dokumentacją techniczną znajduje się w załączniku 1. Ma on za zadanie
wyeliminowanie z plików tekstowych ciągów znaków i pozostawienie w nich jedynie
informacji liczbowych wraz z datami. Proste funkcje służące w środowisku Matlab do
importowania danych z plików tekstowych w formie macierzy zmuszają do umieszczania w
nich jedynie informacji numerycznych.
Kolejnym etapem jest weryfikacja posiadanych notowań pod względem niezgodności
w datach lub wartościach oraz zapisanie ich w formacie zmiennych środowiska Matlab. Służy
temu skrypt wczytaj.m. Wykorzystuje ona dwa inne skrypty, splitakcji.m oraz zledaty.m, a
informacje o wychwyconych błędach zapisuje w plikach tekstowych. Funkcja wczytująca
zapisuje pozyskane notowania w formie zmiennej środowiska Matlab i nadaje jej nazwę
zgodną z nazwą pliku, którego notowania pochodziły. Często niezbędna jest modyfikacja tej
nazwy, gdyż Matlab toleruje jedynie te, które rozpoczynają się znakami alfabetu. Dlatego też
zamiast „01NIF” należy użyć „NIF01”. Nazwane uprzednio zmienne zapisywane są w
zbiorczym pliku Zmienne.mat, znacząco przyspiesza to ich dalszą obróbkę ponieważ Matlab
nienajlepiej radzi sobie z zewnętrznymi źródłami danych. Z racji, iż proces sprawdzania
wartości notowań jest raczej długi, zdecydowano się na jego rejestrowanie. Dzięki temu
moduł wczytywania nigdy nie powraca do miejsc już sprawdzonych. Kod wszystkich

10
procedur wczytywania danych do środowiska Matlab wraz z dokumentacją znajduje się w
załączniku 1. Zbiór tych funkcji jest dość elastyczny i umożliwia wczytywanie i sprawdzanie
notowań dowolnego papieru, nie tylko indeksu giełdowego WIG20. Zatem poszerzenie zbioru
wejściowego bądź wyjściowego na potrzeby nowego systemu nie stanowi dużego problemu.
Podobnie jak w przypadku zmiennej zależnej we wszystkich sieciach zastosowano
identyczny zbiór wejściowy. Umożliwi to w późniejszym etapie ogólną ocenę
poszczególnych struktur pod kątem ich skuteczności w przewidywaniu przyszłych wartości.
Największym problemem podczas formowania wyżej wymienionych zbiorów okazało się
wyznaczenie okresu historycznego, który miał zostać zawarty w danych wejściowych.
Problem ten jest bezpośrednio związany z wpływem przeszłych informacji na bieżącą
sytuację. Z badań wynika, że większość systemów naturalnych nie działa w sposób
przypadkowy, a ich błądzenie jest obciążone przeszłymi wydarzeniami 4. Również
międzynarodowe indeksy giełdowe podlegają tej regule. Niestety w przypadku WIG20 ilość
dostępnych notowań jest zbyt mała, aby możliwe było określenie współczynnika Hursta i
wyznaczenie okresu wpływu przeszłych informacji na podstawie analizy R/S. Dlatego też
posłużono się analogią do giełd zagranicznych. Z analizy przeskalowanego zakresu
przeprowadzonej na kilku indeksach międzynarodowych wynika, iż podstawowym cyklem
giełdowym jest okres czterech do pięciu lat. Zatem informacje, jakie pojawiły się na rynku
przed czterema laty i zostały utrwalone w wynikach indeksu w tamtym okresie, mają wpływ
na obecne zmiany. Zastosowanie tak długiego okresu w tym przypadku może doprowadzić do
znacznego uszczuplenia i tak skromnych danych, a nawet gdyby to było możliwe, to przecież
rynek polski nie jest nawet w połowie tak rozwinięty jak zagraniczne giełdy. Z tych
względów zdecydowałem się na ograniczenie tego okresu do dwóch lat.

11
Zbiór wejściowy składa się z sześciu elementów, z których każdy oznacza zmianę
wartości indeksu WIG20 w pewnym okresie. Pierwszy z nich obejmuje tydzień
poprzedzający moment prognoz. Drugi, okres trzech tygodni poprzedzających pierwszy.
Długości poszczególnych interwałów prezentuje znajdująca się poniżej tabela 1.

Tabela 1. Długość okresów i odpowiadające im zmienne wejściowe.


Liczba tygodni wstecz Długość okresu w
Dana wejściowa
Tydzień końcowy Tydzień początkowy tygodniach
1 1 1 1
2 2 4 3
3 5 12 8
4 13 24 12
5 25 48 24
6 49 96 48
Suma 96

Kolejne okresy nie zachodzą na siebie, a zawarte w danych wejściowych zmiany


indeksu nie są ze sobą bezpośrednio związane. Ogółem przenoszą informacje na temat zmian
w ostatnich 96 tygodniach notowań indeksu (około 2 lata). Zdecydowano się na rozszerzanie
wielkości kolejnych okresów, ponieważ jak wynika to z analizy szeregów czasowych
indeksów zagranicznych, związek historycznych zmian z aktualną sytuacją zmniejsza się
wraz z upływem czasu 4. Podczas projektowania zbioru wejściowego zastanawiałem się nad
możliwością zastosowania wariantu, w którym zmiany indeksu określane są na podstawie
aktualnej jego wartości. Jednak w tym przypadku dane dotyczące zmian w ostatnim tygodniu
byłyby pośrednio zawarte we wszystkich zmiennych wejściowych sieci.

2.2. Sieć neuronowa jako narzędzie wspomagania decyzji


inwestycyjnych
W kolejnych dwóch rozdziałach opisano dwa modele sieci neuronowych. Pierwszy z
nich zwraca wartość indeksu giełdowego WIG20 w przyszłym tygodniu. Drugi dokonuje
wielokrotnej klasyfikacji sygnału wejściowego przy pomocy zbioru kilku sieci. W wyniku
otrzymuje się rozmytą odpowiedź, którą w dalszej kolejności porównuje się z faktycznymi
zmianami indeksu. Szczegóły związane z poszczególnymi modelami przedstawiono w dalszej
części pracy. W tym miejscu pragnę jedynie wspomnieć o kilku metodach wykorzystanych do
konstruowania, nauki i testowania sieci.
Matlab oferuje niezwykle szeroką gamę metod związanych z sieciami neuronowymi.
Wystarczy wspomnieć, iż w tym celu został stworzony osobny moduł o nazwie „Neural

12
Network Toolbox”. Pomimo tej różnorodności jest to jednak wyjątkowo nieprzyjazne
środowisko, głównie ze względu na brak przejrzystego interfejsu graficznego. Początkowo
Matlab działał jedynie w trybie tekstowym. Wraz z rozwojem graficznych interfejsów
systemów operacyjnych również i on uległ modyfikacjom, lecz nawet w najnowszej wersji
rozwiązania te są niedopracowane. Wykorzystywana w ramach tego pakietu tak zwana
„handle graphics” naśladuje współczesne standardy programowania obiektowego i dla
niewielkich projektów jest w zupełności wystarczająca. Jednak stworzona przy jej pomocy
obsługa dla poszczególnych modułów często ogranicza się do podstawowych funkcji
matematycznych w ramach danej dziedziny. Zazwyczaj i tak trzeba powracać do linii poleceń
lub tworzyć własne wyspecjalizowane rozwiązania. Na szczęście podstawowe elementy
środowiska takie jak edytor skryptów, podgląd zmiennych i program uruchomieniowy
zasługują na wysoką ocenę.
Niewątpliwą zaletą tego środowiska jest bardzo wysoki poziom składni.
Implementacja niektórych komend w innych językach programowania wymagałaby często
wielu stron kodu, a czasami stworzenia całego projektu. Wygoda w pisaniu krótkich
projektów jest niestety okupiona długim czasem obliczeń. Jako interpreter Matlab jest
wyjątkowo powolny. Stworzenie szybkiej aplikacji w tym środowisku wymaga dużych
umiejętności. Istnieje możliwość transformacji kodu do C++ w celu stworzenia oddzielnej
aplikacji, jednak jest to bardzo uciążliwe.
Matlab umożliwia naukę sieci neuronowych z wykorzystaniem dziewięciu różnych
algorytmów. Na największe zainteresowanie zasługują dwa z nich. Pierwszym jest algorytm
LM (Levenberg-Marquardt). Jest to prawdopodobnie najszybsza z metod uczenia sieci.
Sprawdza się zarówno w problemach aproksymacji jak i klasyfikacji. Wykorzystywana jest
głównie do nauki sieci o bardzo prostej strukturze, z kilkoma neuronami w warstwie ukrytej,
przez co jej zastosowanie w poważniejszych problemach jest raczej ograniczone. Istnieje
oczywiście możliwość zastosowania tego algorytmu w procesie nauki dowolnej sieci, jednak
już po przekroczeniu liczby 20 neuronów w warstwie ukrytej czas trwania nauki jest
porównywalny z klasyczną metodą wstecznej propagacji błędu. Drugim bardzo interesującym
algorytmem jest SCG (Scaled Conjugate Gradient), czyli metoda gradientów sprzężonych.
Największą zaletą metody gradientów sprzężonych jest jej niezwykła uniwersalność.
Podobnie jak poprzedni omawiany algorytm, także ten świetnie znajduje się w problemach
aproksymacji i klasyfikacji. Ponadto nie posiada ograniczeń wynikających ze złożoności
struktury sieci. Jest stosowany do nauki zarówno małych i dużych sieci. W obu wypadkach
proces ten jest niezwykle krótki, a jego skuteczność porównywalna ze standardowym

13
algorytmem backpropagation. Twórcami tej metody byli Magnus Hestenes i Eduard Stiefel.
W roku 1952 opracowali oni nowy algorytm rozwiązywania układów równań liniowych. W
metodzie tej kolejne kierunki poszukiwań rozwiązania są wzajemnie sprzężone. W niektórych
przypadkach może to powodować wydłużenie czasu nauki. Mimo to algorytm gradientów
sprzężonych znajduje się w ścisłej czołówce najszybszych metod optymalizacji połączeń sieci
neuronowych.
Niewątpliwą zaletą środowiska Matlab jest również możliwość tworzenia sieci
statycznych i dynamicznych. Te ostatnie wymagają jednak dużych możliwości komputera. Na
przeciętnym sprzęcie domowego użytku nauka struktur z opóźnieniem jest wyjątkowo
czasochłonna. Z tego względu w pracy skoncentrowano się jedynie na statycznych sieciach
neuronowych.

2.2.1. Model I

W pierwszym modelu sieci neuronowej skupiłem się na przewidywaniu konkretnych


wartości zmian indeksu WIG20 w nadchodzącym tygodniu. Do prognoz zastosowałem
wspomniany w poprzednich rozdziałach zbiór wartości wzorcowych, obejmujący około 400
rekordów zawierających dane o historycznych zmianach indeksu w całym okresie jego
notowania na Giełdzie Papierów Wartościowych w Warszawie. Kilka przykładowych
rekordów ze zbioru danych wejściowych prezentuje tabela 2.

Tabela 2. Przykładowe rekordy ze zbioru wzorcowego.

Zmienne wejściowe
Data Zmienne wyjściowe
1 2 3 4 5 6
1996/02/04 8.0183 18.1964 3.0665 0.87185 27.3654 -34.26 2.3484
1996/02/11 2.3484 20.1903 8.6604 1.165 31.6638 -36.11 -1.6088
1996/02/18 -1.6088 25.9411 7.8062 0.73344 37.2442 -39.4 -3.1183
1996/02/25 -3.1183 8.7764 23.4878 -5.7039 52.0041 -55.4491 8.5585
1996/03/03 8.5585 -2.4384 35.6855 -9.6016 49.3736 -44.6886 8.9117
1996/03/10 8.9117 3.4813 39.8967 -8.1658 28.3374 -35.9781 -4.8830
1996/03/17 -4.883 14.5461 42.5551 -11.2681 21.0397 -31.1741 -1.2875
1996/03/24 -1.2875 12.4597 36.9239 -6.4501 1.8897 -29.4737 0.0332
1996/03/31 0.03323 2.2598 35.2211 9.0033 -6.4104 -30.6204 2.2423
1996/04/07 2.2423 -6.0764 38.6396 17.0951 -5.3345 -25.6506 0.1706

Wejścia oraz wyjścia prezentowane są sieci w formie procentowych zmian wartości


indeksu w poszczególnych okresach. Data wskazuje niedzielę poprzedzającą tydzień, w
którym nastąpiła zmiana zawarta w danej wyjściowej. Zanim zbiór wzorcowy zostanie

14
zastosowany w procesie nauki, kolejność rekordów jest automatycznie mieszana w celu
usprawnienia nauki.
W pierwszym wariancie sieci rozwiązującej zadany problem zastosowano dwadzieścia
neuronów w warstwie ukrytej z tangensem hiperbolicznym jako funkcją aktywacji. W
warstwie wyjściowej pojawił się pojedynczy neuron z liniową funkcją aktywacji. Jedynie
neurony w warstwie ukrytej zostały zaopatrzone w bias. Była to jedynie struktura testowa, w
związku z powyższym zrezygnowano z wszelkich metod walidacji modelu, niezbędnych do
przerwania nauki w najodpowiedniejszym momencie. Sieć miała za zadanie wykazać czy
przy zadanych parametrach możliwe jest sprowadzenie błędu średniokwadratowego do
odpowiednio niskiego poziomu. Błąd osiągnięty po 10 000 epok wyniósł 3,9226, a procent
zgodnych znaków w zbiorze wzorcowym i na wyjściu sieci osiągnął poziom 86,78. Po
kolejnych 10 000 epok wielkości te nie uległy znaczącej poprawie. Proces wielokrotnie
powtarzano, za każdym razem losowo inicjując wagi połączeń, niestety bez rezultatu.
Tabela 3 prezentuje wyniki, które osiągnęła sieć w przewidywaniu wartości zmian indeksu na
podstawie danych testowych, spoza zbioru wzorcowego.

Tabela 3. Prognoza sieci testowej (20 neuronów w warstwie ukrytej).


Rzeczywista Prognozowana
Data Błąd prognozy
zmiana zmiana
30-Sep-2001 -2.11 3.10 5.21
07-Oct-2001 14.33 14.86 0.54
14-Oct-2001 1.13 -4.06 5.19
21-Oct-2001 8.91 5.52 3.39
28-Oct-2001 -2.92 8.98 11.90
04-Nov-2001 2.47 4.74 2.27
11-Nov-2001 5.67 11.56 5.89
18-Nov-2001 -3.94 5.18 9.13

Średni błąd prognozy 5.44

Wyniki osiągnięte przez sieć na podstawie zbioru testowego są wyjątkowo marne.


Przy średnim błędzie prognozy na poziomie 5,44 właściwie nie można liczyć na zgodność
znaków pomiędzy prognozą a rzeczywistą zmianą wartości indeksu. Sieć nie radzi sobie z
minimalizacją błędu średniokwadratowego w procesie nauki, co sugeruje, że jest zbyt mała,
aby wykryć interesujące zależności w zbiorze wzorcowym.
W kolejnej wersji zastosowano wspomniany algorytm SCG i powiększono liczbę
neuronów w warstwie ukrytej do 40 przy niezmienionych wartościach pozostałych
parametrów. Po przeprowadzeniu obserwacji na danej sieci zauważono, iż po osiągnięciu
błędu średniokwadratowego równego 0,1 dalsza nauka nie dawała znaczącej poprawy

15
wyniku. Aby zminimalizować niebezpieczeństwo przeuczenia sieci, docelowy poziom błędu
ustalono właśnie na tym poziomie. Po osiągnięciu tej wartości Matlab automatycznie
przerywa proces nauki. Taka wartość błędu na etapie nauki z pewnością ulegnie zwiększeniu
w prognozach, jednak wydaje się bezpieczna z punktu widzenia predykcji tygodniowych
zmian indeksu WIG20. Stosując tę metodę weryfikacji modelu skrócono przeciętną długość
nauki do około 10 000 epok. Dla każdej z sieci początkowe wagi były losowane, tylko
niewielka liczba stworzonych w ten sposób modeli została odrzucona z powodu niespełnienia
warunku maksymalnego błędu średniokwadratowego. Na podstawie sieci, które przeszły
pozytywnie ten etap weryfikacji, przeprowadzono predykcję zmian indeksu. Uśrednione
wyniki prognoz dla zakwalifikowanych modeli znajdują się w tabeli 4 oraz na rysunku 1.

Tabela 4. Uśrednione wyniki prognoz sieci (40 neuronów w warstwie ukrytej).


Procent zgodnych znaków pomiędzy zbiorem wzorcowym, a
97.46%
wynikami nauki.
Rzeczywista Prognozowana Błąd
Data Trend
zmiana zmiana prognozy
30-Sep-2001 -2.11 0.04 2.15 0
07-Oct-2001 14.33 18.59 4.27 1
14-Oct-2001 1.13 0.09 1.04 1
21-Oct-2001 8.91 14.46 5.55 1
28-Oct-2001 -2.92 -12.46 9.54 1
04-Nov-2001 2.47 8.20 5.73 1
11-Nov-2001 5.67 7.39 1.72 1
18-Nov-2001 -3.94 -4.88 0.94 1

Średni błąd prognozy 3.87

Procent zgodnych znaków pomiędzy wynikami prognozy, a


87.50%
rzeczywistymi zmianami indeksu giełdowego WIG20

16
Rysunek 1. Wykres uśrednionych wyników prognoz sieci (40 neuronów w warstwie ukrytej).

Ciekawym zjawiskiem w wynikach uzyskanych przy pomocy tych sieci neuronowych


jest duża zgodność pomiędzy znakiem wartości prognozowanych z rzeczywistymi zmianami.
Pomimo wysokiego błędu średniego, wynoszącego w tym wypadku prawie 4 %,
prognozowany kierunek zmian indeksu został przewidziany we wszystkich wartościach
oprócz jednego tygodnia. Może to wynikać ze szczęścia lub specyfiki okresu, w jakim
przeprowadzono prognozę, jednak głębsza analiza tych wyników nie jest możliwa. Sieci
neuronowe, stanowiące swoiste „czarne skrzynki”, skutecznie utrudniają analizę uzyskanych
na ich podstawie informacji. Wiedza zgromadzona w tych strukturach jest rozproszona, a jej
prezentacja właściwie niemożliwa.
Chcąc poprawić otrzymane wyniki zdecydowano się na przetestowanie jeszcze jednej
struktury. Tym razem stworzoną sieć zaopatrzono w 80 neuronów w warstwie ukrytej przy
niezmienionych wartościach pozostałych parametrów. W porównaniu do poprzednich modeli
proces nauki był znacznie krótszy. Po upływie około 10 000 epok sieć osiągnęła błąd równy
0,09. Struktury zaopatrzone w 40 neuronów nie były w stanie przekroczyć tej granicy nawet
po 20 000 epok. Jednak średni błąd prognozy okazał się wyjątkowo duży i wyniósł aż
11,04 %, a poszczególne wyniki wielokrotnie przekroczyły rzeczywiste wartości. Uzyskane
wyniki znajdują się w tabeli 5.

17
Tabela 5. Wyniki prognozy sieci z 80 neuronami w warstwie ukrytej.
Rzeczywista Prognozowana Błąd
Data Trend
zmiana zmiana prognozy
30-Sep-2001 -2.11 8.69 -10.80 0.00
07-Oct-2001 14.33 9.05 5.28 1.00
14-Oct-2001 1.13 10.87 -9.74 1.00
21-Oct-2001 8.91 32.81 -23.89 1.00
28-Oct-2001 -2.92 8.95 -11.87 0.00
04-Nov-2001 2.47 10.58 -8.10 1.00
11-Nov-2001 5.67 -4.09 9.75 0.00
18-Nov-2001 -3.94 -12.80 8.86 1.00

Średni błąd prognozy 11.04

Procent zgodnych znaków pomiędzy wynikami prognozy, a


62.50%
rzeczywistymi zmianami indeksu giełdowego WIG20

Powyższe przypadki przekonują do zastosowania sieci z umiarkowaną liczbą


neuronów w warstwie ukrytej. Poszukiwania w obu kierunkach okazały się chybione, zbyt
małe i zbyt duże sieci nie radzą sobie z tym problemem. Nie oznacza to oczywiście, że
zaproponowana liczba 40 neuronów jest optymalną. Do prawdziwych poszukiwań należałoby
raczej zastosować algorytmy genetyczne, które są coraz powszechniej używane do
optymalizacji sieci neuronowych. Z pomocą genetyki można osiągnąć wyjątkowo korzystne
rezultaty, lecz trzeba uzbroić się w cierpliwość. W Matlabie istnieją dodatkowe biblioteki
funkcji służące optymalizacji sieci przy pomocy algorytmu genetycznego. Stworzony przez
grupę studentów zbiór uniwersalnych funkcji umożliwia właściwe dostrojenie prostych
modeli. Zastosowanie tego pakietu w analizowanych strukturach jest jednak mocno
uzależnione od mocy obliczeniowej. Chcąc osiągnąć wystarczającą liczbę przypadków należy
przeprowadzić przynajmniej tyle samo procesów nauki, a bardzo często więcej. Nawet przy
krótkim czasie trwania treningu, który w przypadku wykorzystanych modeli wyniósł w
przybliżeniu 12 minut, ogólny czas nauki jednego pokolenia może trwać ponad dobę.
W przypadku modeli z dużą liczbą neuronów i połączeń rozwiązaniem jest również
zastosowanie innych metod walidacji. Rozbudowane sieci mają liczne zalety, takie jak duża
pojemność informacyjna i uniwersalność. Jeżeli model jest zbyt skąpy, wówczas nigdy nie
będzie możliwe przeprowadzenie przy jego pomocy rozsądnej predykcji. Natomiast zbyt
rozbudowana sieć jest groźna tylko ze względu na skłonność do przeuczenia w krótkim
okresie czasu. Tego rodzaju struktury osiągają bez najmniejszych problemów niemal zerowy
błąd średniokwadratowy na etapie nauki. Prawdziwy problem pojawia się dopiero na etapie
wnioskowania na podstawie tak stworzonego modelu, kiedy to okazuje się, iż uzyskane
wyniki w żaden sposób nie pasują do rzeczywistych wartości. W takich przypadkach bardzo

18
pomocna okazuje się metoda wprowadzenia na etapie nauki dodatkowego zbioru testowego,
dzięki któremu możliwe będzie sprawdzanie wyników na bieżąco. Sposób bardzo prosty i
niezwykle skuteczny, umożliwia nie tylko przerwanie treningu na odpowiednim etapie, lecz
przede wszystkim wybór najlepszej konfiguracji wag dla zadanego problemu. Matlab w
każdej epoce nauki sprawdza, jaka jest wartość błędu średniokwadratowego dla zbioru
testowego i przechowuje macierze wag tej struktury, dla której wartość ta okazała się
najmniejsza. Zatem wynikiem takiego procesu nauki są dwa modele, pierwszym jest
wytrenowana sieć, drugim zaś model, który uzyskał wyniki najbliższe znajdującym się w
zbiorze walidacyjnym.
Tego rodzaju metoda została zaimplementowana w „Fuzzy Logic Toolbox” pakiecie
służącym tworzeniu sieci rozmyto neuronowych. Minimalizacja błędu w takich strukturach
jest znacznie bardziej czasochłonna. Przerwanie nauki w najodpowiedniejszym momencie jest
kluczowym problemem, którego rozwiązanie pozwala zaoszczędzić wiele czasu.
Szczegółowe opracowanie tego tematu znajduje się w rozdziale 2.3.

2.2.2. Model II

Drugi model oparty na sieciach neuronowych służy klasyfikacji sygnałów


wejściowych. Do jego stworzenia wykorzystałem struktury o parametrach bardzo zbliżonych
do wykorzystanych poprzednio. Sieci te składają się również z dwóch warstw. W warstwie
ukrytej znajduje się 40 neuronów z funkcją aktywacji tangens hiperboliczny. Liczba
neuronów jest identyczna jak w przypadku modelu, który najlepiej realizował predykcje
konkretnych wartości indeksu giełdowego WIG20. Jeżeli sieci te radziły sobie z poprzednim
problemem to wydaje się, że poradzą sobie i w tym przypadku. Z racji, iż mają one za zadanie
klasyfikować sygnały, muszą się zasadniczo różnić od swoich pierwowzorów. Pierwszą
różnicą jest liczba neuronów w warstwie wyjściowej, zależna od liczby przedziałów
związanych z klasyfikacją. Neurony te posiadają funkcję aktywacji o następującym wzorze:
1
f( x) =
1 + exp(( −10 ) ⋅ x)

19
Jest to właściwie funkcja logarytmiczno sigmoidalna, w której argument został
dodatkowo pomnożony przez 10. Dzięki temu jest ona znacznie bardziej zbliżona do funkcji
skoku jednostkowego, a mimo to ciągła w całej dziedzinie. Pozwoliło to w znacznym stopniu
ograniczyć czas nauki prezentowanej sieci. Znajdujący się poniżej rysunek 2 Rysunek
2zawiera graficzną prezentacje wymienionych trzech funkcji.

Rysunek 2. Wybrane funkcje aktywacji neuronów.

Modyfikacjom uległ również zbiór wzorcowy, w którym dane wyjściowe składają się
z wektorów zawierających przynajmniej dwie pozycje. W tym modelu predykcja jest
dokonywana na podstawie szeregu sieci, z których każda dokonuje osobnej klasyfikacji
sygnału wejściowego. Jest to proces trudniejszy od treningu pojedynczej sieci neuronowej,
dlatego zdecydowałem się na wykorzystanie prostej formatki do obsługi całej procedury
(rysunek 3).

20
Rysunek 3. Okno treningowe sieci klasyfikujących.

W oknie tym znajdują się tylko podstawowe parametry, które w miarę rozwoju
modelu ulegały zmianom. Podobnie jak w poprzednim przypadku pozostałe wartości zostały
zapisane w osobnym pliku importowanym na dalszych etapach realizacji zadania.
W polu „Maksymalny błąd średniokwadratowy” określono cel każdego cyklu nauki
dla danej sieci. Po osiągnięciu tego poziomu każda sieć jest dodatkowo douczana przez ilość
epok znajdujących się w polu „Powtórne uczenie (ilość epok)”. Konieczność dodatkowej
nauki wynika z różnic pomiędzy poszczególnymi sieciami. Każda z nich ma różną liczbę
neuronów wyjściowych, a w związku z tym występują duże różnice pomiędzy wartościami
błędu średniokwadratowego na tych samych etapach nauki. Różny jest również okres nauki
poszczególnych struktur. Jak wynika z przeprowadzonych obserwacji, każda z nich była w
stanie osiągnąć błąd na poziomie 0,085. Dodatkowo sieci o najmniejszej liczbie neuronów
wyjściowych minimalizowały błąd do znacznie niższego poziomu i to w bardzo krótkim
czasie. To właśnie z ich powodu postanowiono powtarzać trening. Dodatkowa liczba epok
jest jednym z podstawowych parametrów i często ulegała zmianie. Zbyt duża powodowała

21
znaczne pogorszenie wyników, natomiast zbyt mała skutecznie utrudniała osiągnięcie
optymalnego poziomu błędu w przypadku sieci z najmniejszą liczbą neuronów wyjściowych.
Określenie jej na poziomie 1000 epok pozwoliło uniknąć wymienionych problemów.
„Testowanie sieci” oraz „Prognozowanie” to dwa pola, w których użytkownik
decyduje czy dany model ma dokonać klasyfikacji sygnału na najbliższy tydzień, czy też
testować struktury. Po zaznaczeniu „Testowania sieci” program przeprowadzi naukę sieci na
podstawie zbioru wzorcowego znajdującego się w liście „Zbiory do nauki”. Są to ograniczone
dane z przeszłości umożliwiające testowanie modelu na najświeższych zbiorach znajdujących
się w drugiej liście nazwanej „Zbiory do testów”. Zaznaczenie opcji „Prognozowanie”
powoduje automatyczne odznaczenie „Testowania sieci”. W takiej sytuacji program
przeprowadzi naukę stworzonych struktur na kompletnych zbiorach z listy „Zbiory do
testów”. Użytkownik w wyniku otrzyma prognozę na najbliższy tydzień w postaci
klasyfikacji ostatniego dostępnego sygnału. Do testów i prognoz wykorzystano jedynie dwa
zbiory, dlatego też w listach znajdują się tylko niezbędne pojedyncze pozycje.
Niewątpliwie najważniejszym polem jest „Maksymalna liczba neuronów
wyjściowych”. Od tej wielkości zależy ogólna liczba sieci wykorzystanych do prognoz bądź
testów. Domyślna wartość sześciu neuronów oznacza, że program stworzy pięć sieci.
Pierwsza, posiadająca dwa neurony w warstwie wyjściowej, będzie dokonywała klasyfikacji
sygnałów do dwóch zbiorów, druga do trzech itd.. Zbiór wzorcowy jest przygotowywany na
podstawie danych wykorzystanych w modelu z poprzedniego rozdziału. W pierwszej
kolejności dokonuje się podziału wartości wyjściowych na równe co do liczności segmenty.
W efekcie otrzymuję zbiory całkowicie pokrywające zakres danej wyjściowej. Poszczególne,
różniące się rozmiarami przedziały, wykorzystywane są następnie do stworzenia wektora, w
którym jedynka wskazuje przynależność zmiennej wyjściowej do konkretnego segmentu
zmian wartości indeksu WIG20. Istniał również wariant tworzenia przedziałów poprzez
podział całego zakresu na równe segmenty, jednak znaczne zagęszczenie tygodniowych
zmian indeksu w okolicach zera sprawiło, że większość danych mieściła się w jednym (przy
nieparzystej liczbie przedziałów) bądź w dwóch (przy parzystej liczbie przedziałów)
centralnych segmentach. W efekcie sieci uczyły się dominujących wzorców i nie były w
stanie efektywnie klasyfikować pozostałych rekordów.
Należy zaznaczyć, iż powyższa metoda różni się znacząco od standardowej
segmentacji przeprowadzanej z użyciem sieci neuronowych. W tym przypadku
skoncentrowano się jedynie na zmiennych wyjściowych i świadomie zrezygnowano z
analizowania naturalnych segmentów dla wszystkich zmiennych. Celem tych sieci nie jest

22
znalezienie segmentów w całym obszarze zbioru wzorcowego tylko określenie wzorców
sygnałów odpowiadających odpowiednim zmianom pojawiającym się na wyjściu.
Zakres tygodniowych zmian indeksu w badanych przypadkach wyniósł od -15,05 do
15,58. Na rysunku 4 znajdują się przykładowe wyniki poszczególnych sieci dla pojedynczego
okresu testowego, a na rysunku 5 ich wspólna prezentacja wraz z rzeczywistą zmianą indeksu
w postaci zielonej kreski. Dodatkową informacją, którą można odczytać z rysunku 5 jest
maksymalna wartość, jaką może osiągnąć rozmyta odpowiedź. Wartość ta określona jest
przez wysokość zielonej kreski. W omawianym przypadku wynosi ona 5 i odpowiada liczbie
wykorzystanych sieci.

Rysunek 4. Wyjściowe wyniki poszczególnych struktur (od 2 do 6 neuronów w warstwie wyjściowej).


Prognoza na okres od 30.09.2001 do 7.09.2001.

23
Rysunek 5. Zbiorcza prognoza na okres od 30.09.2001 do 7.10.2001 wraz z rzeczywistą zmianą indeksu.

W przypadku tak zaprezentowanego modelu nie ma możliwości dokładnej oceny


otrzymanych wyników. Mają one rozmyty charakter i mogą służyć jako dane pomocnicze lub
dodatkowe kryterium oceny wyników otrzymanych przy pomocy sieci z poprzedniego
rozdziału bądź systemu rozmytego. W celu wykonania dodatkowych testów, niezbędne jest
wyostrzenie wyników, tak jak w przypadku systemów rozmyto neuronowych.
Ostatnie pole znajdujące się w omawianej formatce nazywa się „Wartości dokładne”.
Odznaczenie tego pola powoduje zaokrąglanie wartości wejść zbiorów do nauki oraz testów
dla każdej stworzonej sieci do jednego miejsca po przecinku. To posunięcie pozwoliło
ograniczyć liczbę radykalnych błędów często popełnianych przez sieci wykorzystujące
wartości dokładne. Sieci nauczane przy pomocy wartości przybliżonych uczyły się nieco
dłużej i nie osiągały tak niskich poziomów błędu, a trafność ich prognoz była porównywalna.
Jest to oczywiście subiektywna ocena, gdyż interpretacja graficznych zbiorczych wyników
jest utrudniona ze względu na ich rozmyty charakter.
Poniżej znajdują się wyniki dwóch modeli. W obu przypadkach zastosowano trzy sieci
zaopatrzone w dwa, trzy oraz pięć neuronów wyjściowych. Dokładne wartości wejściowe
użyto do nauki pierwszego modelu. W drugim zostały wykorzystane wartości zaokrąglone.

24
Wyniki modelu pierwszego dla dziesięciu okresów testowych (od 30.09.2001 do
9.11.2001). Do nauki i testów zostały wykorzystane dokładne wartości zmian indeksu WIG20
w poszczególnych okresach (rysunki poniżej).

25
26
27
Wyniki modelu drugiego dla dziesięciu okresów testowych (od 30.09.2001 do
9.11.2001). Do nauki i testów zostały wykorzystane przybliżone wartości zmian indeksu
WIG20 w poszczególnych okresach (rysunki poniżej)

28
29
Uzyskane wyniki nie nadają się do ścisłej analizy. Znane metody wyostrzania tego
rodzaju danych również nie dają zadowalających rezultatów, które są dalekie od
rzeczywistych zmian indeksu giełdowego WIG20. Ich interpretacja jest oczywiście możliwa
na przykład w oparciu o wyniki uzyskane przy pomocy innych metod. Sieci te nie są w stanie
udzielić konkretnej odpowiedzi na pytanie o względną zmianę indeksu giełdowego,
umożliwiają jednak weryfikację już posiadanych wyników. Z ich pomocą możemy odrzucić
bądź przyjąć prognozy sieci neuronowych omawianych w poprzednim rozdziale lub też
określić przybliżony kierunek zmian wartości indeksu. Niestety w przypadku tego modelu nie
udało się tego osiągnąć. Sieci czasami niezwykle trafnie przewidywały kierunki i wartości
zmian, w innych przypadkach nie udawało im się to w ogóle. Pozostałe wyniki, znajdujące się
w załączniku 3, ujawniają wady tej metody. Przedstawione sieci popełniały bardzo podobne
błędy i w pewnych okresach zupełnie nie radziły sobie z problemem. Nie umiem niestety
odpowiedzieć na pytanie dlaczego tak się dzieje. Mogę jedynie snuć domysły, iż podobnie jak
w przypadku niektórych sieci z poprzedniego rozdziału, nie były one dostatecznie
przystosowane do problemu, który miały rozwiązywać.

2.3. Rozmyto neuronowy system wspomagania decyzji


inwestycyjnych
Inspiracją do stworzenia dziedziny matematyki zwanej logiką rozmytą była potrzeba
opisania zjawisk mających charakter wieloznaczny i nieprecyzyjnych. Matematyczna
prezentacja pojęć takich jak "liczba bliska 7" bądź "duże miasto" jest nadal niedostępna dla
większości ludzi, gdyż sama logika wielowartościowa jak i teoria zbiorów rozmytych nie są
zbyt popularnymi dziedzinami wiedzy. Choć na co dzień używamy tego rodzaju sformułowań
nie zdajemy sobie sprawy, iż nasz naturalny język posiada matematyczną interpretację oraz w
znacznym stopniu ułatwia pracę inżynierów w wielu dziedzinach nauki. Po raz pierwszy
pojęcie zbiorów rozmytych pojawiło się w roku 1965 za sprawą amerykańskiego naukowca
Lotfi A. Zadeha 4. Zaproponował on nie tylko nową metodę matematycznej prezentacji
nieprecyzyjnych pojęć, lecz przede wszystkim sposób wnioskowania na ich podstawie. Dzięki
niemu powstała logika wielowartościowa znana pod nazwą logiki rozmytej. Do dnia
dzisiejszego powstała duża liczba modeli wykorzystujących rozmyte wnioskowanie w
różnych dziedzinach wiedzy. Różnią się między sobą głównie złożonością i zastosowaniem.
Niewątpliwie najbardziej zaawansowanymi są wśród nich sieci rozmyto neuronowe

30
wykorzystujące algorytm wstecznej propagacji dla minimalizacji wyjściowego błędu
obliczeń.
We wszystkich sterownikach, systemach i sieciach rozmytych wyróżnić można trzy
podstawowe bloki, w których wykonywane są kolejne operacje na danych. Są to bloki
rozmywania, rozmytego wnioskowania oraz wyostrzania (rysunek 6). Istnieje wiele metod
realizacji każdego z wymienionych modułów w zależności od zastosowania, jednak ich
obecność jest niezbędna w każdym przypadku. W pracy skupiono się jedynie na systemach
rozmyto neuronowych i na ich przykładzie zaprezentowano temat zastosowania logiki
rozmytej we współczesnych systemach wspomagania decyzji.

Rysunek 6. Kolejne bloki systemu rozmytego.

Pierwsze prace dotyczące rozmytego wnioskowania bazowały na zbiorach reguł


tworzonych przez specjalistów na podstawie wykonanych obserwacji. Pod tym względem
były bardzo zbliżone do prostych drzew decyzyjnych i podobnie jak one w krótkim czasie
ewoluowały w kierunku bardziej złożonych systemów, tworzonych na podstawie surowych
danych. Systemy rozmyte umożliwiają zatem prezentacje danych w postaci prostych zdań
logicznych w języku naturalnym, jednak oprócz klasyfikacji możemy dzięki nim uzyskać
również jednoznaczny wynik. Wyposażone dodatkowo w algorytm wstecznej propagacji
błędu łączą w sobie zalety sieci neuronowych oraz wspomnianych drzew decyzyjnych.
Działania wykonywane przez system rozmyty w warstwie implikacji wymagają
odpowiedniego przygotowania danych. W tym celu są one rozmywane w pierwszym bloku.
Rozmywanie polega na przyporządkowaniu odpowiednim wartościom wejściowym
właściwych zmiennych lingwistycznych. Posiadając dane wejściowe i znając ich zakres
należy określić, które z nich będą należały do zbiorów "niskich", "średnich" bądź "wysokich"
wartości danej zmiennej. Liczba tych podzbiorów jest różna i w prostych sterownikach

31
rozmytych zależy jedynie od człowieka. W publikacjach znaleźć można sugestię, iż powinna
to być liczba nieparzysta, jednak od reguły tej istnieją odstępstwa 4. W bardziej złożonych
systemach, do których należy zaprezentowany w pracy, w celu określenia optymalnej liczby
przedziałów dokonywana jest wstępna segmentacja danych. W dalszej części rozdziału
znajduje się wyjaśnienie sposobu, w jaki ogranicza ona czas obliczeń.
Aby dokładnie wyjaśnić mechanizm działania bloku rozmywania posłużę się
przykładem. Posiadając dane na temat prędkości dowolnego samochodu i znając jego
ograniczenia możemy określić poszczególne przedziały. Obserwator może zatem przyjąć, iż
prędkość poniżej 40 km/h jest "mała". W przedziale pomiędzy 40 km/h, a 80 km/h nazwie
prędkość "średnią", a powyżej górnej granicy tego przedziału "wysoką". Na rysunku 7
znajduje się graficzna prezentacja tych stwierdzeń. Wynika z niej, iż prędkość 20 km/h jest
prędkością "małą" w 100 %, a prędkością średnią i wysoką w stopniu 0 %.

Rysunek 7. Przykładowe funkcje przynależności.

32
Każdy z przedziałów prędkości został zaopatrzony w odrębną funkcję. Są to tak zwane
funkcje przynależności i są odpowiedzialne za przydzielanie konkretnych wartości
wejściowych do odpowiedniego przedziału. Jest to oczywiście jedynie przykładowe
rozwiązanie tego problemu. W rzeczywistości dla lepszego podziału zbioru wejściowego
stosuje się różne funkcje. Poniżej na rysunku 8 znajduje się inna wersja powyższego
rozwiązania. Jako funkcje przynależności zostały wykorzystane krzywe Gauss'a. W
pierwszym przypadku złożenie dwóch funkcji określa granice zbioru rozmytego, w drugim
pojedyncza krzywa.

Rysunek 8. Przykład wykorzystania krzywych Gauss’a jako funkcji przynależności.

Na podstawie funkcji przynależności wyznaczonych dla każdej zmiennej, można


przeprowadzić rozmywanie liczb wejściowych. Dokonuje się to poprzez określenie wartości
poszczególnych funkcji przynależności dla tej liczby. W systemach rozmyto neuronowych
operacja ta realizowana jest w pierwszej warstwie, w której neurony zaopatrzone są w funkcje
aktywacji identyczne bądź zbliżone do funkcji przynależności z rysunku 7 oraz 8. Jest to
prostsza forma rozmywania typu singleton, jedyna jak dotąd stosowana w sieciach. W
klasycznych rozwiązaniach efektem rozmywania jest zazwyczaj zbiór rozmyty dla każdego
przedziału, jednak przesyłanie informacji na temat liczb bądź zbiorów rozmytych jest zbyt
czasochłonne w strukturach neuronowych. Poza tym pojedyncze wartości określające poziom
przynależności do poszczególnych przedziałów są wystarczające do rozmytego

33
wnioskowania. Na rysunku 9 znajduje się graficzne rozwiązanie rozmywania prędkości 50
km/h. Rozmytą odpowiedź można zapisać za pomocą wzoru min{μ(xi), μ(x)} 4, gdzie xi=50
km/h, a μ(x) jest daną funkcją przynależności. Rozmywanie typu singleton stosowane w
strukturach rozmyto neuronowych zwraca jedynie wartość μ(xi) dla każdego przedziału
(rysunek 10).

Rysunek 9. Rozmywanie wartości wejściowej 50 km/h.

34
Rysunek 10. Rozmywanie typu singleton.
Posiadając tak przygotowaną warstwę rozmywania możemy każdą z pojawiających się
na wejściu wartości przedstawić w formie zmiennej lingwistycznej. Przykładowa prędkość 50
km/h jest przede wszystkim prędkością "średnią" i w niewielkim stopniu "wysoką" i "małą".
Ta informacja przepływa następnie do bloku rozmytej implikacji. W warstwie tej znajduje się
baza wszystkich reguł. W prostych systemach pozbawionych wstępnej segmentacji danych
liczba reguł zależy od liczby zmiennych niezależnych i lingwistycznych. Każda z reguł
połączona jest dokładnie z jedną zmienną lingwistyczną danej zmiennej wejściowej. Zatem w
systemie posiadającym trzy zmienne wejściowe podzielone na pięć podzbiorów rozmytych
musi znaleźć się 53=125 reguł i tyle samo neuronów. Tylko w takiej sytuacji reguły pokryją
całą przestrzeń możliwych rozwiązań. Chcąc stworzyć podobną bazę dla danych
wykorzystanych do nauki sieci neuronowych należałoby stworzyć 15 625 reguł w warstwie
implikacji. Jest to liczba gigantyczna, uniemożliwiająca jakiekolwiek obliczenia. Dlatego
pierwsze sterowniki rozmyto neuronowe miały raczej ograniczone zastosowanie. Tworzenie
bazy reguł tą metodą sprawia, iż ich liczba często wielokrotnie przekracza rzeczywistą liczbę
reguł związanych z danym problemem. Większość elementów znajdujących się w bloku
implikacji nigdy nie jest wykorzystywana w procesie wnioskowania, gdyż nie posiadają
swojego odzwierciedlenia w zmiennych. Jednak ich obecność zmusza do propagowania
sygnału dla każdego z tych elementów podczas nauki. Jest to kolosalna strata czasu, której
można uniknąć.
W warstwie rozmytej implikacji wykonywane są dwie czynności. Pierwszą z nich jest
określenie stopnia pobudzenia każdej z reguł. Zazwyczaj czynność ta wykonywana jest przy

35
pomocy funkcji minimum wykorzystywanej w logice rozmytej jako logiczny operator "i".
Oblicza ona minimum zbioru wartości pochodzących z bloku rozmywania. Operacją dającą
podobne rezultaty i często stosowaną do rozwiązywania logicznego "i" jest mnożenie
rozmytych elementów przez siebie. Wynikowa wartość, mieszcząca się w przedziale od 0 do
1 określa poziom pobudzenia danej reguły. Jest to wielkość służąca w dalszej kolejności jako
waga wyjściowej wartości reguły. Podobnie jak w bloku rozmywania w bazie reguł znajdują
się informacje na temat zmiennych lingwistycznych, które w tym przypadku opisują zmienną
zależną. Wnioskowanie można zatem zapisać w postaci zdania: Jeżeli zmienna_wejściowa_1
"mała" i zmienna_wejściowa_2 "wysoka", wówczas zmienna_wyjściowa "mała"
(rysunek 11). I w tym wypadku opis zmiennej został ograniczony do jednej wartości, środka
zbioru rozmytego zmiennej niezależnej związanego z daną reguła. W systemach rozmyto
neuronowych typu Takagi-Sugeno informacja o środku i zakresie segmentu zmiennej
wyjściowej związanego z daną regułą nie jest zapisana wprost. Wyjściową wartość reguły
oblicza się na podstawie liniowej funkcji zmiennych wejściowych. Bias w takim węźle sieci
spełnia rolę wyrazu wolnego tej funkcji. Innym rozwiązaniem jest zastosowanie pojedynczej
stałej wartości tak jak na rysunku 11. Zastosowanie liniowej funkcji zmiennych wejściowych
jako reguły wnioskowania wymaga znacznie większej liczby obliczeń podczas nauki, jednak
pozwala osiągać znacznie lepsze rezultaty w rozwiązywaniu wyjątkowo trudnych problemów.
Zaprezentowany w pracy system jest siecią typu Takagi-Sugeno, w którym każda reguła
zapisana została w formie liniowej funkcji zmiennych wejściowych.
Oprócz samego zdania logicznego otrzymujemy również stopień pobudzenia danej
reguły. W wyniku wnioskowania otrzymujemy dwie wartości: wagę, czyli pobudzenie reguły,
oraz ważoną wartość wyjściową.
W przeciwieństwie do wnioskowania na podstawie drzew decyzyjnych, w logice
rozmytej w jednym procesie implikacji może brać udział wiele reguł. Dlatego obie wartości,
waga i wartość wyjściowa, są bardzo istotne. Na rysunku 11 świadomie przedstawiono regułę,
która nie ma dominującego znaczenia podczas wnioskowania, jednak w dużym stopniu
wpływa na wynik.

36
Rysunek 11. Metoda rozmytego wnioskowania.

37
Posiadając informacje na temat wszystkich reguł spełniających w różnym stopniu
warunek wejściowy nie jesteśmy w stanie udzielić jasnej odpowiedzi. Dane te muszą zostać
ponownie przekształcone. Operacja ta jest wykonywana w ostatnim bloku systemu
rozmytego, jakim jest blok wyostrzania. Jest to działanie przeciwne w stosunku do
wykonywanego w bloku rozmywania i polega na łączeniu odpowiedzi wielu reguł w jedną.
Również i w tym przypadku istnieje szereg algorytmów rozwiązujących ten problem.
Najprostszy z nich polega na obliczeniu średniej ważonej na podstawie dwóch wartości
wyjściowych bloku implikacji. W większości przypadków jest to metoda niezwykle
skuteczna, jednak istnieją obszary, w których użycie jej jest ograniczone. W systemach
rozmytych, w których zmienną zależną jest wartość kąta, metoda ta może doprowadzić do
uzyskania zupełnie sprzecznych wyników. Jeżeli zbiór wartości wyjściowych obejmujący
zakres od -180 do 180 stopni zostanie podzielony na 5 podzbiorów rozmytych, wówczas z
pewnością pojawi się przypadek aktywowania reguł wskazujących na dwa skrajne zbiory,
wartości bliskich -180 oraz 180 stopni, które w rzeczywistości są do siebie bardzo zbliżone.
Efektem wyostrzania takich wyników będzie prawdopodobnie kąt bliski 0 stopni, co jest
zupełnie błędną odpowiedzią. Przypadek kąta jako zmiennej zależnej występuje w jednym z
klasycznych problemów nieliniowego sterowania jakim jest zagadnienie parkowania
ciężarówki. Problem ten został rozwiązany przy pomocy sieci rozmyto neuronowej. Podobnie
jak w rozwiązaniu zagadnienia parkowania ciężarówki w zaawansowanych systemach
rozmyto neuronowych w bloku wyostrzania stosuje się prostą sieć neuronową. Dzięki temu
możliwe jest wnioskowanie na podstawie wielu pozornie sprzecznych ze sobą reguł.
Sterowniki i systemy rozmyte w zaprezentowanej postaci znalazłyby swoje miejsce
jedynie wśród książek akademickich bądź bardzo prostych urządzeń sterujących klimatyzacją,
gdyby nie algorytmy segmentacji danych. Jak już wspomniano w systemach rozmyto
neuronowych z ustalanymi przez użytkownika funkcjami przynależności liczba reguł była
często zbyt duża, aby możliwe było przeprowadzenie obliczeń. Zjawisko to nazywane jest
"klątwą wymiarowości" i występuje w systemach wykorzystujących względnie dużą liczbę
zmiennych wejściowych, czyli około sześciu. Taka liczba zmiennych zmusza do stworzenia
minimum 729 reguł. Ogromna większość z nich znajduje się zazwyczaj poza przestrzenią
ograniczoną danymi. W wyniku nauki takiej struktury otrzymujemy kilka bądź kilkanaście
"istotnych" reguł, czyli takich, które brały udział we wnioskowaniu podczas treningu.
Nieaktywne reguły są eliminowane i dzięki temu po kilkudziesięciu godzinach pracy
komputera otrzymujemy wynikową strukturę. Czas ten może zostać ograniczony do kilku
minut po zastosowaniu segmentacji danych. Matlab udostępnia kilka algorytmów segmentacji

38
danych, w ramach pakietu „Fuzzy Logic Toolbox” została zastosowana metoda subtraktywna
(Subtractive Clustering). W przeciwieństwie do najpopularniejszej metody k-Średnich liczba
segmentów nie jest narzucana, lecz określana na podstawie rozmieszczenia danych w
wielowymiarowej przestrzeni. Jedynym parametrem określanym przez człowieka jest zakres
wpływu środka segmentu. Jest to wartość z przedziału od 0 do 1 określająca maksymalny
rozmiar segmentu w jednym wymiarze przy założeniu, iż pełny zakres danych wynosi 1.
Końcowym efektem procesu jest zbiór segmentów, czyli środków i zakresów w każdym
wymiarze dla każdego znalezionego podzbioru danych. Informacje te są wykorzystywane do
formułowania przesłanek i reguł w pierwszych dwóch blokach systemu. Segmentacja jest
wykonywana na wszystkich zmiennych, zarówno wejściowych jak i wyjściowej, zatem jej
efektem jest w istocie początkowy zbiór reguł. Już na podstawie segmentów danych można
przeprowadzać wnioskowanie. Wykorzystując środki i zakresy każdego z podzbiorów
możemy wyznaczyć funkcje przynależności dowolnej zmiennej wejściowej do danego
segmentu. Analogicznie, mając dane kryteria przynależności zmiennej wyjściowej do danego
segmentu możemy stworzyć regułę. W efekcie uzyskujemy zbiór segmentów, które
pokrywają przestrzeń zajmowaną przez dane. W procesie nauki ich środki i rozmiary mogą
się zmieniać i w efekcie pewne elementy poszczególnych zmiennych mogą z nich zniknąć.
Dzieje się tak zazwyczaj z wyjątkami, które nie znalazły swojego miejsca wśród reguł. Dzięki
temu dane te nie mają większego wpływu na wyniki nauki i testów, gdyż zawsze można
sprawdzić pobudzenie poszczególnych reguł wywołane danym wektorem wejściowym. W
podobny sposób znajduje się niepewne wyniki prognoz. Znikome pobudzenie reguł
stworzonych w procesie segmentacji i nauki oznacza brak jakiegokolwiek wzorca w
przeszłości. Przewidywana wartość uzyskana w ten sposób może być niepewna, zwłaszcza
jeżeli badane zjawisko ma charakter chaotyczny.
Do stworzenia sieci rozmyto neuronowej służy w środowisku Matlab polecenie
genfis2. Na podstawie wyników segmentacji jest tworzona struktura i ustalane są wagi
połączeń. Tak stworzony system jest przygotowany do etapu nauki. Dla lepszej kontroli
procesu tworzenia sieci również i w tym wypadku stworzono pojedynczą formatkę do
modyfikacji podstawowych parametrów (rysunek 12). W oknie możliwy jest wybór
odpowiednich zbiorów do nauki i testów oraz śledzenie wyników. Również i w tym
przypadku posłużono się danymi zawierającymi zmiany indeksu WIG20 w ciągu ostatnich
ośmiu lat, a zbiory wzorcowe mają strukturę identyczną z zastosowanymi w sieciach
neuronowych.

39
Rysunek 12. Okno treningowe systemów rozmyto neuronowych.

W polu "Obszar wpływu" ustala się maksymalną wartość wpływu środka segmentu,
im niższa, tym liczba segmentów i związanych z nimi reguł rośnie. Optymalna wartość tego
parametru dla większości przypadków mieści się między 0.3, a 0.5 4. Segmentacja zbioru
wzorcowego dla krańcowych wartości z tego przedziału prowadziła do podziału odpowiednio
na 124 oraz 8 podzbiorów. Po serii procesów tworzenia i nauki sieci rozmytych ustalono
najkorzystniejszą wartości "Obszaru wpływu" równą w przybliżeniu 0.5. W takiej sytuacji
algorytm znajdywał 8 reguł, a wyniki prognoz uzyskanych z jego pomocą były najbliższe
rzeczywistym zmianom. W kolejnym obszarze nazwanym "Podstawowa ilość epok nauki"
manipulować można długością najmniejszego cyklu treningowego. Cały etap nauki składa się
z wielu takich cykli, po których następuje weryfikacja uzyskanych wyników. Wielkościami
branymi pod uwagę są wartości błędu obliczone na podstawie zbioru walidacyjnego. Na ich
podstawie wyznacza się prostą regresji błędu korzystając z metody najmniejszych kwadratów.

40
Jeżeli z równania prostej wynika, iż w danym cyklu nie nastąpił znaczący spadek wartości
tego błędu, wówczas nauka jest przerywana. Z pomocą tego parametru można dodatkowo
skrócić czas obliczeń o kilkanaście minut. Pola "Testowanie sieci" oraz "Prognozowanie"
działają analogicznie do wykorzystanych w sieciach neuronowych z rozdziału 2.2.2.
Zaznaczenie "Testowania" powoduje naukę na podstawie ograniczonych "Zbiorów do nauki"
oraz testowanie stworzonej struktury za pomocą najświeższych danych ze "Zbiorów do
testów". W przypadku gdy użytkownik zaznaczy "Prognozowanie" zbiorem do nauki staje się
wybrany "Zbiór do testów", a system zwraca w wyniku pojedynczą prognozę na najbliższy
tydzień. "Początkowy rozmiar kroku" to wartość współczynnika szybkości nauki, a
znajdujący się pod nią "Współczynnik odchylenia" służy do tworzenia zbioru walidacyjnego
na podstawie danych wzorcowych. Stosunkowo krótki okres notowania indeksu WIG20 jest
przyczyną ograniczonej ilości danych. Ich podział na jeszcze mniejsze zbiory do nauki oraz
walidacji jest ryzykowny. Zdecydowano się zatem na stworzenie zbioru walidacyjnego na
podstawie danych wzorcowych. Zbiór ten uzyskuje się dodając do poszczególnych sygnałów
wejściowych niewielki szum w postaci liczby losowej. Maksymalna wartość bezwzględna
dodawanego szumu jest równa iloczynowi "Współczynnika odchylenia" oraz odchylenia
standartowego danej zmiennej wejściowej. Wynikiem nauki sieci rozmyto neuronowej z
wykorzystaniem zbioru walidacyjnego są dwie struktury. Pierwsza z nich to końcowy wynik
nauki, czyli sieć, która osiągnęła najniższy poziom błędu dla zbioru wzorcowego. Druga
struktura posiada konfigurację wag minimalizujących wartość błędu dla zbioru
walidacyjnego. Procedura ta wielokrotnie skraca czas nauki lecz przede wszystkim skutecznie
zapobiega przeuczeniu sieci. Można powiedzieć, iż poprawnie przeprowadzona nauka i
odpowiedni zbiór walidacyjny gwarantują uzyskanie najlepszego modelu uogólniającego
zadany problem przy wszystkich jego ograniczeniach wynikających z pozostałych
parametrów i zmiennych. Istotne jest również to, że przy tych samych wartościach "Obszaru
wpływu" i zbliżonych zbiorach walidacyjnych za każdym razem uzyskuje się niemal
identyczne struktury. Proces nauki może spowodować różnicę pomiędzy sieciami
neuronowymi w warstwie wyostrzania, lecz pozostałe elementy systemu będą się powtarzały
za każdym razem. Wielkość "Współczynnika odchylenia" równą 1/9 (czyli w przybliżeniu
0.11111) określono na podstawie obserwacji. Przy mniejszych wartościach sieć miała
tendencję do przeuczenia i po osiągnięciu plato nauka była wciąż kontynuowana. Większe
wartości współczynnika powodowały, że nauka była przerywana już po początkowych 100
epokach.

41
Ostatnie dwa pola służą do wyboru jednej z dwóch metod modyfikacji połączeń,
"Algorytmu backpropagation" lub "Metody hybrydowej". Druga metoda wspiera klasyczny
algorytm wstecznej propagacji błędu metodą najmniejszych kwadratów umożliwiającą
określenie liniowych zależności pomiędzy zmiennymi wejściowymi i wyjściową zanim
nastąpi nauka. Procedura ta również wpływa na skrócenie czasu trwania treningu.
W celu uproszczenia analizy uzyskanych wyników zastosowano moduł Matlab’a
służący do raportowania. Jest to bardzo użyteczne narzędzie, umożliwiające eksport danych,
wykresów i tabel do plików html, rtf, xml oraz sgml. Poniżej znajduje się jeden z uzyskanych
raportów zawierający najlepsze z uzyskanych podczas testów wyników.

Wyniki z dnia 2002/05/19


Podstawowe informacje o systemie:
Data utworzenia systemu 2002/04/24
Metoda optymalizacji parametrów funkcji
Metoda hybrydowa
przynależności
Czas nauki 00:34:43
Ilość epok nauki 6800
Błąd końcowy
system1 2.83715
system2 2.97415
Współczynnik wpływu 0.5
Współczynnik odchylenia 0.111111
Liczba reguł 8

42
Wyniki testów systemu rozmyto neuronowego:
Data Zmiana WIG20 Prognoza WIG20 Błąd Trend
2001/12/30 10.3979 -4.4033 14.8012 0
2002/01/06 5.24096 -4.0506 9.29152 0
2002/01/13 1.00327 -3.7584 4.76166 0
2002/01/20 3.36113 -0.96597 4.32709 0
2002/01/27 -2.4848 -2.2209 0.263952 1
2002/02/03 -4.05402 -4.7353 0.681255 1
2002/02/10 0.136512 -2.1768 2.31328 0
2002/02/17 -2.79068 0.30904 3.09972 0
2002/02/24 4.24319 6.0451 1.80192 1
2002/03/03 1.26978 -2.2327 3.50244 0
2002/03/10 -2.88067 -0.92803 1.95263 1
2002/03/17 -0.740248 -0.58501 0.155237 1
2002/03/24 -1.32204 -4.2885 2.96645 1
2002/03/31 -0.120234 -2.7797 2.65945 1
2002/04/07 -0.121127 -3.5786 3.45752 1
2002/04/14 -1.68062 -1.9636 0.28301 1
2002/04/21 1.21063 -3.4554 4.66608 0
2002/04/28 -1.7897 -3.3384 1.54869 1
Średni błąd
3.4741 55.5556 %
prognozy

Wykres 1. Wyniki na dzień 2002/04/28 (test z dnia 2002/05/19)

43
Wykres 2. Wyniki na dzień 2002/04/28 (test z dnia 2002/05/19)

Wyniki uzyskane przy pomocy tego systemu są pod wieloma względami lepsze od
uzyskanych podczas testów sieci neuronowych rozwiązujących dany problem. Zmniejszeniu
uległ błąd testów, który w tym wypadku wynosi 3.4741. Bardzo obiecującym zjawiskiem jest
również niewielka różnica pomiędzy wartościami błędów uzyskanych podczas nauki.
Wartości te są bardzo zbliżone, choć zostały obliczone na podstawie dwóch różnych zbiorów,
wzorcowego oraz walidacyjnego. Zastosowanie zbioru walidacyjnego pozwoliło ograniczyć
naukę do 6800 epok, dzięki temu trwała ona zaledwie 34 minuty. Jest to czas porównywalny z
osiąganymi przez sieci neuronowe. Zaprezentowana struktura posiada 8 reguł i tyle samo
funkcji przynależności dla każdej zmiennej wejściowej (rysunek 13).

44
Rysunek 13. Schemat systemu rozmyto neuronowego.

Każdą ze znalezionych zależności można przedstawić za pomocą zdania:

"Jeżeli X1 jest w równa około X1i-średnie i X2 równa około X2i-średnie i ...


... i X6 równe około X6i-średnie, wtedy Y równe Yi."

gdzie i jest wybraną regułą, a Yi jest funkcją zmiennych wejściowych określającą


wartość zmiennej wyjściowej dla danej reguły.

Pierwsza reguła znajdująca się w warstwie implikacji zaprezentowanej sieci brzmi


następująco:

Jeżeli zmiana indeksu w ostatnim tygodniu (X1) wyniosła około -1 % i


zmiana od 4 do 2 tygodnia wstecz (X2) wyniosła około -13.9 % i
zmiana od 12 do 5 tygodnia wstecz (X3) wyniosła około -10.2 % i
zmiana od 24 do 13 tygodnia wstecz (X4) wyniosła około 7 % i
zmiana od 48 do 25 tygodnia wstecz (X5) wyniosła około 23.7 % i
zmiana do 96 do 49 tygodnia wstecz (X6) wyniosła około 30.3, wtedy
zmiana indeksu w przyszłym tygodniu (Y1) wyniesie około 1.0961 % .

45
Regułę opisuje następująca funkcja liniowa:

Y1 = (−0.942) ⋅ X1 + 0.195⋅ X2 + (−0.437) ⋅ X3 + (−0.038) ⋅ X4 + (−0.153) ⋅ X5 + (−0.074) ⋅ X6 + 4.579

Wartość Y1 dla środka segmentu zmiennych wejściowych wynosi 1.0961 % i można ją


interpretować jako środek przedziału zmiennej wyjściowej. Przedział ten należy do segmentu
zmiennych związanego z pierwszą regułą.
Dodatkową weryfikację można przeprowadzić porównując wyniki testów z poziomem
aktywacji istniejących reguł dla każdego okresu. Pełne zestawienie aktywacji reguł, ich sumy
oraz maksymalnej wartości zawiera tabela 6. Na rysunku 14 znajduje się porównawczy
wykres błędu, poziomów aktywacji i trafień w trend dla każdego rekordu testowego. Wynika
z niego, że wraz ze wzrostem poziomu aktywności wszystkich reguł rośnie skuteczność w
przewidywaniu trendu zmian indeksu, a maleje wartość błędu prognozy. System rozmyty
umożliwia zatem nie tylko prognozowanie przyszłych wartości, lecz również ocenę
uzyskanych wyników i związanego z nimi ryzyka. Jak już wspomniano, brak wzorca w
przeszłości może uniemożliwić wszelkie przewidywania przyszłych zmian, a niski poziom
aktywacji reguł oznacza właśnie taką sytuację. Uzyskane wyniki obejmują stosunkowo krótki
okres czasu, mimo to można na ich podstawie zaobserwować ciekawe zjawisko. Kolejne
prognozy oraz poziomy pobudzenia reguł układają się w serie. Przez pewien czas system
popełnia poważne błędy, po czym następuje okres wyjątkowo dobrych wyników. Zjawisko to
może wskazywać na chaotyczny charakter systemu gospodarczego i instrumentów z nim
związanych. Chaos w przypadku badanego indeksu WIG20 objawiłby się jako ciąg
następujących po sobie okresów względnego spokoju i przewidywalnych zmian oraz okresów
zupełnie przypadkowych wahań. Jest to oczywiście jedynie przypuszczenie, gdyż ilość
danych jest zbyt skromna, aby na ich podstawie wyciągać takie wnioski.

46
Tabela 6. Zestawienie aktywacji reguł, ich sumy oraz maksymalnej wartości.
Reguły Suma aktywacji Wartość
Data
1 2 3 4 5 6 7 8 reguł maksymalna
2001-12-30 0,000 0,197 0,000 0,000 0,002 0,000 0,000 0,000 0,200 0,197
2002-01-06 0,000 0,166 0,000 0,000 0,011 0,000 0,000 0,008 0,185 0,166
2002-01-13 0,000 0,251 0,000 0,000 0,037 0,002 0,000 0,010 0,300 0,251
2002-01-20 0,000 0,080 0,000 0,000 0,006 0,002 0,000 0,004 0,093 0,080
2002-01-27 0,000 0,163 0,000 0,000 0,006 0,002 0,000 0,004 0,175 0,163
2002-02-03 0,000 0,045 0,000 0,000 0,154 0,000 0,000 0,171 0,371 0,171
2002-02-10 0,002 0,013 0,000 0,000 0,623 0,000 0,000 0,152 0,791 0,623
2002-02-17 0,005 0,224 0,000 0,000 0,653 0,001 0,001 0,067 0,951 0,653
2002-02-24 0,000 0,036 0,000 0,000 0,400 0,000 0,001 0,003 0,440 0,400
2002-03-03 0,001 0,130 0,000 0,000 0,306 0,000 0,000 0,051 0,488 0,306
2002-03-10 0,000 0,374 0,000 0,000 0,480 0,002 0,000 0,003 0,860 0,480
2002-03-17 0,000 0,034 0,000 0,000 0,425 0,000 0,000 0,011 0,471 0,425
2002-03-24 0,000 0,140 0,000 0,000 0,356 0,000 0,000 0,095 0,592 0,356
2002-03-31 0,001 0,099 0,000 0,001 0,572 0,004 0,000 0,144 0,821 0,572
2002-04-07 0,003 0,184 0,000 0,000 0,648 0,000 0,000 0,234 1,071 0,648
2002-04-14 0,021 0,111 0,000 0,000 0,441 0,005 0,002 0,089 0,668 0,441
2002-04-21 0,015 0,051 0,000 0,000 0,232 0,002 0,001 0,202 0,503 0,232
2002-04-28 0,008 0,064 0,000 0,000 0,285 0,006 0,001 0,106 0,471 0,285

Rysunek 14. Wykres aktywacji reguł, błędu i trafności prognoz.

Jednoczesna analiz uzyskanych wyników i poziomów aktywacji reguł umożliwia


odrzucanie niepewnych prognoz i dalsze ograniczanie poziomu błędu. Przyjmując minimalną

47
wartość sumy aktywacji reguł na poziomie 0.35 (rysunek 15) jako kryterium odrzucania
prognoz można zmniejszyć wartość średniego błędu testów do 2.24 % (tabela 7).

Rysunek 15. Ocena uzyskanych wyników na podstawie aktywacji reguł.

48
Tabela 7. Wyniki dla zakwalifikowanych prognoz.

Data Zmiana WIG20 Prognoza WIG20 Błąd Trend


2002/02/03 -4.05402 -4.7353 0.681255 1
2002/02/10 0.136512 -2.1768 2.31328 0
2002/02/17 -2.79068 0.30904 3.09972 0
2002/02/24 4.24319 6.0451 1.80192 1
2002/03/03 1.26978 -2.2327 3.50244 0
2002/03/10 -2.88067 -0.92803 1.95263 1
2002/03/17 -0.740248 -0.58501 0.155237 1
2002/03/24 -1.32204 -4.2885 2.96645 1
2002/03/31 -0.120234 -2.7797 2.65945 1
2002/04/07 -0.121127 -3.5786 3.45752 1
2002/04/14 -1.68062 -1.9636 0.28301 1
2002/04/21 1.21063 -3.4554 4.66608 0
2002/04/28 -1.7897 -3.3384 1.54869 1
Średni błąd
2.2375 69,2308 %
prognozy

Jest to najlepszy wynik jaki udało się osiągnąć i zarazem jedna z najniższych wartości
średniego błędu z jaką się spotkałem pracując z aplikacjami wspomagającymi decyzje
inwestycyjne w podobny sposób.
Przejrzysta struktura i natychmiastowa ocena uzyskanych wyników są niewątpliwie
największymi zaletami powyższej sieci rozmytej i dają jej ogromną przewagę nad
pozostałymi strukturami neuronowymi.

49
3. Wnioski
Spośród trzech zawartych w pracy modeli, dwa osiągnęły zadowalającą skuteczność.
Najlepsze wyniki uzyskano z pomocą struktury rozmyto neuronowej. Możliwość szybkiej i
skutecznej weryfikacji prognoz jest dodatkowym atutem tej metody przewidywania. Drugim
modelem jest zbiór sieci neuronowych z rozdziału 2.2.1. Chociaż uśredniona prognoza sieci
była daleka od rzeczywistych zmian indeksu WIG20, to jednak bardzo dokładnie określała
kierunki tych zmian. Informacja taka jest bardzo przydatna podczas ostatecznej weryfikacji
uzyskanych wyników.
Dalszym etapem wspomagania decyzji na podstawie wyników prognoz jest
odpowiednie ich wykorzystanie. Jest to dość proste zadanie, gdyż aktualnie istnieje
możliwość inwestowania w instrumenty finansowe związane z indeksami giełdowymi takimi
jak WIG20. Znając przybliżoną przyszłą wartość indeksu można dokonywać zakupu,
sprzedaży bądź wykonania kontraktów terminowych lub jednostek indeksowych MiniWIG20.
Drugim rozwiązaniem jest tworzenie portfela akcji na podstawie ich korelacji z
indeksem. Jest to rozwiązanie trudniejsze wymagające określenia przedziału czasu w jakim
badamy związki pomiędzy instrumentami. Po określeniu tego parametru tworzenie i
modyfikowanie portfela na podstawie prognoz indeksu i korelacji nie stanowi wielkiego
wyzwania. Jest to bezpieczniejsza metoda inwestowania zważywszy, że opcje i kontrakty
terminowe mają dość krótką historię na polskiej giełdzie.
Praca moja miała teoretyczny charakter, dlatego też nie umiem dać jasnej odpowiedzi
na pytanie o kryteria rentownej inwestycji w papiery wartościowe z wykorzystaniem
zaproponowanych metod prognostycznych. Wydaje się jednak, iż uzyskane wyniki są w
stanie w znacznym stopniu usprawnić proces podejmowania decyzji i poprawić jego trafność.
Moim zdaniem obie wymienione struktury mogą być zastosowane do stworzenia systemu
predykcji przyszłych zmian indeksu WIG20. System będzie w stanie prognozować z dużą
dokładnością, a wyniki uzyskane z dwóch źródeł mogą być porównywane i weryfikowane w
celu ograniczenia ryzyka inwestycji.
Podczas projektowania i nauki struktur neuronowych ograniczono ilość zmiennych i
zrezygnowano z optymalizacji wielu parametrów. Były to ograniczenia wynikające z
szybkości obliczeniowej posiadanego sprzętu komputerowego oraz zastosowania niezwykle
wymagającego środowiska Matlab. Pełne wykorzystanie zaprezentowanych sieci jest możliwe
jedynie przy użyciu dedykowanej aplikacji wielostanowiskowej bądź przystosowanej do

50
wydajniejszych maszyn obliczeniowych. Takie rozwiązanie umożliwiłoby zastosowanie
algorytmu genetycznego do optymalizacji parametrów oraz sprawdzenie różnych konfiguracji
nowych zmiennych wejściowych. Szczególnie interesujące może okazać się zastosowanie
indeksów branżowych i zagranicznych lub wielkości obrotu giełdowego jako zmiennych
wejściowych obu struktur. Użycie innych, pozornie niezwiązanych z gospodarką wielkości,
również może znacząco wpłynąć na poprawę prognoz. Otaczający nas świat jest niezwykle
skomplikowanym organizmem. Wszystko co na nas wpływa kształtuje każdy aspekt naszego
życia, również gospodarczy. Każdego dnia mamy kontakt z ogromną liczbą przeróżnych
informacji. Moim zdaniem dopiero zaczynamy się uczyć jak je wykorzystywać.

51
4. Literatura
[1] Sieci neuronowe, algorytmy genetyczne i systemy rozmyte; D. Rutkowska, M. Piliński,
L. Rutkowski, PWN; Warszawa 1997;
[2] Teoria chaosu a rynki kapitałowe; E. Peters, WIG-Press; Warszawa 1997;
[3] Sieci neuronowe w ujęciu algorytmicznym; S. Osowski, WNT; Warszawa 1996;
[4] Wstęp do teorii obliczeń neuronowych; J. Hertz, A. Krogh, R. Palmer, WNT; Warszawa
1993;
[5] Sieci neuronowe; R. Tadeusiewicz, Akademicka Oficyna Wydawnicza; Warszawa
1993;
[6] Specyfikacja środowiska Matlab dla dwóch pakietów: „Neural Network Toolbox”,
„Fuzzy Logic Toolbox”;
[7] Fuzzy sets, L. Zadeh, 1965;
[8] Teoria chaosu w analizie finansowych szeregów czasowych; K. Jajuga, D. Papla; V
Ogólnopolskie Seminarium Naukowe; Toruń 1997;

52
5. Aneks
1. Programy do importowania notowań, przenoszenia danych do
środowiska Matlab i weryfikacji danych.

• aktualizacja - moduł Visual Basic służący importowaniu notowań do sformatowanych


plików tekstowych,

Option Base 1 'zmiana domyślnego minimalnego indeksu wszystkich tabel w poniższej aplikacji
'na 1

Dim Katalog As String 'zmienna wykorzystywana w funkcji kasowanie


Dim KatalogGlowny As String 'główny katalog notowań
Dim KatalogDane As String 'katalog z plikami poszczególnych walorów
Dim KatalogAktualizacji As String 'pliki zawierające najnowsze notowania
Dim NowyObjekt As Object 'FileSystemObject
Dim ZawartoscDane As String 'skrót do pliku zawierającego ścieżki i nazwy plików
'znajdujących się w katalogu KatalogDane

'************************************************************************************************
Sub Aktualizacja()
'************************************************************************************************

KatalogGlowny = "C:\Praca\01mgr\notowania"
KatalogDane = KatalogGlowny & "\dane"
KatalogAktualizacji = KatalogGlowny & "\aktu"
ZawartoscDane = KatalogGlowny & "\zawartosc.txt" 'ścieżka i nazwa pliku z zawartością katalogu
'KatalogDane
ChDir (KatalogGlowny)

Set NowyObjekt = CreateObject("Scripting.FileSystemObject")

Kasowanie (KatalogDane)

PlikiNowe (KatalogAktualizacji) 'funkcja wyszukująca pliki z notowaniami giełdowymi

Kasowanie (KatalogAktualizacji)

End Sub

'************************************************************************************************
Function Kasowanie(Katalog)
'************************************************************************************************

With Application.FileSearch 'wyszukiwanie plików znajdujących się w katalogu Katalog


.NewSearch
.LookIn = Katalog
.FileType = msoFileTypeAllFiles
.Execute
For i11 = 1 To .FoundFiles.Count

53
NowyObjekt.DeleteFile .FoundFiles(i11), True

Next i11
End With

End Function

'************************************************************************************************
Function PlikiNowe(Katalog)
'************************************************************************************************
Set PlikDane = NowyObjekt.CreateTextFile(ZawartoscDane, True, False)

With Application.FileSearch 'wyszukiwanie plików w katalogu KatalogAktualizacji


.NewSearch
.LookIn = Katalog
.FileType = msoFileTypeAllFiles
.Execute
For i11 = 1 To .FoundFiles.Count

pomstart = Len(Katalog) + 2
pomdlug = Len(.FoundFiles(i11)) - 5 - Len(Katalog)
nazwa = StrConv(Mid(.FoundFiles(i11), pomstart, pomdlug), 1)
sciezka = KatalogDane & "\" & nazwa & ".txt"
PlikDane.WriteLine (nazwa)

Set PlikNowy = NowyObjekt.CreateTextFile(sciezka, True, False)

pomocnicza = 0
Open .FoundFiles(i11) For Input As #1 'wyszukiwanie ostatniego wiersza w pliku
Do While Not EOF(1)
Line Input #1, Wiersz
pomocnicza = pomocnicza + 1
If pomocnicza > 1 Then
NowyWiersz = Mid(Wiersz, pomdlug + 2)
PlikNowy.WriteLine (NowyWiersz)
End If
Loop
Close #1

Next i11
End With

End Function

• wczytaj.m - skrypt wczytujący dane ze sformatowanych plików z notowaniami i


weryfikujący te dane pod kątem błędnych wartości i powtarzających się dat,

%*************************************************************************************
%wczytaj.m
%*************************************************************************************

clear;clc

KatalogGlowny='e:\praca\01mgr\notowania';

54
KatalogDane=[KatalogGlowny '\dane'];
KatalogSplit=[KatalogGlowny '\split'];

cd(KatalogGlowny);

zawartosc=dir(KatalogDane);
%polecenie, dzięki któremu w zmiennej zawartosc pojawia się informacja
%o wszystkich plikach zgromadzonych w katalogu KatalogDane

cd(KatalogDane);

znacznik=0;

stopyzwrotu=[];

datypowtorki=[];

for i11=1:size(zawartosc,1)

if ~zawartosc(i11).isdir %sprawdza czy wybrany element znajdujący się w


%katalogu KatalogDane jest jego podkatalogiem,
%jeżeli jest wówczas zostaje on pominięty

if zawartosc(i11).bytes>=2000 %wybiera tylko te pliki których wielkość


%jest większa niż 2000 bitów, ponieważ jest to
%najmniejsza możliwa wielkość pliku zawierającego
%minimum 100 linii tekstu (100 rekordów)

tablica=dlmread(zawartosc(i11).name,','); %wczytuje do zmiennej


%tablica dane znajdujące się w kolejnych plikach
%tekstowych (separatorem tekstu użytym w tych
%plikach jest tabulator)

if size(tablica,1)>=100 %ponownie sprawdza czy pliki zawierają


%minimum 100 linii tekstu (100 rekordów)

znacznik=znacznik+1;

irr=splitakcji(tablica,znacznik); %funkcja splitakcji oblicz maksymalna i minimalna


%dzienna stopę zwrotu

stopyzwrotu=[stopyzwrotu;irr];

powtorki=zledaty(tablica,znacznik); %funkcja zledaty znajduje powtarzające się


%złe daty w plikach z danymi

datypowtorki=[datypowtorki; powtorki];

snazwa=zawartosc(i11).name; %pobieranie nazwy wczytanego pliku


snazwa=snazwa(1,1:size(snazwa,2)-4); %usuniecie rozszerzenia
nnazwa=snazwa;

%poniższa instrukcja if oraz pętla while sprawdzają czy na początku


%nazwy pliku znajdują się liczby, jeżeli tak to liczby te zostają
%przeniesione na koniec nazwy, jest to konieczne, aby nazwa spółki
%mogła jednocześnie służyć jako nazwa zmiennej zawierającej dane tej
%spółki

if sum(isletter(nnazwa))<size(nnazwa,2)

55
while ~isletter(nnazwa(1,1))
pierwsza=nnazwa(1,1);
nnazwa(1,1:size(nnazwa,2)-1)=nnazwa(1,2:size(nnazwa,2));
nnazwa(1,size(nnazwa,2))=pierwsza;
end
end

%w poniższych instrukcjach z nazwy spółki usuwane są inne znaki


%(tzn. wszystkie znaki oprócz liter oraz cyfr), ponieważ nie mogą
%one wchodzić w skład nazwy zmiennej

pomocnicza=[];
for i12=1:size(nnazwa,2)
if isletter(nnazwa(1,i12))
pomocnicza=[pomocnicza nnazwa(1,i12)];
elseif abs(nnazwa(1,i12))>=48 & abs(nnazwa(1,i12))<=57
pomocnicza=[pomocnicza nnazwa(1,i12)];
end
end
nnazwa=pomocnicza;

TabelaNazw(znacznik,1)={snazwa}; %zmienna TabelaNazw to tablica


TabelaNazw(znacznik,2)={nnazwa}; %komórek, w której przetrzymywane
%są nazwy plików oraz odpowiadające im nazwy zmiennych

eval([nnazwa '=tablica;']); %instrukcja, dzięki której odpowiednio


%przetworzona nazwa pliku może posłużyć jako nazwa
%zmiennej przechowującej dane zawarte w tym pliku

end
end
end
end

cd(KatalogGlowny);

load datasplit

notowania=stopyzwrotu(:,2)>=DataSplit-1;
notowania=find(notowania);
stopyzwrotu=stopyzwrotu(notowania,:);

if ~isempty(stopyzwrotu)
DataSplit=max(stopyzwrotu(:,2));
save datasplit DataSplit

cd(KatalogSplit);

dlmwrite('01stopyzwrotu.txt',stopyzwrotu,'\t');
dlmwrite('01nazwystopy.txt',char(TabelaNazw(stopyzwrotu(:,1),1)),'');

end

if ~isempty(datypowtorki)
cd(KatalogSplit);

datypowtorki=datypowtorki(find(datypowtorki(:,2)),:);

dlmwrite('02datypowtorki.txt',datypowtorki,'\t');

56
dlmwrite('02nazwydaty.txt',char(TabelaNazw(datypowtorki(:,1),1)),'');

end

cd(KatalogGlowny);

clear datypowtorki DataSplit i11 i12 irr nnazwa notowania pierwsza pomocnicza powtorki snazwa
stopyzwrotu tablica zawartosc znacznik
save Zmienne

• splitakcji.m – funkcja sprawdzająca czy nie nastąpił split akcji,

%*************************************************************************************
%splitakcji.m
%*************************************************************************************

function irr=splitakcji(tablica,znacznik)

otwarcie=tablica(:,2);
poprzednie=otwarcie(1:size(otwarcie,1)-1,1);
nastepne=otwarcie(2:size(otwarcie,1),1);

dsz=(nastepne-poprzednie)./poprzednie*100; %dzienne stopy zwrotu

wskaznik1=dsz>60;
wskaznik2=dsz<-35;
wskaznik=wskaznik1+wskaznik2;

wskaznik=find(wskaznik);

if ~isempty(wskaznik)

wskaznik=[wskaznik;wskaznik+1;wskaznik-1];
wskaznik=sort(wskaznik);

flaga1=wskaznik<=0;
flaga2=wskaznik>size(poprzednie,1);
flaga=flaga1+flaga2;

if sum(flaga)>0
pomocnicza=[];
for i11=1:size(wskaznik,1)
if wskaznik(i11,1)>0 & wskaznik(i11,1)<=size(poprzednie,1)
pomocnicza=[pomocnicza;wskaznik(i11,1)];
end
end
wskaznik=pomocnicza;
end

irr=[znacznik*ones(size(wskaznik,1),1) tablica(wskaznik+1,:) dsz(wskaznik,:)];

else
irr=[znacznik 0 0 0 0 0 0 0];
end

57
• zledaty.m – funkcja sprawdzająca poprawność dat w posiadanych notowaniach,

%*************************************************************************************
%zledaty.m
%*************************************************************************************

function powtorki=zledaty(tablica,znacznik);

daty=(1:size(tablica,1))';
daty=[daty tablica(:,1)];
pomocnicza=[];

for i11=1:size(daty,1)
if daty(i11,1)~=0
b=daty(i11,2);
daty(i11,1:2)=[0 0];
a=find(daty(:,2)==b);

if ~isempty(a)
pomocnicza=[pomocnicza;daty(a,:)];
end

daty(a,1)=0;
daty(a,2)=0;
end
end

if ~isempty(pomocnicza)
pomocnicza=[znacznik*ones(size(pomocnicza,1)) pomocnicza];
else
pomocnicza=[znacznik 0 0];
end

powtorki=pomocnicza;

• tszidaty.m – funkcja obliczająca tygodniowe zmiany dowolnego papieru


wartościowego lub indeksu,

%*************************************************************************************
%tszidaty.m
%*************************************************************************************

function [wynik,tygsz]=tszidaty(spolka)

pomocnicza=num2str(spolka(:,1));

y=str2num(pomocnicza(:,1:4));
m=str2num(pomocnicza(:,5:6));
d=str2num(pomocnicza(:,7:8));

daty=datenum(y,m,d);

spolka=[daty spolka];

58
pierwsze=daty(1,1)+8-weekday(daty(1,1));
ostatnie=floor((daty(size(daty,1),1)-pierwsze)/7)*7+pierwsze;

pomoc=[pierwsze:7:ostatnie]';

if daty(1,1)<pomoc(1,1)
pomoc=[daty(1,1);pomoc];
end

if daty(size(daty,1),1)>pomoc(size(pomoc,1),1)
pomoc=[pomoc;daty(size(daty,1),1)];
end

odstepy=pomoc;

pomoc=[odstepy(1,1) spolka(1,3)];
for i11=2:size(odstepy,1)
a=spolka(find(odstepy(i11-1,1)<=spolka(:,1)&spolka(:,1)<=odstepy(i11,1)),:);
if ~isempty(a)
pomoc=[pomoc;odstepy(i11,1) a(size(a,1),6)];
else
pomoc=[pomoc;odstepy(i11,1) 0];
end
end

b=find(pomoc(:,2)==0);

if ~isempty(b)
for i12=1:size(b,1)
pomoc(b(i12,1),2)=pomoc(b(i12,1)-1,2);
end
end

obliczenia=stopyz(pomoc(:,2)); %funkcja obliczajaca stopy zwrotu dla wektora podanych wartosci

wynik=spolka;

tygsz=[pomoc obliczenia];

2. Funkcje do nauki i testów klasyfikujących sieci neuronowych


(rozdział 2.2.2)

• sieci.m – funkcje do obsługi formatki nauki sieci neuronowych (rysunek 3),

%*************************************************************************************
%sieci.m
%*************************************************************************************

function varargout = sieci(varargin)

cd('e:\praca\01mgr\notowania\siec');
nazwy_nauka = nazwyzmiennych('Zmienne_siec.mat','double');

59
nazwy_testy = nazwyzmiennych('Zmienne.mat','double');

if nargin == 0

fig = openfig(mfilename,'reuse');

handles = guihandles(fig);
guidata(fig, handles);

set(handles.checkbox1,'Value',1);
set(handles.listbox1,'String',nazwy_nauka);
set(handles.listbox3,'String',nazwy_testy);
set(handles.checkbox2,'Value',1);

if nargout > 0
varargout{1} = fig;
end

elseif ischar(varargin{1})

try
[varargout{1:nargout}] = feval(varargin{:});
catch
disp(lasterr);
end

end

% --------------------------------------------------------------------
function varargout = pushbutton1_Callback(h, eventdata, handles, varargin)

tic;

katalog = cd;

dataczas = datestr(now,0);
pomoc = (abs(dataczas) == 32) + (abs(dataczas) == 58);
dataczas(find(pomoc == 1)) = '_';

katalog_nowy = ['wyniki_' dataczas];


mkdir(katalog,katalog_nowy);
katalog_nowy = [katalog '\' katalog_nowy];
cd(katalog_nowy);

if get(handles.checkbox2,'Value')==1
pomoc=get(handles.listbox1,'String');
load('Zmienne_siec.mat',pomoc{get(handles.listbox1,'Value'),1});
eval(['nauka = ' pomoc{get(handles.listbox1,'Value'),1} ';']);
[nauka_dane, nauka_tsz] = tszidaty(nauka);

pomoc=get(handles.listbox3,'String');
load('Zmienne.mat',pomoc{get(handles.listbox3,'Value'),1});
eval(['testy = ' pomoc{get(handles.listbox3,'Value'),1} ';']);
[testy_dane, testy_tsz] = tszidaty(testy);

else
pomoc=get(handles.listbox3,'String');
load('Zmienne.mat',pomoc{get(handles.listbox3,'Value'),1});

60
eval(['nauka = ' pomoc{get(handles.listbox1,'Value'),1} ';']);
[nauka_dane, nauka_tsz] = tszidaty(nauka);

testy=nauka;
testy_dane=nauka_dane;
testy_tsz=[nauka_tsz; nauka_tsz(size(nauka_tsz,1)-1,1)+14 nauka_tsz(size(nauka_tsz,1),2) 1];

end

dokladnosc = get(handles.checkbox1,'Value');
blad=str2num(get(handles.edit3,'String'));
max_epok=40000;
powtorki=str2num(get(handles.edit4,'String'));

[nauka_wejscie, nauka_wyjscie_p, nauka_daty] = inoutsiec1(nauka_tsz(:,3)', nauka_tsz(:,1)',


dokladnosc);
[testy_wejscie, testy_wyjscie_p, testy_daty_p] = inoutsiec1(testy_tsz(:,3)', testy_tsz(:,1)',
dokladnosc);
testy_wejscie=testy_wejscie(:,(size(nauka_wejscie,2)+1):size(testy_wejscie,2));

argumenty = (floor(100*min(cell2num2(testy_wyjscie_p)))/100) : 0.01 :


(ceil(100*max(cell2num2(testy_wyjscie_p)))/100);
wyniki = zeros(size(testy_wejscie,2),size(argumenty,2),2);
wartosc_max=str2num(get(handles.edit1,'String'))-1;

pomoc_1 = cell2num2(testy_wyjscie_p(:, (size(nauka_wyjscie_p,2)+1) : size(testy_wyjscie_p,2) ));


for i10 = 1 : size(wyniki,1)
pomoc_2 = round(pomoc_1(1,i10) * 100) / 100;
indeks = (pomoc_2 - argumenty(1,1)) / 0.01 + 1;
wyniki(i10,fix(indeks), 2) = wartosc_max;
end

load siec

for i11 = str2num(get(handles.edit1,'String')) : -1 : 2

siec.layers{2,1}.dimensions=i11;
siec.trainParam.epochs=max_epok;
siec.trainParam.goal=blad;

[nauka_wyjscie, nauka_granice] = inoutsiec2(nauka_wyjscie_p, i11);

[testy_wyjscie, testy_granice] = inoutsiec2(testy_wyjscie_p, i11);

testy_wyjscie=testy_wyjscie(:,(size(nauka_wyjscie,2)+1):size(testy_wyjscie,2));
testy_daty=testy_daty_p(:,(size(nauka_daty,2)+1):size(testy_daty_p,2));

blad_sieci=1;
while blad_sieci>blad
siec_wynik=init(siec);
[siec_wynik,nauka_zapis,nauka_outputs,nauka_bledy]=train(siec_wynik,nauka_wejscie,nauka_wyj
scie);
blad_sieci=nauka_zapis.perf(1,size(nauka_zapis.perf,2));
end

siec_wynik.trainParam.epochs=powtorki;
siec_wynik.trainParam.goal=0;

61
[siec_wynik,nauka_zapis,nauka_outputs,nauka_bledy]=train(siec_wynik,nauka_wejscie,nauka_wyjscie
);

[testy_outputs,opoznienie1,opoznienie2,testy_bledy]=sim(siec_wynik,testy_wejscie,[],
[],testy_wyjscie);
clear opoznienie1 opoznienie2

wyniki_testy = siecout(argumenty, testy_outputs, testy_granice);

wyniki(:,:,1) = wyniki(:,:,1) + wyniki_testy;

pomoc = zeros(size(wyniki));
pomoc(:,:,1) = wyniki_testy;
pomoc(:,:,2) = wyniki(:,:,2);
wyniki_testy = pomoc;

pomoc=['siec' num2str(i11)];
save(pomoc,'nauka','nauka_dane','nauka_daty','nauka_granice','nauka_tsz','nauka_wejscie','nauka
_wyjscie',...
'siec_wynik','testy','testy_dane','testy_daty','testy_granice','testy_tsz','testy_wejscie',
'testy_wyjscie',...
'nauka_zapis','nauka_outputs','nauka_bledy',...
'testy_outputs','testy_bledy',...
'wyniki_testy');

end

testy_daty = datestr(testy_daty', 1);

czas = toc;
czas = datestr( czas/60/60/24, 13)

save('wyniki','argumenty','wyniki','testy_daty','czas');
cd(katalog);

% --------------------------------------------------------------------
function varargout = pushbutton2_Callback(h, eventdata, handles, varargin)
clc;
close(handles.figure1)

% --------------------------------------------------------------------
function varargout = checkbox1_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = checkbox2_Callback(h, eventdata, handles, varargin)
set(handles.checkbox3,'Value',~get(handles.checkbox2,'Value'));

% --------------------------------------------------------------------
function varargout = checkbox3_Callback(h, eventdata, handles, varargin)
set(handles.checkbox2,'Value',~get(handles.checkbox3,'Value'));

% --------------------------------------------------------------------
function varargout = edit1_Callback(h, eventdata, handles, varargin)

62
% --------------------------------------------------------------------
function varargout = edit3_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = edit4_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = listbox1_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = listbox3_Callback(h, eventdata, handles, varargin)

3. Wyniki testów sieci klasyfikujących (rozdział 2.2.2)

• Każdy z raportów zawiera serię trzynastu prognoz tygodniowych zmian indeksu


WIG20 w okresie od 30 września do 30 grudnia 2002 roku.

• Raport 2002.01.16 01:50

63
• Raport 2002.01.18 3:37

• Raport 2002.01.18 20:16

64
4. Funkcje do nauki sieci rozmyto neuronowych (rozdział 2.3)

• smrn.m – funkcje do obsługi formatki nauki sieci rozmyto neuronowych (rysunek 12),

%*************************************************************************************
%smrn.m
%*************************************************************************************

function varargout = smrn(varargin)

cd('e:\praca\01mgr\notowania\smrn');
nazwy_nauka = nazwyzmiennych('Zmienne_siec.mat','double');
nazwy_testy = nazwyzmiennych('Zmienne.mat','double');

if nargin == 0

fig = openfig(mfilename,'reuse');

handles = guihandles(fig);
guidata(fig, handles);

set(handles.listbox1, 'String', nazwy_nauka);


set(handles.listbox3, 'String', nazwy_testy);
set(handles.checkbox2, 'Value', 1);
set(handles.checkbox4, 'Value', 1);
set(handles.edit5, 'String', '0.5');
set(handles.edit6, 'String', '100');
set(handles.edit7, 'String', '0.1');
set(handles.edit9, 'String', '0.11111');

if nargout > 0
varargout{1} = fig;
end

elseif ischar(varargin{1})

try
[varargout{1:nargout}] = feval(varargin{:});
catch
disp(lasterr);
end

end

% --------------------------------------------------------------------
function varargout = pushbutton1_Callback(h, eventdata, handles, varargin)

tic;

if ~(str2num(get(handles.edit5, 'String')) < 1 & str2num(get(handles.edit5, 'String')) > 0)


set(handles.edit5, 'String', '0.5');
elseif isempty(str2num(get(handles.edit5, 'String')))
set(handles.edit5, 'String', '0.5');
end

65
if str2num(get(handles.edit6, 'String')) < 0
set(handles.edit6, 'String', '100');
elseif isempty(str2num(get(handles.edit6, 'String')))
set(handles.edit6, 'String', '100');
end

if str2num(get(handles.edit7, 'String')) < 0


set(handles.edit7, 'String', '0.1');
elseif isempty(str2num(get(handles.edit7, 'String')))
set(handles.edit7, 'String', '0.1');
end

if ~(str2num(get(handles.edit9, 'String')) > 0 & str2num(get(handles.edit9, 'String')) < 1)


set(handles.edit9, 'String', '0.12');
elseif isempty(str2num(get(handles.edit9, 'String')))
set(handles.edit9, 'String', '0.12');
end

katalog = cd;

dataczas = datestr(now,0);
pomoc = (abs(dataczas) == 32) + (abs(dataczas) == 58);
dataczas(find(pomoc == 1)) = '_';

katalog_nowy = ['wyniki_' dataczas];


mkdir(katalog,katalog_nowy);
katalog_nowy = [katalog '\' katalog_nowy];
cd(katalog_nowy);

if get(handles.checkbox2,'Value')==1
znacznik = 1;
pomoc=get(handles.listbox1,'String');
load('Zmienne_siec.mat',pomoc{get(handles.listbox1,'Value'),1});
eval(['nauka = ' pomoc{get(handles.listbox1,'Value'),1} ';']);
[nauka_dane, nauka_tsz] = tszidaty(nauka);

pomoc=get(handles.listbox3,'String');
load('Zmienne.mat',pomoc{get(handles.listbox3,'Value'),1});
eval(['testy = ' pomoc{get(handles.listbox3,'Value'),1} ';']);
[testy_dane, testy_tsz] = tszidaty(testy);

else
znacznik = 0;
pomoc=get(handles.listbox3,'String');
load('Zmienne.mat',pomoc{get(handles.listbox3,'Value'),1});
eval(['nauka = ' pomoc{get(handles.listbox1,'Value'),1} ';']);
[nauka_dane, nauka_tsz] = tszidaty(nauka);

testy=nauka;
testy_dane=nauka_dane;
testy_tsz=[nauka_tsz; nauka_tsz(size(nauka_tsz,1)-1,1)+14 nauka_tsz(size(nauka_tsz,1),2) 1];
end

[nauka_wejscie, nauka_wyjscie, nauka_daty] = inoutsiec1(nauka_tsz(:,3)', nauka_tsz(:,1)', 1);


[testy_wejscie, testy_wyjscie, testy_daty] = inoutsiec1(testy_tsz(:,3)', testy_tsz(:,1)', 1);

testy_wejscie = testy_wejscie(:,(size(nauka_wejscie,2)+1):size(testy_wejscie,2));
testy_wyjscie = testy_wyjscie(:,(size(nauka_wyjscie,2)+1):size(testy_wyjscie,2));
testy_daty = testy_daty(:,(size(nauka_daty,2)+1):size(testy_daty,2));

66
nauka_wejscie = cell2num1(nauka_wejscie);
nauka_wyjscie = cell2num1(nauka_wyjscie);
testy_wejscie = cell2num1(testy_wejscie);
testy_wyjscie = cell2num1(testy_wyjscie);

nauka_daty = nauka_daty';
nauka_inout = [nauka_wejscie' nauka_wyjscie'];

testy_daty = testy_daty';
testy_inout = [testy_wejscie' testy_wyjscie'];

wspl_odchylenia = str2num(get(handles.edit9, 'String'));

check_inout = (rand(size(nauka_inout)) - 0.5) * 2;


odchylenia = std(nauka_inout,1) * wspl_odchylenia;
for i11 = 1:size(odchylenia, 2)
check_inout(:, i11) = check_inout(:, i11) * odchylenia(1, i11);
end
check_inout = nauka_inout + check_inout;

wplyw = str2num(get(handles.edit5, 'String'));


ilosc_epok = str2num(get(handles.edit6, 'String'));
krok_start = str2num(get(handles.edit7, 'String'));

metoda_id = get(handles.checkbox4, 'Value');


if metoda_id
metoda = get(handles.text20, 'String');
else
metoda = get(handles.text21, 'String');
end

blad_full = [];

system = genfis2(nauka_inout(:,1:6), nauka_inout(:,7), wplyw, [], [1.25 0.5 0.15 1]);

[system1, blad1, krok, system2, blad2] = anfis(nauka_inout, system, [ilosc_epok 0 krok_start 0.9
1.1], [1 1 1 1], check_inout, metoda_id)

blad_full = [blad1 blad2];


suma_epok = ilosc_epok;

wspl = polyfit([1:size(blad2,1)]',blad2,1);

set(handles.text17, 'String', suma_epok);


set(handles.text10, 'String', datestr( toc/60/60/24, 13));

while wspl(1,1) < 0


[system1, blad1, krok, system2, blad2] = anfis(nauka_inout, system1, [ilosc_epok 0
krok(size(krok,1),1) 0.9 1.1], [1 1 1 1], check_inout, metoda_id)
suma_epok = suma_epok + ilosc_epok;
wspl = polyfit([1:size(blad2,1)]',blad2,1);
set(handles.text17, 'String', suma_epok);
set(handles.text10, 'String', datestr( toc/60/60/24, 13));
blad_full = [blad_full; blad1 blad2];
end

testy_wynik=evalfis(testy_inout(:,1:size(testy_inout,2)-1),system2);

67
testy_wynik=[testy_inout(:,1:size(testy_inout,2)-1) testy_wynik];

testy_blad = abs(testy_inout(:, size(testy_inout, 2)) - testy_wynik(:, size(testy_wynik, 2)));


sredni_blad_prognozy = sum(testy_blad) / size(testy_daty, 1);
trend = sign(testy_inout(:, size(testy_inout, 2))) == sign(testy_wynik(:, size(testy_wynik, 2)));
trend_skutecznosc = sum(trend) / size(trend, 1);

czas = toc;
czas = datestr( czas/60/60/24, 13);
set(handles.text10, 'String', czas);

save('smrn_zmienne','blad_full','check_inout','czas','krok','metoda','nauka_daty','nauka_inout',...
'sredni_blad_prognozy','suma_epok','system','system1','system2',...
'testy_blad','testy_daty','testy_inout','testy_wynik','trend','trend_skutecznosc',...
'wplyw','wspl_odchylenia','znacznik');

% --------------------------------------------------------------------
function varargout = pushbutton2_Callback(h, eventdata, handles, varargin)
clc;
close(handles.figure1)

% --------------------------------------------------------------------
function varargout = checkbox2_Callback(h, eventdata, handles, varargin)
set(handles.checkbox3,'Value',~get(handles.checkbox2,'Value'));

% --------------------------------------------------------------------
function varargout = checkbox3_Callback(h, eventdata, handles, varargin)
set(handles.checkbox2,'Value',~get(handles.checkbox3,'Value'));

% --------------------------------------------------------------------
function varargout = checkbox4_Callback(h, eventdata, handles, varargin)
set(handles.checkbox5,'Value',~get(handles.checkbox4,'Value'));

% --------------------------------------------------------------------
function varargout = checkbox5_Callback(h, eventdata, handles, varargin)
set(handles.checkbox4,'Value',~get(handles.checkbox5,'Value'));

% --------------------------------------------------------------------
function varargout = listbox1_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = listbox3_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = edit5_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = edit6_Callback(h, eventdata, handles, varargin)

68
5. Wyniki testów sieci rozmyto neuronowych (rozdział 2.3)

• Wyniki z dnia 2002/05/19


Podstawowe informacje o systemie:
Data utworzenia systemu 2002/04/28
Metoda optymalizacji parametrów
Metoda hybrydowa
funkcji przynależności
Czas nauki 00:12:12
Ilość epok nauki 2400
Błąd końcowy
system1 3.07803
system2 3.39585
Współczynnik wpływu 0.5
Współczynnik odchylenia 0.2
Liczba reguł 8

Wyniki testów systemu rozmyto neuronowego:


Data Zmiana WIG20 Prognoza WIG20 Błąd Trend
2001/12/30 10.3979 -3.7119 14.1098 0
2002/01/06 5.24096 -5.3241 10.565 0
2002/01/13 1.00327 -4.2572 5.2605 0
2002/01/20 3.36113 -1.3155 4.6766 0
2002/01/27 -2.4848 -3.0637 0.578888 1
2002/02/03 -4.05402 -2.5139 1.54015 1
2002/02/10 0.136512 -1.3525 1.48899 0
2002/02/17 -2.79068 1.0263 3.81698 0
2002/02/24 4.24319 7.2924 3.04917 1
2002/03/03 1.26978 -2.0485 3.31828 0
2002/03/10 -2.88067 -1.5431 1.33755 1
2002/03/17 -0.740248 -0.46301 0.277239 1
2002/03/24 -1.32204 -2.4668 1.14471 1
2002/03/31 -0.120234 0.015513 0.135747 0
2002/04/07 -0.121127 -1.4415 1.32036 1
2002/04/14 -1.68062 -0.80403 0.876582 1
2002/04/21 1.21063 -2.2757 3.48634 0
2002/04/28 -1.7897 -1.2488 0.540926 1
Średni błąd prognozy 3.1958 50 %

69
Wykres 1. Wyniki na dzień 2002/04/28 (test z dnia 2002/05/19)

Wykres 2. Wyniki na dzień 2002/04/28 (test z dnia 2002/05/19)

70
• Wyniki z dnia 2002/05/19
Podstawowe informacje o systemie:
Data utworzenia systemu 2002/04/29
Metoda optymalizacji parametrów funkcji
Metoda hybrydowa
przynależności
Czas nauki 00:11:52
Ilość epok nauki 200
Błąd końcowy
system1 1.58227
system2 2.50282
Współczynnik wpływu 0.4
Współczynnik odchylenia 0.111111
Liczba reguł 20

Wyniki testów systemu rozmyto neuronowego:


Data Zmiana WIG20 Prognoza WIG20 Błąd Trend
2001/12/30 10.3979 -1.66022 12.0581 0
2002/01/06 5.24096 -2.55736 7.79832 0
2002/01/13 1.00327 -7.88265 8.88592 0
2002/01/20 3.36113 -6.66299 10.0241 0
2002/01/27 -2.4848 -15.6022 13.1174 1
2002/02/03 -4.05402 -3.47941 0.574602 1
2002/02/10 0.136512 0.583184 0.446672 1
2002/02/17 -2.79068 -1.77309 1.01759 1
2002/02/24 4.24319 2.13776 2.10543 1
2002/03/03 1.26978 2.69784 1.42806 1
2002/03/10 -2.88067 -0.511212 2.36945 1
2002/03/17 -0.740248 2.40018 3.14043 0
2002/03/24 -1.32204 1.89447 3.21651 0
2002/03/31 -0.120234 2.96717 3.08741 0
2002/04/07 -0.121127 13.2842 13.4053 0
2002/04/14 -1.68062 -0.776552 0.904064 1
2002/04/21 1.21063 14.6163 13.4057 1
2002/04/28 -1.7897 7.82528 9.61499 0
Średni błąd prognozy 5.9222 50 %

71
Wykres 1. Wyniki na dzień 2002/04/28 (test z dnia 2002/05/19)

Wykres 2. Wyniki na dzień 2002/04/28 (test z dnia 2002/05/19)

72
• Wyniki z dnia 2002/05/19
Podstawowe informacje o systemie:
Data utworzenia systemu 2002/04/29
Metoda optymalizacji parametrów
Metoda hybrydowa
funkcji przynależności
Czas nauki 17:00:02
Ilość epok nauki 2000
Błąd końcowy
system1 4.02306e-005
system2 7.03386
Współczynnik wpływu 0.33
Współczynnik odchylenia 0.111111
Liczba reguł 53

Wyniki testów systemu rozmyto neuronowego:


Data Zmiana WIG20 Prognoza WIG20 Błąd Trend
2001/12/30 10.3979 -2.925014 13.32292 0
2002/01/06 5.24096 -91.29129 96.53225 0
2002/01/13 1.00327 -123.2706 124.2739 0
2002/01/20 3.36113 -95.5228 98.88393 0
2002/01/27 -2.4848 -140.1937 137.7089 1
2002/02/03 -4.05402 -86.92697 82.87295 1
2002/02/10 0.136512 -6.923875 7.060387 0
2002/02/17 -2.79068 6.732115 9.522792 0
2002/02/24 4.24319 5.996921 1.753728 1
2002/03/03 1.26978 -22.10175 23.37153 0
2002/03/10 -2.88067 -20.19572 17.31505 1
2002/03/17 -0.740248 -5.012896 4.272648 1
2002/03/24 -1.32204 -10.27355 8.951511 1
2002/03/31 -0.120234 -9.799844 9.679609 1
2002/04/07 -0.121127 -30.4254 30.30427 1
2002/04/14 -1.68062 5.943523 7.624138 0
2002/04/21 1.21063 -15.96364 17.17427 0
2002/04/28 -1.7897 -3.360914 1.57121 1
Średni błąd prognozy 38.4553 50 %

73
Wykres 1. Wyniki na dzień 2002/04/28 (test z dnia 2002/05/19)

Wykres 2. Wyniki na dzień 2002/04/28 (test z dnia 2002/05/19)

74

You might also like