Категория статьи: Нейронные сети
Проект: Shazam своими руками
Некоторые часть кода выполняются многократно, я выделил их в отдельные функции
Всем привет!
В этой статье речь пойдёт о вспомогательных функциях.
Функции для работы с каталогами
В одной из статей я уже упоминал функции для работы с каталогами, добавил еще парочку.
import os
import shutil
# Глобальные переменные
# Максимальная длина сгенерированного имени директории
max_len_dirname = 6
# Максимальная длина сгенерированного имени файла
max_len_filename = 6
def del_create_dir(src_dir):
"""Удаление директории с вложенными файлами и папками
и создание её снова
Parameters
----------
src_dir: str
Директория для удаления и создания
"""
# Проверяем существует ли директория src_dir
if os.path.exists(src_dir):
# Удаляем её и все вложенные файлы и папки
shutil.rmtree(src_dir)
# Создаём директорию src_dir
os.makedirs(src_dir)
def create_dir_if_not_exists(src_dir, echo=False):
"""Создание директории если она не существует
Parameters
----------
src_dir: str
Директория для создания
echo: bool (default=False)
Флаг вывода сообщения
"""
# проверяем отсутствует ли директория src_dir
if not os.path.exists(src_dir):
# Создаём директорию src_dir
os.makedirs(src_dir)
# Если флаг вывода сообщения установлен
if echo:
# Выводим сообщение
print(f"Создана директория '{src_dir}'")
# Если директория src_dir уже существует
else:
# Проверим флаг вывода сообщения, если он True
if echo:
# Выводим сообщение о том, что директория уже существует
print(f"Директория '{src_dir}' уже существует")
def create_labeled_dir(parent_dir, label):
"""Создание директории с именем соответствующим метке label
с дополнением нулями спереди
Parameters
----------
parent_dir: str
Родительская директория
label: int
Метка класса на основе которого будет создана директория
Returns
-------
full_dirname: str
Полный пить к созданной директории
"""
# Формируем имя директории
dirname = str(label).zfill(max_len_dirname)
# Формируем полный пить к директории
full_dirname = os.path.join(parent_dir, dirname)
# Создаем директорию если она не создана
create_dir_if_not_exists(full_dirname)
# Возвращаем полный пить к созданной директории
return full_dirname
Pickle
Нарезанные 2х секундные кусочки файлов mp3, особенно когда их становится много, не реально все поместить в оперативную память, для этого нам нужно их сохранить на диске. А загружать будем перед подачей данных для обучения модели. Для сохранения/загрузки объектов в файл воспользуемся библиотекой pickle.
import pickle
def unpickle(filename):
"""Распаковать объект из файла
Parameters
----------
filename: str
Имя файла
Returns
-------
obj: Объект
Любой объект
"""
# Открываем файл для чтения в бинарном режиме
with open(filename, 'rb') as f:
# Загружаем данные из файла в объект
obj = pickle.load(f, encoding='bytes')
# Закрываем файл
f.close()
# Возвращаем объект
return obj
def dumppickle(filename, obj):
"""Запаковать объект в файл
Parameters
----------
filename: str
Имя файла
obj: Объект
Любой объект
"""
# Открываем файл для записи в бинарном режиме
with open(filename, 'wb') as f:
# Сохраняем объект в файл
pickle.dump(obj, f)
# Закрываем файл
f.close()
Измерение времени выполнения функции или блока кода
Иногда необходимо оценить время выполнения той или иной операции (итерации), например, для того чтобы примерно понимать общее время выполнение определенного количества итераций. Для этого я подготовил класс с примерами его использования.
from timeit import default_timer
class MeasuringRunTime():
"""Измерение времени выполнения функции или блока кода.
Example
-------
t1 = MeasuringRunTime.Timer()
t1.Start()
for i in range(100000000):
pass
# Останавливаем таймер, можем посмотреть сколько прошло секунд
print(t1.Stop())
# Просматриваем истекшее время
print(t1.Elapsed())
def test_fn(a, b):
for i in range(100000000):
a += b
return a
mrt = MeasuringRunTime()
print(mrt.Measuring(test_fn, 0, 1))
# Обвертка прокидывает результат функции и можно дальше работать
x = mrt.Measuring(test_fn, 1, 1)
y = mrt.Measuring(test_fn, 2, 1)
print(x + y)
mrt.Info()
"""
class Timer():
"""Класс таймер
"""
def __init__(self, start=True):
self.__timer_start = None
if start:
self.Start()
self.__elapsed = 0
def Start(self):
self.__timer_start = default_timer()
def Elapsed(self):
if self.__timer_start is not None:
self.__elapsed = default_timer() - self.__timer_start
return self.__elapsed
def Stop(self):
self.Elapsed()
self.__timer_start = None
return self.__elapsed
def __init__(self):
self.timers = {}
def ClearTimer():
self.timers = {}
def Info(self):
for key, val in self.timers.items():
i = 0
for item in val:
print("{:>20} : {} - {:.10f} секунд".format(key, i, item.Elapsed()))
i += 1
def Measuring(self, fn, *args, **kwargs):
t = MeasuringRunTime.Timer()
if fn.__name__ not in self.timers:
self.timers[fn.__name__] = [t]
else:
self.timers[fn.__name__].append(t)
t.Start()
ret = fn(*args, **kwargs)
t.Stop()
return ret
Функция отображения истории обучения модели
После обучения модели несколько эпох иногда бывает полезно взглянуть на историю обучения модели в графическом виде. По графику видно не возникло ли переобучение модели? Способна ли модель охватить все данные и обучиться? Качество обучаемой и проверочной выборок.
import matplotlib.pyplot as plt
def ShowHistory(h, metrics=["loss"]):
"""Отображение графиков обучения модели.
Parameters
----------
h: Объект History
History.history содержит информацию об ошибках и метриках
на этапах обучения модели.
metrics: list (default=["loss"])
Список ошибок и метрик.
"""
# Для каждой метрики из списка
for m in metrics:
# Проверяем есть ли история
if m in h.history:
# Рисуем метрику на графике
plt.plot(h.history[m], label='train')
# Есть ли история для метрики на проверочном наборе
if 'val_' + m in h.history:
# Рисуем метрику на графике
plt.plot(h.history['val_' + m], label='val')
# Подписываем ось x
plt.xlabel('Эпоха обучения')
# Подписываем ось y
plt.ylabel(m)
# добавляем легенду
plt.legend()
# Отображаем график
plt.show()