통계적 중앙값, 모드, 왜도, 첨도를 추정하기위한 "온라인"(반복자) 알고리즘?


86

값 집합의 중앙값, 모드, 왜도 및 / 또는 첨도를 추정하는 알고리즘이 있지만 한 번에 모든 값을 메모리에 저장할 필요는 없습니까?

기본 통계를 계산하고 싶습니다.

  • 평균 : 산술 평균
  • 분산 : 평균에서 제곱 된 편차의 평균
  • 표준 편차 : 분산의 제곱근
  • 중앙값 : 숫자의 큰 절반과 작은 절반을 구분하는 값
  • 모드 : 세트에서 가장 자주 발견되는 값
  • 왜도 : tl; 박사
  • 첨도 : tl; 박사

이것들 중 하나를 계산하는 기본 공식은 초등학교 산술이며, 나는 그것들을 알고 있습니다. 이를 구현하는 많은 통계 라이브러리도 있습니다.

내 문제는 내가 처리하고있는 집합에있는 많은 수 (십억)의 값입니다. Python으로 작업하면 수십억 개의 요소로 목록이나 해시를 만들 수 없습니다. 내가 이것을 C로 썼더라도 10 억 요소 배열은 너무 실용적이지 않습니다.

데이터가 정렬되지 않습니다. 다른 프로세스에 의해 즉석에서 무작위로 생성됩니다. 각 세트의 크기는 매우 가변적이며 크기는 미리 알 수 없습니다.

나는 이미 평균과 분산을 꽤 잘 처리하는 방법을 알아 냈고, 어떤 순서로든 세트의 각 값을 반복합니다. (사실, 제 경우에는 생성 된 순서대로 가져옵니다.) 다음은 제가 사용하는 알고리즘입니다. http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm :

  • 세 가지 변수 초기화 : 개수, 합계 및 sum_of_squares
  • 각 값에 대해 :
    • 증가 카운트.
    • 합계에 값을 더합니다.
    • sum_of_squares에 값의 제곱을 더합니다.
  • 합계를 개수로 나누고 변수 평균으로 저장합니다.
  • sum_of_squares를 개수로 나누고 변수 mean_of_squares로 저장합니다.
  • 제곱 평균, square_of_mean으로 저장합니다.
  • mean_of_squares에서 square_of_mean을 빼서 분산으로 저장합니다.
  • 출력 평균 및 분산.

이 "온라인"알고리즘에는 약점이 있지만 (예 : sum_of_squares가 정수 범위 또는 부동 소수점 정밀도보다 빠르게 커짐에 따른 정확도 문제) 기본적으로 각 세트에 모든 값을 저장할 필요없이 필요한 것을 제공합니다.

하지만 추가 통계 (중앙값, 모드, 왜도, 첨도)를 추정하는 데 유사한 기법이 있는지 여부는 알 수 없습니다. N 값을 처리하는 데 필요한 메모리가 실질적으로 O (N)보다 작은 한 편향된 추정기 또는 정확도를 어느 정도 저하시키는 방법으로 살 수 있습니다.

라이브러리에 "온라인"작업 중 하나 이상을 계산하는 함수가있는 경우 기존 통계 라이브러리를 가리키는 것도 도움이됩니다.


데이터가 정렬되어 전달되며 입력 수를 미리 알 수 있습니까?
chillysapien 2009-06-29

StackOverflow의 유용한 기존 링크 : stackoverflow.com/questions/895929/…
dmckee --- ex-moderator kitten

정수 데이터입니까 아니면 부동 데이터입니까? 최대 또는 최소 값이 있습니까?
stephan 2009-06-29

dmckee : 저는 실제로 표준 편차에 대해 Welford의 방법을 사용하고 있습니다. 하지만 모드, 중앙값, 첨도 또는 왜도에 대한 링크가 보이지 않습니다.
Ryan B. Lynch

stephan : 일부 데이터 세트는 정수이고 다른 데이터 세트는 부동 소수점입니다. 모집단 분포는 정규 (가우시안)에 매우 가깝기 때문에 신뢰 구간을 설정할 수 있지만 하드 범위 경계는 없습니다 (일부 경우 x> 0 제외).
Ryan B. Lynch

답변:


53

왜도 및 첨도

왜도 및 첨도에 대한 온라인 알고리즘 (분산 선을 따라)에 대해서는 동일한 위키 페이지 에서 더 높은 순간 통계에 대한 병렬 알고리즘을 참조 하십시오 .

