Nano Hash - криптовалюты, майнинг, программирование

Вычислить стандартное отклонение (σ) от предыдущего и нового элемента (совокупное / инкрементное SD)

Выполняется сравнительный анализ запущенного процесса, при котором следующие числа вычисляются «кумулятивно» (из предыдущих значений + новый элемент):

  • Минимальная продолжительность
  • Максимальная продолжительность
  • Средняя продолжительность

Стандартное отклонение (σ) продолжительности должно быть также вычисляется, потому что он указывает на статистический разброс.

Исходя из приложения, неудобно хранить каждый элемент / номер, поэтому необходимо вычислять его относительно предыдущего значения и нового элемента.

Пример:

NewElement  Min  Max  Avg  StdDev           // AllElements (which are NOT meant to be stored)
1           1    1    1    -                   [1]
2           1    2    1.5  0.5                 [1,2]
3           1    3    2    0.8164965809277     [1,2,3]
4           1    4    2.5  1.1180339887499     [1,2,3,4]
0           0    4    2    1.4142135623731     [1,2,3,4,0]

это онлайн-калькулятор SD для справочных значений)

Упрощенная версия цели:

const calculateNewStats = (stats, newElement) => {
  const newStats = {};
  newStats.count = stats.count + 1;
  newStats.min = Math.min(stats.min, newElement);
  newStats.max = Math.max(stats.max, newElement);
  newStats.avg = (stats.avg * stats.count + newElement) / newStats.count;

  // newStats.sd = ??? that's the problem

  return newStats;
};

// initial values
let stats = {
  count: 0,
  min: 0,
  max: 0,
  avg: 0,
  // initial SD is theoretically controversial (N/A), but that's not the point
  sd: 0,
};

// loopStart goes here ... an infinite one

    // many things goes here ... eventually, we have a `newElement`

    stats = calculateNewStats(stats, newElement);

// loopEnd goes here

Некоторое время был произведен поиск, были найдены и тщательно применены некоторые математические уравнения (например, this), но в результате числа не были правильными.


  • Я думаю, что это что-то вроде Math.sqrt((stats.sd + Math.pow(newElement - stats.avg, 2)) / 2), но я не уверен, что вы можете рассчитать это без всех данных. 22.06.2019
  • @Titus Применив его к элементам [1,2] = ›Math.sqrt((0 + Math.pow(0 - 1, 2)) / 2), результат будет 0,707106, где ожидаемый результат - 0,5. 22.06.2019
  • Вместо stats.avg я должен был использовать newStats.avg, но это тоже дает неверный результат. 22.06.2019

Ответы:


1

Алгоритм на странице, на которую вы указали ссылку, работает, вот рабочая реализация:

const calculateNewStats = (stats, newElement) => {
  const newStats = {};

  newStats.count = stats.count + 1;
  newStats.min = Math.min(stats.min, newElement);
  newStats.max = Math.max(stats.max, newElement);
  newStats.avg = (stats.avg * stats.count + newElement) / newStats.count;

  newStats.sd = Math.sqrt(
    (
      (newStats.count - 1) * stats.sd * stats.sd +
      (newElement - newStats.avg) * (newElement - stats.avg)
    ) / (newStats.count)
  );

  return newStats;
};

// initial values
let stats = {
  count: 0,
  min: 0,
  max: 0,
  avg: 0,
  sd: 0
};

let newElements = [1, 2, 3, 4, 0];

for (let newElement of newElements) {
  stats = calculateNewStats(stats, newElement);
  console.log(stats);
}

Результат на JSBin

Может вы пропустили последнее предложение?

Если вы хотите дисперсию генеральной совокупности или стандартное отклонение, замените N-1 на N и N-2 на N-1.


Примечание: будет небольшая потеря точности, которая будет увеличиваться по мере добавления элементов. Я бы посоветовал:

  • сохранить дисперсию в stats вместе с sd; прямо сейчас я вычисляю квадратный корень из дисперсии, чтобы получить SD, затем возводил в квадрат SD, чтобы получить дисперсию в следующей итерации.
  • сохранять общее значение в stats, вместо того, чтобы пересчитывать его с stats.avg * stats.count на каждой итерации

Вы сохраняете еще 2 числа в stats, но ваши числа должны стать более точными.

Это лучшая реализация:

const calculateNewStats = (stats, newElement) => {
  const newStats = {};
  newStats.count = stats.count + 1;
  newStats.total = stats.total + newElement;
  newStats.min = Math.min(stats.min, newElement);
  newStats.max = Math.max(stats.max, newElement);
  newStats.avg = (stats.total + newElement) / newStats.count;

  newStats.variance = (
    (newStats.count - 1) * stats.variance +
    (newElement - newStats.avg) * (newElement - stats.avg)
  ) / (newStats.count);

  newStats.sd = Math.sqrt(newStats.variance);

  return newStats;
};

// initial values
let stats = {
  count: 0,
  total: 0,
  min: 0,
  max: 0,
  avg: 0,
  sd: 0,
  variance: 0
};

let newElements = [1, 2, 3, 4, 0];

for (let newElement of newElements) {
  stats = calculateNewStats(stats, newElement);
  console.log(stats);
}

JSBin

21.06.2019
  • и я бы предпочел сохранить дисперсию, как вы предлагали, чтобы избежать операций sqrt, а затем pow2. Однако я не вижу пользы от хранения суммы, она все равно не используется! 22.06.2019
  • @Hossam: общая сумма используется для пересчета среднего. newStats.avg = (stats.total + newElement) / newStats.count; (Вместо хранения среднего, это просто результат, вычисленный из общего количества.) Это позволяет вам накапливать больше элементов с меньшими затратами, если у вас когда-либо будет несколько элементов для добавления без необходимости дорогие дополнительные выходы для каждого. 22.06.2019
  • @PeterCordes да, я только что заметил, но это не повлияет на точность, я думаю, потому что и avg, и count являются целыми числами 22.06.2019
  • @Hossam: нет, count является целым числом, а totalis, если вы передаете только целочисленные входные данные. Но одно из ваших средних значений в вашем примере в вопросе - 1.5. Бывает, что 1.5 можно представить точно как double, но среднее значение [1, 0, 0] равно 1/3, что не может быть представлено точно. Только дроби со знаменателем степени двойки могут быть точно представлены двоичным числом с плавающей запятой. В любом случае, отслеживание итогов - это меньше общей работы, чем отслеживание среднего. 22.06.2019
  • о нет, не могу поверить, что написал то, что написал, наверное, вчера я не совсем проснулся. Спасибо, парни! 22.06.2019
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..