05 декабря 2016

Базовые функции SciPy

Взаимодействие с Numpy

SciPy основывается на Numpy, поэтому для всех основных видов обработки массива можно использовать функции Numpy:

>>> import numpy as np
>>> np.some_function()


Вместо того, чтобы давать подробное описание каждой из этих функций (которые можно найти в справочном руководстве по Numpy или с помощью команд help, info и source, в данном руководстве мы обсудим некоторые из наиболее полезных команд, которые требуют небольшого введения для использования всего их потенциала

Для использования функции из модулей SciPy:

>>> from scipy import some_module
>>> some_module.some_function()


Верхний уровень SciPy также содержит функции из NumPy и numpy.lib.scimath. Тем не менее, лучше использовать их непосредственно из модуля NumPy.

Хитрости с указателями

Есть некоторые экземпляры классов, которые используют специальную функциональность нарезания для обеспечения эффективности построения массива. Эта часть будет обсуждать работу np.mgrid, np.ogrid, np.r_ и np.c_ для быстрого построения массивов.

Например, вместо того, чтобы писать что-то вроде следующий

>>> a = np.concatenate(([3], [0]*5, np.arange(-1, 1.002, 2/9.0)))

с r_ командой можно ввести это как:

>>> a = np.r_[3,[0]*5,-1:1:10j]

это облегчит ввод и сделает код более читаемым. Обратите внимание на синтаксис сцепления и разделения объектов, который используется для построения диапазонов. Другой момент, который заслуживает небольшого объяснения — использование комплексного числа 10j как размер шага в синтаксисе разделения. Это нестандартное использование числа должно интерпретироваться как число точек в диапазоне, а не размера шага (обратите внимание, мы бы использовали длинное целое обозначение, 10L, но эта запись может интерпретироваться Python, как приведение к целому). Это нестандартное использование может быть ненаглядным для некоторых, но это дает пользователю возможность быстро построить сложные векторы в очень доступной форме. Когда число точек задается таким образом, конечная точка включается в диапазон.

"r" обозначает строку конкатенации, поэтому, если объекты между запятыми двумерные массивы, они соединяются построчно (и, следовательно, должны быть соразмерные столбцы). Существует эквивалентная команда c_, которая складывает двумерные массивы по столбцам, но работает идентично r_ для одномерных массивов.

Еще один очень полезный экземпляр класса, который позволяет использование расширенной нотации квантования функции mgrid. В простейшем случае эта функция может быть использована для построения одномерных диапазонов в качестве удобной замены для arange. Она также позволяет использовать комплексное число в размер шага, для указания количества точек для размещения между (включительно) конечными точками. Истинная цель этой функции, получения N-мерных массивов, которые обеспечивают координаты массива для N-мерного объема. Самый простой способ понять — это пример его использования:

>>> np.mgrid[0:5,0:5]
array([[[0, 0, 0, 0, 0],
[1, 1, 1, 1, 1],
[2, 2, 2, 2, 2],
[3, 3, 3, 3, 3],
[4, 4, 4, 4, 4]],
[[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]]])
>>> np.mgrid[0:5:4j,0:5:4j]
array([[[ 0. , 0. , 0. , 0. ],
[ 1.6667, 1.6667, 1.6667, 1.6667],
[ 3.3333, 3.3333, 3.3333, 3.3333],
[ 5. , 5. , 5. , 5. ]],
[[ 0. , 1.6667, 3.3333, 5. ],
[ 0. , 1.6667, 3.3333, 5. ],
[ 0. , 1.6667, 3.3333, 5. ],
[ 0. , 1.6667, 3.3333, 5. ]]])


Для массивов, имеющих сложную топологию, это иногда бывает очень полезно. Тем не менее, иногда нужно просто оценить некоторую N-мерную функции над сеткой из-за массива вещания правил Numpy и SciPy. Если это единственная цель для создания meshgrid, вы должны вместо этого использовать функцию ogrid, который генерирует "открытую" сетку , используя newaxis , чтобы создать N-мерные массивы, где только одно измерение в каждом массиве имеет длину больше 1. Это позволит сэкономить память и получить один и тот же результат, если единственная цель для meshgrid является создание точек отбора проб для оценки N-мерной функции.

Многочлены

Есть два взаимозаменяемых способа работы с одномерными полиномами в SciPy. Во-первых, использование класса poly1d из Numpy. Этот класс принимает коэффициенты или полиномиальные корни, чтобы инициализировать многочлен. Объект полинома можно использовать в алгебраических выражениях, интегрировании, дифференцировании, и вычисления. Он также выводится как полином:

>>> from numpy import poly1d
>>> p = poly1d([3,4,5])
>>> print p
2
3 x + 4 x + 5
>>> print p*p
4 3 2
9 x + 24 x + 46 x + 40 x + 25
>>> print p.integ(k=6)
3 2
1 x + 2 x + 5 x + 6
>>> print p.deriv()
6 x + 4
>>> p([4, 5])
array([ 69, 100])

Другой способ работы с многочленами — как с массивом коэффициентов: первый элемент массива дает коэффициент старшего порядка. Есть явные функции сложения, вычитания, умножения, деления, интегрирования, дифференцирования, и вычисления полиномов, представленных в виде последовательности коэффициентов.

Векторизация функций

Одной из возможностей, обеспечиваемой NumPy — преобразование обычной функции Python, которая принимает скаляры и возвращает скаляры в "Векторизованные-функции" с теми же правилами работы, как и другие функции NumPy (то есть Универсальные функции, или ufuncs). Например, предположим, что у вас есть функция Python с именем addsubtract определяемая следующим образом:

>>> def addsubtract(a,b):
... if a > b:
... return a - b
... else:
... return a + b


которая определяет функцию двух скалярных переменных и возвращает скалярный результат. Класс векторизации может быть использован для "векторизации" этой функции следующим образом:

>>> vec_addsubtract = np.vectorize(addsubtract)

команда возвращает функцию, которая принимает в качестве аргумента массив и возвращает результирующий массив:

>>> vec_addsubtract([0,3,6,9],[1,3,5,7])
array([1, 6, 1, 2])


Эта конкретная функция могла быть написана в векторной форме без использования Vectorize. Но, что если функция, которую вы написали, является результатом некоторой оптимизации или интеграции. Такие функции, зачастую, могут быть векторизованы только с помощью vectorize

Обработка типов

Обратите внимание на разницу между np.iscomplex/np.isreal и np.iscomplexobj/np.isrealobj. Первые команды основаны на массиве и возвращает массив байт нулей и единиц, и вычисляют результат поэлементно. Вторые команды — объекты, основанные и возвращающие скаляры, описывающий результат на всем объекте.

Часто требуется, получить только действительную и/или мнимую части комплексного числа. В то время как комплексные числа и массивы имеют атрибуты, которые возвращают эти значения, если вы не уверены, в том, что объект будет комплекснозначным, то лучше использовать функциональные формы np.real и np.imag. Эти функции могут быть превращены в массив Numpy. Рассмотрим также функцию np.real_if_close, преобразовывающую комплексно-значных числа с малой мнимой частью в вещественное число.

Иногда необходимо проверить, является ли или нет число является скаляром (Python (long)int, Python float, Python complex, или массивом с нулевым рангом) при кодировании. Эта функциональность обеспечивается удобной функцией np.isscalar, которая возвращает 1 или 0.

И, наконец, вследствие того, что объекты определенных типа Numpy используются достаточно часто, был создан интерфейс в SciPy через использование np.cast словаря. Словарь имеет ключ по типу желательной цели приведения словарных функций и хранит значения для выполнения приведения. Таким образом, np.cast['f'](d) возвращает массив np.float32 из d. Эта функция также полезна как простой способ, получения скаляр определенного типа:
>>> np.cast['f'](np.pi)
array(3.1415927410125732, dtype=float32)


Другие полезные функции

Имеется также несколько других полезных функций, которые должны быть упомянуты. Они полезны для обработки фазы, угла и развертки функции. Кроме того, linspace и logspace функции возвращают равноудаленные представления в линейной или логарифмической шкале. И, наконец, полезно знать о возможностях индексирования Numpy. Следует упомянуть о функции select, которая расширяет функциональные возможности, и может включать множественное условие или множественный выбор. Соглашение о вызове select(condlist,choicelist,default=0). select это векторизованная форма множественного условия. Она позволяет быстро создавать функции, которые возвращают массив результатов на основе списка условий. Каждый элемент возвращаемого массива берется из массива в choicelist соответствующем первому верному условию в condlist. Например:

>>> x = np.r_[-2:3]
>>> x
array([-2, -1, 0, 1, 2])
>>> np.select([x > 3, x >= 0], [0, x+2])
array([0, 0, 2, 3, 4])


Некоторые дополнительные полезные функции также могут быть найдены в модуле scipy.misc. Например факториальные и комбинаторные функции вычисления n! и n!/k!(n−k)! с использованием либо точной арифметики целых чисел (с использованием длинного целого Python), или с помощью вычислений с плавающей запятой и гамма-функции. Другие функции возвращают общее изображение, используемое при обработке изображений: lena.

Наконец, две функции, которые могут быть использованы для аппроксимации производных функций с использованием дискретных разностей. Функция central_diff_weights возвращает весовые коэффициенты для равномерно разнесенных N-точечных приближения к производной порядка o. Эти весовые коэффициенты должны быть умножены на функцию, соответствующую этим точкам, а результаты складываются, чтобы получить приближенную производную. Эта функция предназначена для использования, если доступны образцы функции. Когда функция является объектом, который может быть передан в процедуру и вычислена, функция производной может быть использована для автоматической оценки объекта в правильных точках, для получения аппроксимации в N-точках к нулевой производной в данной точке.