중앙값

정렬 된 데이터가 없으면 중앙값이 어렵습니다. 알고 있다면, 이론적으로는 선택 알고리즘 을 사용하여 부분적으로 만 정렬하면됩니다 . 그러나 그것은 수십억 개의 가치에 그다지 도움이되지 않습니다. 주파수 카운트를 사용하는 것이 좋습니다. 다음 섹션을 참조하십시오.

주파수 카운트가있는 중앙값 및 모드

정수인 경우 주파수를 계산 하여 더 이상 관련이 없다고 확신하는 일부 값을 넘어 가장 높은 값과 가장 낮은 값을 잘라냅니다. 실수 (또는 너무 많은 정수)의 경우 아마도 버킷 / 간격을 만든 다음 정수와 동일한 접근 방식을 사용합니다. (근사치) 모드 및 중앙값 계산은 빈도 표를 기반으로보다 쉬워집니다.

일반적으로 분포 된 랜덤 변수

정규 분포를 따르는 경우 모집단 표본 평균 , 분산 , 왜도첨도 를 작은 부분 집합에 대한 최대 가능성 추정기로 사용합니다. 그것들을 계산하는 (온라인) 알고리즘, 당신은 이미 지금. 예를 들어, 추정 오류가 충분히 작아 질 때까지 수십만 또는 백만 개의 데이터 포인트를 읽습니다. 세트에서 무작위로 선택해야합니다 (예 : 처음 100'000 개의 값을 선택하여 편향을 도입하지 않음). 동일한 접근 방식을 추정 모드에 사용할 수도 있고 정상 사례에 대한 중앙값을 사용할 수도 있습니다 (두 표본 평균은 모두 추정치입니다).

추가 의견

도움이된다면 위의 모든 알고리즘을 병렬로 실행할 수 있습니다 (많은 정렬 및 선택 알고리즘 (예 : QuickSort 및 QuickSelect) 포함).

나는 항상 (정규 분포에 대한 섹션을 제외하고) 우리가 알려진 분포가 주어진 이론적 모멘트에 대한 추정자가 아니라 샘플 모멘트, 중앙값 및 모드에 대해 이야기한다고 가정했습니다.

일반적으로 모든 관측치가 동일한 무작위 변수 (동일한 분포를 가짐)와 모멘트, 모드 및 중앙값은 실제로이 분포에 존재합니다. 마지막 경고는 무해하지 않습니다. 예를 들어, 코시 분포에 대한 평균 (및 모든 더 높은 모멘트)은 존재하지 않습니다. 이 경우 "작은"하위 집합의 표본 평균은 전체 표본의 표본 평균과 크게 다를 수 있습니다.


57

나는 다음과 같은 증분 / 재귀 평균 및 중앙 추정치를 사용하는데, 둘 다 상수 저장을 사용합니다.

mean += eta * (sample - mean)
median += eta * sgn(sample - median)

여기서 eta 는 작은 학습률 매개 변수 (예 : 0.001)이고 sgn ()은 {-1, 0, 1} 중 하나를 반환하는 signum 함수입니다. ( 데이터가 비정상이고 시간에 따른 변화를 추적 하려면 상수 eta를 사용하십시오 . 그렇지 않으면 고정 소스의 경우 평균 추정량에 eta = 1 / n 과 같은 것을 사용할 수 있습니다 . 여기서 n은 표시되는 샘플 수입니다. 지금까지 ... 안타깝게도 이것은 중앙값 추정치에서는 작동하지 않는 것 같습니다.)

이러한 유형의 증분 평균 추정기는 감독되지 않은 신경망 학습 규칙에서와 같이 모든 곳에서 사용되는 것처럼 보이지만, 중앙값 버전은 이점 (이상치에 대한 견고성)에도 불구하고 훨씬 덜 일반적으로 보입니다. 중앙값은 많은 응용 프로그램에서 평균 추정치를 대체 할 수있는 것으로 보입니다.

비슷한 형태의 증분 모드 추정기를보고 싶습니다.

최신 정보

임의의 분위수를 추정하기 위해 증분 중앙값 추정기를 수정했습니다. 일반적으로 Quantile 함수 ( http://en.wikipedia.org/wiki/Quantile_function )는 데이터를 p와 1-p의 두 분수로 나누는 값을 알려줍니다. 다음은이 값을 점진적으로 추정합니다.

quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)

값 p는 [0,1] 내에 있어야합니다. 이것은 본질적으로 sgn () 함수의 대칭 출력 {-1,0,1}을 한쪽으로 기울여 데이터 샘플을 크기가 다른 두 개의 빈으로 분할합니다 (데이터의 분수 p와 1-p는 다음보다 작거나 큼). 분위수 추정치). p = 0.5의 경우 이는 중앙 추정량으로 감소합니다.


