Open in Colab

© Семён Лукашевский сайт автора

Пожалуй, первое с чего стоит начать, так это с того, что массивы NumPy могут быть обычными операндами в математических выражениях:

Для выполнения таких операций на Python, мы были вынуждены писать циклы.

Писать такие циклы в NumPy, нет никакой необходимости, потому что все операции и так выполняются поэлементно:

Точно так же обстоят дела и с математическими функциями:

Такие операции как +=, -=, *=, /= и прочие подобные, могут применяться к массивам и так же выполняются поэлементно.

Они не создают новый массив, а изменяют старый:

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

Применение логических операций к массивам, так же возможно и так же выполняется поэлементно.

Результатом таких операций является массив булевых значений (True и False):

Мы уже знаем что массив и число могут быть операндами самых разных математических выражений:

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

Хотя, если честно, их размеры должны быть не равны, а должны быть совместимыми.

Если их размеры совместимы, т.е. один массив может быть растянут до размеров другого, то в дело включается механизм транслирования массивов NumPy.

Этот механизм очень прост, но имеет весьма специфичные нюансы.

Рассмотрим простой пример:

В данном примере массив b может быть растянут до размеров массива a и станет абсолютно идентичен массиву c.

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

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

Вычисление суммы всех элементов в массиве и прочие унарные операции в NumPy реализованы как методы класса ndarray:

По умолчанию, эти операции применяются к массиву, как к обычному списку чисел, без учета его ранга (размерности).

Но если указать в качестве параметра одну из осей axis, то вычисления будут производиться именно по ней:

Значения -inf, inf и nan

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

Убедимся в этом еще раз:

Более того, в NumPy мы даже можем делить на ноль:

NumPy предупредил нас о том, что встретил деление на ноль, но тем не менее выдал ответ inf (плюс бесконечность).

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

Если результатом математической операции является плюс или минус бесконечность, то логичнее выдать значение inf или -inf, чем выдавать ошибку.

В NumPy есть еще одно специальное значение - nan. Данное значение выдается тогда, когда результат вычислений не удается определить:

Заметьте, что NumPy нас просто предупредил о том, что ему попалось недопустимое значение, но ошибки не возникло.

Дело в том, что в реальных вычислениях значения nan, inf или -inf встречается очень часто, поэтому появление этого значения проще обрабатывать специальными методами (функции numpy.isnan() и numpy.isinf()), чем постоянно лицезреть сообщения об ошибках.

Новичкам, довольно трудно привыкнуть, к тому что в недрах компьютера вся арифметика на самом деле является двоичной и с этим связано очень много казусов.

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

Число 1.633123935319537e+16 появилось потому что в NumPy выполняются арифметические, а не символьные вычисления, т. е. число π хранится в памяти компьютера не как знание о том, что это математическая константа с бесконечным количеством десятичных знаков после запятой, а как обычное число с десятичной точкой (десятичная дробь) равная числу π с очень маленькой, но все же, погрешностью:

Если из-за самых незначительных погрешностей вычисления все же возможны, то NumPy их обязательно выполнит.

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

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

Если вы решили отправиться в самые дебри теории чисел, алгебры и криптографии, то лучшим решением окажется программа GAP.

Программа GAP не является программой Python, но имеет Python интерфейс в замечательной программе Sage, которая определенно заслуживает вашего внимания (см. книгу).

Линейная алгебра

Много функций.

Произведение одномерных массивов представляет собой скалярное произведение векторов:

Произведение двумерных массивов по правилам линейной алгебры также возможно:

При этом размеры матриц (массивов) должны быть либо равны, а сами матрицы квадратными, либо быть согласованными, т.е. если размеры матрицы А равны [m,k], то размеры матрицы В должны быть равны [k,n]:

Также по правилам умножения матриц, мы можем умножить матрицу на вектор (одномерный массив).

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

Квадратные матрицы можно возводить в степень n т.е. умнажать сами на себя n раз:

Довольно часто приходится вычислять ранг матриц:

Еще чаще приходится вычислять определитель матриц, хотя результат вас может немного удивить:

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

Это связано с тем, что алгоритм вычисления определителя использует LU-разложение - это намного быстрее, чем обычный алгоритм, но за скорость все же приходится немного заплатить ручным округлением (конечно, если таковое требуется):

Транспонирование матриц:

Вычисление обратных матриц:

Решение систем линейных уравнений:

Статистика

Элементарные статистические функции:

Средние значения элементов массива и их отклонения:

Корреляционные коэфициенты и ковариационные матрицы величин:

Так же NumPy предоставляет функции для вычисления гистограмм наборов данных различной размерности и некоторые другие статистичские функции.

Генерация случайных значений

Получение простых случайных данных:

Перестановки:

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

Вы так же имеете доступ к состоянию генератора случайных чисел, а так же можете управлять им:

Множества

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

В двумерных и многомерных массивах уникальные массивы можно искать, как по всему множеству его значений, так и по отдельным осям:

Так же имеется ряд других полезных функций:

Логические операции

Логические функции NumPy, условно, можно разделить на два множества: первое - позволяет определять специфику элементов массива и самого массива; второе - обычные логические операции, которые действуют над массивами поэлементно.

Иногда, возникает потребность определить тип элементов:

Привычные нам логические операции выполняются над массивами булевых значений (массивы из значений True и False):

Помимо всего прочего, NumPy позволяет производить различные сравнения: