Skip to content

Instantly share code, notes, and snippets.

@antosha417
Created March 15, 2019 12:44
Show Gist options
  • Save antosha417/66eb51fdc32a0c813feced97abc92f48 to your computer and use it in GitHub Desktop.
Save antosha417/66eb51fdc32a0c813feced97abc92f48 to your computer and use it in GitHub Desktop.
Пример работы с NumPy
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**NumPy** - это фундаментальный пакет для научных вычислений на Python. \n",
"Он содержит, помимо прочего: \n",
"* мощный N-мерный массив объектов\n",
"* полезные элементы линейной алгебры написанные на языке C / C ++ и Фортран\n",
"* преобразования Фурье и случайные чисела. \n",
"\n",
"Помимо очевидного научного использования, NumPy также может использоваться как эффективный многомерный контейнер данных."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Массивы\n",
"\n",
"Массив numpy представляет собой сетку значений одного типа и индексируется кортежем неотрицательных целых чисел. Число измерений-это ранг массива; форма массива - это кортеж целых чисел, дающих размер массива вдоль каждого измерения.\n",
"\n",
"Мы можем инициализировать массивы numpy из стандартных списков Python и получить доступ к элементам с помощью квадратных скобок:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = np.array([1, 2, 3])\n",
"print(type([1, 2, 3]))\n",
"print(type(a)) \n",
"print(a.shape) \n",
"print(a[0], a[1], a[2]) \n",
"a[0] = 5 \n",
"print(a) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"b = np.array([[1,2,3],[4,5,6]])\n",
"print(b.shape)\n",
"print(b)\n",
"print(b[0, 0], b[0, 1], b[1, 0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"NumPy включает в себя множество функций для создания массивов:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = np.zeros((2,2))\n",
"print(a) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"b = np.ones((1,2))\n",
"print(b)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"c = np.full((2,2), 7)\n",
"print(c)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"d = np.eye(2)\n",
"print(d) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"e = np.random.random((2,2))\n",
"print(e)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Про все остальные способы создать массив можно прочитать в документации https://docs.scipy.org/doc/numpy/user/basics.creation.html#arrays-creation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Индексации массива \n",
"Numpy предлагает несколько способов индексирования."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Срезы:\n",
"так же как в списках в Python.\n",
"Поскольку массивы могут быть многомерными, необходимо указать срез для каждого измерения массива."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n",
"print(a, '\\n')\n",
"b = a[:2, 1:3]\n",
"print(b)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Срез списка указывает на те же данные, изменяя срез мы изменим и исходный список"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"b[0, 0] = 123\n",
"print(a, '\\n')\n",
"print(b)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Целочисленное индексирование\n",
"При индексировании с помощью срезов резултат всегда будет подмассивом исходного. Целочисленное индексирование позволяет создавать произвольные массивы, используя данные из другого массива."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = np.array([[1,2], [3, 4], [5, 6]])\n",
"b = a[[0, 1, 2], [0, 1, 0]]\n",
"\n",
"print(a, a.shape, '\\n')\n",
"print(b, b.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Пример выше эквивалентен такому:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"b = np.array([a[0, 0], a[1, 1], a[2, 0]])\n",
"print(b, b.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Так же можно использовать один и тот же элемент несколько раз"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(a[[0, 0], [1, 1]])\n",
"# Пример выше эквивалентен такому:\n",
"print(np.array([a[0, 1], a[0, 1]]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Один полезный трюк с целочисленным индексированием массива -- выбор или изменеие одного элемента из каждой строки матрицы:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Create a new array from which we will select elements\n",
"a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
"\n",
"print(a, '\\n')\n",
"\n",
"# Создадим массив индексов\n",
"b = np.array([0, 2, 0, 1])\n",
"\n",
"# Выбирем один элемент из скаждой строки по индексам из b\n",
"print(a[np.arange(4), b], '\\n') \n",
"\n",
"# Изменим эти элементы\n",
"a[np.arange(4), b] += 10\n",
"\n",
"print(a)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Можно также смешивать целочисленное индексирование со срезами.Это даст массив более низкого ранга, чем исходный массив. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n",
"\n",
"row_r1 = a[1, :] # Rank 1 ссылается на вторую строчку a\n",
"row_r2 = a[1:2, :] # Rank 2 ссылается на вторую строчку a\n",
"print(row_r1, row_r1.shape)\n",
"print(row_r2, row_r2.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Со столбцами всё точно так же"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"col_r1 = a[:, 1]\n",
"col_r2 = a[:, 1:2]\n",
"print(col_r1, col_r1.shape) \n",
"print(col_r2, col_r2.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Логическое индексирование\n",
"позволяет выбирать произвольные элементы массива. Часто этот тип индексирования используется для выбора элементов массива, удовлетворяющих некоторому условию. Вот пример:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a = np.array([[1,2], [3, 4], [5, 6]])\n",
"\n",
"bool_idx = (a > 2) # Возвращает массив Booleans такого же размера как a\n",
"\n",
"print(bool_idx)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Используем логическое индексирование массива чтобы построить массив\n",
"состоящий из элементов `a`, соответствующих истинным значениям из `bool_idx`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(a[bool_idx])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Всё можно записать в одну строчку. Очень лаконично"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(a[a > 2]) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Для краткости мы оставили много деталей об индексации массива numpy; если вы хотите узнать больше, вы должны прочитать документацию. https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Типы данных\n",
"Каждый массив numpy представляет собой сетку элементов одного типа. Numpy содержит большой набор числовых типов данных, которые можно использовать для создания массивов. Numpy пытается угадать тип данных при создании массива, но функции, которые строят массивы, обычно также включают необязательный аргумент для явного указания типа данных. Вот пример:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.array([1, 2])\n",
"print(x.dtype)\n",
"\n",
"x = np.array([1.0, 2.0]) \n",
"print(x.dtype)\n",
"\n",
"x = np.array([1, 2], dtype=np.float64)\n",
"print(x.dtype) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В первых двух примерах тип данных выбрался автоматически. В третьем мы явно его указали.\n",
"Не будем подробно останавливаться на типах данных, если интересно вы можете прочитать подробнее в документации. https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Арифметика массивов\n",
"Основные математические функции работают поелементно в массивах и доступны как в качестве перегрузок операторов, так и в качестве функций в модуле numpy:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.array([[1,2],[3,4]], dtype=np.float64)\n",
"y = np.array([[5,6],[7,8]], dtype=np.float64)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Поэлементная сумма, разность, умножение, деление и квадратный корень"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(x + y)\n",
"print(np.add(x, y))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(x - y)\n",
"print(np.subtract(x, y))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(x * y)\n",
"print(np.multiply(x, y))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(x / y)\n",
"print(np.divide(x, y))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(np.sqrt(x))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обратите внимание, что `x * y` это поэлементное умножене, а не матричное произведение из линала. Если нужно матричное произведение, нужно использовать специальную функцию."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.array([[1,2],[3,4]])\n",
"y = np.array([[5,6],[7,8]])\n",
"\n",
"v = np.array([9,10])\n",
"w = np.array([11, 12])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Скалярное произведение векторов"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(v.dot(w))\n",
"print(np.dot(v, w))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Умножение матрицы на вектор"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(x.dot(v))\n",
"print(np.dot(x, v))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Матричное умножение"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(x.dot(y))\n",
"print(np.dot(x, y))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Numpy предоставляет множество полезных функций для выполнения вычислений на массивах; одна из самых полезных-`sum`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.array([[1,2],[3,4]])\n",
"\n",
"print(x, '\\n')\n",
"\n",
"print(np.sum(x)) # Сумма всех элементов\n",
"print(np.sum(x, axis=0)) # Сумма каждого столбца\n",
"print(np.sum(x, axis=1)) # Сумма каждой строки"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Полный список математических функций можете посмотреть в документации\n",
"https://docs.scipy.org/doc/numpy/reference/routines.math.html"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Помимо вычисления математических функций с использованием массивов, нам часто приходится изменять или иным образом манипулировать данными в массивах. Самый простой пример такого типа операции-транспонирование матрицы; чтобы транспонировать матрицу, просто используйте атрибут T объекта array:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.array([[1,2], [3,4]])\n",
"print(x,'\\n')\n",
"print(x.T)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Транспонирование ветора ничего не делает"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"v = np.array([1,2,3])\n",
"print(v)\n",
"print(v.T)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Numpy предоставляет гораздо больше функций для управления массивами; вы можете увидеть полный список в документации. https://docs.scipy.org/doc/numpy/reference/routines.array-manipulation.html"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Broadcasting\n",
"мощный механизм, позволяющий numpy работать с массивами различной формы при выполнении арифметических операций. Часто у нас есть меньший массив и больший массив, и мы хотим использовать меньший массив несколько раз для выполнения некоторой операции над большим массивом."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Например, предположим, что мы хотим добавить постоянный вектор к каждой строке матрицы. Мы можем сделать это так:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
"v = np.array([1, 0, 1])\n",
"y = np.empty_like(x) # Пустая (заполненная мусором) матрица той же размерности, что и x\n",
"\n",
"# Для каждой строки матрицы x в цикле доболяем вектор v\n",
"for i in range(4):\n",
" y[i, :] = x[i, :] + v\n",
"\n",
"print(x, '\\n')\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Это работает! \n",
"Но, когда матрица `x` очень велика, вычисление цикла в Python может быть медленным. Обратите внимание, что добавление вектора v в каждую строку матрицы x эквивалентно формированию матрицы `vv` путем укладки нескольких копий v вертикально, а затем выполнения элементарного суммирования `x` и `vv`. Мы могли бы реализовать такой подход:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
"v = np.array([1, 0, 1])\n",
"vv = np.tile(v, (4, 1)) # Склеить 4 копии вектора v друг на друга\n",
"print(vv, '\\n') \n",
"\n",
"y = x + vv # Сложение из numpy\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Numpy broadcasting позволяет нам выполнять это вычисление без фактического создания нескольких копий `v`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
"v = np.array([1, 0, 1])\n",
"y = x + v\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Строчка `y = x + v` работает несмотря на то, что `x.shape == (4, 3)` и `v.shape == (3,)`. Это работает как если бы `v.shape` было `(4,3)` где каждая строка была копией `v`, а сумма считается поэлементно."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Этот краткий обзор коснулся многих важных вещей, которые вы должны знать о numpy, но далек от завершения. По ссылке вы можете узнать много нового и полезного. https://docs.scipy.org/doc/numpy/reference/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Зачем всё это?\n",
"Вы могли слышать, что один из минусов питона, это его большое время работы. NumPy пытается как-то решить эту проблему. Многие его функции реализованы на си или фортране. Рассмотрим пример"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"\n",
"size_of_vec = 30000\n",
"\n",
"def python():\n",
" start = time.time()\n",
" X = range(size_of_vec)\n",
" Y = range(size_of_vec)\n",
" Z = [X[i] + Y[i] for i in range(len(X)) ]\n",
" return time.time() - start\n",
"\n",
"def numpy():\n",
" start = time.time()\n",
" X = np.arange(size_of_vec)\n",
" Y = np.arange(size_of_vec)\n",
" Z = X + Y\n",
" return time.time() - start\n",
"\n",
"print(\"Numpy is in this example {} times faster!\".format(python()/numpy()))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Упражнение 1\n",
"Постройте график ускорения получаемого с использованием массивов numpy по сравнению со списками в питоне от размера массива. \n",
"Для более точных результатов замеряйте время выполнения функции несколько раз и усредняйте. (можно использовать модуль Timer из библиотеки timeit)\n",
"* Используйте функцию `z = 2*x**2 + 4*y`\n",
"* Перемножение матриц размера n на n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Упражнение 2\n",
"* Создать массив чисел от 2 до 75. Вывести только нечётные. \n",
"* Присвоить нечётным числам этого массива значение -1.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Упражнение 3\n",
"* прочитать про функцию reshape, запустить и понять все пимеры https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html?highlight=reshape#numpy.reshape\n",
"* Найти в документации функцию, которая удаляет из одного массива элементы, которые есть в другом. Вспомнить как то же самое проделать с множествами"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Упражнение 4\n",
"\n",
"* Создать случаую квадратную матрицу случайного размера от 10 до 100. \n",
"* Найти максимум и сумму элементов.\n",
"* Поделить каждый элемент на максимум.\n",
"* Отнять от каждой строки матрицы среднее по строке\n",
"* Заменить максимальное значение на -1."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Упражнение 5\n",
"* Научиться записывать наймпай массив в файл.\n",
"* Научиться читать массив из файла."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Упражнение 6\n",
"* Как в массиве найти ближайший элемент к данному? "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Упражнение*\n",
"* Напишите игру жизнь используя массивы нампай.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment