Добавлен: 02.05.2024
Просмотров: 18
Скачиваний: 0
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ «АЛИУТСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
ИМЕНИ И.И. ИВАНОВА»
Факультет цифровых технологий и кибербезопасности
Кафедра цифровых технологий
Отчет по лабораторной работе № 1
«Использование NumPy»
выполнена в рамках изучения дисциплины
«Инструментальные средства систем ИИ»
Направление подготовки: 09.04.02. Информационные системы и технологии
Направленность (профиль): Проектирование и разработка систем искусственного интеллекта" (ДИИ) очная форма обучения
Исполнитель: студент группы ДИИ-15
Иванов Иван Иванович
Проверил: доцент кафедры прикладной математики и информатики
Петров Иван Иванович
Использование NumPy
Описание работы
Данная работа представлена набором заданий, которые позволят на практике узнать о возможностях библиотеки Numerical Python.
Задачи
1. Выполнить установку и подключение библиотеки в программе на языке Python. Для этого рекомендуется использовать менеджер пакетов pip.
2. Выполнить генерацию:
a. линейного массива (вектора) чисел с плавающей точкой произвольного размера;
b. выполнить генерацию двумерного массива (матрицы) чисел с плавающей точкой произвольного размера;
c. генерацию массивов выполнять с размерностью в сотни, тысячи, сотни тысяч элементов.
d. для каждого массива выполнить оценку времени, затраченного на генерацию.
e. сравнить показатели с массивами, генерируемыми средствами стандартной библиотеки языка Python аналогичной размерности.
3. Выполнить все арифметические операции над элементами двумерного массива.
4. В качестве полноценного упражнения реализовать игру «Жизнь» с использованием NumPy.
Ход работы
Задание 1.
Для выполнения данной работы необходимо установить и подключить библиотеку NumPy. Работа выполнялась в среде Jupiter Notebook, установленной на локальном компьютере. Установка производилась с использованием менеджера пакетов pip. Для осуществления установки достаточно ввести команду:
pip install numpy
П осле завершения установки должно появиться сообщение о корректной установке указанной библиотеки и сообщение о необходимости перезапуска ядра среды исполнения:
Установка выполнена в ОС Linux Ubuntu 22.04, используемый браузер — Яндекс.Браузер для Linux.
Задание 2.
import numpy as np import time import random # а) генерация и замер времени выполнения одномерных массивов произвольного размера #(по 10 элементов) %time arr = np.random.rand(10) %time lst = [float(random.random()) for _ in (range(10))] # b) генерация и замер времени выполнения двумерных массивов произвольного размера 10 #Х 10 (по 100 элементов) %time arr = np.random.rand(10,10) %time lst = [[float(random.random()) for _ in range(10)] for _ in range(10)] # c)генерация и замер времени выполнения одномерных массивов произвольного размера #(по 100 элементов) %time arr = np.random.rand(100) %time lst = [float(random.random()) for _ in (range(100))] # генерация и замер времени выполнения одномерных массивов произвольного размера #(по 1000 элементов) %time arr = np.random.rand(1000) %time lst = [float(random.random()) for _ in (range(1000))] # генерация и замер времени выполнения одномерных массивов произвольного размера #(по 100 000 элементов) %time arr = np.random.rand(100000) %time lst = [float(random.random()) for _ in (range(100000))]
Результаты замера времени приведены ниже. Первые две строки вывода — замер времени выполнения функции библиотеки numpy, следующие две строки вывода — стандартной библиотеки.
Генерация массива (списка), состоящего из 10 элементов:
CPU times: user 22 µs, sys: 8 µs, total: 30 µs Wall time: 36.7 µs CPU times: user 13 µs, sys: 4 µs, total: 17 µs Wall time: 22.2 µs
Генерация двумерного массива (списка) из 100 элементов (10 х 10):
CPU times: user 14 µs, sys: 5 µs, total: 19 µs
Wall time: 24.6 µs CPU times: user 43 µs, sys: 15 µs, total: 58 µs Wall time: 62.9 µs
Генерация массива (списка) из 100 элементов:
CPU times: user 19 µs, sys: 0 ns, total: 19 µs Wall time: 25.3 µs CPU times: user 48 µs, sys: 0 ns, total: 48 µs Wall time: 52 µs
Генерация массива (списка) из 1000 элементов:
CPU times: user 30 µs, sys: 0 ns, total: 30 µs Wall time: 35.3 µs CPU times: user 357 µs, sys: 0 ns, total: 357 µs Wall time: 367 µs
Генерация массива (списка) из 100000 элементов:
CPU times: user 147 µs, sys: 2.41 ms, total: 2.56 ms Wall time: 1.58 ms CPU times: user 16.6 ms, sys: 53 µs, total: 16.7 ms Wall time: 16.4 ms
Выводы по заданию 2:
1. На небольших списках (в примере список из 10 элементов) стандартная библиотека работает быстрее. Скорее всего это связано с тем, что для обращения к библиотеке numpy требуется дополнительное время.
2. На массивах большей размерности время выполнения функции библиотеки numpy заметно меньше, это связано со спецификой реализации данной библиотеки, она написана на языке C (низкоуровневый компилируемый язык), что даёт прирост производительности вычислений.
Задание 3
import numpy as np import time import random # Генерируем целочисленный массив [1, 2, 3] средствами numpy p = np.arange(1, 4) # создаём "сетку" значений, то есть создаём два двумерных массива средствами numpy m1, m2 = np.meshgrid(p, p*2) print(m1) print('----------') print(m2) print('----------') # Сложение print(m1 + m2) print('----------') # Вычитание print(m1 - m2) print('----------') # Умножение print(m1 * m2) print('----------') # Деление print(m1 / m2) print('----------') # Матричное умножение print(m1 @ m2)
Получаем следующие выходные данные:
[[1 2 3] [1 2 3] [1 2 3]] ---------- [[2 2 2] [4 4 4] [6 6 6]] ---------- [[3 4 5] [5 6 7] [7 8 9]] ---------- [[-1 0 1] [-3 -2 -1] [-5 -4 -3]] ---------- [[ 2 4 6] [ 4 8 12] [ 6 12 18]] ---------- [[0.5 1. 1.5 ] [0.25 0.5 0.75 ] [0.16666667 0.33333333 0.5 ]] ---------- [[28 28 28] [28 28 28] [28 28 28]]
Вывод по заданию 3: все основные арифметические операции в библиотеке numpy векторизованы, что позволяет обойтись при написании кода без явного использования циклов.
Задание 4
Версия Jupiter из репозитория Ubuntu не позволила корректно отработать приложению с использованием библиотеки pygame, по этой причине реализация игры «Жизнь» была запущена в среде Visual Studio Code.
Листинг второй программы, выполняющей пункт 4, представлен ниже. Программа была выполнена с использованием библиотеки NumPy для генерации чисел и массивов, и библиотеки PyGame для визуализации.
Программа состоит из двух классов: Life и App. Класс Life предназначен для работы с игрой «Жизнь».
Одна из генераций игры «Жизнь»
Реализация игры «Жизнь»
import numpy as np
from time import sleep
import pygame as pg
import os
WIDTH = 1000 # Ширина окна
HEIGHT = 1000 # Высота окна
FPS = 10 # Количество обновлений в секунду
UNIT_COLOR = (216, 75, 32) # Цвет живой клетки
BACKGROUND = (204, 200, 200) # Цвет неживой клетки
class App:
def __init__(self, game):
pg.init()
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption("Life game")
self.game = game
self.unit_width = WIDTH // game.cols
self.unit_height = HEIGHT // game.rows
self.run = True
self.clock = pg.time.Clock()
# Вычисляет новую генерацию игры.
def update(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.run = False
self.game.step()
# Выводит генерацию игры на экран.
def draw(self):
while self.run:
self.clock.tick(FPS)
self.screen.fill((255, 255, 255))
for i in range(self.game.field.shape[0]):
for j in range(self.game.field.shape[1]):
unit = pg.Rect(j*self.unit_width, i*self.unit_height, self.unit_width, self.unit_height)
color = BACKGROUND
if self.game.field[i][j] == 1:
color = UNIT_COLOR
pg.draw.rect(self.screen, color, unit)
self.update()
pg.display.set_caption(f"Life game. Units: {int(self.game.units_count)}")
pg.display.flip()
class Life:
def __init__(self, rows, cols):
self.units_count = 0
self.rows = rows
self.cols = cols
self.field = None
# Создаёт первую жизнь
def start(self):
self.field = np.zeros((self.rows, self.cols))
for i in range(self.field.shape[0]):
for j in range(self.field.shape[1]):
unit = np.random.choice([0, 1])
if unit:
self.field[i][j] = unit
self.units_count += 1
# Вычисляет количество соседей unit.
# Входные параметры:
# unit: np.array - координаты клетки
# Выходные параметры:
# count: int - число соседей unit
def get_neighbours(self, unit):
count = 0
for i in range(-1, 2):
for j in range(-1, 2):
if [i, j] == [0, 0]:
continue
neighbI = (unit[0] + i) % self.rows
neighbJ = (unit[1] + j) % self.cols
if self.field[neighbI][neighbJ] == 1:
count += 1
return count
# Создаёт новую генерацию игры.
def step(self):
next_generation = np.zeros(self.field.shape)
for i in range(self.field.shape[0]):
for j in range(self.field.shape[1]):
if self.field[i][j]:
if self.get_neighbours([i, j]) in (2, 3):
next_generation[i][j] = 1
continue
else:
if self.get_neighbours([i, j]) == 3:
next_generation[i][j] = 1
continue
self.field = next_generation
self.units_count = np.sum(self.field)
if __name__ == '__main__':
life = Life(250, 250)
life.start()
app = App(life)
app.draw()
Выводы по заданию 4:
Использование средств библиотеки numpy не только ускоряет вычисления за счёт использования низкоуровневого кода, но и значительно упрощает написание приложений. Операция векторизации делает код более лаконичным и схожа с подобным подходом языка R.
Можайск – 2022