Учебное пособие по классификации изображений часов (классификация изображений часов по брендам)
Требуемые пакеты
pip install git+https://github.com/lanpa/tensorboard-pytorch
pip install tensorflow
pip install git+https://github.com/fastai/fastai.git
pip install google_images_download
Сбор данных с помощью googleimagesскачать
Классы, используемые для классификации, будут Audemars Piguet, Hamilton, Hublot, Jaeger Lecoultre, Omega, Patek Philippe, Rolex, Seiko, Sinn, Tag Heuer и Vacheron Constantin (не стесняйтесь добавлять столько классов/брендов, сколько хотите).
Чтобы получить обучающие образцы для каждого класса, мы будем использовать библиотеку загрузки googleimages здесь, которая собирает обучающие изображения из Google. Библиотека также позволяет пользователям указывать желаемый размер изображений и расширение файла, а также различные другие параметры, которые можно найти на странице github.
Чтобы скачать изображения, запустите команду шаблона
googleimagesdownload -k 'KEYWORD' -o 'OUTPUT DIRECTORY' -l <NUMBER OF IMAGES> --chromedriver 'PATH TO CHROMEDRIVER' --size SIZE
Замените KEYWORD на один из классов/брендов часов, OUTPUT DIRECTORY на каталог, в котором вы хотите сохранить изображения, ‹NUMBER OF IMAGES› на желаемое количество обучающих изображений (рекомендуется 1000), PATH TO CHROMEDRIVER на путь к исполняемый файл chromedriver (см. подробнее об установке chromedriver здесь) и SIZE с малым, средним или большим (рекомендуется большой, чтобы обеспечить лучшую точность классификации)
Пример:
googleimagesdownload -k "seiko" -o "C:\Users\Aidan\Documents\DL_Practice\DL Part 2 2018\data\watch_brands\images" -l 1000 --chromedriver "C:\\Users\\Aidan\\Downloads\\chromedriver.exe" --size large
Fast.ai
Импортировать необходимые пакеты
from fastai.imports import * from fastai.conv_learner import * from fastai.sgdr import * from tensorboardX import SummaryWriter torch.backends.cudnn.benchmark=True
torch.backends.cudnn.benchmark=True увеличивает производительность/скорость обучения
PATH = Path('data/watch_brands') IMG_PATH = PATH/'images' FILES_CSV = PATH/'files.csv'
Сохраните необходимые пути к каталогам, FILES_CSV — это путь к csv, который мы создадим, в котором будут храниться имена файлов и классы изображений.
sz=224; bs=64 arch=resnet50
Сохраняйте размер изображений как 224 (медленно обучайте модель на меньших изображениях до больших изображений, что называется прогрессивным изменением размера), а размер пакета должен быть настолько большим, насколько позволяет память графического процессора. Мы будем использовать архитектуру resnet50.
img_files = IMG_PATH.glob('**/**/*.*') img_files = np.array([x for x in img_files]) np.random.shuffle(img_files) img_clas = np.array([str(x).split('\\')[-2] for x in img_files])
Сохраните имена файлов изображений в виде массива numpy, перетасуйте расположение массива, а затем сохраните классы каждого изображения (имя каталога изображений)
with FILES_CSV.open('w') as f: for fn, c in zip(img_files, img_clas): f.write(f'{fn.relative_to(IMG_PATH)},{c}\n')
Создайте CSV-файл с именем файла, в котором первый столбец содержит путь к файлу относительно каталога изображений, а второй столбец содержит класс изображения.
val_idxs = get_cv_idxs(len(img_files)) aug_tfms = [RandomFlip(), RandomRotate(10), RandomLighting(0.05, 0.05)] tfms = tfms_from_model(arch, sz, aug_tfms=aug_tfms) md = ImageClassifierData.from_csv(PATH, 'images', FILES_CSV, bs=bs, tfms=tfms, val_idxs=val_idxs, test_name='test')
Создайте набор проверки, получив индексы для установки в качестве проверки (по умолчанию 20% всех изображений).
Создайте преобразования, создав массив желаемых преобразований fast.ai (RandomFlip, RandomRotate, RandomLighting) и передав его в функцию tfms_from_model, которая возвращает объект tfms (кортеж trn_tfm и val_tfm)
Создайте объект ModelData, используя имя файла csv, желаемый размер пакета, преобразования, индексы проверки и имя тестового каталога (если есть)
Обучение модели
Создание модели учащегося и обучения с использованием циклических скоростей обучения, прогрессивного изменения размера и дифференциальных скоростей обучения
learner = ConvLearner.pretrained(arch, md, ps=[0.5, 0.5]) learner.metrics = [accuracy]
Установите показатели обучения для точности классификации
learner.lr_find(end_lr=100, wds=1e-5) learner.sched.plot(n_skip=1)
Используйте lr_finder, чтобы определить оптимальную скорость обучения для обучения модели.
class TensorboardLogger(Callback): def __init__(self, model, md, log_name, metrics_names=[], path=None, histogram_freq=100): super().__init__() self.model = model self.md = md self.metrics_names = ["validation_loss"] self.metrics_names += metrics_names self.histogram_freq = histogram_freq path = path or os.path.join(md.path, "logs") self.log_dir = os.path.join(path, log_name) def on_train_begin(self): self.iteration = 0 self.epoch = 0 self.writer = SummaryWriter(log_dir=self.log_dir) def on_batch_begin(self): pass def on_phase_begin(self): pass def on_epoch_end(self, metrics): self.epoch += 1 for val, name in zip(metrics, self.metrics_names): self.writer.add_scalar(name, val, self.iteration) def on_phase_end(self): pass def on_batch_end(self, loss): self.iteration += 1 self.writer.add_scalar("loss", loss, self.iteration) if self.iteration%self.histogram_freq==0: for name, param in self.model.model.named_parameters(): self.writer.add_histogram(name, param, self.iteration) def on_train_end(self): try: with warnings.catch_warnings(): warnings.simplefilter("ignore") dummy_input = tuple(next(iter(self.md.trn_dl))[:-1]) self.writer.add_graph(self.model, dummy_input) except Exception as e: print("Unable to create graph.") print(e) self.writer.close()
Создайте пользовательский обратный вызов TensorboardLogger, чтобы обеспечить производительность / статистику обучения с использованием tensorboard (полученный пользовательский класс здесь)
lr=3e-3; wd=1e-5 tb_logger = TensorboardLogger(learner.model, md, 'watch classification test', ['accuracy']) learner.fit(lr, 1, cycle_len=5, wds=wd, use_clr=(20, 10), callbacks=[tb_logger], best_save_name='bestbest')
Установите скорость обучения на значение, немного меньшее минимального значения на графике, и установите скорость снижения веса либо на 1e-6, либо на 1e-5 (соответственно отрегулируйте уменьшение веса, большее уменьшение веса -> больше регуляризации)
Создайте обратный вызов регистратора tensorboard и обучите учащегося. Чтобы просмотреть производительность на tensorboard, выполните команду: tensorboard -logdir='путь к каталогу журналов'
Функция fit принимает несколько обязательных параметров:
1. скорость обучения: установите скорость обучения на 3e-3 на основе lr_finder
2. количество циклов: установите на 1
3. длина цикла: установите значение 5 (определяет количество эпох/количество итераций по всему обучающему набору, обычно определяемое на основе параметров CLR)
4. снижение веса (необязательно): установите значение 1e-5, помогает с регуляризацией (наказывает большие веса)
5. обратные вызовы (необязательно): список обратных вызовов, которые выполняются в конце каждого пакета или эпохи
6. use_clr (циклическая скорость обучения): принимает кортеж, содержащий 2 значения (количество чтобы разделить скорость обучения на, чтобы получить минимальную скорость и количество итераций для увеличения и уменьшения скорости обучения)
7. best_save_name (необязательно): сохранить модель с наилучшей производительностью, основанную на потерях/точности проверки.
Например, установка значения use_clr (20, 10) подразумевает, что минимальная скорость обучения будет 3e-3/20, и что обучение начнется с минимальной скорости обучения и постепенно будет увеличиваться и достигать максимальной скорости обучения (3e-3) за 1 /10 от общего числа итераций. После этого скорость обучения начнет постепенно снижаться и достигнет минимальной скорости обучения (3e-3/20) после 9/10 от общего числа итераций.
learner.unfreeze() lr=3e-3; wd=1e-5 lrs=np.array([lr/100, lr/10, lr]) learner.fit(lrs/20, 1, cycle_len=10, wds=wd, use_clr=(32, 10), callbacks=[tb_logger], best_save_name='bestbest')
После первоначального обучения разморозьте слои модели и создайте массив из 3 разных скоростей обучения, каждая для разных слоев модели, причем нижние слои имеют значительно меньшие скорости обучения.
learner.fit(lrs/200, 1, cycle_len=30, wds=wd, use_clr=(32, 10), callbacks=[tb_logger], best_save_name='bestbest') learner.save('4')
Наконец, тренируйтесь с длиной цикла 30 и пониженной скоростью обучения, чтобы гарантировать, что модель больше не может быть улучшена. Затем измените размер и пакетные параметры объекта ModelData и перезапустите весь процесс, но на этот раз с изображениями большего размера.
После повторения этого процесса до размера изображения 1024 модель должна иметь точность около 88%.
epoch trn_loss val_loss accuracy 0 0.62359 0.410226 0.862729 1 0.670505 0.41044 0.872306 2 0.703594 0.418569 0.868316 3 0.540351 0.418307 0.876297 4 0.586124 0.425277 0.858739 5 0.6451 0.433394 0.865124 6 0.513875 0.418064 0.865124 7 0.560347 0.417235 0.86672 8 0.569284 0.42699 0.865922 9 0.540357 0.406808 0.869912 10 0.585541 0.424397 0.871508 11 0.629697 0.403836 0.873105 12 0.578186 0.399353 0.869912 13 0.580718 0.393956 0.871508 14 0.520731 0.446471 0.857941 15 0.598394 0.41884 0.860335 16 0.611838 0.393764 0.873105 17 0.553723 0.41744 0.865922 18 0.612677 0.411182 0.869114 19 0.6611 0.410436 0.865124 20 0.542844 0.390165 0.876297 21 0.659803 0.398199 0.874701 22 0.563547 0.403286 0.865922 23 0.623685 0.386968 0.87071 24 0.599079 0.414476 0.865922 25 0.521744 0.396762 0.877095 26 0.681244 0.413879 0.868316 27 0.525194 0.397991 0.875499 28 0.627125 0.391735 0.877893 29 0.439041 0.391175 0.879489