Я создал класс для возврата доверительного интервала после начальной загрузки, но мой доверительный интервал выглядит странно узким. Что я сделал не так?

Мое намерение состоит в том, чтобы код выполнял начальную загрузку (статистику) в заданном списке с размером выборки, равным длине списка 10 000 раз, а затем вычислял доверительный интервал 95%.

import numpy
from random import choice

class bootstrapping(object):

    def __init__(self,bslist=[],iteration=10000):
        self.bslist = bslist
        self.iteration = iteration

    def CI(self):
        listofmeans = []

        for numbers in range(0,self.iteration):
            bootstraplist = [choice(self.bslist) for _ in range(len(self.bslist))]
            listofmeans.append(sum(bootstraplist) / len(bootstraplist))

        s = numpy.std(listofmeans)
        z = 1.96
        n = self.iteration**0.5

        lower_confidence = (sum(listofmeans) / len(listofmeans)) - (z*s/n)
        upper_confidence = (sum(listofmeans) / len(listofmeans)) + (z*s/n)

        return lower_confidence,upper_confidence

test = bootstrapping([60,33,102,53,63,33,42,19,31,86,15,50,
                      45,47,26,23,30,20,18,48,22,20,17,29,43,52,29],10000)
test.CI()

Доверительный интервал, который я получаю (37,897427638499948, 38,102572361500052), странно узок. Когда я ввожу тот же список чисел в Minitab, я получаю 95-процентный доверительный интервал (30,74, 47,48). Я что-то сделал не так?


person Shing Tse    schedule 01.02.2017    source источник
comment
Если вы не установите random.seed(), давать разные варианты выбора в разных прогонах. Это не объясняет несоответствие, но его стоит исправить для будущего тестирования.   -  person TemporalWolf    schedule 02.02.2017
comment
@TemporalWolf Я не совсем уверен, что понимаю, что ты имеешь в виду. Не могли бы вы уточнить немного подробнее?   -  person Shing Tse    schedule 02.02.2017
comment
установка определенного случайного начального числа делает так, что он будет давать вам один и тот же выбор каждый раз, когда вы его запускаете: это полезно для проверки того, работает ли алгоритм с известными входными данными.   -  person TemporalWolf    schedule 02.02.2017


Ответы (1)


Чтобы найти доверительный интервал 95 %, позвольте z = 1.96 (приблизительно) и вычислите интервал относительно среднего плюс или минус z*std, где std — стандартное отклонение. Другими словами, используйте z*std, а не z*std/n:

import numpy as np
import random
random.seed(2017)

class Bootstrapping(object):

    def __init__(self,bslist=[],iteration=10000):
        self.bslist = bslist
        self.iteration = iteration

    def CI(self):
        listofmeans = []

        for numbers in range(0,self.iteration):
            bootstraplist = [random.choice(self.bslist) for _ in range(len(self.bslist))]
            mean = sum(bootstraplist) / len(bootstraplist)
            listofmeans.append(mean)

        mean = np.mean(listofmeans, axis=0)
        std = np.std(listofmeans, axis=0)
        z = 1.96
        err = z*std
        lower_confidence = mean - err
        upper_confidence = mean + err

        return lower_confidence, upper_confidence

test = Bootstrapping([60,33,102,53,63,33,42,19,31,86,15,50,
                      45,47,26,23,30,20,18,48,22,20,17,29,43,52,29],10000)
print(test.CI())

урожаи

(31.309540089458281, 46.876348799430602)

Кроме того, вы можете вычислить доверительный интервал, не обращаясь к формуле среднего +/- 1,96 * стандартное значение. Вы можете получить эмпирическую оценку доверительного интервала, отсортировав listofmeans и найдя значения в 5-м и 95-м процентиле:

import random
random.seed(2017)

class Bootstrapping(object):

    def __init__(self,bslist=[],iteration=10000):
        self.bslist = bslist
        self.iteration = iteration

    def CI(self):
        listofmeans = []

        for numbers in range(0,self.iteration):
            bootstraplist = [random.choice(self.bslist) for _ in range(len(self.bslist))]
            mean = sum(bootstraplist) / len(bootstraplist)
            listofmeans.append(mean)

        listofmeans = sorted(listofmeans)    
        a, b = round(self.iteration*0.05), round(self.iteration*0.95)
        lower_confidence = listofmeans[a]
        upper_confidence = listofmeans[b]

        return lower_confidence, upper_confidence

test = Bootstrapping([60,33,102,53,63,33,42,19,31,86,15,50,
                      45,47,26,23,30,20,18,48,22,20,17,29,43,52,29],10000)
print(test.CI())

урожаи

(32.888888888888886, 45.888888888888886)
person unutbu    schedule 01.02.2017
comment
Что делает random.seed()? - person Shing Tse; 02.02.2017
comment
Он заполняет генератор случайных чисел, поэтому результат повторяемый. - person unutbu; 02.02.2017
comment
Я почти уверен, что доверительный интервал равен mean += z*stderror, где стандартная ошибка = (стандартное отклонение) / sqrt (n). Стандартная ошибка — это просто стандартное отклонение распределения выборки. - person juanpa.arrivillaga; 02.02.2017
comment
@juanpa.arrivillaga В этом случае std = np.std(listofmeans, axis=0) дает стандартную ошибку без необходимости извлечения квадратного корня из n. Насколько я понимаю, если бы я знал стандартное отклонение населения, чего в данном случае я не знаю, то я бы разделил на квадратный корень из n. - person Shing Tse; 02.02.2017
comment
@ShingTse Ах, да. Кажется, теперь я вижу. Меня смутила загрузка. Да, у вас есть listofmeans. - person juanpa.arrivillaga; 02.02.2017
comment
@juanpa.arrivillaga: Это немного сбивает с толку, потому что здесь так много средств. Но я думаю, что то, что делает бутстреп, похоже на обследование роста 10000 мальчиков, нахождение среднего значения и стандартного отклонения этих высот, а затем получение среднего значения +/- 1,96 * стандартное значение. Мы не вычисляем стандартное отклонение среднего, а только стандартное отклонение выборки. - person unutbu; 02.02.2017
comment
Я добавил второй способ вычисления доверительного интервала, который, возможно, более соответствует духу начальной загрузки - найдя его эмпирически , а не по формуле. - person unutbu; 02.02.2017
comment
Да, в данном случае мы используем выборку непосредственно. - person juanpa.arrivillaga; 02.02.2017
comment
@unutbu Еще один вопрос: я не вижу метода random.seed(), используемого в теле кода. Я что-то пропустил? Где этот метод меняет то, что делает код? - person Shing Tse; 02.02.2017
comment
@ShingTse: Моя ошибка. Я должен был позвонить random.seed, а не np.random.seed, так как мы используем random.choice, а не np.random.choice. Я обновил приведенный выше код, чтобы исправить это. Теперь при запуске кода результат должен повторяться. - person unutbu; 02.02.2017
comment
Чтобы закончить упомянутую выше аналогию, мы находим интервал, который включает 95% мальчиков. - person unutbu; 02.02.2017