programing

표본 데이터에서 신뢰 구간 계산

stoneblock 2023. 6. 13. 21:56

표본 데이터에서 신뢰 구간 계산

정규 분포를 가정하여 신뢰 구간을 계산하려는 표본 데이터가 있습니다.

나는 numpy 패키지와 scipy 패키지를 찾아서 설치했고 평균과 표준 편차(numpy.mean(data))를 반환하기 위해 numpy가 되었습니다.샘플 신뢰 구간을 얻는 것에 대한 조언을 해주시면 감사하겠습니다.

import numpy as np
import scipy.stats

def mean_confidence_interval(data, confidence=0.95):
    a = 1.0 * np.array(data)
    n = len(a)
    m, se = np.mean(a), scipy.stats.sem(a)
    h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1)
    return m, m-h, m+h

이렇게 계산할 수 있습니다.

여기서 배열 평균의 95% 신뢰 구간을 계산하는 Shasan 코드의 단축된 버전a:

import numpy as np, scipy.stats as st

st.t.interval(0.95, len(a)-1, loc=np.mean(a), scale=st.sem(a))

그러나 StatsModel'을 사용하는 것이 훨씬 더 좋습니다.

import statsmodels.stats.api as sms

sms.DescrStatsW(a).tconfint_mean()

다 array 둘기배인가입표정은본다니적다본열배입표▁the본▁the가다(array니)입니다.a)는 표준 편차를 알 수 없는 정규 분포로부터 독립적으로 그려졌습니다(수학 세계 또는 위키백과 참조).

크기 n의 분포를 따르며, 큰 표 의 크 경 표 평 분 따 정 다 르 다 있 니 습 수 할 계 산 구 을 간 신 뢰 여 사 하 을 본 용 며 음 를을 사용하여 표본 평균의 할 수 .st.norm.interval()(Jaime의 논평에서 제안된 바와 같이).그러나 위의 해결책은 작은 n에 대해서도 정확합니다.st.norm.interval()너무 좁은 신뢰 구간(즉, "가짜 신뢰")을 제공합니다.자세한 내용은 유사한 질문에 대한 답변을 참조하십시오(그리고 여기서 Russ의 의견 중 하나).

다음은 올바른 옵션이 (기본적으로) 동일한 신뢰 구간을 제공하는 예입니다.

In [9]: a = range(10,14)

In [10]: mean_confidence_interval(a)
Out[10]: (11.5, 9.4457397432391215, 13.554260256760879)

In [11]: st.t.interval(0.95, len(a)-1, loc=np.mean(a), scale=st.sem(a))
Out[11]: (9.4457397432391215, 13.554260256760879)

In [12]: sms.DescrStatsW(a).tconfint_mean()
Out[12]: (9.4457397432391197, 13.55426025676088)

그리고 마지막으로, 잘못된 결과는 다음과 같습니다.st.norm.interval():

In [13]: st.norm.interval(0.95, loc=np.mean(a), scale=st.sem(a))
Out[13]: (10.23484868811834, 12.76515131188166)

하는 중Python 3.8표준 라이브러리는 객체를 모듈의 일부로 제공합니다.

from statistics import NormalDist

def confidence_interval(data, confidence=0.95):
  dist = NormalDist.from_samples(data)
  z = NormalDist().inv_cdf((1 + confidence) / 2.)
  h = dist.stdev * z / ((len(data) - 1) ** .5)
  return dist.mean - h, dist.mean + h

다음 항목:

  • 다음을 작성합니다.NormalDist데이터 NormalDist.from_samples(data)샘플의 개체(, 및 를 통해 샘플의 평균 및 표준 편차에 액세스할 수 있습니다.

  • 을 합니다.Z-score표준 정규 분포를 기반으로 합니다(로 표시됨).NormalDist()) 누적 분포 inv_cdf함수의 역함수()를 사용하여 주어진 신뢰도에 대해 계산합니다.

  • 표본의 표준 편차와 평균을 기반으로 신뢰 구간을 생성합니다.


하여 계산하기에 충분하다고 가정합니다(~ 이상이라고 가정합니다zvalue.value.value.

조회 표에서 원하는 신뢰 구간의 z-값을 조회하는 것부터 시작합니다.신뢰 구간은 다음과 같습니다.mean +/- z*sigma,어디에sigma표본 평균의 추정 표준 편차는 다음과 같습니다.sigma = s / sqrt(n),어디에s표본 데이터에서 계산된 표준 편차입니다.n샘플 크기입니다.

원본을 기반으로 하지만 몇 가지 구체적인 예를 들어보면 다음과 같습니다.

import numpy as np

def mean_confidence_interval(data, confidence: float = 0.95) -> tuple[float, np.ndarray]:
    """
    Returns (tuple of) the mean and confidence interval for given data.
    Data is a np.arrayable iterable.

    ref:
        - https://stackoverflow.com/a/15034143/1601580
        - https://github.com/WangYueFt/rfs/blob/f8c837ba93c62dd0ac68a2f4019c619aa86b8421/eval/meta_eval.py#L19
    """
    import scipy.stats
    import numpy as np

    a: np.ndarray = 1.0 * np.array(data)
    n: int = len(a)
    if n == 1:
        import logging
        logging.warning('The first dimension of your data is 1, perhaps you meant to transpose your data? or remove the'
                        'singleton dimension?')
    m, se = a.mean(), scipy.stats.sem(a)
    tp = scipy.stats.t.ppf((1 + confidence) / 2., n - 1)
    h = se * tp
    return m, h

def ci_test_float():
    import numpy as np
    # - one WRONG data set of size 1 by N
    data = np.random.randn(1, 30)  # gives an error becuase len sets n=1, so not this shape!
    m, ci = mean_confidence_interval(data)
    print('-- you should get a mean and a list of nan ci (since data is in wrong format, it thinks its 30 data sets of '
          'length 1.')
    print(m, ci)

    # right data as N by 1
    data = np.random.randn(30, 1)
    m, ci = mean_confidence_interval(data)
    print('-- gives a mean and a list of length 1 for a single CI (since it thinks you have a single dat aset)')
    print(m, ci)

    # multiple data sets (7) of size N (=30)
    data = np.random.randn(30, 7)
    print('-- gives 7 CIs for the 7 data sets of length 30. 30 is the number ud want large if you were using z(p)'
          'due to the CLT.')
    m, ci = mean_confidence_interval(data)
    print(m, ci)

ci_test_float()

출력:

-- you should get a mean and a list of nan ci (since data is in wrong format, it thinks its 30 data sets of length 1.
0.1431623130952463 [nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan
 nan nan nan nan nan nan nan nan nan nan nan nan]
-- gives a mean and a list of length 1 for a single CI (since it thinks you have a single dat aset)
0.04947206018132864 [0.40627264]
-- gives 7 CIs for the 7 data sets of length 30. 30 is the number ud want large if you were using z(p)due to the CLT.
-0.03585104402718902 [0.31867309 0.35619134 0.34860011 0.3812853  0.44334033 0.35841138
 0.40739732]

Num_datasets의 Num_samples가 맞는 것 같은데, 만약 그것이 댓글 부분에 없다면 알려주세요.


어떤 유형의 데이터에 대해 작동합니까?

다음과 같은 이유로 모든 데이터에 사용할 수 있다고 생각합니다.

평균과 표준은 일반 숫자 데이터에 대해 계산되고 z_p/t_p 값은 신뢰 구간과 데이터 크기만 포함하므로 데이터 분포에 대한 가정과는 무관하다고 생각합니다.

그래서 회귀 분석과 분류에 사용될 수 있다고 생각합니다.


추가적으로 토치만 거의 사용하는 토치 구현:

def torch_compute_confidence_interval(data: Tensor,
                                      confidence: float = 0.95
                                      ) -> Tensor:
    """
    Computes the confidence interval for a given survey of a data set.
    """
    n: int = len(data)
    mean: Tensor = data.mean()
    # se: Tensor = scipy.stats.sem(data)  # compute standard error
    # se, mean: Tensor = torch.std_mean(data, unbiased=True)  # compute standard error
    se: Tensor = data.std(unbiased=True) / (n ** 0.5)
    t_p: float = float(scipy.stats.t.ppf((1 + confidence) / 2., n - 1))
    ci = t_p * se
    return mean, ci

CI에 대한 일부 의견(또는 https://stats.stackexchange.com/questions/554332/confidence-interval-given-the-population-mean-and-standard-deviation?noredirect=1&lq=1) 참조):

"""
Review for confidence intervals. Confidence intervals say that the true mean is inside the estimated confidence interval
(the r.v. the user generates). In particular it says:
    Pr[mu^* \in [mu_n +- t.val(p) * std_n / sqrt(n) ] ] >= p
e.g. p = 0.95
This does not say that for a specific CI you compute the true mean is in that interval with prob 0.95. Instead it means
that if you surveyed/sampled 100 data sets D_n = {x_i}^n_{i=1} of size n (where n is ideally >=30) then for 95 of those
you'd expect to have the truee mean inside the CI compute for that current data set. Note you can never check for which
ones mu^* is in the CI since mu^* is unknown. If you knew mu^* you wouldn't need to estimate it. This analysis assumes
that the the estimator/value your estimating is the true mean using the sample mean (estimator). Since it usually uses
the t.val or z.val (second for the standardozed r.v. of a normal) then it means the approximation that mu_n ~ gaussian
must hold. This is most likely true if n >= 0. Note this is similar to statistical learning theory where we use
the MLE/ERM estimator to choose a function with delta, gamma etc reasoning. Note that if you do algebra you can also
say that the sample mean is in that interval but wrt mu^* but that is borning, no one cares since you do not know mu^*
so it's not helpful.

An example use could be for computing the CI of the loss (e.g. 0-1, CE loss, etc). The mu^* you want is the expected
risk. So x_i = loss(f(x_i), y_i) and you are computing the CI for what is the true expected risk for that specific loss
function you choose. So mu_n = emperical mean of the loss and std_n = (unbiased) estimate of the std and then you can
simply plug in the values.

Assumptions for p-CI:
    - we are making a statement that mu^* is in mu+-pCI = mu+-t_p * sig_n / sqrt n, sig_n ~ Var[x] is inside the CI
    p% of the time.
    - we are estimating mu^, a mean
    - since the quantity of interest is mu^, then the z_p value (or p-value, depending which one is the unknown), is
    computed using the normal distribution.
    - p(mu) ~ N(mu; mu_n, sig_n/ sqrt n), vial CTL which holds for sample means. Ideally n >= 30.
    - x ~ p^*(x) are iid.

Std_n vs t_p*std_n/ sqrt(n)
    - std_n = var(x) is more pessimistic but holds always. Never shrinks as n->infity
    - but if n is small then pCI might be too small and your "lying to yourself". So if you have very small data
    perhaps doing std_n for the CI is better. That holds with prob 99.9%. Hopefuly std is not too large for your
    experiments to be invalidated.

ref:
    - https://stats.stackexchange.com/questions/554332/confidence-interval-given-the-population-mean-and-standard-deviation?noredirect=1&lq=1
    - https://stackoverflow.com/questions/70356922/what-is-the-proper-way-to-compute-95-confidence-intervals-with-pytorch-for-clas
    - https://www.youtube.com/watch?v=MzvRQFYUEFU&list=PLUl4u3cNGP60hI9ATjSFgLZpbNJ7myAg6&index=205
"""

Ulrich의 답변과 관련하여 - 그것은 t-값을 사용하는 것입니다.실제 분산을 알 수 없을 때 사용합니다.이때 데이터는 표본 데이터뿐입니다.

bogatron의 대답은 z 테이블을 포함합니다.z-표는 분산이 이미 알려져 있고 제공되는 경우에 사용됩니다.표본 데이터도 있습니다.시그마는 표본 평균의 추정된 표준 편차가 아닙니다.그것은 이미 알려져 있습니다.

분산이 알려져 있고 95% 신뢰도를 원한다고 가정해 보겠습니다.

from scipy.stats import norm
alpha = 0.95
# Define our z
ci = alpha + (1-alpha)/2
#Lower Interval, where n is sample siz
c_lb = sample_mean - norm.ppf(ci)*((sigma/(n**0.5)))
c_ub = sample_mean + norm.ppf(ci)*((sigma/(n**0.5)))

표본 데이터와 알 수 없는 분산(분산은 표본 데이터에서만 계산해야 함)만 있으면 Ulrich의 대답은 완벽하게 작동합니다.그러나 신뢰 구간을 지정할 수 있습니다.데이터가 a이고 0.95의 신뢰 구간을 원하는 경우:

import statsmodels.stats.api as sms
conf = sms.DescrStatsW(a).tconfint_mean(alpha=0.05)
conf

언급URL : https://stackoverflow.com/questions/15033511/compute-a-confidence-interval-from-sample-data