Примечания к выпуску NumPy 1.17.0#
Этот релиз NumPy содержит ряд новых функций, которые должны значительно улучшить его производительность и полезность, см. Основные моменты ниже для краткого обзора. Поддерживаемые версии Python — 3.5-3.7, обратите внимание, что Python 2.7 был исключён. Python 3.8b2 должен работать с выпущенными исходными пакетами, но никаких гарантий на будущее нет.
Разработчикам нижестоящих проектов следует использовать Cython >= 0.29.11 для поддержки Python 3.8 и OpenBLAS >= 3.7 (пока не выпущен), чтобы избежать проблем на архитектуре Skylake. Колеса NumPy на PyPI собраны из ветки разработки OpenBLAS, чтобы избежать этих проблем.
Основные моменты#
Новый расширяемый
randomмодуль вместе с четырьмя выбираемыми генераторы случайных чисел и улучшенная инициализация генератора, предназначенная для использования в параллельных процессах, была добавлена. В настоящее время доступны следующие генераторы битов: MT19937, PCG64, Philox, и SFC64. См. ниже в разделе Новые возможности.NumPy
FFTреализация была изменена с fftpack на pocketfft, что привело к более быстрым и точным преобразованиям и лучшей обработке наборов данных простой длины. См. ниже в разделе Улучшения.Новые методы сортировки: поразрядная сортировка и timsort. В настоящее время невозможно выбрать, какой из них будет использоваться. Они жестко привязаны к типу данных и используются, когда либо
stableилиmergesortпередаётся как метод. Смотрите ниже в разделе Улучшения.Переопределение функций numpy теперь возможно по умолчанию, см.
__array_function__ниже.
Новые функции#
numpy.errstateтеперь также является декоратором функции
Устаревшие функции#
numpy.polynomial функции предупреждают при передаче float вместо int#
Ранее функции в этом модуле принимали float значения при условии, что они были целочисленными (1.0, 2.0, и т.д.). Для согласованности с остальной частью numpy,
это теперь устарело, и в будущем будет вызывать TypeError.
Аналогично, передача числа с плавающей точкой, такого как 0.5 вместо целого числа теперь вызовет
TypeError вместо предыдущего ValueError.
Устарело numpy.distutils.exec_command и temp_file_name#
Внутреннее использование этих функций было переработано, и есть лучшие альтернативы. Замените exec_command с subprocess.Popen и
temp_file_name с tempfile.mkstemp.
Флаг записи массивов, обёрнутых в C-API#
Когда массив создается из C-API для обертывания указателя на данные, единственное
указание на возможность чтения-записи данных — это writeable
флаг, установленный при создании. Опасно принудительно устанавливать флаг в записываемый. В будущем будет невозможно переключить флаг записи на True
из python. Это устаревание не должно затронуть многих пользователей, поскольку массивы, созданные таким образом, очень редки на практике и доступны только через NumPy C-API.
numpy.nonzero больше не должен вызываться на 0d массивах#
Поведение numpy.nonzero на 0d массивах было неожиданным, делая его использование почти всегда некорректным. Если старое поведение было задумано, его можно сохранить без предупреждения, используя nonzero(atleast_1d(arr)) вместо
nonzero(arr). В будущем релизе, скорее всего, это вызовет
ValueError.
Запись в результат numpy.broadcast_arrays будет предупреждать#
Обычно numpy.broadcast_arrays возвращает записываемый массив с внутренним
перекрытием, что делает его небезопасным для записи. В будущей версии будет установлен
writeable флаг для False, и требуют от пользователей вручную установить его в
True если они уверены, что это то, что они хотят сделать. Теперь запись в него будет выдавать предупреждение об устаревании с инструкциями по установке writeable флаг
True. Обратите внимание, что если проверить флаг перед его установкой,
можно обнаружить, что он уже True. Явная установка этого параметра, хотя и потребуется в будущих версиях, очищает внутренний флаг, используемый для генерации предупреждения об устаревании. Для уменьшения путаницы добавлен
FutureWarning будет выдаваться при доступе к writeable состояние флага для
уточнения противоречия.
Обратите внимание, что для протокола буфера на стороне C такой массив вернет буфер только для чтения, если не запрошен буфер для записи. Если запрошен буфер для записи, будет выдано предупреждение. При использовании Cython, const квалификатор следует использовать с такими массивами, чтобы избежать предупреждения (например, cdef const double[::1] view).
Будущие изменения#
Поля размерности 1 в типах данных не будут сворачиваться в скаляры в будущей версии#
В настоящее время поле, указанное как [(name, dtype, 1)] или "1type" интерпретируется как скалярное поле (т.е., то же самое, что [(name, dtype)] или
[(name, dtype, ()]). Теперь это вызывает FutureWarning; в будущей версии
это будет интерпретироваться как поле формы (1,), т.е. то же самое, что [(name,
dtype, (1,))] или "(1,)type" (согласованно с [(name, dtype, n)]
/ "ntype" с n>1, что уже эквивалентно [(name, dtype,
(n,)] / "(n,)type").
Примечания по совместимости#
float16 округление субнормальных чисел#
Преобразование из числа с плавающей точкой другой точности в float16 использовалось некорректное округление в некоторых крайних случаях. Это означает, что в редких случаях субнормальные результаты теперь будут округляться вверх вместо вниз, изменяя последний бит (ULP) результата.
Знаковый ноль при использовании divmod#
Начиная с версии 1.12.0, numpy некорректно возвращал отрицательный ноль
при использовании divmod и floor_divide functions, когда результат был нулевым. Например:
>>> np.zeros(10)//1
array([-0., -0., -0., -0., -0., -0., -0., -0., -0., -0.])
С этим выпуском результат правильно возвращается как положительно знаковый ноль:
>>> np.zeros(10)//1
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
MaskedArray.mask теперь возвращает представление маски, а не саму маску#
Возврат самой маски был небезопасен, так как её можно было изменить на месте, что
нарушило бы ожидания кода маскированного массива. Поведение mask теперь согласуется с data,
что также возвращает представление.
Базовая маска все еще может быть доступна с помощью ._mask если это необходимо.
Тесты, которые содержат assert x.mask is not y.mask или аналогичные потребуют обновления.
Не искать __buffer__ атрибут в numpy.frombuffer#
Поиск __buffer__ атрибут в numpy.frombuffer был недокументированным и нефункциональным. Этот код был удален. При необходимости используйте
frombuffer(memoryview(obj), ...) вместо этого.
out буферизуется для перекрытий памяти в take, choose, put#
Если аргумент out для этих функций предоставлен и имеет перекрытие памяти с другими аргументами, он теперь буферизуется, чтобы избежать поведения, зависящего от порядка.
Распаковка при загрузке требует явного согласия#
Функции load, и lib.format.read_array принять
allow_pickle ключевое слово, которое теперь по умолчанию False в ответ на
CVE-2019-6446.
Потенциальные изменения в потоке случайных чисел в старом модуле random#
Из-за ошибок в применении log к случайным числам с плавающей запятой,
поток может измениться при выборке из beta, binomial,
laplace, logistic, logseries или
multinomial если 0 генерируется в базовом MT19937
случайный поток. Существует 1 в
\(10^{53}\) вероятность этого события, поэтому вероятность того, что поток
изменится для любого заданного сида, крайне мала. Если 0 встречается в базовом генераторе, то некорректное значение, полученное (либо numpy.inf или
numpy.nan) теперь удаляется.
i0 теперь всегда возвращает результат с той же формой, что и входные данные#
Ранее выходные данные сжимались, так что, например, входные данные с единственным элементом приводили к возврату скаляра массива, а входные данные с такими формами, как (10, 1) даст результаты, которые не будут транслироваться на входные данные.
Обратите внимание, что мы обычно рекомендуем реализацию SciPy вместо numpy: это настоящая ufunc, написанная на C, и более чем на порядок быстрее.
can_cast больше не предполагает, что все небезопасные преобразования типов разрешены#
Ранее, can_cast возвращён True для почти всех входных данных для
casting='unsafe', даже для случаев, когда приведение было невозможно, например,
из структурированного dtype в обычный. Это исправлено, делая его
более согласованным с фактическим приведением с использованием, например, .astype
метод.
ndarray.flags.writeable может быть переключено на true немного чаще#
В редких случаях не удавалось переключить массив из режима только для чтения
в режим записи, хотя базовый массив доступен для записи. Это может произойти, если промежуточный ndarray.base объект доступен для записи. Ранее только самый глубокий базовый объект учитывался для этого решения. Однако в редких случаях этот объект не имеет необходимой информации. В таких случаях переключение на запись никогда не разрешалось. Теперь это исправлено.
Изменения в C API#
аргументы измерения или шага теперь передаются по npy_intp const*#
Ранее эти аргументы функций объявлялись как более строгие
npy_intp*, что предотвращало передачу постоянных данных вызывающей стороной. Это изменение обратно совместимо, но теперь позволяет код, подобный:
npy_intp const fixed_dims[] = {1, 2, 3};
// no longer complains that the const-qualifier is discarded
npy_intp size = PyArray_MultiplyList(fixed_dims, 3);
Новые возможности#
Новый расширяемый numpy.random модуль с выбираемыми генераторами случайных чисел#
Новый расширяемый numpy.random модуль вместе с четырьмя выбираемыми генераторами случайных чисел
и улучшенным начальным заполнением, предназначенным для использования в параллельных процессах, был
добавлен. В настоящее время доступные Bit Generators являются
MT19937, PCG64, Philox, и SFC64.
PCG64 является новым значением по умолчанию, в то время как MT19937 сохраняется для обратной
совместимости. Обратите внимание, что устаревший модуль random не изменен и теперь
заморожен, ваши текущие результаты не изменятся. Дополнительная информация доступна в Описание изменения API и в top-level view документация.
libFLAME#
Поддержка сборки NumPy с пакетом линейной алгебры libFLAME в качестве реализации LAPACK, см. libFLAME подробности.
Пользовательский порядок обнаружения BLAS#
distutils теперь использует переменную окружения, разделенную запятыми и нечувствительную к регистру, для определения порядка обнаружения библиотек BLAS.
По умолчанию NPY_BLAS_ORDER=mkl,blis,openblas,atlas,accelerate,blas.
Однако, чтобы принудительно использовать OpenBLAS, просто сделайте:
NPY_BLAS_ORDER=openblas python setup.py build
что вынуждает использовать OpenBLAS. Это может быть полезно для пользователей, у которых установлен MKL, но которые хотят попробовать другие реализации.
Пользовательский порядок обнаружения LAPACK#
numpy.distutils теперь использует переменную окружения, разделенную запятыми и нечувствительную к регистру, для определения порядка обнаружения библиотек LAPACK. По умолчанию NPY_LAPACK_ORDER=mkl,openblas,flame,atlas,accelerate,lapack.
Однако, чтобы принудительно использовать OpenBLAS, просто сделайте:
NPY_LAPACK_ORDER=openblas python setup.py build
что вынуждает использовать OpenBLAS. Это может быть полезно для пользователей, у которых установлен MKL, но которые хотят попробовать другие реализации.
Timsort и поразрядная сортировка заменили сортировку слиянием для стабильной сортировки#
Были реализованы поразрядная сортировка и Timsort, которые теперь используются вместо
сортировки слиянием. Из-за необходимости сохранения обратной совместимости, сортировка
kind опции "stable" и "mergesort" были сделаны псевдонимами друг друга, причём фактическая реализация сортировки зависит от типа массива. Сортировка по основанию используется для небольших целочисленных типов размером 16 бит или меньше, а timsort — для остальных типов. Timsort обеспечивает улучшенную производительность на данных, которые уже или почти отсортированы, и работает как сортировка слиянием на случайных данных, требуя \(O(n/2)\) рабочее пространство. Подробности алгоритма timsort можно найти на CPython listsort.txt.
packbits и unpackbits принимать order ключевое слово#
The order ключевое слово по умолчанию равно big, и будет упорядочивать биты
соответственно. Для 'order=big' 3 станет [0, 0, 0, 0, 0, 0, 1, 1],
и [1, 1, 0, 0, 0, 0, 0, 0] для order=little
unpackbits теперь принимает count параметр#
count позволяет заранее ограничить количество битов, которые будут распакованы, вместо последующего изменения формы и ограничения, что делает packbits операция обратима, и распаковка менее расточительна. Счётчики, превышающие количество доступных битов, добавляют нулевое заполнение. Отрицательные счётчики обрезают биты с конца вместо подсчёта с начала. None счётчики реализуют существующее поведение распаковки всего.
linalg.svd и linalg.pinv может быть быстрее на эрмитовых входных данных#
Эти функции теперь принимают hermitian аргумент, соответствующий добавленному
в linalg.matrix_rank в версии 1.14.0.
Операция divmod теперь поддерживается для двух timedelta64 операнды#
Оператор divmod теперь обрабатывает два timedelta64 операнды, с
сигнатурой типа mm->qm.
fromfile теперь принимает offset аргумент#
Эта функция теперь принимает offset ключевой аргумент для бинарных файлов, который указывает смещение (в байтах) от текущей позиции файла.
По умолчанию 0.
Новый режим "empty" для pad#
Этот режим дополняет массив до желаемой формы без инициализации новых элементов.
Скаляры с плавающей точкой реализуют as_integer_ratio чтобы соответствовать встроенному float#
Это возвращает пару (числитель, знаменатель), которую можно использовать для построения
fractions.Fraction.
Структурированный dtype объекты могут индексироваться несколькими именами полей#
arr.dtype[['a', 'b']] теперь возвращает dtype, эквивалентный
arr[['a', 'b']].dtype, для согласованности с
arr.dtype['a'] == arr['a'].dtype.
Подобно dtype структурированных массивов, индексированных списком полей, этот dtype
имеет то же самое itemsize как исходный, но сохраняет только подмножество полей.
Это означает, что arr[['a', 'b']] и arr.view(arr.dtype[['a', 'b']]) эквивалентны.
.npy файлы поддерживают имена полей в юникоде#
Была введена новая версия формата 3.0, которая позволяет структурированным типам с именами полей не на латинице. Это используется автоматически при необходимости.
Улучшения#
Утверждения сравнения массивов включают максимальные различия#
Сообщения об ошибках из тестов сравнения массивов, таких как
testing.assert_allclose теперь включают «максимальную абсолютную разницу» и
«максимальную относительную разницу» в дополнение к предыдущему проценту «несоответствия».
Эта информация упрощает обновление абсолютных и относительных допусков ошибок.
Замена основанного на fftpack fft модуль библиотекой pocketfft#
Обе реализации имеют общего предка (Fortran77 FFTPACK от Paul N. Swarztrauber), но pocketfft содержит дополнительные модификации, которые улучшают как точность, так и производительность в некоторых случаях. Для длин БПФ, содержащих большие простые множители, pocketfft использует алгоритм Блюстейна, который сохраняет \(O(N log N)\) временная сложность выполнения вместо ухудшения до \(O(N*N)\) для простых длин. Также точность для вещественных FFT с почти простыми длинами улучшилась и сравнялась с точностью комплексных FFT.
Дальнейшие улучшения для ctypes поддержка в numpy.ctypeslib#
Новый numpy.ctypeslib.as_ctypes_type функция была добавлена, которая может использоваться для преобразования dtype в наилучшее предположение ctypes тип. Благодаря этой
новой функции, numpy.ctypeslib.as_ctypes теперь поддерживает гораздо более широкий диапазон
типов массивов, включая структуры, логические значения и целые числа с нестандартным
порядком байтов.
numpy.errstate теперь также является декоратором функции#
В настоящее время, если у вас есть функция, такая как:
def foo():
pass
и вы хотите обернуть все это в errstate, вам нужно переписать это
так:
def foo():
with np.errstate(...):
pass
но с этим изменением вы можете сделать:
@np.errstate(...)
def foo():
pass
тем самым сохраняя уровень вложенности
numpy.exp и numpy.log ускорение для реализации float32#
реализация float32 exp и log теперь используют преимущества набора инструкций AVX2/AVX512,
которые определяются во время выполнения. exp имеет максимальную ошибку ulp
2.52 и log имеет максимальную ошибку ulp 3.83.
Улучшена производительность numpy.pad#
Производительность функции была улучшена для большинства случаев путем заполнения предварительно выделенного массива желаемой формой с заполнением вместо использования конкатенации.
numpy.interp более надежно обрабатывает бесконечности#
В некоторых случаях, когда interp ранее возвращал nan, теперь он возвращает соответствующую бесконечность.
Поддержка Pathlib для fromfile, tofile и ndarray.dump#
fromfile, ndarray.ndarray.tofile и ndarray.dump теперь поддерживают pathlib.Path тип для file/fid параметр.
Специализированный isnan, isinf, и isfinite ufuncs для типов bool и int#
Булевские и целочисленные типы не способны хранить nan и inf значений, что позволяет нам предоставлять специализированные универсальные функции, которые работают до 250 раз быстрее, чем предыдущий подход.
isfinite поддерживает datetime64 и timedelta64 типы#
Ранее, isfinite использовался для вызова TypeError при использовании на этих
двух типах.
Новые ключевые слова, добавленные в nan_to_num#
nan_to_num теперь принимает ключевые слова nan, posinf и neginf
позволяя пользователю определить значение для замены nan, положительные и
отрицательные np.inf значения соответственно.
MemoryErrors, вызванные выделением слишком больших массивов, более описательны#
Часто причиной MemoryError является некорректное вещание, которое приводит к очень большой и неправильной форме. Сообщение об ошибке теперь включает эту форму, чтобы помочь диагностировать причину сбоя.
floor, ceil, и trunc теперь учитываются встроенные магические методы#
Эти ufunc теперь вызывают __floor__, __ceil__, и __trunc__
методы при вызове на объектных массивах, делая их совместимыми с
decimal.Decimal и fractions.Fraction объекты.
quantile теперь работает на fraction.Fraction и decimal.Decimal объекты#
В целом, это более корректно обрабатывает массивы объектов и избегает операций с плавающей точкой, если используются типы для точной арифметики.
Поддержка массивов объектов в matmul#
Теперь можно использовать matmul (или @ оператор) с массивами объектов.
Например, теперь можно сделать:
from fractions import Fraction
a = np.array([[Fraction(1, 2), Fraction(1, 3)], [Fraction(1, 3), Fraction(1, 2)]])
b = a @ a
Изменения#
median и percentile семейство функций больше не предупреждает о nan#
numpy.median, numpy.percentile, и numpy.quantile используется для выдачи
RuntimeWarning при встрече с nan. Поскольку они возвращают
nan значение, предупреждение избыточно и было удалено.
timedelta64 % 0 поведение скорректировано для возврата NaT#
Операция модуля с двумя np.timedelta64 операнды теперь возвращает
NaT в случае деления на ноль, а не возврата нуля
Функции NumPy теперь всегда поддерживают переопределения с __array_function__#
NumPy теперь всегда проверяет __array_function__ метод для реализации переопределений
функций NumPy на не-NumPy массивах, как описано в NEP 18. Функция
была доступна для тестирования в NumPy 1.16, если установлены соответствующие переменные окружения,
но теперь всегда включена.
lib.recfunctions.structured_to_unstructured не сжимает представления с одним полем#
Ранее structured_to_unstructured(arr[['a']]) привело бы к сжатому
результату, несовместимому с structured_to_unstructured(arr[['a', b']]). Это было случайно. Прежнее поведение можно сохранить с помощью
structured_to_unstructured(arr[['a']]).squeeze(axis=-1) или гораздо проще,
arr['a'].
clip теперь использует ufunc в основе#
Это означает, что регистрация функций clip для пользовательских типов данных в C через
descr->f->fastclip устарел - вместо этого следует использовать механизм регистрации ufunc, прикрепляя к np.core.umath.clip универсальная функция.
Это также означает, что clip принимает where и casting аргументы, и могут быть переопределены с помощью __array_ufunc__.
Следствием этого изменения является то, что некоторые поведения старого clip были устаревшими:
Передача
nanозначает "не обрезать" как одну или обе границы. Это не работало во всех случаях в любом случае, и может быть лучше обработано передачей бесконечностей соответствующего знака.Использование «небезопасного» приведения по умолчанию, когда
outаргумент передается. Используяcasting="unsafe"явно отключит это предупреждение.
Кроме того, есть некоторые крайние случаи с изменениями поведения:
Заполнение
max < minизменился, чтобы быть более согласованным между типами данных, но на это не следует полагаться.Скаляр
minиmaxучаствуют в правилах продвижения типов, как и во всех других универсальных функциях.
__array_interface__ offset теперь работает как описано в документации#
Интерфейс может использовать offset значение, которое было ошибочно проигнорировано.
Протокол Pickle в savez установлено в 3 для force zip64 флаг#
savez не использовал force_zip64 флаг, который ограничивал размер архива 2 ГБ. Но использование флага требует от нас использования протокола pickle 3 для записи object массивы. Используемый протокол был обновлен до версии 3, что означает, что архив
не будет читаться Python2.
Структурированные массивы, индексированные несуществующими полями, вызывают KeyError не ValueError#
arr['bad_field'] на структурированном типе вызывает KeyError, для согласованности
с dict['bad_field'].