Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Find mean and standard deviation example

Boost , Math Toolkit 2.5.0 , Find Location and Scale Examples

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Во-первых, нам нужно, чтобы некоторые из них включали доступ к нормальному распределению, алгоритмы для поиска местоположения и масштаба (и, конечно же, некоторый вывод std).

#include <boost/math/distributions/normal.hpp> // for normal_distribution
  using boost::math::normal; // typedef provides default type is double.
#include <boost/math/distributions/cauchy.hpp> // for cauchy_distribution
  using boost::math::cauchy; // typedef provides default type is double.
#include <boost/math/distributions/find_location.hpp>
  using boost::math::find_location;
#include <boost/math/distributions/find_scale.hpp>
  using boost::math::find_scale;
  using boost::math::complement;
  using boost::math::policies::policy;
#include <iostream>
  using std::cout; using std::endl; using std::left; using std::showpoint; using std::noshowpoint;
#include <iomanip>
  using std::setw; using std::setprecision;
#include <limits>
  using std::numeric_limits;
#include <stdexcept>
Using find_location and find_scale to meet dispensing and measurement specifications

Рассмотрим пример из K Krishnamoorthy, Handbook of Statistical Distributions with Applications, ISBN 1-58488-635-8, (2006) p 126, example 10.3.7.

"Машина должна упаковывать по 3 кг говядины на упаковку. За длительный период времени установлено, что средний упакованный вес составил 3 кг при стандартном отклонении 0,1 кг. Предположим, что упаковка обычно распределяется".

Начнем с построения нормального распределения с заданными параметрами:

double mean = 3.; // kg
double standard_deviation = 0.1; // kg
normal packs(mean, standard_deviation);

Затем мы можем найти долю (или %) упаковок, которые весят более 3,1 кг.

double max_weight = 3.1; // kg
cout << "Percentage of packs > " << max_weight << " is "
<< cdf(complement(packs, max_weight)) * 100. << endl; // P(X > 3.1)

Мы можем захотеть убедиться, что 95% упаковок имеют минимальный вес, тогда мы хотим, чтобы среднее значение было таким, чтобы P(X< 2,9) = 0,05.

Используя среднее значение 3 кг, можно оценить долю упаковок, которые не соответствуют спецификации 2,9 кг.

double minimum_weight = 2.9;
cout <<"Fraction of packs <= " << minimum_weight << " with a mean of " << mean
  << " is " << cdf(complement(packs, minimum_weight)) << endl;
// fraction of packs <= 2.9 with a mean of 3 is 0.841345

Это 0,84 - больше целевой фракции 0,95. Если мы хотим, чтобы 95% весили больше минимального, то какой должен быть средний вес?

С помощью программы KK StatCalc, поставляемой с книгой, и метода, приведенного на странице 126, выдается 3.06449.

Мы можем подтвердить это, построив новый дистрибутив, который мы называем «xpacks» со средним значением запаса прочности 3.06449.

double over_mean = 3.06449;
normal xpacks(over_mean, standard_deviation);
cout << "Fraction of packs >= " << minimum_weight
<< " with a mean of " << xpacks.mean()
  << " is " << cdf(complement(xpacks, minimum_weight)) << endl;
// fraction of packs >= 2.9 with a mean of 3.06449 is 0.950005

Используя этот набор математических инструментов, мы можем рассчитать требуемое среднее значение напрямую:

double under_fraction = 0.05;  // so 95% are above the minimum weight mean - sd = 2.9
double low_limit = standard_deviation;
double offset = mean - low_limit - quantile(packs, under_fraction);
double nominal_mean = mean + offset;
// mean + (mean - low_limit - quantile(packs, under_fraction));
normal nominal_packs(nominal_mean, standard_deviation);
cout << "Setting the packer to " << nominal_mean << " will mean that "
  << "fraction of packs >= " << minimum_weight
  << " is " << cdf(complement(nominal_packs, minimum_weight)) << endl;
// Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95

Этот расчет обобщается как свободная функция, называемаяfind_location., см.Алгоритмы.

Чтобы использовать это, нам нужно

#include <boost/math/distributions/find_location.hpp>
  using boost::math::find_location;

и затем использовать функцию find_location для поиска safe_mean, & построить новое нормальное распределение под названием Goodpacks.

double safe_mean = find_location<normal>(minimum_weight, under_fraction, standard_deviation);
normal good_packs(safe_mean, standard_deviation);

с тем же подтверждением, что и раньше:

cout << "Setting the packer to " << nominal_mean << " will mean that "
  << "fraction of packs >= " << minimum_weight
  << " is " << cdf(complement(good_packs, minimum_weight)) << endl;
// Setting the packer to 3.06449 will mean that fraction of packs >= 2.9 is 0.95
Using Cauchy-Lorentz instead of normal distribution

Изучив распределение веса большого количества упаковок, мы можем решить, что, в конце концов, предположение о нормальном распределении не совсем оправдано. Мы можем обнаружить, что подгонка лучше дляраспределения Коши. Это распределение имеет более широкие «крылья», так что, хотя большинство значений ближе к среднему значению, чем нормальное, есть также больше значений, чем «нормальное», которые лежат дальше от среднего, чем нормальное.

Это может произойти потому, что большая, чем обычно, часть мяса либо включена, либо исключена.

Сначала мы создаемCauchy Distributionс исходным средним и стандартным отклонением и оцениваем фракцию, которая лежит ниже нашей минимальной спецификации веса.

cauchy cpacks(mean, standard_deviation);
cout << "Cauchy Setting the packer to " << mean << " will mean that "
  << "fraction of packs >= " << minimum_weight
  << " is " << cdf(complement(cpacks, minimum_weight)) << endl;
// Cauchy Setting the packer to 3 will mean that fraction of packs >= 2.9 is 0.75

Обратите внимание, что гораздо меньше упаковок соответствует спецификации, только 75% вместо 95%. Теперь мы можем повторить местоположение find_location, используя распределение cauchy в качестве параметра шаблона, вместо обычного, используемого выше.

double lc = find_location<cauchy>(minimum_weight, under_fraction, standard_deviation);
cout << "find_location<cauchy>(minimum_weight, over fraction, standard_deviation); " << lc << endl;
// find_location<cauchy>(minimum_weight, over fraction, packs.standard_deviation()); 3.53138

Обратите внимание, что настройка Safe_mean должна быть намного выше, 3.53138 вместо 3.06449, поэтому мы получим гораздо меньшую прибыль.

И еще раз подтвердите, что спецификация соответствия фракции соответствует ожиданиям.

cauchy goodcpacks(lc, standard_deviation);
cout << "Cauchy Setting the packer to " << lc << " will mean that "
  << "fraction of packs >= " << minimum_weight
  << " is " << cdf(complement(goodcpacks, minimum_weight)) << endl;
// Cauchy Setting the packer to 3.53138 will mean that fraction of packs >= 2.9 is 0.95

Наконец, мы могли бы оценить эффект гораздо более жесткой спецификации, что 99% упаковок соответствовали спецификации.

cout << "Cauchy Setting the packer to "
  << find_location<cauchy>(minimum_weight, 0.99, standard_deviation)
  << " will mean that "
  << "fraction of packs >= " << minimum_weight
  << " is " << cdf(complement(goodcpacks, minimum_weight)) << endl;

Установка упаковщика на 3.13263 будет означать, что доля упаковок >= 2.9 составляет 0,99, но более чем удвоит среднюю потерю от 0,0644 до 0,133 кг на упаковку.

Конечно, этот расчет не ограничивается упаковками мяса, он относится к раздаче чего-либо, а также к «виртуальному» материалу, как и любое измерение.

Единственное предостережение заключается в том, что расчет предполагает, что стандартное отклонение (шкала) известно с достаточно низкой неопределенностью, что не так легко обеспечить на практике. И что распределение хорошо определено,нормальное распределениеилираспределение Кошиили какое-то другое.

Если вы просто распределяете очень большое количество упаковок, то можно измерить вес сотен или тысяч упаковок. При здоровых "градусах свободы" доверительные интервалы для стандартного отклонения не слишком широки, как правило, около + и - 10% для сотен наблюдений.

Для других приложений, где сделать много наблюдений сложнее или дороже, доверительные интервалы удручающе широки.

См.Интервалы доверия по стандартному отклонениюдля работающего примераchi_square_std_dev_test.cppоценки этих интервалов.

Changing the scale or standard deviation

В качестве альтернативы мы могли бы инвестировать в лучший (более точный) упаковщик (или измерительное устройство) с более низким стандартным отклонением или масштабом.

Это может стоить дороже, но уменьшит сумму, которую мы должны «отдать», чтобы соответствовать спецификации.

Чтобы оценить, насколько лучше (насколько меньше стандартное отклонение) это должно быть, нам нужно получить 5% квантиль, чтобы быть расположенным на пределе ниже веса, 2,9.

double p = 0.05; // wanted p th quantile.
cout << "Quantile of " << p << " = " << quantile(packs, p)
  << ", mean = " << packs.mean() << ", sd = " << packs.standard_deviation() << endl;

Количественное значение 0,05 = 2.83551, среднее = 3, sd = 0,1

При текущем упаковщике (среднее значение = 3, sd = 0,1) 5% квантиле составляет 2,8551 кг, что немного ниже нашей цели в 2,9 кг. Поэтому мы знаем, что стандартное отклонение должно быть меньше.

Начнем с предположения, что ее (сейчас 0,1) нужно сократить вдвое, до стандартного отклонения в 0,05 кг.

normal pack05(mean, 0.05);
cout << "Quantile of " << p << " = " << quantile(pack05, p)
  << ", mean = " << pack05.mean() << ", sd = " << pack05.standard_deviation() << endl;