3
이 중앙값 추정치는 훌륭합니다. 0.25 / 0.75 분위수에 대해 유사한 추정량이 있는지 알고 있습니까?
Gacek

1
@Gacek, 확실합니다. 입력 스트림을 Lohalf <median 및 Hihalf> median으로 분할하고 각 절반에 running-median을 사용합니다.
denis

2
@Gacek : 방금 모든 분위수를 추정하는 증분 방법으로 답변을 업데이트했습니다. 여기서 p를 0.25, 0.75 또는 [0,1] 내의 모든 값으로 설정할 수 있습니다 .
Tyler Streeter 2011 년

10
이것은 평균에 대해 훌륭하게 작동하지만 중앙값에 원격으로 가까운 것을 생성하는 방법을 보지 못했습니다. 예를 들어 일련의 밀리 초 타임 스탬프를 살펴 보겠습니다 . [1328083200000, 981014400000, -628444800000, 318240000000, 949392000000]중앙값이 318240000000. 이 방정식은 이전 중앙값을 eta권장 값이였던 +/-만큼 이동합니다 0.001. 이것은 이와 같은 큰 숫자에 대해서는 아무것도하지 않을 것이고, 정말 작은 숫자에는 너무 클 수도 있습니다. eta선험적으로 답을 모르고 실제로 정답을 준 것을 어떻게 고르 겠습니까?
mckamey

9
숫자에 단위 (예 : 밀리미터)가 있다고 상상해보십시오. 그렇다면 명확한 eta (중앙값 추정치)는 측정 값과 동일한 단위를 가져야하므로 0.001과 같은 일반 값은 의미가 없습니다. 더 나은 접근 방식은 절대 편차의 실행 추정치에서 eta를 설정하는 것입니다. 각각의 새 값 sample에 대해 update cumadev += abs(sample-median). 그런 다음을 설정합니다 eta = 1.5*cumadev/(k*k). 여기서는 k지금까지 본 샘플 수입니다.
tholy

12

나는 LiveStats 라는 깔끔한 Python 모듈에서 관측 값저장하지 않고 Quantiles 및 Histograms의 동적 계산을위한 P-Square Algorithm을 구현했습니다 . 문제를 아주 효과적으로 해결해야합니다. 라이브러리는 모드를 제외하고 언급 한 모든 통계를 지원합니다. 모드 추정에 대한 만족스러운 솔루션을 아직 찾지 못했습니다.


참고 : p-square 알고리즘은 C ++ boost : <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp>.
Neil G

7

라이언, 당신이 평균과 분산을 제대로하지 못하고있는 것 같네요 ... 이것은 몇 주 전에 여기에서 나왔습니다 . 그리고 온라인 버전의 강점 중 하나 (실제로 Welford의 방법이라는 이름으로 진행됨)는 그것이 특별히 정확하고 안정적이라는 사실입니다 . 여기 에서 토론을 참조 하십시오 . 장점 중 하나는 총합 또는 총 제곱합을 저장할 필요가 없다는 것입니다.

한 번에 전체 목록을 고려해야하는 것처럼 보이는 모드와 중앙값에 대한 온라인 접근 방식은 생각할 수 없습니다. 그러나 분산 및 평균에 대한 접근 방식과 유사한 접근 방식이 왜도 및 첨도에도 효과가있을 수 있습니다.


re : skewness and kurtosis네. :이 문서를 참조하십시오 johndcook.com/blog/skewness_kurtosis
제시 치솜

3

질문에 인용 된 Wikipedia 기사에는 온라인으로 왜도 및 첨도를 계산하는 공식이 포함되어 있습니다.

모드의 경우-나는 이것을 온라인으로 할 방법이 없다고 생각합니다. 왜? 입력의 모든 값이 이전 값을 복제하는 마지막 값 외에 다른 것으로 가정하십시오. 이 경우 입력에서 볼 수있는 모든 값을 기억하여 마지막 값이 이전에 본 값을 복제하고 가장 빈번하게 만드는 값을 감지해야합니다.

