Файл: Отчет по лабораторной работе 1 Использование NumPy.odt

ВУЗ: Не указан

Категория: Отчеты по практике

Дисциплина: Не указана

Добавлен: 02.05.2024

Просмотров: 15

Скачиваний: 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