25 Şubat 2014 Salı

Delphi XE5 - Ortalaması ve Standart Sapması Bilinen Normal Dağılımdan Veri Üretme

     Veri üretme yazılarına başlamışken birazda istatistikten veri üretme türlerine ve de olasılık hesaplamalarına giriş yapayım dedim. Bu yazıda sadece normal dağılım göstereceğim. Blogun ilk zamanların ters dönüşüm fonksiyonları ile veri üretme dökümanı paylaşmıştım. Orada diğer dağılımlardan veri üretme algoritmalarını bulup veri üretebilirsiniz.



   Gel gelelim ortalaması ve standart sapması bilinen normal dağılımdan veri üretmeye. Bunu yapmak için yine bilgisayarın bir fonksiyonu olan random dan yararlanacağız. Random bize 0 ile 1 arasında rasgele uniform dağılan bir veri verecek bizde bu veriyi kullanarak normal dağılım verisine dönüştüreceğiz.

  Öncelikle normal dağılımın fonksiyonuna bakalım.

                     e8cf730ec1a7587ee84403dbc1c64008

 Çok karmaşık görünmesine karşın çok basit bir şekilde buradan veri üreteceğiz. Algoritmamıza bir bakalım. Bu algoritmanın ismi Marsaglia-Bray algoritması olarak literatürde geçmektedir.

Standard Normal According to Marsaglia-Bray
generate V = random number
if V < 0.8638 then
generate Vt.V2,VJ = random numbers
set Z = 2(VI + V2 + VJ ) - 3
else if V < 0.9745 then
generate V I,V2 = random numbers
set Z = 1.5(VI + V2 - 1)
else if V < 0.9973002039
repeat
generate V I = random number
set V = 6*VI - 3
generate V2 = random number
until 0.358*V2 :s; g(V) *
setZ=V
else
repeat
repeat
generate V t.V2 = random numbers
set VI = 2*VI - 1, V2 = 2*V2 until
W = V~ + Vi < 1
set A = sqrt((9-2*ln(W»/W)
setB = AVt. setC = AV2
until IBI > 3 or Ici > 3
if IBI > 3 then Z = B else Z = C
endif
return Z

  Marsaglia-Bray ve diğer veri üretme algoritmalarını Yandex Diskim'den indirebilirsiniz.

  Şimdi de algoritmayı fonksiyona dönüştürerek kodlayalım. İlk önce her zamanki gibi fonksiyon oluşturma kalıbımızı hatırlayalım.

funciton ....(...;...;...):....;
 begin
.
.
.
 Result := ....;
end;

 Şimdi fonksiyonumuza bir isim verelim RndGauss olsun ismi. Normal dağılımdan rastgele veri üretme. Parametrelerimize bakalım. Ortalaması ve standart sapması bilineceği için ortalama ve standart sapmayı biz gireceğiz.

parametreler

ortalama: double
standartsapma: double

ikiside tam sayı yada ondanlıklı olabileceği için double veri tipinde giriş yapacağız. Fonksiyonumuz hazır. Genel görünümüne bakalım.

function RndGauss(ortalama, standartsapma: Double): Double;

 Şimdi algoritmik kısmı kodlamaya başlayalım. Öncelikle iki tane rastgele üretilmiş veriye ihtiyacımız var. Bunları tanımlarsak

var
  rastgele1, rastgele2: Extended;

olarak tanımlayalım bunları. Algoritmamızda önce rastgele1 oluşturulacak ve oluşturulan bu veride rastgele1'in bir türevi olacak. Rastgele1 den rastgele2 yi üretmek için:

    rastgele1 := 2*Random - 1;
    rastgele2 := Sqr(rastgele1) + Sqr(2*Random-1);

 ürettiğimiz yeni verinin de birden küçük olmasını istiyoruz o halde bu kodu repeat until kod bloğunun içine yerleştirmem lazım.

  repeat
    rastgele1 := 2*Random - 1;
    rastgele2 := Sqr(rastgele1) + Sqr(2*Random-1);
  until rastgele2 < 1;

Artık kodlamamız hazır sayılır. Bu yeni rastgele2 verisini kullanarak ortalaması ve standart sapması bilinen veriye dönüştürebilirim.

  Result := Sqrt(-2*Ln(rastgele2)/rastgele2) * rastgele1 * standartsapma + ortalama;

Fonskiyonun en genel haline bakacak olursak.

 function RndGauss(ortalama, standartsapma: Double): Double;
var
  rastgele1, rastgele2: Extended;
begin
  repeat
    rastgele1 := 2*Random - 1;
    rastgele2 := Sqr(rastgele1) + Sqr(2*Random-1);
  until rastgele2 < 1;
  Result := Sqrt(-2*Ln(rastgele2)/rastgele2) * rastgele1 * standartsapma + ortalama;
end;

Şimdi bu fonksiyonu kullanalım. Bunun için şöyle bir örnek yapabilirsiniz. Ortalama standart sapma ve kaç tane veri üreteceğinizi girmek için bir edit oluşturun. Verileri memo yada istediğiniz bir yere aktarın. Sonrada gerçekten işe yarıyormu diye kontrol etmek için memodaki verilerin ortalamasını bulun ver başka bir edite yazdırın. Örneklem büyüklüğü ne kadar artarsa o kadar ortalamaya yaklaşıyor görüldüğü üzere.




 Memo 'ya verileri eklemeniz için kaynak kod:

ortalaması:= StrToFloat(edit1.Text);

standartsapması:=StrToFloat(edit3.Text);

 for I := 0 to StrToInt(edit2.Text)-1 do
 begin memo1.Lines.Insert(I,floattostr(rndgauss(ortalaması, standartsapması)));

 end;

Okuduğunuz İçin Teşekkür Ederim
Hakan UÇAR
İstatistikçi ve Amatör Programcı
İçerikler Tamamen Ücretsiz Olup Özgün Anlatımdır Paylaşırken Kaynak Belirtiniz Lütfen.

Bumerang - Yazarkafe



1 yorum:

  1. delphide slash dağılımdan array de veri üretip bunun media nını nasıl bulabilirz,yardımcı olabilirmisiniz?

    YanıtlaSil