Питон для нормальных. Учебник Москва Базальт спо макс пресс 2018
Скачать 2.54 Mb.
|
z = 2xy x 2 + y 2 (6.1) Решение задачи 21 f r o m numpy i m p o r t * f r o m m a t p l o t l i b . pyplot i m p o r t * f r o m m a t p l o t l i b . mlab i m p o r t * f r o m m p l _ t o o l k i t s . mplot3d i m p o r t Axes3D x = arange ( -3 , 3 , 0.01) y = arange ( -3 , 3 , 0.01) X , Y = m e s h g r i d (x , y ) Z = 2* X * Y /( X **2+ Y **2) c o n t o u r f (X , Y , Z ) savefig ( ’ plot . png ’) fig = figure () ax = Axes3D ( fig ) ax . p l o t _ s u r f a c e (X , Y , Z ) savefig ( ’3 D . png ’) show () 6.9 Задания на построение графиков Для каждого из заданий данного раздела следует выполнить 1 вариант с номером (n − 1)%m + 1, где n — номер в списке группы, а m — число заданий. Задание 18 Постройте графики следующих функций, используя шаг вы- борки данных по абсциссе из задания 17: 6.9. Задания на построение графиков 157 1. x 2 на отрезке x ∈ [−2; 2]; 2. x 3 на отрезке x ∈ [−2; 2]; 3. x 4 на отрезке x ∈ [−2; 2]; 4. cos(2πt) на отрезке t ∈ [−10; 10]; 5. 1 t cos(2πt) на отрезке t ∈ [1; 10]; 6. e − t cos(2πt) на отрезке t ∈ [−10; 10]; 7. 4 sin(πt + π/8) − 1 на отрезке t ∈ [−10; 10]; 8. 2 cos(t − 2) + sin(2 ∗ t − 4) на отрезке t ∈ [−20π; 10π]; 9. ln(x + 1) на отрезке x ∈ [0; e − 1]; 10. log 2 (|x|) на отрезке x ∈ [−4; 4] за исключением точки x = 0; 11. 2 x на отрезке x ∈ [−2; 2]; 12. e x на отрезке x ∈ [−2; 2]; 13. 2 − x на отрезке x ∈ [−2; 2]; 14. 3 √ x на отрезке x ∈ [1; 125]; 15. 5 √ x на отрезке x ∈ [1; 32]. Задание 19 Для построенного в рамках задания 18 графика измените: • цвет линии; • тип линии и маркеров; • шаг выборки данных. Далее введите сетку. Сохраните полученный график в файл, опробуйте сохранять файл в разных форматах: png, pdf, jpg, eps. Задание 20 Постройте семейство функций на одном графике различны- ми цветами: 1. степенные многочлены с целыми степенями от 1 до 6 на отрезке [−1; 1]; 2. синусоиды y = sin(ωt) с частотами ω = 2π, ω = 3π, . . . , ω = 8π на отрезке t ∈ [−1; 1]; 3. синусоиды y = sin(2πt + φ 0 ) с начальными фазами φ 0 = 0, φ 0 = π/6, . . . , φ 0 = 5π/6 на отрезке t ∈ [−1; 1]; 158 Глава 6. Графики. Модуль matplotlib 4. логарифмические функции log 2 (x), ln(x) и log 10 (x) на отрезке x ∈ [1; 10]; 5. гиперболические функции sh(x), ch(x) и th(x) на отрезке x ∈ [−10; 10], для их вычисления воспользуйтесь их выражением через экспоненту. Задание 21 Для построенного в задании 20 графика сделайте сетку и ле- генду. Перестройте графики так, чтобы каждая кривая располагалась на одном графике с помощью команды subplot, легенду уберите, а её текст переместите в название соответствующего графика. Графики располо- жите на полотне: • в одни столбец; • в два столбца; • в 3 столбца; • в одну строку. Перестройте графики из задания каждый в своём окне. Сделайте так, чтобы эти графики автоматически сохранялись каждый в свой файл. Задание 22 Постройте круговую диаграмму, которая показывала бы до- ли от общего числа студентов вашей группы, сдавших сессию на: 1. одни пятёрки, 2. пятёрки и четвёрки, 3. с тройками, но без задолжностей, 4. с задолжностями, сумевших в итоге пересдать, 5. несдавших и отчисленных (если такие имеются). Задание 23 Постройте закрашенную контурную диаграмму и трёхмер- ный график для следующих функций двух переменных, определённых в прямоугольной области x ∈ [−3; 3], y ∈ [−3; 3]: 1. z = x 2 + y 2 , 2. z = x 2 − y 2 , 3. z = x 3 + y 3 , 4. z = x 3 − y 3 , 5. z = x 2 − y 2 + x, 6. z = x 2 − y 2 + y, 6.9. Задания на построение графиков 159 7. z = x 2 + y 2 + x, 8. z = x 2 + y 2 + y, 9. z = sin(xy), 10. z = cos(xy), 11. z = tg(xy), 12. z = xy, 13. z = x − sin(xy), 14. z = x + cos(xy), 15. z = px 2 + y 2 Построенные графики сохраните в файлы с расширением png. Глава 7 Библиотеки, встроенные в numpy Исторически numpy имеет в своём составе 3 библиотеки численных мето- дов: linalg для задач линейной алгебры, fft для выполнения быстрого Фурье- преобразования и random для генерации случайных чисел. Хотя основным мо- дулем для научных и инженерных вычислений стал scipy, построенный на базе numpy , поддержка этих трёх библиотек сохраняется из соображений обратной совместимости со старыми программами. Освоение возможностей этих библио- тек позволяет писать много полезных прикладных программ. 7.1 Элементы линейной алгебры Библиотека linalg даёт возможность вычислять определители матриц, ре- шать системы линейных уравнений и задачу наименьших квадратов, произво- дить QR и SVD разложения. Вот пример простой программы, решающей систему линейных уравнений с помощью функции solve и вычисляющей определитель матрицы с помощью функции det из linalg: f r o m numpy i m p o r t * A = array ([[2 , 3] , [ -1 , 5]]) b = array ([ -7 , -16]) x = linalg . solve (A , b ) p r i n t ( x ) D = linalg . det ( A ) p r i n t ( D ) Результаты её работы легко проверить вручную и получить искомые решения: [ 1. -3.] 13.0 Синтаксис функций solve и det простой и очевидный для тех, кто привычен к записи систем уравнений в матричной форме вида ˆ Ax = b. Функция solve тре- бует 2 параметра: матрицу коэффициентов ˆ A и вектор свободных членов (правая 7.1. Элементы линейной алгебры 161 часть системы уравнений) b. Результат выполнения функции — вектор искомых значений x. Функция det требует один параметр — матрицу, определитель кото- рой следует отыскать. Кроме определителя для матриц можно вычислить собственные значения и собственные векторы матрицы (linalg.eig(a)), а также норму вектора или опе- ратора (linalg.norm(x[, ord, axis])). Уже реализованы все основные методы разложения матриц: • inalg.cholesky(a) — разложение Холецкого; linalg.qr(a[, mode]) — QR разложение; linalg.svd(a[, full_matrices, compute_uv]) — сингуляр- ное разложение; linalg.lstsq(a, b) — метод наименьших квадратов. Используя возможности встроенной в модуль numpy библиотеки linalg, по- пробуем решить популярную задачу аппроксимации сток-затворной характери- стики полевого транзистора полиномиальной (параболой) и кусочно-линейной функцией. В данном случае, под аппроксимацией будем понимать замену изме- ренных пар значений (напряжение, ток) некоторою функцией ток(напряжение). Предположим, что у нас есть результаты измерения тока стока i c (список y) при изменении напряжения на затворе U ЗИ (массив x). Данная вольт-амперная характеристика (ВАХ) показана на рис. 7.1. Программа для её отображения бу- дет иметь следующий вид: f r o m numpy i m p o r t * f r o m m a t p l o t l i b . pyplot i m p o r t * f r o m m a t p l o t l i b i m p o r t r c P a r a m s r c P a r a m s [ ’ font . sans - serif ’] = ’ L i b e r a t i o n Ђ Sans ’ x = arange (0 , -4.5 , -0.5) y = [50 , 35 , 22 , 11 , 4 , 0 , 0 , 0 , 0] plot (x , y , ’o ’ , color = ’ grey ’) title ( ’Сток-затворная характеристика’) xlabel ( r ’ $U_ {ЗИ} , В$ ’ , f o n t s i z e =18) ylabel ( r ’ $i_ {с} , мкA$ ’ , f o n t s i z e =18) xlim ( -5 , 0.5) ylim ( -10 , 60) show () Кусочно-линейная аппроксимация заменяет ВАХ транзистора двумя отрез- ками: i с = α 0 + α 1 U ЗИ при U ЗИ > U отс 0 при U ЗИ < U отс (7.1) Используя метод наименьших квадратов (lstsq) и функцию матричного умножения (dot), произведём аппроксимацию этих двух участков ВАХ прямыми линиями (рис. 7.2(а)). Разделим все измерения на два отрезка от 0 В до −1.5 В (b = 0; e = 4) и от −2.5 В до −4 В (b = 5; e = 9). Выведем значения ко- эффициентов аппроксимации, для чего добавим следующий код перед выводом изображения на экран функцей show(): 162 Глава 7. Библиотеки, встроенные в numpy 5 4 3 2 1 0 U , 10 0 10 20 30 40 50 60 i , A - Рис. 7.1. Сток-затворная характеристика полевого транзистора (ВАХ) — резуль- таты эксперимента. b =0; e =4; r =e - b a = ones (( r , 2)) a [: , 1] = x [1: r +1] result = linalg . lstsq (a , y [ b : e ]) ya1 = dot (a , result [0]) plot ( x [ b : e ] , ya1 , color = ’ black ’) p r i n t ( result [0]) b =5; e =9; r =e - b a = ones (( r , 2)) a [: , 1] = x [1: r +1] result = linalg . lstsq (a , y [ b : e ]) ya1 = dot (a , result [0]) plot ( x [ b : e ] , ya1 , color = ’ black ’) p r i n t ( result [0]) Результаты: [ 62. 26.] [ 0. 0.] Функция lstsq возвращает кортеж, нулевой элемент которого — коэффициен- ты модели, первый элемент — сумма квадратов ошибок аппроксимации (разниц между реальными и аппроксимированными значениями). Теперь, используя те же функции из модуля numpy, произведём аппроксимацию полиномом второго порядка (7.2) для участка от 0 В до −3 В (b=0; e=7) (рис. 7.2(b)). i с = α 0 + α 1 U ЗИ + α 2 U 2 ЗИ (7.2) Для получения параболической аппроксимации (см. рис. 7.2(b)) нужно заме- нить код из предыдущего листинга на следующий: 7.2. Быстрое преобразование Фурье 163 5 4 3 2 1 0 U , 10 0 10 20 30 40 50 60 i , A - 5 4 3 2 1 0 U , 10 0 10 20 30 40 50 60 i , A - (a) (b) Рис. 7.2. Различные подходы к аппроксимации вольт-амперной характеристики полевого транзистора: (a) — кусочно-линейная, (b) — параболическая. b =0; e =7; r =e - b a = ones (( r , 3)) a [: , 1] = x [1: r +1] a [: , 2] = x [1: r +1]**2 result = linalg . lstsq (a , y [ b : e ]) ya1 = dot (a , result [0]) plot ( x [ b : e ] , ya1 , color = ’ black ’) p r i n t ( result [0]) Результат: [ 69.71428571 41.38095238 6.0952381 ] 7.2 Быстрое преобразование Фурье Библиотека fft позволяет быстро и легко делать все возможные варианты преобразования Фурье над массивами. Многие реализации преобразования Фу- рье до сих пор поддерживают только массивы длиною в 2 N значений, где N — целое число, иначе массив либо обрезается до ближайшей степени двойки, либо удлиняется нулями или периодически. Функции библиотеки fft поддерживают длины массивов, являющиеся степенями 2, 3, 5 и 7 или произвольными их про- изведениями. Самые востребованные методы библиотеки fft — rttf и irfft позволяют произвести прямое Фурье-преобразование над действительнозначны- ми данными и обратное Фурье-преобразование над комплексными данными, для которых половина значений является комплексно-сопряжёнными, причём сопря- жённые значения не включаются в обрабатываемый массив. Далее приведём при- мер расчёта Фурье-преобразования синусоиды: 164 Глава 7. Библиотеки, встроенные в numpy f r o m numpy i m p o r t * t = arange (0 , 1 , 0.1) x = sin (2* pi * t ) fx = fft . rfft ( x ) p r i n t ( fx ) Как и положено нормальной синусоиде, Фурье-образ которой рассчитан на це- лом числе периодов, наша имеет только одну существенно отличную от нуля компоненту: [ -3.33066907e-16 +0.00000000e+00j -1.72084569e-15 -5.00000000e+00j 7.35173425e-16 +4.55540506e-16j -6.24151122e-16 -1.76490554e-15j 1.83186799e-15 +4.44089210e-16j -1.11022302e-16 +0.00000000e+00j] Все остальные значения порядка 10 − 15 или ещё меньше следует признать нулями с точностью вычислений. Часто требуется построить спектр мощности или амплитудный спектр сиг- нала. С помощью numpy эта задача легко решается. Проще всего построить так называемую периодограмму — неусреднённую оценку спектра по одной реализа- ции. Для получения периодограммы мощности достаточно взять квадрат модуля Фурье-образа. Чтобы мощность соответствовала коэффициентам при гармони- ках в исходном сигнале, нужно учесть нормировку. Дело в том, что большинство библиотечных функций Фурье-преобразования производят необходимое для ал- горитма суммирование, но не нормируют результат, поскольку в ряде случа- ев (например, при реализации преобразования Гильберта, для фильтрации, для расчёта функции когерентности) это излишне, а вычислительные ресурсы эко- номятся. Поэтому нормировку необходимо произвести вручную. Для реализации Фурье-преобразования в numpy необходимая нормировка — половина длины ис- ходного ряда. Для начала можно построить амплитудный спектр моногармони- ческого сигнала (рис. 7.3(a)): f r o m numpy i m p o r t * f r o m m a t p l o t l i b . pyplot i m p o r t * r c P a r a m s [ ’ font . sans - serif ’ ]=[ ’ L i b e r a t i o n Ђ Sans ’] dt = 0.1 t = arange (0 , 100 , dt ) x = 2.5* sin (2* pi * t ) fx = fft . rfft ( x ) / ( l e n ( x )/2) # нормировка на половину длины ряда fn = 1/(2* dt ) # частота Найквиста freq = l i n s p a c e (0 , fn , l e n ( fx )) # массив частот plot ( freq , a b s ( fx ) , color = ’ black ’) title ( ’Амплитудный спектр’) xlabel ( ’Частота, Гц’ ); ylabel ( ’Напряжение, В’) ylim ([0 , 3]) 7.2. Быстрое преобразование Фурье 165 0 1 2 3 4 5 , 0.0 0.5 1.0 1.5 2.0 2.5 3.0 , 0 1 2 3 4 5 , 0 2 4 6 8 10 , 2 (a) (b) Рис. 7.3. Амплитудный спектр моногармонического сигнала — (a) и спектр мощ- ности бигармонического сигнала — (b). savefig ( ’ FFT . png ’) show () Здесь частота Найквиста — максимально разрешимая частота в спектре, равная половине частоты выборки. Чтобы построить спектр, нужно рассчитать массив частот, для которых с помощью преобразования Фурье получены значения ам- плитуд гармоник. Это несложно сделать с помощью функции linspace из numpy, если учесть, что минимальная частота равна 0, максимальная — частота Найк- виста, а число частот равно числу амплитуд. Если умножить Фурье образ синусоиды на e iϕ , а затем сделать обратное пре- образование, получится сигнал, сдвинутый по фазе относительно исходного на ϕ. Чаще всего оказывается нужно сдвинуть сигнал на π/2 или −π/2. По пра- вилу Эйлера e − iπ/2 = cos(−π/2) + i sin(−π/2) = −i, то есть мы сдвинули фазу синусоиды на и получили вместо синуса минус косинус: fy = fx * -1 j y = fft . irfft ( fy ) p r i n t ( y ) Вывод: [-1. -0.80901699 -0.30901699 0.30901699 0.80901699 1. 0.80901699 0.30901699 -0.30901699 -0.80901699] Одинокая синусоида единичной амплитуды — не очень интересный пример. Рассчитаем и построим график бигармонического сигнала, состоящего из двух синусоид разных амплитуд (рис. 7.3(b)): f r o m numpy i m p o r t * 166 Глава 7. Библиотеки, встроенные в numpy t = arange (0 , 2 , 0.1) x = 2* sin (2* pi * t ) + 3* cos ( pi * t ) Px = a b s ( fft . rfft ( x )/(0.5* l e n ( t )))**2 p r i n t ( Px ) Получаем коэффициент 9 при 2 члене, что соответствует квадрату амплитуды косинуса, и 4 при третьем — квадрат амплитуды синуса, остальные коэффици- енты — нули: [1.97215226e-33 9.00000000e+00 4.00000000e+00 7.29696337e-31 2.30741815e-31 1.28189897e-31 1.04524070e-31 3.82597539e-31 3.86541844e-31 1.28189897e-31 1.97215226e-33] Строим спектр мощности, увеличив длину ряда: f r o m numpy i m p o r t * f r o m m a t p l o t l i b . pyplot i m p o r t * r c P a r a m s [ ’ font . sans - serif ’ ]=[ ’ L i b e r a t i o n Ђ Sans ’] dt = 0.1 t = arange (0 , 100 , dt ) x = 2* sin (2* pi * t ) + 3* cos ( pi * t ) Px = a b s ( fft . rfft ( x )/(0.5* l e n ( t )))**2 fn = 1/(2* dt ) plot ( l i n s p a c e (0 , fn , l e n ( Px )) , Px , color = ’ black ’) title ( ’Спектр мощности’) xlabel ( ’Частота, Гц’ ); ylabel ( r ’Мощность сигнала, В$ ^2 $ ’) ylim ([0 , 10]) show () 7.3 Генерация случайных чисел Кроме стандартного модуля random есть библиотека random из модуля numpy, которая позволяет генерировать псевдослучайные числа с самыми различными распределениями. Самыми распространёнными являются равномерное, которо- му соответствует функция uniform, и нормальное — функция normal. Обе эти функции имеют одинаковый синтаксис: сначала идут параметры распределения, потом — число значений, которое нужно сгенерировать. Если это число не ука- зать, получится не массив, а одно случайное число. Для равномерного распреде- ления на отрезке [a; b] параметрами являются величины a и b, для нормального со средним µ и дисперсией σ 2 — величины µ и σ. f r o m numpy i m p o r t * x = random . uniform ( -2 , 1 , 10) p r i n t ( x ) y = random . normal (5 , 0.5 , 10) 7.4. Примеры решения заданий 167 p r i n t ( y ) Вывод программы: [-0.41038517 0.33622363 -0.24998561 0.58409914 0.96982331 -1.11356063 -0.43092171 -0.92418957 -0.49456604 -0.61474565] [ 4.89630265 3.68213872 4.97692322 4.4682948 5.19711419 4.87308781 5.51078962 5.68588492 4.65777752 5.66324449] Кроме генерации непрерывно распределённых чисел библиотека random под- держивает также множество дискретных распределений. Самое простое — равно- мерное дискретное, когда вероятности всех событий равны, задаётся с помощью функции randint: f r o m numpy i m p o r t * x = random . randint ( -10 , 10 , 10) p r i n t ( x ) y = random . p e r m u t a t i o n ( x ) p r i n t ( y ) Синтаксис randint полностью повторяет таковой у uniform. В приведён- ном примере использована ещё одна весьма полезная на практике функция permutation . Она случайно тасует элементы массива, но не меняет оригиналь- ный массив, как это видно из сравнения первой и второй строк вывода приве- дённой программы, а вместо этого создаёт новый: [-9 -1 -7 2 8 -8 -4 5 -9 5] [-9 -9 2 -4 5 -7 -1 5 8 -8] В заключение раздела хотелось бы сказать, что numpy обладает гораздо бо- лее мощными и гибкими возможностями, чем это можно проиллюстрировать в рамках приведённого краткого ознакомительного курса. Но красота numpy и его удобство становятся очевидными только по мере использования. |