// Quantile of 0.05 = 2.91776, mean = 3, sd = 0.05
cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean
  << " and standard deviation of " << pack05.standard_deviation()
  << " is " << cdf(complement(pack05, minimum_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.05 is 0.97725

Так что 0,05 было довольно хорошей догадкой, но мы немного превысили цель 2,9, так что стандартное отклонение может быть немного больше. Так что мы могли бы сделать еще несколько догадок, чтобы приблизиться, скажем, увеличив стандартное отклонение до 0,06 кг, построив еще одно новое распределение под названием Pack06.

normal pack06(mean, 0.06);
cout << "Quantile of " << p << " = " << quantile(pack06, p)
  << ", mean = " << pack06.mean() << ", sd = " << pack06.standard_deviation() << endl;
// Quantile of 0.05 = 2.90131, mean = 3, sd = 0.06
cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean
  << " and standard deviation of " << pack06.standard_deviation()
  << " is " << cdf(complement(pack06, minimum_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.06 is 0.95221

Теперь мы действительно приближаемся, но для правильного выполнения работы нам, возможно, потребуется использовать метод поиска корней, например, инструменты, предоставленные и используемые в другом месте, в Math Toolkit, см.

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

Наш необходимый предел - минимальный вес = 2,9 кг, часто называемый случайной вариацией z. Для стандартного нормального распределения вероятность p = N((minimum_weight - среднее)/sd).

Мы хотим найти стандартное отклонение, которое было бы необходимо для достижения этого предела, так что p th quantile находится в точке z (минимальный вес). В этом случае квантиль 0,05 (5%) имеет вес упаковки 2,9 кг, в то время как средний вес составляет 3 кг, гарантируя, что 0,95 (95%) упаковок превышают минимальный вес.

Перегруппировавшись, можно напрямую рассчитать требуемое стандартное отклонение:

normal N01; // standard normal distribution with mean zero and unit standard deviation.
p = 0.05;
double qp = quantile(N01, p);
double sd95 = (minimum_weight - mean) / qp;
cout << "For the "<< p << "th quantile to be located at "
  << minimum_weight << ", would need a standard deviation of " << sd95 << endl;
// For the 0.05th quantile to be located at 2.9, would need a standard deviation of 0.0607957

Теперь мы можем построить новый (нормальный) пакет 95 распределения для «лучшего» упаковщика и проверить, что наш дистрибутив будет соответствовать спецификации.

normal pack95(mean, sd95);
cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean
  << " and standard deviation of " << pack95.standard_deviation()
  << " is " << cdf(complement(pack95, minimum_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95

Это вычисление обобщается в свободной функции find_scale, как показано ниже, давая такое же стандартное отклонение.

double ss = find_scale<normal>(minimum_weight, under_fraction, packs.mean());
cout << "find_scale<normal>(minimum_weight, under_fraction, packs.mean()); " << ss << endl;
// find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957

Если бы мы определили over_fraction или процент, который должен пройти спецификацию

double over_fraction = 0.95;

(неправильно написанный)

double sso = find_scale<normal>(minimum_weight, over_fraction, packs.mean());

С политикой дефолта мы получим сообщение, подобное

Message from thrown exception was:
   Error in function boost::math::find_scale<Dist, Policy>(double, double, double, Policy):
   Computed scale (-0.060795683191176959) is <= 0! Was the complement intended?

Но это вернетотрицательноестандартное отклонение — очевидно, невозможное. Вероятность должна быть 1 - over_fraction, а не over_fraction, таким образом:

double ss1o = find_scale<normal>(minimum_weight, 1 - over_fraction, packs.mean());
cout << "find_scale<normal>(minimum_weight, under_fraction, packs.mean()); " << ss1o << endl;
// find_scale<normal>(minimum_weight, under_fraction, packs.mean()); 0.0607957

Но обратите внимание, что использование 1 - over_fraction приведет к потере точности, особенно если over_fraction был близок к единству. (См.Почему это так?)В этом (очень распространенном) случае мы должны вместо этого использоватьдополнения, давая наиболее точный результат.

double ssc = find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean()));
cout << "find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); " << ssc << endl;
// find_scale<normal>(complement(minimum_weight, over_fraction, packs.mean())); 0.0607957

Обратите внимание, что наша догадка 0,06 была близка к точному значению 0,060795683191176959.

Мы можем подтвердить наш прогноз таким образом:

normal pack95c(mean, ssc);
cout <<"Fraction of packs >= " << minimum_weight << " with a mean of " << mean
  << " and standard deviation of " << pack95c.standard_deviation()
  << " is " << cdf(complement(pack95c, minimum_weight)) << endl;
// Fraction of packs >= 2.9 with a mean of 3 and standard deviation of 0.0607957 is 0.95

Обратите внимание, что эти два обманчиво простых вопроса:

  • Мы переполняем, чтобы убедиться, что мы удовлетворяем минимальным требованиям (или недополняем, чтобы избежать передозировки)?

и/или

  • Мы лучше измеряем?

На самом деле они чрезвычайно распространены.

Вес говядины может быть заменен измерением более или менее чего-либо, от содержания лекарственных таблеток, десантных ракетных стрельб Аполлона, доз рентгеновского лечения.

Шкала может быть вариацией в распределении или неопределенностью в измерении.

См.find_mean_and_sd_normal.cppдля полного исходного кода & добавлен выход программы.


PrevUpHomeNext

Статья Find mean and standard deviation example раздела Math Toolkit 2.5.0 Find Location and Scale Examples может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Find Location and Scale Examples ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 01:28:16/0.0071601867675781/0