Python ravel что это
numpy.ravel¶
Return a contiguous flattened array.
A 1-D array, containing the elements of the input, is returned. A copy is made only if needed.
As of NumPy 1.10, the returned array will have the same type as the input array. (for example, a masked array will be returned for a masked array input)
Parameters a array_like
Input array. The elements in a are read in the order specified by order, and packed as a 1-D array.
order <‘C’,’F’, ‘A’, ‘K’>, optional
The elements of a are read using this index order. ‘C’ means to index the elements in row-major, C-style order, with the last axis index changing fastest, back to the first axis index changing slowest. ‘F’ means to index the elements in column-major, Fortran-style order, with the first index changing fastest, and the last index changing slowest. Note that the ‘C’ and ‘F’ options take no account of the memory layout of the underlying array, and only refer to the order of axis indexing. ‘A’ means to read the elements in Fortran-like index order if a is Fortran contiguous in memory, C-like order otherwise. ‘K’ means to read the elements in the order they occur in memory, except for reversing the data when strides are negative. By default, ‘C’ index order is used.
Returns y array_like
1-D iterator over an array.
1-D array copy of the elements of an array in row-major order.
Change the shape of an array without changing its data.
In row-major, C-style order, in two dimensions, the row index varies the slowest, and the column index the quickest. This can be generalized to multiple dimensions, where row-major order implies that the index along the first axis varies slowest, and the index along the last quickest. The opposite holds for column-major, Fortran-style index ordering.
When a view is desired in as many cases as possible, arr.reshape(-1) may be preferable.
Библиотека Numpy. Полезные инструменты
В статье рассмотрены некоторые полезные инструменты из библиотеки Numpy, которые довольно часто приходится использовать при решении задач в рамках машинного обучения и анализа данных.
Создание векторов и матриц
Вектора и матрицы – это основные объекты, которыми приходится оперировать в машинном обучении. Numpy предоставляет довольно много удобных функций, которые строят эти объекты.
Перед тем как их использовать не забудьте импортировать Numpy в проект.
np.arange()
Синтаксис использования функции следующий:
arange(start, stop, step)
Второй вариант позволяет задавать интервал, в этом случае вектор также будет содержать целые числа.
Третий вариант позволяет определить интервал чисел и шаг, который может быть десятичным числом
np.matrix()
Matrix является удобным инструментом для задания матрицы. При этом можно использовать Matlab стиль, либо передать в качестве аргумента список Python (или массив Numpy ).
Вариант в Matlab стиле.
np.zeros(), np.eye()
Функция eye() создает единичную матрицу – квадратную матрицу, у которой элементы главной диагонали равны единицы, все остальные – нулю.
Работа с матрицами и векторами
Вектора и матрицы, построенные с помощью Numpy можно складывать, вычитать, умножать, транспонировать и умножать на число. Перечисленные операции используются в большинстве задач, более специфические функции, в рамках данной статьи, рассматриваться не будут.
Создадим две матрицы.
Сложение матриц
Вычитание матриц
Умножение матрицы на число
Умножение матриц
Транспонирование матриц
… И другие полезные функции
Далее будет представлен список функций, их описание и пример использования, которые могут быть полезны, если о них знать)
np.ravel()
Функция np.ravel() используется для того, чтобы преобразовать матрицу в одномерный вектор.
Применим функцию ravel() к этой матрице.
Если указать order = ‘F ‘, то в качестве элементов для сборки будут выступать столбцы матрицы.
np.where()
Данная функция возвращает один из двух заданных элементов в зависимости от условия. Ее можно использовать для обработки численных данных.
В задачах машинного обучения эта функция хорошо подходит для реализации обработки данных с помощью пороговой функции.
np.meshgrid()
Функция meshgrid() позволят получить матрицу координат из координатных векторов. Если, например, у нас есть два одномерных вектора координат, то передав их в качестве аргументов в meshgrid() мы получим две матрицы, в которой элементы будут составлять пары, заполняя все пространство, определяемое этими векторами. Проще посмотреть это на примере.
Создадим два вектора
Для начала импортируем matplotlib (он должен быть установлен).
Теперь построим график
np.random.permutation()
Функция permutation() либо генерирует список заданной длины из натуральных чисел от нуля до указанного числа, либо перемешивает переданный ей в качестве аргумента массив.
Основное практическое применение эта функция находит в задачах машинного обучения, где довольно часто требуется перемешать выборку данных перед тем, как передавать ее в алгоритм.
Например у нас есть вектор с данными
Перемешаем эту выборку
P.S.
Если вам интересна тема анализа данных, то мы рекомендуем ознакомиться с библиотекой Pandas. На нашем сайте вы можете найти вводные уроки по этой теме. Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.
Библиотека Numpy. Использование boolean массива для доступа к ndarray >>>
7 примеров, чтобы знать о функции Numpy Ravel
Numpy Ravel () используется для возврата непрерывных сплющенных массив. Это означает 1-D массив со всеми входными элементами и с тем же типом, что и он.
Вступление
Что такое метод Numpy Ravel ()?
Numpy.ndarray.ravel () используется, когда возвращать непрерывные сплющенные массива. Это означает 1-D массив со всеми входными элементами и с тем же типом, что и он.
Синтаксис Numpy Ravel
Параметры
Заказ: <‘C,’ ‘F,’ ‘A,’ ‘K’>– Это необязательна функция на входе. Все элементы входного массива прочитаны в соответствии с порядком индекса. Во-первых, если мы используем это означает, что заказ индекса будет соревнователем. Заказ в памяти медленнее на первом индексе и быстрее всего на последнем индексе.
Во-вторых, если мы используем это означает, что заказ индекса будет основным столбцом. Он также известен как «Заказ в стиле Fortran», который изменяет самый быстрый по первому индексу и самым медленным в последнем индексе. Помните, что оба не учитывают макет памяти массива и относятся только к порядку индексации оси.
В-третьих, если мы используем это означает чтение и запись элементов массива в порядке индекса в стиле Fortran. Если массив является крестуным смещением в памяти, в противном случае он возьмет C-подобный порядок.
В-четвертых, если мы используем Он прочитает элементы в том порядке, в котором они происходят в памяти. За исключением изменения данных. По умолчанию заказ всегда устанавливается на «C».
Возвращаемое значение Numpy Ravel
Массив с тем же типом, что и входной массив с порядком согласно вашему требованию.
Примеры метода Numpy Ravel
Давайте понять Numpy Ravel () Функция The Numpy Module в деталях с помощью примеров:
1. Использование 2-D массива в функции Numpy Ravel ()
В этом примере мы импортируем модуль NUMPY как NP. Затем мы сделаем входной массив в качестве 2-D массива. Наконец, мы будем применять функцию numpy Ravel () для преобразования 2-D массива в 1-D массив.
Выход:
Здесь, во-первых, мы импортировали модуль Numpy с именем псевдонимов как NP. Во-вторых, мы создали 2-D массив, используя функцию массива. В-третьих, мы создали переменную как вывод и назначили ее Функция Ravel (). Наконец, мы напечатали значение вывода массива.
2. Чтобы показать, что numpy.ravel () эквивалентен изменить
В этом примере мы будем импортировать NUMPY модуль как имя псевдонима NP. Затем мы сделаем входной массив в качестве 2-D массива. Наконец, мы будем применять функцию numpy Ravel () для преобразования 2-D массива в 1-D массив. И наконец, мы будем применять функцию array.reeshape ().
Здесь, во-первых, мы импортировали модуль Numpy с именем псевдонимов как NP. Во-вторых, мы создали 2-D массив, используя функцию массива. В-третьих, мы создали переменную как вывод и назначили ее Функция Ravel (). В-четвертых, мы напечатали значение выходного массива. В-пятых, мы применили ARR. Функция Reshape (-1) и хранить значение в новом ARR1. Наконец, мы напечатали вывод функции Reshape и видели, что numpy.ravel () эквивалентен Array.Reshape ().
3. Используя в качестве параметра в функции Numpy Ravel ()
В этом примере мы импортируем модуль NUMPY как NP. Затем мы сделаем входной массив в качестве 2-D массива. Наконец, мы будем нанести функцию Numpy Ravel () с преобразованием 2-D массива в 1-D массив.
Здесь, во-первых, мы импортировали модуль Numpy с именем псевдонимов как NP. Во-вторых, мы создали 2- D массив используя функцию массива. В-третьих, мы создали переменную в качестве вывода и назначали ее функцию Ravel (). В-четвертых, мы использовали заказ «F», чтобы распечатать вывод как основной столбец. Наконец, мы напечатали значение вывода массива.
4. Используя в качестве параметра в функции Numpy Ravel ()
В этом примере мы импортируем модуль NUMPY как NP. Затем мы сделаем входной массив в качестве 2-D массива. Наконец, мы будем нанести функцию Numpy Ravel () с преобразованием 2-D массива в 1-D массив.
Здесь, во-первых, мы импортировали модуль Numpy с именем псевдонимов как NP. Во-вторых, мы создали 2-D массив, используя функцию массива. В-третьих, мы создали переменную в качестве вывода и назначали ее значение функции Ravel (). В-четвертых, мы использовали заказ «C», чтобы распечатать вывод как майор строки. Наконец, мы напечатали значение вывода массива.
5. Используя в качестве параметра в функции Numpy Ravel ()
В этом примере мы импортируем модуль NUMPY как NP. Затем мы сделаем входной массив в качестве 2-D массива. Наконец, мы будем нанести функцию Numpy Ravel () с преобразованием 2-D массива в 1-D массив.
Здесь, во-первых, мы импортировали модуль Numpy с именем псевдонимов как NP. Во-вторых, мы создали 2-D массив, используя функцию массива. В-третьих, мы создали переменную в качестве вывода и назначали ее функцию Ravel (). В-четвертых, мы использовали заказ «A», чтобы распечатать вывод как майор строки. Наконец, мы напечатали значение вывода массива.
6. Используя в качестве параметра в функции Numpy Ravel ()
В этом примере мы импортируем модуль NUMPY как NP. Затем мы сделаем входной массив в качестве 2-D массива. Наконец, мы будем нанести функцию Numpy Ravel () с преобразованием 2-D массива в 1-D массив.
Здесь, во-первых, мы импортировали модуль Numpy с именем псевдонимов как NP. Во-вторых, мы создали 2-D массив, используя функцию массива. В-третьих, мы создали переменную в качестве вывода и назначали ее функцию Ravel (). В-четвертых, мы использовали заказ «K», чтобы распечатать вывод как майор строки. Наконец, мы напечатали значение вывода массива.
7. Использование Reshigepe () с обмениванием оси
В этом примере мы импортируем модуль NUMPY как NP. Затем мы организуем массив с помощью функции Reshape и функции Swapaxes.
Здесь, во-первых, мы импортировали модуль Numpy с именем псевдонимов как NP. Во-вторых, мы организовали массив до 18, чтобы помочь функции Reshape () функции и Swapaxees (). В-третьих, мы применили функцию Ravel со всеми заказами и хранили их в новую переменную. Наконец, мы напечатали все переменные и видели разницу в выходе.
Разница между сглаженным () и Numpy Ravel ()
Эти обе функции используются для преобразования многомерного массива в одномерный массив. Но есть некоторые различия, через которые они отличаются самим собой.
Numpy Ravel ()
Numpy Flatten ()
Во-первых, мы импортировали модуль NUMPY как NP. Во-вторых, мы предприняли входной массив и напечатали входную массив и измерение массива. В-третьих, мы применили функцию Ravel () и напечатали вывод функции Ravel (). Затем мы обновили значение и снова напечатали вывод Ravel и напечатал входной массив. Таким образом, мы можем легко увидеть изменения. То же самое сделано с функцией Flatten (), также обновила значение, но входной массив не меняется.
Заключение
В этом руководстве мы обсудили функцию The Ravel () The Numpy Module. Все параметры и их значения объясняются с помощью примеров подробно. Примеры помогут вам понять концепцию более точно. Вы можете использовать заказ согласно вашему требованию вывода одномерного массива.
NumPy, часть 2: базовые операции над массивами
Здравствуйте! Я продолжаю работу над пособием по python-библиотеке NumPy.
В прошлой части мы научились создавать массивы и их печатать. Однако это не имеет смысла, если с ними ничего нельзя делать.
Сегодня мы познакомимся с операциями над массивами.
Базовые операции
Математические операции над массивами выполняются поэлементно. Создается новый массив, который заполняется результатами действия оператора.
Для этого, естественно, массивы должны быть одинаковых размеров.
Также можно производить математические операции между массивом и числом. В этом случае к каждому элементу прибавляется (или что вы там делаете) это число.
NumPy также предоставляет множество математических операций для обработки массивов:
Полный список можно посмотреть здесь.
Многие унарные операции, такие как, например, вычисление суммы всех элементов массива, представлены также и в виде методов класса ndarray.
По умолчанию, эти операции применяются к массиву, как если бы он был списком чисел, независимо от его формы. Однако, указав параметр axis, можно применить операцию для указанной оси массива:
Индексы, срезы, итерации
Одномерные массивы осуществляют операции индексирования, срезов и итераций очень схожим образом с обычными списками и другими последовательностями Python (разве что удалять с помощью срезов нельзя).
У многомерных массивов на каждую ось приходится один индекс. Индексы передаются в виде последовательности чисел, разделенных запятыми (то бишь, кортежами):
Когда индексов меньше, чем осей, отсутствующие индексы предполагаются дополненными с помощью срезов:
Например, если x имеет ранг 5 (то есть у него 5 осей), тогда
Итерирование многомерных массивов начинается с первой оси:
Однако, если нужно перебрать поэлементно весь массив, как если бы он был одномерным, для этого можно использовать атрибут flat:
Манипуляции с формой
Как уже говорилось, у массива есть форма (shape), определяемая числом элементов вдоль каждой оси:
Форма массива может быть изменена с помощью различных команд:
Порядок элементов в массиве в результате функции ravel() соответствует обычному «C-стилю», то есть, чем правее индекс, тем он «быстрее изменяется»: за элементом a[0,0] следует a[0,1]. Если одна форма массива была изменена на другую, массив переформировывается также в «C-стиле». Функции ravel() и reshape() также могут работать (при использовании дополнительного аргумента) в FORTRAN-стиле, в котором быстрее изменяется более левый индекс.
Метод reshape() возвращает ее аргумент с измененной формой, в то время как метод resize() изменяет сам массив:
Объединение массивов
Несколько массивов могут быть объединены вместе вдоль разных осей с помощью функций hstack и vstack.
hstack() объединяет массивы по первым осям, vstack() — по последним:
Функция column_stack() объединяет одномерные массивы в качестве столбцов двумерного массива:
Аналогично для строк имеется функция row_stack().
Разбиение массива
Используя hsplit() вы можете разбить массив вдоль горизонтальной оси, указав либо число возвращаемых массивов одинаковой формы, либо номера столбцов, после которых массив разрезается «ножницами»:
Функция vsplit() разбивает массив вдоль вертикальной оси, а array_split() позволяет указать оси, вдоль которых произойдет разбиение.
Копии и представления
При работе с массивами, их данные иногда необходимо копировать в другой массив, а иногда нет. Это часто является источником путаницы. Возможно 3 случая:
Вообще никаких копий
Простое присваивание не создает ни копии массива, ни копии его данных:
Python передает изменяемые объекты как ссылки, поэтому вызовы функций также не создают копий.
Представление или поверхностная копия
Разные объекты массивов могут использовать одни и те же данные. Метод view() создает новый объект массива, являющийся представлением тех же данных.
Срез массива это представление:
Глубокая копия
Метод copy() создаст настоящую копию массива и его данных:
Нескучный туториал по NumPy
Меня зовут Вячеслав, я хронический математик и уже несколько лет не использую циклы при работе с массивами…
Ровно с тех пор, как открыл для себя векторные операции в NumPy. Я хочу познакомить вас с функциями NumPy, которые чаще всего использую для обработки массивов данных и изображений. В конце статьи я покажу, как можно использовать инструментарий NumPy, чтобы выполнить свертку изображений без итераций (= очень быстро).
Что такое NumPy?
Это библиотека с открытым исходным кодом, некогда отделившаяся от проекта SciPy. NumPy является наследником Numeric и NumArray. Основан NumPy на библиотеке LAPAC, которая написана на Fortran. Не-python альтернативой для NumPy является Matlab.
В силу того, что NumPy базируется на Fortran это быстрая библиотека. А в силу того, что поддерживает векторные операции с многомерными массивами — крайне удобная.
Кроме базового варианта (многомерные массивы в базовом варианте) NumPy включает в себя набор пакетов для решения специализированных задач, например:
Создание массива
Создать массив можно несколькими способами:
Либо взять размеры уже существующего массива:
По умолчанию from = 0, step = 1, поэтому возможен вариант с одним параметром, интерпретируемым как To:
Либо с двумя — как From и To:
Обратите внимание, что в методе №3 размеры массива передавались в качестве одного параметра (кортеж размеров). Вторым параметром в способах №3 и №4 можно указать желаемый тип элементов массива:
Используя метод astype, можно привести массив к другому типу. В качестве параметра указывается желаемый тип:
Все доступные типы можно найти в словаре sctypes:
Доступ к элементам, срезы
Доступ к элементам массива осуществляется по целочисленным индексами, начинается отсчет с 0:
Если представить многомерный массив как систему вложенных одномерных массивов (линейный массив, элементы которого могут быть линейными массивами), становится очевидной возможность получать доступ к подмассивам с использованием неполного набора индексов:
С учетом этой парадигмы, можем переписать пример доступа к одному элементу:
При использовании неполного набора индексов, недостающие индексы неявно заменяются списком всех возможных индексов вдоль соответствующей оси. Сделать это явным образом можно, поставив «:». Предыдущий пример с одним индексом можно переписать в следующем виде:
«Пропустить» индекс можно вдоль любой оси или осей, если за «пропущенной» осью последуют оси с индексацией, то «:» обязательно:
Индексы могут принимать отрицательные целые значения. В этом случае отсчет ведется от конца массива:
Можно использовать не одиночные индексы, а списки индексов вдоль каждой оси:
Либо диапазоны индексов в виде «From:To:Step». Такая конструкция называется срезом. Выбираются все элементы по списку индексов начиная с индекса From включительно, до индекса To не включая с шагом Step:
Шаг индекса имеет значение по умолчанию 1 и может быть пропущен:
Значения From и To тоже имеют дефолтные значения: 0 и размер массива по оси индексации соответственно:
Если вы хотите использовать From и To по умолчанию (все индексы по данной оси) а шаг отличный от 1, то вам необходимо использовать две пары двоеточий, чтобы интерпретатор смог идентифицировать единственный параметр как Step. Следующий код «разворачивает» массив вдоль второй оси, а вдоль первой не меняет:
Как видите, через B мы изменили данные в A. Вот почему в реальных задачах важно использовать копии. Пример выше должен был бы выглядеть так:
В NumPy также реализована возможность доступа ко множеству элементов массива через булев индексный массив. Индексный массив должен совпадать по форме с индексируемым.
Как видите, такая конструкция возвращает плоский массив, состоящий из элементов индексируемого массива, соответствующих истинным индексам. Однако, если мы используем такой доступ к элементам массива для изменения их значений, то форма массива сохранится:
Над индексирующими булевыми массивами определены логические операции logical_and, logical_or и logical_not выполняющие логические операции И, ИЛИ и НЕ поэлементно:
logical_and и logical_or принимают 2 операнда, logical_not — один. Можно использовать операторы &, | и
для выполнения И, ИЛИ и НЕ соответственно с любым количеством операндов:
Что эквивалентно применению только I1.
Получить индексирующий логический массив, соответсвующий по форме массиву значений можно, записав логическое условие с именем массива в качестве операнда. Булево значение индекса будет рассчитано как истинность выражения для соответствующего элемента массива.
Найдем индексирующий массив I элементов, которые больше, чем 3, а элементы со значениями меньше чем 2 и больше 4 — обнулим:
Форма массива и ее изменение
Многомерный массив можно представить как одномерный массив максимальной длины, нарезанный на фрагменты по длине самой последней оси и уложенный слоями по осям, начиная с последних.
Для наглядности рассмотрим пример:
В этом примере мы из одномерного массива длиной 24 элемента сформировали 2 новых массива. Массив B, размером 4 на 6. Если посмотреть на порядок значений, то видно, что вдоль второго измерения идут цепочки последовательных значений.
В массиве C, размером 4 на 3 на 2, непрерывные значения идут вдоль последней оси. Вдоль второй оси идут последовательно блоки, объединение которых дало бы в результате строки вдоль второй оси массива B.
А учитывая, что мы не делали копии, становится понятно, что это разные формы преставления одного и того же массива данных. Поэтому можно легко и быстро менять форму массива, не изменяя самих данных.
Чтобы узнать размерность массива (количество осей), можно использовать поле ndim (число), а чтобы узнать размер вдоль каждой оси — shape (кортеж). Размерность можно также узнать и по длине shape. Чтобы узнать полное количество элементов в массиве можно воспользоваться значением size:
Обратите внимание, что ndim и shape — это атрибуты, а не методы!
Чтобы увидеть массив одномерным, можно воспользоваться функцией ravel:
Чтобы поменять размеры вдоль осей или размерность используется метод reshape:
Важно, чтобы количество элементов сохранилось. Иначе возникнет ошибка:
Можно reshape использовать вместо ravel:
Рассмотрим практическое применение некоторых возможностей для обработки изображений. В качестве объекта исследования будем использовать фотографию:
Попробуем ее загрузить и визуализировать средствами Python. Для этого нам понадобятся OpenCV и Matplotlib:
Результат будет такой:
Обратите внимание на строку загрузки:
OpenCV работает с изображениями в формате BGR, а нам привычен RGB. Мы меняем порядок байтов вдоль оси цвета без обращения к функциям OpenCV, используя конструкцию
«[:, :, ::-1]».
Уменьшим изображение в 2 раза по каждой оси. Наше изображение имеет четные размеры по осям, соответственно, может быть уменьшено без интерполяции:
Поменяв форму массива, мы получили 2 новые оси, по 2 значения в каждой, им соответствуют кадры, составленные из нечетных и четных строк и столбцов исходного изображения.
Низкое качество свзано с использованием Matplotlib, за то там видны размеры по осям. На самом деле, качество уменьшенного изображения такое:
Перестановка осей и траспонирование
В кроме изменения формы массива при неизменном порядке единиц данных, часто встречается необходимость изменить порядок следования осей, что естественным образом повлечет перестановки блоков данных.
Примером такого преобразования может быть транспонирование матрицы: взаимозамена строк и столбцов.
В этом примере для транспонирования матрицы A использовалась конструкция A.T. Оператор транспонирования инвертирует порядок осей. Рассмотрим еще один пример с тремя осями:
У этой короткой записи есть более длинный аналог: np.transpose(A). Это более универсальный инструмент для замены порядка осей. Вторым параметром можно задать кортеж номеров осей исходного массива, определяющий порядок их положения в результирующем массиве.
Для примера переставим первые две оси изображения. Картинка должна перевернуться, но цветовую ось оставим без изменения:
Для этого примера можно было применить другой инструмент swapaxes. Этот метод переставляет местами две оси, указанные в параметрах. Пример выше можно было реализовать так:
Объединение массивов
Объединяемые массивы должны иметь одинаковое количество осей. Объединять массивы можно с образованием новой оси, либо вдоль уже существующей.
Для объединения с образованием новой оси исходные массивы должны иметь одинаковые размеры вдоль всех осей:
Как видно из примера, массивы-операнды стали подмассивами нового объекта и выстроились вдоль новой оси, которая стоит самой первой по порядку.
Для объединения массивов вдоль существующей оси, они должны иметь одинаковый размер по всем осям, кроме выбранной для объединения, а по ней могут иметь произвольные размеры:
Для объединения по первой или второй оси можно использовать методы vstack и hstack соответсвенно. Покажем это на примере изображений. vstack объединяет изображения одинаковой ширины по высоте, а hsstack объединяет одинаковые по высоте картинки в одно широкое:
Обратите внимание на то, что во всех примерах этого раздела объединяемые массивы передаются одним параметром (кортежем). Количество операндов может быть любым, а не обязательно только 2.
Также обратите внимание на то, что происходит с памятью, при объединении массивов:
Так как создается новый объект, данные в него копируются из исходных массивов, поэтому изменения в новых данных не влияют на исходные.
Клонирование данных
Оператор np.repeat(A, n) вернет одномерный массив с элементами массива A, каждый из которых будет повторен n раз.
После этого преобразования, можно перестроить геометрию массива и собрать повторяющиеся данные в одну ось:
Этот вариант отличается от объединения массива с самим собой оператором stack только положением оси, вдоль которой стоят одинаковые данные. В примере выше это последняя ось, если использовать stack — первая:
Как бы ни было выполнено клонирование данных, следующим шагом можно переместить ось, вдоль которой стоят одинаковые значения, в любую позицию с системе осей:
Если же мы хотим «растянуть» какую либо ось, используя повторение элементов, то ось с одинаковыми значениями надо поставить после растягиваемой (используя transpose), а затем объединить эти две оси (используя reshape). Рассмотрим пример с растяжением изображения вдоль вертикальной оси за счет дублирования строк:
Математические операции над элементами массива
Если A и B массивы одинакового размера, то их можно складывать, умножать, вычитать, делить и возводить в степень. Эти операции выполняются поэлементно, результирующий массив будет совпадать по геометрии с исходными массивами, а каждый его элемент будет результатом выполнения соответствующей операции над парой элементов из исходных массивов:
Можно выполнить любую операцию из приведенных выше над массивом и числом. В этом случае операция также выполнится над каждым из элементов массива:
Учитывая, что многомерный массив можно рассматривать как плоский массив (первая ось), элементы которого — массивы (остальные оси), возможно выполнение рассматриваемых операций над массивами A и B в случае, когда геометрия B совпадает с геометрией подмассивов A при фиксированном значении по первой оси. Иными словами, при совпадающем количестве осей и размерах A[i] и B. Этом случае каждый из массивов A[i] и B будут операндами для операций, определенных над массивами.
В этом примере массив B подвергается операции с каждой строкой массива A. При необходимости умножения/деления/сложения/вычитания/возведения степень подмассивов вдоль другой оси, необходимо использовать транспонирование, чтобы поставить нужную ось на место первой, а затем вернуть ее на свое место. Рассмотри пример выше, но с умножением на вектор B столбцов массива A:
Для более сложных функций (например, для тригонометрических, экспоненты, логарифма, преобразования между градусами и радианами, модуля, корня квадратного и.д.) в NumPy есть реализация. Рассмотрим на примере экспоненты и логарифма:
С полным списком математических операций в NumPy можно ознакомиться тут.
Матричное умножение
Описанная выше операция произведения массивов выполняется поэлементно. А при необходимости выполнения операций по правилам линейной алгебры над массивами как над тензорами можно воспользоваться методом dot(A, B). В зависимости от вида операндов, функция выполнит:
Рассмотрим примеры со скалярами и векторами:
С тензорами посмотрим только на то, как меняется размер геометрия результирующего массива:
Для выполнения произведения тензоров с использованием других осей, вместо определенных для dot можно воспользоваться tensordot с явным указанием осей:
Мы явно указали, используем третью ось первого массива и вторую — второго (размеры по этим осям должны совпадать).
Агрегаторы
Агрегаторы — это методы NumPy позволяющие заменять данные интегральными характеристиками вдоль некоторых осей. Например, можно посчитать среднее значение, максимальное, минимальное, вариацию или еще какую-то характеристику вдоль какой-либо оси или осей и сформировать из этих данных новый массив. Форма нового массива будет содержать все оси исходного массива, кроме тех, вдоль которых подсчитывался агрегатор.
Для примера, сформируем массив со случайными значениями. Затем найдем минимальное, максимальное и среднее значение в его столбцах:
При таком использовании mean и average выглядят синонимами. Но эти функции обладают разным набором дополнительных параметров. У нах разные возможности по маскированию и взвешиванию усредняемых данных.
Можно подсчитать интегральные характеристики и по нескольким осям:
В этом примере рассмотрена еще одна интегральная характеристика sum — сумма.
Список агрегаторов выглядит примерно так:
Если не указать оси, то по умолчанию все рассматриваемые характеристики считаются по всему массиву. В этом случае argmin и argmax тоже корректно отработают и найдут индекс максимального или минимального элемента так, как буд-то все данные в массиве вытянуты вдоль одной оси командой ravel().
Еще следует отметить, агрегирующие методы определены не только как методы модуля NumPy, но и для самих массивов: запись np.aggregator(A, axes) эквивалентна записи A.aggregator(axes), где под aggregator подразумевается одна из рассмотренных выше функций, а под axes — индексы осей.
Вместо заключения — пример
Давайте построим алгоритм линейной низкочастотной фильтрации изображения.
Для начала загрузим зашумленное изображение.
Рассмотрим фрагмент изображения, чтобы увидеть шум:
Фильтровать изображение будем с использованием гауссова фильтра. Но вместо выполнения свертки непосредственно (с итерированием), применим взвешенное усреднение срезов изображения, сдвинутых относительно друг друга:
Применим эту функцию к нашему изображению единожды, дважды и трижды:
Получаем следующие результаты:
при однократном применении фильтра;
Видно, что с повышением количества проходов фильтра снижается уровень шума. Но при этом снижается и четкость изображения. Это известная проблема линейных фильтров. Но наш метод денойзинга изображения не претендует на оптимальность: это лишь демонстрация возможностей NumPy реализации свертки без итераций.
Теперь давайте посмотрим, сверткам с какими ядрами эквивалентна наша фильтрация. Для этого подвергнем аналогичным преобразованиям одиночный единичный импульс и визуализируем. На самом деле импульс будет не единичным, а равным по амплитуде 255, так как само смешивание оптимизировано под целочисленные данные. Но это не мешает оценить общий вид ядер:
Мы рассмотрели далеко не полный набор возможностей NumPy, надеюсь, этого было достаточно для демонстрации всей мощи и красоты этого инструмента!