Как рассчитать доверительные интервалы для будущих значений случайного блуждания в Javascript? - PullRequest
0 голосов
/ 26 декабря 2018

У меня есть генератор случайных чисел, подключенный к простому эксперименту "случайного блуждания".Это выглядит примерно так:

let valueAtStepX = [];
let lastValue = 0;
for (let i = 0; i < 1000; i++) {
    let randomDeviationThisStep = Math.floor(Math.random() * 201) - 100;
    lastValue += randomDeviationThisStep;
    valueAtStepX[i] = lastValue;
}

Теперь я хочу иметь возможность рассчитать «доверительный интервал» для значения X шагов в будущем.То есть я хочу знать, в каком диапазоне я могу быть на 95% уверен, что значение шага X в будущем будет в пределах.

Я считаю, что нашел функцию для прогнозирования этого доверительного интервала, однако этона другом языке (R): https://github.com/robjhyndman/forecast/blob/master/R/naive.R

Кто-нибудь знает функцию Javascript для выполнения этого вычисления?А пока попробую преобразовать приведенную выше функцию R в Javascript.

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Хорошо, я думаю, что мне удалось преобразовать приведенную выше функцию R в Typescript / Javascript.(хотя я удалил некоторые параметры и тому подобное, поскольку у меня не было возможности использовать эти другие параметры)

export function GetUpperAndLowerBoundForRandomWalkOfXSteps(maxDeviationPerStep: number, stepsAhead: number, confidenceLevel = .95) {
    let standardDeviationOfStep = Math.sqrt(maxDeviationPerStep / 2);
    let standardDeviationOfStepX = Math.sqrt((maxDeviationPerStep / 2) * stepsAhead);

    let z = InverseCumulativeProbability(confidenceLevel, standardDeviationOfStep);
    let upperBound = z * standardDeviationOfStepX;
    //let lowerBound = -upperBound;
    return upperBound;
}

const Sqrt2 = 1.4142135623730950488016887;
function InverseCumulativeProbability(probability: number, standardDeviationOfStep: number) {
    var Z = Sqrt2 * InverseErrorFunc(probability);
    return Z * standardDeviationOfStep;
}
function InverseErrorFunc(x: number){
    if (x == 0) return 0;
    var a = 0.147;

    var the_sign_of_x =
        x > 0 ? 1 :
        x < 0 ? -1 :
        0;

    var ln_1minus_x_sqrd = Math.log(1 - x * x);
    var ln_1minusxx_by_a = ln_1minus_x_sqrd / a;
    var ln_1minusxx_by_2 = ln_1minus_x_sqrd / 2;
    var ln_etc_by2_plus2 = ln_1minusxx_by_2 + (2 / (Math.PI * a));
    var first_sqrt = Math.sqrt((ln_etc_by2_plus2 * ln_etc_by2_plus2) - ln_1minusxx_by_a);
    var second_sqrt = Math.sqrt(first_sqrt - ln_etc_by2_plus2);
    let z = second_sqrt * the_sign_of_x;
    return z;
}

Вот снимок экрана, используемый на графике, с серыми линиями, отмеченными95% доверительные интервалы: confidence intervals

ПРИМЕЧАНИЕ : После дальнейшего прочтения этой темы я считаю, что приведенное выше решение не совсем корректно.Похоже, что он дает аналогичный результат для «правильного» алгоритма, но он отключен, потому что функции R предназначались для работы с фактическими «выборочными» данными, в то время как мой вариант использования пытается вычислить теоретические доверительные интервалы на основе известного поколениявероятности.

С тех пор я собрал набор функций, которые, на мой взгляд, являются правильными, но он использует некоторый код из другого репозитория Github (https://github.com/RajahBimmy/Sungear/tree/master/public/javascripts/hyperGeo/distribution),, поэтому нецелесообразно его выкладывать вполный здесь.

Тем не менее, я включу часть, которую я собрал, поверх этой основы:

/**
 * Finds the standard-deviation for a Binomial distribution with the given parameters. (a Binomial distribution consists of a series of yes/no trials, where each trial is independent of the previous one)
 * For a Binomial distribution, the theoretical/expected variance is: yesNoTrialCount * yesProbability * (1 - yesProbability) [https://en.wikipedia.org/wiki/Binomial_distribution#Variance]
 * To then get the standard-deviation, just calculate the square-root of that variance.
 */
export function GetStandardDeviationForBinomialDistribution(yesNoTrialCount: number, yesProbability: number) {
    let variance = yesNoTrialCount * yesProbability * (1 - yesProbability);
    return Math.sqrt(variance);
}

let binomialDistributionToRange_cache = {};

/**
 * @param yesNoTrialCount The total number of yes/no trials (eg. 0 or 1 bits) that went into creating the data set.
 * @param yesProbability The probability each trial had of yielding a "1" bit. (assumes a binomial distribution, ie. that each trial is independent of the previous one)
 * @param confidenceInterval The certainty level, ie. how "wide" of a confidence interval we want to calculate. Range: 0-1 (eg: 0.95 means 95%)
 * @returns The smallest distance from the theoretical mean, within which we're X% (confidenceInterval) sure that the terminal-value/end-point of a random walk with these parameters will be found.
 */
export function GetRangeHavingXPercentCertaintyOfContainingRandomWalkEndPoint_Binomial(yesNoTrialCount: number, yesProbability: number, confidenceInterval = .95, minLower?: number, maxUpper?: number) {
    if (yesNoTrialCount == 0) return 0;

    let key_part1 = `${yesProbability}|${confidenceInterval}`;
    let key_part2 = yesNoTrialCount;

    binomialDistributionToRange_cache[key_part1] = binomialDistributionToRange_cache[key_part1] || {};
    let highestKeyPart2UnderCurrent = binomialDistributionToRange_cache[key_part1].VKeys().map(ToInt).filter(a=>a <= key_part2).OrderBy(a=>a).LastOrX();

    if (highestKeyPart2UnderCurrent != key_part2) {
        // works I think, but doesn't seem to be needed
        /*if (highestKeyPart2UnderCurrent != null) {
            let highestKeyPart2UnderCurrent_result = binomialDistributionToRange_cache[key_part1][highestKeyPart2UnderCurrent];
            minLower = (minLower != null ? minLower : 0).KeepAtLeast(highestKeyPart2UnderCurrent_result);
        }*/

        let binomialDistribution = new BinonomialDistribution(yesNoTrialCount, yesProbability);
        let result = binomialDistribution.inverseCumulativeProbability(confidenceInterval, minLower, maxUpper).Distance(binomialDistribution.getNumericalMean());
        binomialDistributionToRange_cache[key_part1][key_part2] = result;
    }
    return binomialDistributionToRange_cache[key_part1][key_part2];
}
0 голосов
/ 26 декабря 2018

В Javascript нет встроенной функции, эквивалентной той, что вы нашли в R. Хотя R - это инструмент, созданный специально для науки о данных, Javascript предназначен для использования в Интернете;методы статистики не входят в число задач веб-разработки.Поэтому вам либо нужна библиотека Javascript, либо вы выполняете работу самостоятельно.

Наилучшим соответствием для вашей проблемы может быть jStat.js .

...