Прежде чем приступать к машинному обучению, следует понять, как эффективно хранить данные. Даже если вы знаете самый изощрённый обучающий алгоритм, этого может быть недостаточно, его может не хватить. И случится это лишь потому, что доступ к данным слишком медленный. Плюс сюда же можно отнести то, что Python интерпретируемый язык.
Здесь и приходит на помощь библиотека NumPy, которая отвечает за высоко оптимизированные многомерные массивы — основную структуру данных для большинства современных алгоритмов.
Разберём работу с NumPy на примере первых 15 задач из 100 задач, которые есть на Github. Данная коллекция представляет набор задач из numpy рассылки, вопросов StackOverflow и самой документации numpy, плюс дополненные задачи от автора.
Перед тем, как начать, я рекомендую не просто читать данную статью, а руками проделать все эти шаги и посмотреть на работу библиотеки вживую. Таким образом, данный материал отпечатается в Вашей голове :)
Задача 1. Необходимо импортировать библиотеку под именем "np"
Сделать, как видно это не сложно. Поэтому продолжим.
Задача 2. Распечатать версию и конфигурацию numpy
В данном примере тоже нет ничего сложного. С помощью встроенных методов и значений можно получить эти данные. Однако, версию библиотеки можно получить ещё одним способом:
Задача 3. Создать нулевой вектор длины 10 (вектор, заполненный нулями)
Данная задача решается в одну строчку с помощью встроенного метода numpy.zeros(...). В приведённом выше решении будет создан вектор размерности 10, у которого все значения нули.
Если мы хотим создать матрицу с помощью numpy, то применяется следующий синтаксис:
Данный код создаст матрицу, состоящую из нулей, размера 3 на 3.
Задача 4. Как найти размер памяти любого массива
Пусть у нас есть матрица 10 на 10:
Для решения поставленной задачи воспользуемся двумя атрибутами.
1. Первый из них это numpy.ndarray.size.
Данный атрибут отвечает за количество элементов в numpy-массиве. Так как у нас матрица 10 на 10, то количество элементов 100.
2. Следующий атрибут это numpy.dtype.itemsize.
Прежде чем разобрать этот атрибут, прежде всего необходимо знать, что у каждого элемента numpy-массива есть тип. Этот тип задаётся сразу при инициализации массива, либо библиотека задаст его по умолчанию, либо определит входные данные.
Например, при инициализации матрицы выше, мы могли указать тип явно:
В данном примере мы указали, что значения являются вещественными. По умолчанию этот тип был задан в первом примере выше для данных. За это отвечает атрибут dtype. Подробнее о типах можно прочитать здесь.
Вернёмся к атрибуту itemsize. Он определяет сколько байт будет занимать в памяти каждый тип.
Как видно, тип float64 у numpy занимает 8 байт 1 значение. Таким образом, получаем количество памяти, занимаемое нашей матрицей размера 10 на 10.
Задача 5. Как получить документацию numpy-функции "add" из командной строки
Документацию каждой numpy-функции можно получить в командной строке следующим образом:
python -c "import numpy; numpy.info(numpy.add)"
Как Вы, я думаю, догадались это можно вызвать и в коде. Просто пример работы с командной строкой.
Задача 6. Создать нулевой вектор размером 10, но пятое значение которого равно 1
Это простая задача. Воспользуемся уже знакомым методом numpy.zeros(...) и заменим пятое значение вектора на 1. Так как нумерация начинается с 0, то пятый будет под индексом 4
Задача 7. Создать вектор с последовательными значениями в диапазоне от 10 до 49
Для решения этой задачи используется встроенный метод numpy.arange.
Задача 8. Перевернуть (reverse) вектор (первый элемент становится последним)
В данной задаче необходимо сделать вектор в обратном порядке. Чтобы видно было результат, воспользуемся функцией генерации последовательных чисел вектора numpy.arange.
О двойном двоеточии можно прочитать статью на Хабре в разделе "Срезы".
Задача 9. создайте матрицу 3х3 с последовательными значениями в диапазоне от 0 до 8
То есть нужно получить вот такую матрицу
Когда мы создаём массив в numpy, у каждого массива есть атрибут shape (форма), который говорит, какого вида у нас массив: вектор, матрица и т.д.
Например, для вектора атрибут shape выглядит следующим образом:
В NumPy есть встроенная функция, которая позволяет преобразовать numpy-массив в другую форму (shape): numpy.reshape. Рассмотрим сразу на решении поставленной задачи:
Мы создали одномерный вектор из последовательно идущих цифр от 0 до 8. Изначально этот вектор имел форму (9, ). Но после мы преобразовали форму в матрицу 3х3.
Не сложно убедиться, что форма массива стала другой
Задача 10. Найти индексы ненулевых элементов из [1,2,0,0,4,0]
Для этого есть встроенная функция np.nonzero, которая возвращает список индексов ненулевых элементов:
Кстати, за счёт встроенного механизма индексирования в numpy-массивах, можно получить все ненулевые элементы массива:
Задача 11. Создать единичную матрицу размера 3х3
Для этого есть встроенная функция numpy.eye:
Задача 12. Создать массив 3x3x3 со случайными значениями
Здесь используется функция функция numpy.random.random:
Как видно для указания размера массива нужно передать tuple. Данный метод заполняет массив значениями из интервала [0.0, 1.0).
Задача 13. Создать массив 10х10 со случайными значениями и найти минимальное и максимальное значения
Сначала создадим массив с уже знакомой нам функцией:
Далее используем встроенные функции min и max, чтобы найти соответствующие значения:
Задача 14. Создать случайный вектор размером 30 и найти среднее значение
Для тех, кто забыл. Среднее значение вектора — это сумма всех его элементов, делённое на их количество:
Для вычисления среднего значения массив используется встроенная функция mean:
Задача 15. Создать двумерный массив с 1 на границе и 0 внутри
Для начала посмотрим решение:
Первым делом здесь создаётся массив, заполненный единицами с помощью метода numpy.ones.
Теперь про заполнение нулями. Прежде всего напомним, что индексация массива начинается с нуля. Поэтому вторая строка имеет индекс 1.
При обращении Z[1:-1, ...] мы говорим брать строки со второй и до предпоследней (-1 значит с конца).
Z[..., 1:-1] — наоборот указываем столбцы со второго и до предпоследнего.
Z[1:-1, 1:-1] — Таким образом получим весь внутренний срез матрицы, не включающий границы. Подробнее про срезы в numpy-массивах можно прочитать в этой статье.
На этом всё :) Остальные задачи рассмотрим в следующих частях.
Ставьте лайк, если статья понравилась и подписывайтесь на канал. Впереди ещё много интересного!