중앙값의 경우 거의 동일합니다. 마지막 입력까지 모든 입력 값이 현재 중앙값 이전 또는 이후 일 수 있기 때문에 어떤 값이 중앙값이 될지 알 수 없습니다. 입력의 길이를 알고 있다면 모든 값을 메모리에 저장하지 않고도 중앙값을 찾을 수 있지만 잘못된 입력 시퀀스가 ​​중앙값을 크게 이동할 수 있기 때문에 여전히 많은 값을 저장해야합니다 (약 절반 정도). 후반부는 중앙값의 전반부에서 값을 만들 수 있습니다.

(정확한 계산만을 참조하고 있습니다.)


2

수십억 개의 데이터 포인트가있는 경우 마감 답변이 아니라 정확한 답변이 필요하지 않을 수 있습니다. 일반적으로 수십억 개의 데이터 포인트가있는 경우이를 생성하는 기본 프로세스는 일종의 통계적 정상 성 / 에르 고딕 성 / 혼합 속성을 따를 가능성이 높습니다. 또한 분포가 합리적으로 연속적 일 것으로 예상하는지 여부도 중요 할 수 있습니다.

이러한 상황에서 정확한 답변이 필요하지 않은 경우 온라인, 낮은 메모리, 분위수 추정 (중앙값은 0.5 분위수의 특수한 경우)에 대한 알고리즘이 있습니다 . 이것은 통계의 활성 분야입니다.

분위수 추정 예 : http://www.computer.org/portal/web/csdl/doi/10.1109/WSC.2006.323014

모드 추정 예 : Bickel DR. 연속 데이터의 최빈값 및 왜도에 대한 강력한 추정량입니다. 계산 통계 및 데이터 분석. 2002; 39 : 153–163. 도이 : 10.1016 / S0167-9473 (01) 00057-3.

이들은 계산 통계의 활성 분야입니다. 가장 정확한 알고리즘은 하나도 없지만 다양한 속성, 가정 및 성능을 가진 다양한 알고리즘 (실제로는 통계적 추정기)이있는 분야에 진입하고 있습니다. 실험적인 수학입니다. 이 주제에 관한 논문이 수백 개에서 수천 개에 달할 것입니다.

마지막 질문은 왜도 및 첨도 자체가 정말로 필요한지 아니면 확률 분포를 특성화하는 데 더 신뢰할 수있는 다른 매개 변수가 더 필요한지 여부입니다 (확률 분포가 있다고 가정합니다!). 가우스를 기대하고 있습니까?

데이터를 대부분 가우 시아 어로 만들기 위해 데이터를 정리 / 전처리하는 방법이 있습니까? (예를 들어, 금융 거래 금액은 종종 로그를 취한 후 다소 가우스입니다). 유한 표준 편차를 기대하십니까? 뚱뚱한 꼬리를 기대하십니까? 관심있는 양이 꼬리 또는 대량입니까?


2

모두가 온라인 방식으로 모드를 할 수 없다고 계속 말하지만 그것은 사실이 아닙니다. 다음은 예일 대학의 Michael E. Fischer와 Steven L. Salzberg가 1982 년에 발명 한 바로이 문제를 해결하기위한 알고리즘을 설명 하는 기사 입니다. 기사에서 :

다수 찾기 알고리즘은 스트림에서 단일 항목의 임시 저장을 위해 레지스터 중 하나를 사용합니다. 이 항목은 현재 다수 요소 후보입니다. 두 번째 레지스터는 0으로 초기화 된 카운터입니다. 스트림의 각 요소에 대해 알고리즘에 다음 루틴을 수행하도록 요청합니다. 카운터가 0이면 현재 스트림 요소를 새 다수 후보로 설치합니다 (이미 레지스터에있을 수있는 다른 요소를 대체). 그런 다음 현재 요소가 다수 후보와 일치하면 카운터를 증가시킵니다. 그렇지 않으면 카운터를 줄입니다. 사이클의이 시점에서 지금까지 본 스트림의 일부에 다수 요소가있는 경우 해당 요소는 후보 레지스터에 있으며 카운터는 0보다 큰 값을 보유합니다. 다수 요소가 없으면 어떻게됩니까? 스트림 환경에서는 불가능한 데이터를 두 번째로 전달하지 않으면 알고리즘이이 상황에서 항상 명확한 답변을 제공 할 수 없습니다. 다수의 요소가있는 경우이를 정확하게 식별 할뿐입니다.

더 많은 메모리가있는 상위 N 개를 찾기 위해 확장 할 수도 있지만 모드에 대해 해결해야합니다.


4
그것은 흥미로운 알고리즘이지만, 내가 뭔가를 놓치지 않는 한 모든 대다수 값은 모드가 될 것이지만 모든 모드가 다수 값이되는 것은 아닙니다.
jkebinger

링크가 끊어 졌으므로 설명이 포함되어 기쁩니다. 그러나 설명 된 바와 같이 카운터는 다수의 후보 두 번째 발생이 첫 번째 발생에 인접한 경우에만 증가합니다. 정렬 된 데이터를 IMPLIES합니다. 온라인 (스트리밍) 데이터 사례에서는 보장되지 않습니다. 무작위로 정렬 된 데이터를 사용하면 모드를 찾을 가능성이 거의 없습니다.
Jesse Chisholm

1

궁극적으로 분포에 대한 사전 모수 적 지식이 없다면 모든 값을 저장해야한다고 생각합니다.

그것은 당신이 어떤 종류의 병리 적 상황을 다루지 않는 한 치료법 (Rousseuw and Bassett 1990)이 당신의 목적에 충분할 것이라고 말했습니다.

매우 간단하게 중앙값 배치의 중앙값을 계산하는 것입니다.


0

중앙값 및 모드는 사용 가능한 일정한 공간 만 사용하여 온라인으로 계산할 수 없습니다. 그러나 중앙값과 최빈값은 "정량적"보다 "설명 적"이기 때문에 데이터 세트를 샘플링하여 추정 할 수 있습니다.

데이터가 장기적으로 정규 분포를 따르는 경우 평균을 사용하여 중앙값을 추정 할 수 있습니다.

다음 기술을 사용하여 중앙값을 추정 할 수도 있습니다. 데이터 스트림의 모든 항목 1,000,000 개에 대해 중앙값 추정 M [i]을 설정하여 M [0]이 처음 100 만 항목의 중앙값이되도록 M [1] 두 번째 100 만 항목의 중앙값 등. 그런 다음 M [0] ... M [k]의 중앙값을 중앙값 추정기로 사용합니다. 이것은 물론 공간을 절약하고 1,000,000 매개 변수를 "조정"하여 공간을 얼마나 사용할 것인지 제어 할 수 있습니다. 이것은 또한 재귀 적으로 일반화 될 수 있습니다.


0

OK 친구 다음을 시도하십시오.

C ++의 경우 :

double skew(double* v, unsigned long n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow((v[i] - mu)/sigma, 3);
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

double kurt(double* v, double n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow( ((v[i] - mu[i]) / sigma) , 4) - 3;
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

샘플 분산 (svar)과 평균 (avg)을 이미 계산할 수 있다고 말한 곳에서는이를 수행하기 위해 함수를 가리 킵니다.

또한 Pearson의 근사값을 살펴보십시오. 그렇게 큰 데이터 세트에서는 꽤 비슷할 것입니다. 3 (평균-중앙값) / 중앙값이 최대 값 인 표준 편차-최소 / 2

수레 모드에는 의미가 없습니다. 일반적으로 1/100 * (최대-최소)와 같은 엄청난 크기의 저장소에 넣습니다.



-1

저는 적응할 수있는 버킷을 사용하는 경향이 있습니다. 버킷 크기는 필요한 정확도 여야합니다. 그런 다음 각 데이터 포인트가 들어 오면 관련 버킷의 수에 하나를 추가합니다. 각 버킷을 개수에 의해 가중치를 부여한 값으로 계산하여 중앙값과 첨도에 대한 간단한 근사치를 제공해야합니다.

한 가지 문제는 수십억 번의 작업 후 부동 소수점 해상도가 손실 될 수 있습니다. 즉, 하나를 추가해도 더 이상 값이 변경되지 않습니다! 이 문제를 해결하기 위해 최대 버킷 크기가 일부 제한을 초과하면 모든 카운트에서 많은 수를 제거 할 수 있습니다.


-1
for j in range (1,M):
    y=np.zeros(M) # build the vector y
    y[0]=y0

    #generate the white noise
    eps=npr.randn(M-1)*np.sqrt(var)

    #increment the y vector
    for k in range(1,T):
        y[k]=corr*y[k-1]+eps[k-1]

    yy[j]=y

list.append(y)

이것을 원래 질문과 더 잘 연결하기 위해 몇 가지 설명을 사용할 수 있습니다.
Erica
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.