확률 분포를 특성화하는 매개변수는 평균과 분산뿐 아니라

15883 단어 C++통계학

평균과 분산만으로 확률 분포를 특성화할 수 없는 이유



생각해 보면 당연합니다만, 평균 $\mu$ 와 분산 $\sigma^2$ 라고 하는 둘만으로는 일반적으로 파라미터가 부족합니다. 가우스 분포의 경우는 파라미터가 2개이므로 $\mu$와 $\sigma^2$로 완전하게 특징짓을 수 있습니다만, 테일러 전개를 생각하면 일반적으로는 무한개의 파라미터가 필요하고, 분명히 부족 입니다.

관측 가능한 양으로부터 확률 분포를 어떻게 특징 지을 수 있습니까?



확률 밀도 함수가 2차까지의 급수 전개로 표현할 수 있는 것을 알고 있다고 합니다.
$$
f(x) = a_0 + a_1x + a_2x^2
$$
여기에서는 논의를 간단하게 하기 위해, $-\beta$$
\int_{-\beta}^{+\beta}f(x)dx = 2\beta a_0+\frac{2}{3}\beta^3 a_2 = 1
$$
또한 평균값(=1차 모멘트)도 알고 있는 것으로 합니다.
$$
\int_{-\beta}^{+\beta}xf(x)dx =\frac{2}{3}\beta^3a_1 =\mu_1'
$$
이제 $a_1$를 결정할 수 있었습니다. 또한
$$
\int_{-\beta}^{+\beta}x^2f(x)dx =\frac{2}{3}\beta^3a_0+\frac{2}{5}\beta^5a_2 =\mu_2'
$$
알고 있는 것으로 합니다(2차 모멘트). 이것들을 연립해 풀면 $a_0,a_2$도 결정할 수 있는 것을 알 수 있습니다. 앞으로 표본을 바탕으로 $N$차 모멘트까지 알면 확률밀도함수의 $N$차 테일러 근사가 구해질 것 같습니다.

수치 실험



분포 함수로서 다음과 같은 분포 함수를 생각합니다.
$$
f(x) =\alpha(x+\beta)(x-\beta)
$$
분포 함수의 범위는 $[-\beta,+\beta]$입니다. 규격화 조건에서
$$
\int_{-\beta}^\beta f(x) dx = -\frac{4}{3}\alpha\beta^3 = 1
$$
이어야하기 때문에,
$$
\alpha=-\frac{3}{4\beta^3}
$$
됩니다. 수치 실험을 위해서는 이러한 분포 함수에 따른 난수가 필요하므로 기각법이라는 방법으로 생성합니다. 균일 난수를 발생시켜 분포 함수의 안쪽에 넣으면 채용, 그렇지 않으면 기각한다는 간단한 알고리즘입니다. 여기서는 상세한 내용을 생략합니다.
#include <iostream>
#include <random>

int main()
{
        double beta = 1;
        double alpha = -3./4./beta/beta/beta;

        auto f = [&](double x)
        {
                return alpha * (x+beta) * (x-beta);
        };
        auto in_f = [&](double x, double y)
        {
                if(y<=f(x)) return true;
                else return false;
        };
        double ymax = f(0);
        std::mt19937 mt(0);
        std::uniform_real_distribution<double> r(0,1);
        int num_of_sample = 1000000;

        std::vector<double> data;

        for(int n=0; n<num_of_sample; n++)
        {
                double x,y;
                do
                {
                        double xr = r(mt);
                        double yr = r(mt);
                        x = -beta+2*beta*xr;
                        y = ymax*yr;
                }while(!in_f(x,y));
                data.push_back(x);
        }
        for(int n=0; n<num_of_sample; n++) std::cout << data[n] << std::endl;

        return 0;
}

$10^6$개의 데이터를 생성했습니다. 원하는 난수를 얻었는지 확인하기 위해 히스토그램을 만들어 보겠습니다.
./a.out | gsl-histogram -1 1 100 > hist.txt

gsl-histogram 명령은 유명한 과학 계산 라이브러리를 설치하면 따라오는 데모 프로그램이지만 편리합니다.

분명히 원하는 데이터를 얻는 것 같습니다.

자, 이제 생성된 표본에서 원래 분포 함수를 추정해 보겠습니다.
#include <random>
#include <iostream>
#include <vector>

int main()
{
        std::vector<double> data;
        double tmp;
        while(std::cin >> tmp)
        {
                data.push_back(tmp);
        }
        int num_of_sample = data.size();

        double m1 = 0, m2 = 0;
        for(int n=0; n<num_of_sample; n++)
        {
                m1 += data[n] / (double)num_of_sample;
                m2 += data[n]*data[n] / (double)num_of_sample;
        }

        double beta = 1;
        double a[3];
        a[1] = m1*3./2./beta/beta/beta;
        a[2] = (beta*beta/3.-m2)/beta/beta/beta/beta/beta/(2./9.-2./5.);
        a[0] = (1.-2./3.*beta*beta*beta*a[2])/beta/2.;

        for(double x=-beta;x<=beta;x+=0.001)
        {
                std::cout << x << " " << a[0]+a[1]*x+a[2]*x*x << " " << -3./4./beta/beta/beta*(x+beta)*(x-beta) << std::endl;
        }
        return 0;
}

추정한 분포 함수와 진정한 분포 함수를 플로팅해 봅니다.

잘 작동했습니다 (거의 겹쳐서 구별이 없습니다). 덧붙여서 표본 사이즈를 $10^3$까지 줄인 경우는 다음과 같이 되었습니다.

약간 벗어났습니다. 이것은 모집단 모멘트의 추정 오차로 인한 것으로 간주됩니다.

요약



표본에서 도수 분포를 사용하지 않고 분포 함수를 추정할 수 있었습니다(실용성은 없다?). 모멘트를 주는 것으로 확률 분포의 특징화를 할 수 있을 것 같습니다. 확률 분포를 지정하기 위해서는 보통 함수형과 몇개의 파라미터를 주지만, 구체적인 함수형을 주지 않고 대신 모멘트를 주는 것으로 분포 함수를 지정할 수 있을 것 같습니다.
(2910/11/2 추기) 분명히 이 방법은 모멘트법이라고 하는 방법인 것 같습니다.

좋은 웹페이지 즐겨찾기