Обзор модуля Uncertainties.
Введение
В предыдущем туториале Применение языка Python в инженерной практике. Обзор модуля Pint / Хабр было сказано, что результат любых инженерных измерений и расчётов не имеет никакого смысла, если не указаны две его основные характеристики: единица измерения и точность. Как использовать единицы измерения при вычислениях на Питоне мы уже обсудили - теперь перейдём к точности и связанным ней понятиям погрешности и неопределённости
Погрешность измерения — это отклонение измеренного значения величины от её истинного (действительного) значения. Погрешность измерения является характеристикой точности измерения. Выяснить с абсолютной точностью истинное значение измеряемой величины, как правило, невозможно, поэтому невозможно и указать величину отклонения измеренного значения от истинного. Это отклонение принято называть ошибкой измерения. Возможно лишь оценить величину этого отклонения, например, при помощи статистических методов. На практике вместо истинного значения используют действительное значение величины , то есть значение физической величины, полученное экспериментальным путём и настолько близкое к истинному значению, что в поставленной измерительной задаче может быть использовано вместо него. Такое значение обычно вычисляется как среднестатистическое значение, полученное при статистической обработке результатов серии измерений. Это полученное значение не является точным, а лишь наиболее вероятным. Поэтому при записи результатов измерений необходимо указывать их точность. Например, запись
означает, что истинное значение величины
лежит в интервале от 2.7 s до 2.9 s с доверительной вероятностью 95%. Количественная оценка величины погрешности измерения — мера сомнения в измеряемой величине — приводит к такому понятию, как неопределённость измерения. Синонимом термина "погрешность измерения" (англ. measurement error) является "неопределённость измерения" (англ. measurement uncertainty). Таким образом мы плавно и ненавязчиво подошли к названию модуля языка Питон, которому посвящён настоящий туториал -
uncertainties
(неопределённости).
Установка и подключение модуля
Установка модуля производится стандартным для Python образом:
c:\>pip install uncertainties
Если вы используете менеджер Anaconda, то команда установки будет такой:
c:\>conda install uncertainties --channels conda-forge
Для использования модуля его надо импортировать в вашу программу. Рекомендуется это делать следующими командами:
>>>from uncertainties import ufloat, ufloat_fromstr, uarray, umatrix
>>>from uncertainties.umath import * # импортировать математические функции
>>>from uncertainties.unumpy import * # импортировать функции для работы с массивами NumPy
Создание чисел с неопределённостями
Для примера введём в программу число
>>>x = ufloat(0.20, 0.01)
>>>print('{:.2eP}'.format(x))
Помимо непосредственного ввода числа возможен ввод парсингом строковых его представлений:
>>>x = ufloat_fromstr("0.20+/-0.01")
>>>x = ufloat_fromstr("(2+/-0.1)e-01")
>>>x = ufloat_fromstr("0.20(1)")
>>>x = ufloat_fromstr("20(1)e-2")
>>>x = ufloat_fromstr(u"0.20±0.01")
Все эти варианты ввода приведут к одному и тому же результату
Более подробную информацию о парсинге строк можно получить консольной командой:
pydoc uncertainties.ufloat_fromstr
Введённое число фактически состоит из двух частей - номинального значения (.nominal_value
) и стандартного отклонения (.std_dev
)
>>>print(x.nominal_value)
>>>print(x.std_dev)
Аналогичные результаты можно получить и с помощью функций nominal_value()
и std_dev()
.
Наконец, предусмотрен служебный метод, который непосредственно возвращает стандартную оценку - число стандартных отклонений между числом, вводимом в аргументе метода, и результатом с неопределенностью:
>>>print(x.std_score(0.17))
Cтандартные отклонения введённых чисел можно изменять:
>>>x.std_dev = 0.05
>>>print(x.std_dev)
Модуль предусматривает ещё и третью часть .tag
- cвоего рода пояснение к переменной
>>>u = ufloat(1, 0.05, "u variable")
>>>print(u.tag)
u variable
>>>u
<u variable = 1.0+/-0.05 >
Теги не обязательно должны быть различными.
ПРИМЕЧАНИЕ 1: Tag переменной при выполнении вычислений результату не передаётся
ПРИМЕЧАНИЕ 2: Tag переменной может быть утерян, при использовании переменной в операциях из других модулей Python
Основы математики
Простые вычисления между числами с неопределённостями с помощью математических операторов выполняются как с обычными вещественными числами - за счёт перегрузки операторов библиотекой:
>>>summa = x + x
>>>print('{:.2eP}'.format(summa))
>>>square = x**2
>>>print('{:.2eP}'.format(square))
Разумеется, полностью аналогично можно применять операторы вычитания, умножения и деления, а так же операторы сравнения:
>>>y = ufloat(0.50, 0.01)
>>>print('{:.2P}'.format(y))
>>>print(x < y)
True
>>>print(x > y)
False
Так же можно умножать и делить число с неопределённостью на целые или вещественные числа, но складывать и вычитать нельзя. Не работают с числами с неопределённостями и функции модулей math
и numpy
. Как раз для замены этих функций мы и импортировали выше библиотеки uncertainties.umath
и uncertainties.unumpy
.
ПРИМЕЧАНИЕ: Строго говоря, операции с целыми и вещественными числами ошибку не вызовут, но надо помнить, что результат такой операции будет соответственно целым или вещественным, т.е. неопределённость будет потеряна. Поэтому для изменения только номинального значения с сохранением стандартного отклонения надо сложить (вычесть) с числом, имеющим неопределённость
Модуль uncertainties.umath
содержит одноимённые варианты (с добавлением символа "u" перед именем) для работы с числами с неопределённостями для всех функций стандартного модуля math
. В принципе, ничего особенно добавить здесь нечего.
Неопределённости в массивах
Массивы чисел с неопределенностями могут быть построены из списков значений и их неопределенностей:
>>>arr = uarray([1, 2], [0.01, 0.002])
>>>print('{:.2P}'.format(arr))
>>>arr = uarray([1, 2], [0.01, 0.002])
>>>print('{:.2P}'.format(arr))
Векторы и матрицы чисел с неопределенностями можно создавать аналогично массивам:
>>>mat = umatrix([1, 2], [0.01, 0.002])
Корреляции
Корреляции между переменными обрабатываются автоматически независимо от количества задействованных переменных и сложности вычислений:
>>>square = x**2
>>>print ('{:.2P}'.format(square))
>>>y = x * x + 1
>>>difference = y - square
>>>print ('{:.2P}'.format(difference))
Модуль содержит функции для вычисления ковариационной и корелляционной матриц неопределённостей:
>>>sum_value = u + 2 * v
>>>cov_matrix = covariance_matrix([u, v, sum_value])
>>>cov_matrix
[[0.01, 0.0, 0.01],
[0.0, 0.01, 0.02],
[0.01, 0.02, 0.05]]
>>>corr_matrix = correlation_matrix([u, v, sum_value])
>>>corr_matrix
[[ 1. , 0. , 0.4472136 ],
[ 0. , 1. , 0.89442719],
[ 0.4472136 , 0.89442719, 1. ]]
Через ковариационную матрицу можно получить коррелированные переменные:
>>>(u2, v2, sum2) = correlated_values([1, 10, 21], cov_matrix)
>>>print('{:.2P}'.format(sum_value))
>>>print('{:.P}'.format(sum2))
>>>print('{:.2eP}'.format(sum2 - (u2+2*v2)))
Доступ к отдельным источникам неопределенности
Различные вклады в неопределенность могут быть получены с помощью метода .error_components()
В соответствии с теорией линейного распространения ошибок, cумма квадратов этих вкладов равна квадрату неопределённости:
>>>u = ufloat(1, 0.1, "u variable")
>>>v = ufloat(10, 0.1, "v variable")
>>>sum_value = u+2*v
>>>print('{:2P}'.format(sum_value))
for (var, error) in sum_value.error_components().items():
... print "{}: {}".format(var.tag, error)
...
u variable: 0.1
v variable: 0.2
Дисперсия (т.е. квадрат неопределенности) результата – квадратичная сумма этих независимых неопределенностей.