SangQ

MATLAB을 이용한 표준정규분포(가우스분포)에 따른 랜덤수 발생기 본문

과제

MATLAB을 이용한 표준정규분포(가우스분포)에 따른 랜덤수 발생기

SangQ 2010. 1. 26. 15:44
1.MATLAB에 randn() 함수가 있는데 왜 이런것을 했느냐??

-과제 ^^ (과제지만 소스 짜는 동안 재밌었다 ㅋㅋ)


2. 정규분포란 ??

고등학교때 배웠다고 하는데 전 전혀 기억이 없네요 ㅋㅋ
네이버에서 살짝 퍼옴!! 

                                                       곡선의 함수
 


 도수분포곡선이 평균값을 중앙으로 하여 좌우대칭인 종 모양을 이루는 것으로 키나 IQ의 분포 등 그 예는 많다. K.F.가우스가 측정오차의 분포에서 그 중요성을 강조하였기 때문에 이것을 가우스분포*오차분포라고도 하며, 그 곡선을 가우스 곡선 또는 오차곡선이라 한다. 또한 A.J.케틀레가 통계에 이용하였으므로 이것을 케틀레곡선이라고도 한다.

이 함수는 오늘날에 통계학에 많이 쓰이며 6시그마(6σ)라는 경영프로세스를 만들기도 하였다.

21세기형 경영기법으로 불리는 '6시그마'의 목표는 제품이나 서비스 중 불량품이나 에러 발생률을 1백만 개당 3.4개로 줄이는 것이다. 이 같은 불량률을 통계적으로 볼 때 99.99966%가 합격품이라는 의미이다.

ps. 통계학의 중심극한정리에서 나온것 같던데 유심히 보질 않았다. ㅎㅎ;;


3. 표준정규분포란 ??

정규분포에서 m = 0 ,  σ = 1 인 함수가 표준정규분포 함수이다.



그러니까 그래프에서 m 이 중심값이고, σ 가 오차 범위라고 보면된다.



4. 설계

rand() 함수를 이용하여 랜덤값을 발생시켜 if문으로 범위를 쪼개고 while문으로 난수값을 찾음.

이분법으로 난수를 발생시키는 것을 생각해봤으나 생각보다 까다로운 부분이 있었다.
시간만 좀 더 있었으면 해결했을꺼 같아  아쉽다.




function y = f(x)
y = exp(-x.^2/2)/sqrt(2*pi);
end
▲ 표준정규분포 난수 발생기의 기본이 되는 함수



function y = ra(x,i)
% x 는 0 ~ 1 값
% i 는 적분의 시작값
a = 0;
    while( a < x )   % a가 x보다 커질 때 까지 아래 명령문 반복
        i = i + 0.1;
        a = quad('f', -5 , i );  % -5에서 조건을 만족할 때 까지 적분
    end
.
.
.
.
.
.
end
▲ 적분함수 quad 와 반복문을 통해 난수를 추출하는 함수



function y = gvr_04(x)
ran = rand(1); % 0~1까지 랜덤한 값을 추출 적분값과 비교하면서 난수 값을 찾아냄

 while ( ran ==0 || rand ==1)
     ran = rand(1);
 end

min_point = 0; % ran에서 제일 작은 값
plus = 0.1; % 0.1 씩 더해가면서 구간을 나눔

if ( min_point < ran ) && ( min_point + plus > ran) % ran 값이 0이상 0.1미만 일때
    rr = ra( ran,-5); % 난수를 -5부터 -1.2814 까지 에 있는 난수를 찾아낸다 
elseif ( min_point + plus <= ran ) && ( min_point + plus * 2 > ran) % ran 값이 0.1이상 0.2미만일때
    rr = ra( ran,-1.28155024); %-1.2815 ~ -0.8415 까지 에 있는 난수를 찾아낸다.
