MKZR:Dodatek

Z Skrypty dla studentów Ekonofizyki UPGOW

Spis treści

Wektoryzacja obliczeń w środowsku matlab/GNU Octave

Matlab/GNU Octave są językami interpretowanymi. W znacznym stopniu ułatwia to przejście do sedna rozwiązywanego problemu z pominięciem wielu informatycznych aspektów programowania. Jednak ceną za taki komfort jest często wydajność pisanych programów. W przypadku ogólnym bezpośrednie przepisanie kodu w języku typu Fortran czy C/C++ na matlab może spowolnić jego działanie kilkaset razy. Stosując jednak języki interpretowane świadomie i wykorzystując ich możliwości w wielu przypadkach można uniknąć spowolnienia i otrzymać bardzo wydajny program.

Podstawowym elementem języka wykorzystywanym w jest pętla "for". Rozważmy następujący program:


N=1000;
x(1)=1;
for i=2:N
   x(i)=x(i-1)*0.1;
endfor

Histogramy

Ważną umiejętnością jest estymacja funkcji gęstości z pewnej (dużej) liczby danych. Proces taki jest nazywany histogramowaniem.

Histogram jest to sposób przedstawienia częstości występowania pewnej cechy w postaci wykresu słupkowego. Weźmy na przykład ciągłą zmienną losową. Podzielmy przestrzeń wartości przyjmowanych przez tą zmienna na N równych przedziałów. Przypuścmy, że dysponumemy M realizacjami zmiennej losowej. Na histogramie można umieścić liczbę realizacji, które należa do danego przedziału. Co więcej taki wykres bedzie w granicy \(N,M\to \infty\) taki sam jak wykres gęstości prawdopodobieństwa nasze zmiennej losowej. By otrzymać dokładnie gęstość prawdopodobieństwa trzeba przeskalować liczbę zliczeń do gęstości. Niech \(n_i, i=1..N\) będą zliczeniami w kolejnych przedziałach. Gęstość prawdopodobieństwa jest unormowana do jedności (bierzemy zmienną losową przyjmującą wartości między a i b):

\(1=\int_a^b f(x) dx=\sum_{i=1}^N f(x_i) h\)

gdzie h jest szerokością jednego przedziału \(h=(x_i-x_{i-1})/(N-1)\). Wynika z tego, że

\(\sum_{i=1}^N f(x_i) =1/h\),

podczas gdy liczby zliczeń są unormowane do pewnej wartości \(\sum_{i=1}^N n_i \).

Widać z tego, że formuła łącząca liczby zliczeń z wartościami gęstości wewnątrz odcinków wyraża się:

\(f_i=f(x_i)=\frac{1}{h}\frac{n_i}{\sum_{i=1}^N n_i} \).

W systemie GNU Octave wbudowana funkcja hist umożliwia podanie drugiego argumentu, który jest czynnikiem normalizacyjnym sumy wszystkich zliczeń i w rozważanym przypadku powinien od wynosić 1/h.

Histogramy 1D

Jako przykład wykonajmy histogram 10000 liczb o rozkładzie normalnym i porównajmy go ze wzrorem analitycznym na funkcję Gaussa. Najprostszy skrypt w GNU Octave realizujący to zadanie to:

xmax=5;
h=0.1;
mydata=normrnd (0,1,10000,1);
hist(mydata,[-xmax:h:xmax],1/h);

Zauważmy, że:

Nie została zadana liczba przedziałow, ale szerokość. Liczba przedziałow w tym przypadku to:

octave:38> length( [xmin:h:xmax] )
ans =  101

Pomimo, ze zmienna losowa przyjmuje wartości na całej osi rzeczywistej, to histogram wykonaliśmy na skończonym przedziale. Wybranie wartości x a przedziału -5..5 jest w przypadku rozkładu Gaussa dobrym wyborem. Zauważmy jest stosunek funkcji gęstości w punktach 0 i 5 wynosi

octave:42> normpdf(0,0,1)/normpdf(5,0,1)
ans =  2.6834e+05

więc dla 10000 punktów możemy się spodziewać, że zaden z nim nie wyjdzie poza przedział -5...5.

Proszę sprawdzić jak będzie wyglądał histogram jeśli weżmiemy xmin=-1 i xmax=1

Funkcja hist została wywołana bez argumentów zwrotnych i zgodnie z dokumentacja narysowała ona wykres. Można postąpić inaczej:

xmax=5;
h=0.1;
mydata=normrnd (0,1,10000,1);
[NN,XX]=hist(mydata,[-xmax:h:xmax],1/h);

Podając argumenty zwrotne funkcja hist zamiast rysować wykres, zwraca wektor liczb zliczeń i wartość zmiennej w przedziałach. Można to wykorzystać:

plot(XX,NN,"-",XX,normpdf(XX,0,1),"r-")
bar(XX,NN)
Jak działa funkcja hist?

Poniższy kod ilustruje prostą implementacje funkcji histogramującej w GNU/Octave. Nie jest ona efektywna, gdyż wykorzystuje pętlę po wszystkich danych wejściowych (kod nie jest wektorowy).

xmax=5;
xmin=-5;
h=.1;
XX=[xmin:h:xmax];
mydata=normrnd (0,1,10000,1);
NN=zeros(1,101);
for i=1:length(mydata)
	idx=  ceil ( (mydata(i)-xmin)/(xmax-xmin) * length(NN)  ) ;
	if idx>0 && idx<=length(NN)
 		NN(idx)++;
	endif
endfor
plot(XX,NN)

Histogramy 2D

Estymacja gęstości dla dwów nielależnych zmiennych losowych Gaussowskich za pomocą funkcji hist2d.

Podobnie jak w przypadku jednej zmiennej losowej, histogram można utworzyć dla wielu zmiennych losowych. Do celów wizualizacyjnych nadaje się jednak tylko przypadek dwuwymiarowy. W sysemie GNU/Octave nie ma bezpośrednio wbudowanej funkcji histogramującej dwie zmienne losowe, ale jest pakiet rozszerzający plot (dostępny z [1]). Po zciągnieciu pliku instalujemy go za pomocą

pkg install 'plot-1.0.8.tar.gz'


Z jego pomoca narysujemy histogram dwoch niezależnych gausowskich zmienych losowych:


hist2d(normrnd(0,1,250000,2),60);

Podobnie jak w przypadku funkcji hist można dane zapisać do tablic by np. użyć innej procedury rysującej:

[nn,x,y]=hist2d(normrnd(0,1,134100,2),60);
imagesc(nn)


Estymacja gęstości dla dwów nielależnych zmiennych losowych Gaussowskich za pomocą funkcji hist2d, dane przedstawione za pomocą imagesc.


Wektoryzacja obliczeń w środowsku matlab/GNU Octave

Matlab/GNU Octave są językami interpretowanymi. W znacznym stopniu ułatwia to przejście do sedna rozwiązywanego problemu z pominięciem wielu informatycznych aspektów programowania. Jednak ceną za taki komfort jest często wydajność pisanych programów. W przypadku ogólnym bezpośrednie przepisanie kodu w języku typu Fortran czy C/C++ na matlab może spowolnić jego działanie kilkaset razy. Stosując jednak języki interpretowane świadomie i wykorzystując ich możliwości w wielu przypadkach można uniknąć spowolnienia i otrzymać bardzo wydajny program.

Podstawowym elementem języka wykorzystywanym w jest pętla "for". Rozważmy następujący program:


N=1000;
x(1)=1;
for i=2:N
   x(i)=x(i-1)*0.1;
endfor