.
.
.
.
.
.
.
.
.
.
.
.
end
▲ if문으로 적분값을 0.1씩 나눔 (최종 메인 함수)
-1.28155024 라는 수는 -5부터 더해가면서 적분값이 0.1이 되는 순간의 x축값이다.
이 수는 직접내가 돌려본 것으로 꼼수라고 보면된다. ㅋㅋ;;


function y = repeat(N,n)

x_origin = linspace(-5,5,100);
y_origin = f(x_origin);

for i=1:N      % for 문 사용하여 1부터 N 까지 반복
    y(i)=gvr_04;  
end


rr=randn(1,N);



figure(1) % 원래 그래프와 임의로 생성한 값을 넣은 그래프 비교
plot(x_origin,y_origin)
grid on
axis([-5,5,0,0.4])
title('Original Graph')

figure(2) % 랜덤하게 나오는 값들 , 1에 가깝운 값들이 많이 나온다.
subplot(1,2,1),plot(rr,'xr')
axis([0,N,-6,6])
grid on
title('Randn Graph')
subplot(1,2,2),plot(y,'xr')
axis([0,N,-6,6])
grid on
title('Simulation Graph')

figure(3) % 램덤값의 분포도
subplot(1,2,1),hist(rr,n)
hold on
plot(x_origin,y_origin*N/3,'r')
axis([-5,5,0,N/6])
grid on
title('Randn Graph')
hold off
subplot(1,2,2),hist(y,n)
axis([-5,5,0,N/6])
hold on
plot(x_origin,y_origin*N/3,'r')
grid on
title('Simulation Graph')
hold off
▲ 마지막으로 그래프로 비교해보는 소스


5. 결과


▲난수들이 0 에 가까이 발생 했는가?? 를 보여주는 그래프 
사실 이 그래프는 필요 없었다. 이것 왜 그려봤는지 모르겠다 =0=;;






▲난수 발생 수에 따른 randn()의 분포도와 내가 만든 난수 발생기의 분포도를 비교해보았다.
중간에 빨간 그래프가 표준정규분포에 따른 그래프이다.
보면 알겠지만 내가 만든 소스가 좀 더 표준정규분포 그래프와 비슷하다는 것을 알수있다.

내가 잘한건지 randn()함수가 원래 그런건지?? ㅎㅎ 

그런데 난수값을 발생하는 속도는 하늘과 땅 차이였다.
randn()함수는 10000 개 발생 시키는데 1초도 안걸리던데
내가 만든 함수는 10000개 만드는데 2분이나 걸리더라 ㅠ.ㅠ 





6. 마치면서 ...

편법을 사용하긴 했지만 
if 문을 사용하여 적분값을 0.1로 구간을 나눈것만으로 
다른 조와 1/4정도의 시간을 단축하여 함수를 발생시켰서 왠지 뿌듯하다. 
다른 조들이 발표 할 때는  길어봐야 10분~20분정도 했었는데, 우리조는 한시간 다 쓴거 같다.
(아!!참!! 영우행님이 만든 소스도 1시간정도 발표 했었었지ㅋㅋ;;)
교수님의 지적이 많으셨으나 마지막에는 잘 했다고 칭찬 해주셨다. 
기존의 소스와 적분값을 퓨전 시켜 뭔가 다른 소스를 만들었다고 ㅋㅋ 
솔직히 이분법을 사용해서 만들고 싶었으나 시간이 모자라서 못 만들었다.
(이분법으로 만들어봤었는데 쉽지 안터이다 ㅎㅎ;;)  
조원들 중에 왜 나혼자만 소스를 짰었어야 했는가??-_-;;
(그래도 pt는 만들어줬으니 다행으로 생각한다.)


교수님께서 마지막 시간에 즉석에서 이분법을 통하여 좀 더 빠른 난수 발생기를 만드시는걸 보고 깜짝 놀랐다 +_+ 1시간만에 다 만들지는 못하셨지만 1시간만 더 있었으면 다 많드셨을듯...ㅋㅋ;;
역시 대단하신 교수님 !!