вводить
Навыки, необходимые для успешного участия в хакатоне по глубокому обучению (или, честно говоря, в любомХакатон по науке о данных) обычно сводится к разработке функций. Насколько креативным вы можете быть, если у вас недостаточно данных для построения успешной модели глубокого обучения?
Я говорю о своем собственном опыте участия в нескольких конкурсах хакатонов по глубокому обучению, где мы получили набор данных с сотнями изображений — этого просто недостаточно, чтобы выиграть или даже занять первое место в таблице лидеров. Итак, как нам справиться с этой проблемой?
Отвечать? Ну, это зависит от навыков специалиста по данным! Здесь проявляется наше любопытство и креативность. В этом и заключается идея разработки функций — насколько хорошо мы можем придумать новые функции, учитывая существующие. Та же идея применяется, когда мы работаем с данными изображения.
Это основная роль улучшения изображения. Концепция не ограничивается хакатонами — мы работаем в промышленности и в реальном мире.модель глубокого обученияИспользуется во всех проектах!
Аугментация изображений помогает мне дополнять существующие наборы данных без затрат времени и усилий. И я уверен, что вы найдете эту технику очень полезной для ваших собственных проектов.
Итак, в этой статье мы поймем концепцию улучшения изображения, почему это полезно и каковы различные методы улучшения изображения. Мы также реализуем эти методы увеличения изображений для создания моделей классификации изображений с использованием PyTorch.
содержание
- Зачем нужно улучшение изображения?
- Различные методы улучшения изображения
- Основные рекомендации по выбору правильной техники аугментации
- Практический пример: использование увеличения изображения для решения проблем классификации изображений
Зачем нужно улучшение изображения?
Модели глубокого обучения обычно требуют больших объемов данных для обучения. Как правило, чем больше данных, тем лучше производительность модели. Но доступ к огромным объемам данных сопряжен со своими проблемами. Не у всех есть глубокие карманы крупных корпораций.
Отсутствие данных делает нашу [модель глубокого обучения](курсы.аналитика vi.com/courses/com…-learning-pytorch) может быть не в состоянии изучить шаблоны или функции из данных и, следовательно, не может обеспечить хорошую производительность на невидимых данных.
Так что же нам делать в такой ситуации? мы можем использоватьТехнология улучшения изображения, не тратя дни на ручной сбор данных.
Увеличение изображения — это процесс создания новых изображений для обучения нашей модели глубокого обучения. Эти новые изображения создаются с использованием существующих обучающих изображений, поэтому нам не нужно собирать их вручную.
Существует множество методов улучшения изображения, и мы обсудим некоторые из распространенных и наиболее широко используемых методов в следующем разделе.
Различные методы улучшения изображения
Поворот изображения
Поворот изображения является одним из наиболее часто используемых методов улучшения изображения. Это помогает нашей модели стать устойчивой к изменениям в ориентации объекта. Даже если мы повернем изображение, информация об изображении останется прежней. Автомобиль есть автомобиль, даже если посмотреть на него под другим углом:
Следовательно, мы можем использовать эту технику для увеличения объема данных, создавая повернутое изображение из исходного изображения. Давайте посмотрим, как повернуть изображение:
# 导入所有必需的库
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import skimage.io as io
from skimage.transform import rotate, AffineTransform, warp
from skimage.util import random_noise
from skimage.filters import gaussian
import matplotlib.pyplot as plt
% matplotlib inline
я используюэто изображениеПродемонстрируйте различные методы улучшения изображения. Вы также можете попробовать другие изображения в соответствии с вашими требованиями.
Давайте сначала импортируем изображение и визуализируем его:
# reading the image using its path
image = io.imread('emergency_vs_non-emergency_dataset/images/0.jpg')
# shape of the image
print(image.shape)
# displaying the image
io.imshow(image)
Это исходное изображение. Теперь давайте посмотрим, как его повернуть. я используюskimageФункция поворота библиотеки для поворота изображения:
print('Rotated Image')
#rotating the image by 45 degrees
rotated = rotate(image, angle=45, mode = 'wrap')
#plot the rotated image
io.imshow(rotated)
очень хороший! Установите режим «обтекание», чтобы заполнить точки за пределами входных границ оставшимися пикселями изображения.
Панорамирование изображения
Может случиться так, что объекты на изображении не идеально выровнены по центру. В этих случаях перевод изображения можно использовать для придания изображению инвариантности к переводу.
Перемещая изображение, мы можем менять положение объекта на изображении, делая модель более разнообразной. В конце концов будет создана более общая модель.
Преобразование изображения — это геометрическое преобразование, которое сопоставляет положение каждого объекта на изображении с новой позицией в конечном выходном изображении.
После операции сдвига объект в позиции (x, y) на входном изображении смещается в новую позицию (X, Y):
- X = x + dx
- Y = y + dy
где dx и dy — перемещения по разным измерениям соответственно. Давайте посмотрим, как применить сдвиг к изображению:
# 应用平移操作
transform = AffineTransform(translation=(25,25))
wrapShift = warp(image,transform,mode='wrap')
plt.imshow(wrapShift)
plt.title('Wrap Shift')
Гиперпараметр перевода определяет количество пикселей, на которое должно быть перемещено изображение. Здесь я сдвинул изображение на (25, 25) пикселей. Вы можете свободно установить значение этого гиперпараметра.
Я снова использую режим «WRAP», который заполняет точку, отличную от границы ввода, оставшимися пикселями изображения. В приведенном выше выводе вы можете видеть, что высота и ширина изображения перемещаются на 25 пикселей.
перевернуть изображение
Флип - это продолжение вращения. Это позволяет нам переворачивать изображение влево и вправо, а также вверх и вниз. Давайте посмотрим, как реализовать флип:
#flip image left-to-right
flipLR = np.fliplr(image)
plt.imshow(flipLR)
plt.title('Left to Right Flipped')
Здесь я использовал NumPyfliplrФункция переворачивает изображение слева направо. Он переворачивает значения пикселей для каждой строки, и вывод подтверждает то же самое. Точно так же мы можем переворачивать изображение вверх и вниз:
# 上下翻转图像
flipUD = np.flipud(image)
plt.imshow(flipUD)
plt.title('Up Down Flipped')
Вот как мы можем перевернуть изображение и создать более общую модель, которая будет изучать исходное изображение, а также перевернутое изображение. Добавление случайного шума к изображению также является методом улучшения изображения. Давайте разберемся на примере.
Добавьте шум к изображению
Шум изображения — важный шаг улучшения, который позволяет нашей модели научиться разделять сигнал и шум в изображениях. Это также делает модель более устойчивой к изменениям входных данных.
Мы добавим случайный шум к исходному изображению, используя функцию «random_noise» библиотеки «skipage».
Я взял стандартное отклонение шума равным 0,155 (это тоже можно изменить). Имейте в виду, что увеличение этого значения добавит больше шума к изображению и наоборот:
# 要添加到图像中的噪声的标准差
sigma=0.155
# 向图像添加随机噪声
noisyRandom = random_noise(image,var=sigma**2)
plt.imshow(noisyRandom)
plt.title('Random Noise')
Мы видим, что к исходному изображению был добавлен случайный шум. Попробуйте разные значения стандартного отклонения и посмотрите, какие результаты вы получите.
размытое изображение
Все любители фотографии сразу поймут эту идею.
Изображения приходят из разных источников. Поэтому качество изображения каждого источника будет разным. Некоторые изображения могут быть высокого качества, в то время как другие могут быть плохими.
В этом случае мы можем размыть изображение. Как это поможет? Что ж, это помогает сделать нашу модель глубокого обучения более мощной.
Давайте посмотрим, как мы можем это сделать. Мы будем использовать фильтр Гаусса, чтобы размыть изображение:
# 模糊图像
blurred = gaussian(image,sigma=1,multichannel=True)
plt.imshow(blurred)
plt.title('Blurred Image')
Sigma — это стандартное отклонение фильтра Гаусса. Я вижу это как 1. Чем выше значение сигмы, тем сильнее эффект размытия.Установка для параметра *Multichannel* значения true гарантирует, что каждый канал изображения фильтруется отдельно.
Опять же, вы можете поэкспериментировать с разными значениями сигмы, чтобы изменить размытость.
Это некоторые методы увеличения изображения, которые помогают сделать наши модели глубокого обучения надежными и обобщаемыми. Это также помогает увеличить размер тренировочного набора.
Мы собираемся завершить часть реализации этого руководства. Перед этим давайте рассмотрим некоторые основные рекомендации, чтобы выбрать правильный метод улучшения изображения.
Основные рекомендации по выбору правильной техники аугментации
Я думаю, что важно иметь некоторые рекомендации при выборе методов аугментации, основанных на проблеме, которую вы пытаетесь решить. Вот краткий обзор этих рекомендаций:
- Первым шагом в любом процессе построения модели является обеспечение того, чтобы размер входных данных соответствовал ожиданиям модели. Мы также должны убедиться, что все изображения должны быть одинаковыми по размеру. Для этого мы можем изменить размер нашего изображения до нужного размера.
- Предположим, вы имеете дело с проблемой классификации и имеете относительно небольшой объем выборочных данных. В этом случае могут использоваться различные методы улучшения, такие как поворот изображения, шум изображения, отражение, смещение и т. д. Помните, что все эти операции применимы к задачам классификации, где расположение объектов на изображении несущественно.
- Если вы работаете над задачей обнаружения объекта, где положение объекта — это то, что мы хотим обнаружить, эти методы могут не подойти.
- Нормализация значений пикселей изображения — хорошая стратегия для обеспечения лучшей и быстрой сходимости модели. Если у модели есть особые требования, мы должны предварительно обработать изображение в соответствии с требованиями модели.
Теперь, не дожидаясь больше, давайте перейдем к части построения модели. Мы будем применять методы увеличения, обсуждаемые в этой статье, для создания изображений, а затем использовать эти изображения для обучения модели.
Мы изучим проблему классификации автомобилей скорой помощи и автомобилей, не являющихся аварийными. если ты виделМои предыдущие статьи о PyTorch, вы должны быть знакомы с описанием проблемы.
Цель этого проекта состоит в том, чтобы классифицировать изображения транспортных средств на аварийные и неаварийные категории. Как вы уже догадались, это проблема классификации изображений. ты сможешьотздесьСкачать набор данных.
Загрузить набор данных
Давайте начнем! Давайте сначала загрузим данные в блокнот. Затем мы применим методы улучшения изображения и, наконец, построимСверточная нейронная сеть (CNN)Модель.
Импортируем необходимые библиотеки:
# 导入库
from torchsummary import summary
import pandas as pd
import numpy as np
from skimage.io import imread, imsave
from tqdm import tqdm
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from skimage.transform import rotate
from skimage.util import random_noise
from skimage.filters import gaussian
from scipy import ndimage
Теперь мы прочитаем файл CSV, содержащий имена изображений и соответствующие им метки:
# 加载数据集
data = pd.read_csv('emergency_vs_non-emergency_dataset/emergency_train.csv')
data.head()
0 означает, что автомобиль не является аварийным транспортным средством, 1 означает, что автомобиль является аварийным транспортным средством. Теперь давайте загрузим все изображения из набора данных:
# 加载图像
train_img = []
for img_name in tqdm(data['image_names']):
image_path = 'emergency_vs_non-emergency_dataset/images/' + img_name
img = imread(image_path)
img = img/255
train_img.append(img)
train_x = np.array(train_img)
train_y = data['emergency_or_not'].values
train_x.shape, train_y.shape
Всего в наборе данных 1646 изображений. Давайте разделим эти данные на наборы для обучения и проверки. Мы будем использовать набор проверки для оценки производительности модели на невидимых данных:
train_x, val_x, train_y, val_y = train_test_split(train_x, train_y, test_size = 0.1, random_state = 13, stratify=train_y)
(train_x.shape, train_y.shape), (val_x.shape, val_y.shape)
** Я оставил «test_size» равным 0,1, поэтому 10 % данных будут выбраны случайным образом в качестве проверочного набора, а оставшиеся 90 % будут использованы для обучения модели. **Обучающий набор содержит 1481 изображение, что довольно много для обучения модели глубокого обучения.
Итак, далее мы добавим эти тренировочные изображения, чтобы увеличить тренировочный набор и, возможно, улучшить производительность модели.
Улучшить изображение
Мы будем использовать методы улучшения изображения, рассмотренные ранее:
final_train_data = []
final_target_train = []
for i in tqdm(range(train_x.shape[0])):
final_train_data.append(train_x[i])
final_train_data.append(rotate(train_x[i], angle=45, mode = 'wrap'))
final_train_data.append(np.fliplr(train_x[i]))
final_train_data.append(np.flipud(train_x[i]))
final_train_data.append(random_noise(train_x[i],var=0.2**2))
for j in range(5):
final_target_train.append(train_y[i])
Мы создали 4 дополненных изображения для каждого из 1481 изображения в обучающем наборе. Давайте преобразуем изображение в массив и проверим размер набора данных:
len(final_target_train), len(final_train_data)
final_train = np.array(final_train_data)
final_target_train = np.array(final_target_train)
Это подтверждает, что мы увеличили изображения и увеличили размер обучающей выборки. Давайте визуализируем эти дополненные изображения:
fig,ax = plt.subplots(nrows=1,ncols=5,figsize=(20,20))
for i in range(5):
ax[i].imshow(final_train[i+30])
ax[i].axis('off')
Первое изображение здесь — исходное изображение из набора данных. Остальные четыре изображения были сгенерированы с использованием различных методов улучшения изображения (поворот, перелистывание слева направо, перелистывание вверх и вниз и добавление случайного шума).
Наш набор данных готов. Пришло время определить структуру нашей модели глубокого обучения и обучить ее на расширенном обучающем наборе. Давайте начнем сPyTorchИмпортируйте все функции в:
# PyTorch 库和模块
import torch
from torch.autograd import Variable
from torch.nn import Linear, ReLU, CrossEntropyLoss, Sequential, Conv2d, MaxPool2d, Module, Softmax, BatchNorm2d, Dropout
from torch.optim import Adam, SGD
Нам нужно преобразовать наборы для обучения и проверки в формат PyTorch:
# 将训练图像转换为torch格式
final_train = final_train.reshape(7405, 3, 224, 224)
final_train = torch.from_numpy(final_train)
final_train = final_train.float()
# 将target转换为torch格式
final_target_train = final_target_train.astype(int)
final_target_train = torch.from_numpy(final_target_train)
Опять же, мы преобразуем набор проверки:
# 将验证图像转换为torch格式
val_x = val_x.reshape(165, 3, 224, 224)
val_x = torch.from_numpy(val_x)
val_x = val_x.float()
# 将target转换为torch格式
val_y = val_y.astype(int)
val_y = torch.from_numpy(val_y)
Структура модели
Далее мы определим структуру модели. Это немного сложно, потому что структура модели состоит из 4 сверточных блоков, за которыми следуют 4 полносвязных слоя:
torch.manual_seed(0)
class Net(Module):
def __init__(self):
super(Net, self).__init__()
self.cnn_layers = Sequential(
# 定义2D convolution层
Conv2d(3, 32, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
# 添加batch normalization层
BatchNorm2d(32),
MaxPool2d(kernel_size=2, stride=2),
# 添加 dropout
Dropout(p=0.25),
# 定义另一个2D convolution层
Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
# 添加batch normalization层
BatchNorm2d(64),
MaxPool2d(kernel_size=2, stride=2),
# 添加 dropout
Dropout(p=0.25),
# 定义另一个2D convolution层
Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
# 添加batch normalization层
BatchNorm2d(128),
MaxPool2d(kernel_size=2, stride=2),
# 添加 dropout
Dropout(p=0.25),
# 定义另一个2D convolution层
Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
# 添加batch normalization层
BatchNorm2d(128),
MaxPool2d(kernel_size=2, stride=2),
# 添加 dropout
Dropout(p=0.25),
)
self.linear_layers = Sequential(
Linear(128 * 14 * 14, 512),
ReLU(inplace=True),
Dropout(),
Linear(512, 256),
ReLU(inplace=True),
Dropout(),
Linear(256,10),
ReLU(inplace=True),
Dropout(),
Linear(10,2)
)
# 定义前向过程
def forward(self, x):
x = self.cnn_layers(x)
x = x.view(x.size(0), -1)
x = self.linear_layers(x)
return x
Давайте определим другие гиперпараметры модели, включая оптимизатор, скорость обучения и функцию потерь:
# defining the model
model = Net()
# defining the optimizer
optimizer = Adam(model.parameters(), lr=0.000075)
# defining the loss function
criterion = CrossEntropyLoss()
# checking if GPU is available
if torch.cuda.is_available():
model = model.cuda()
criterion = criterion.cuda()
print(model)
Обучите модель
Обучите нашу модель глубокого обучения в течение 20 эпох:
torch.manual_seed(0)
# 模型的batch size
batch_size = 64
# 训练模型的epoch数
n_epochs = 20
for epoch in range(1, n_epochs+1):
train_loss = 0.0
permutation = torch.randperm(final_train.size()[0])
training_loss = []
for i in tqdm(range(0,final_train.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = final_train[indices], final_target_train[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
optimizer.zero_grad()
outputs = model(batch_x)
loss = criterion(outputs,batch_y)
training_loss.append(loss.item())
loss.backward()
optimizer.step()
training_loss = np.average(training_loss)
print('epoch: \t', epoch, '\t training loss: \t', training_loss)
Это краткое изложение этапа обучения. Вы заметите, что потери при обучении уменьшаются по мере увеличения эпохи. Сохраним веса обученной модели, чтобы можно было использовать их в будущем без переобучения модели:
torch.save(model, 'model.pt')
Если вы не хотите обучать модель в своем терминале, вы можете использоватьэта ссылкаЗагрузите веса для модели, обученной в течение 20 эпох.
Далее, давайте загрузим эту модель:
the_model = torch.load('model.pt')
Проверьте производительность нашей модели
Наконец, давайте сделаем прогнозы для обучающего и проверочного наборов и проверим соответствующую точность:
torch.manual_seed(0)
# 预测训练集
prediction = []
target = []
permutation = torch.randperm(final_train.size()[0])
for i in tqdm(range(0,final_train.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = final_train[indices], final_target_train[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction.append(predictions)
target.append(batch_y)
# 训练准确度
accuracy = []
for i in range(len(prediction)):
accuracy.append(accuracy_score(target[i].cpu(),prediction[i]))
print('training accuracy: \t', np.average(accuracy))
Точность на тренировочном наборе составляет более 91%! Очень надеюсь. Но давайте подождем и посмотрим. Нам нужно сделать ту же проверку на наборе проверки:
# 预测验证集
torch.manual_seed(0)
output = model(val_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.detach().numpy())
predictions = np.argmax(prob, axis=1)
accuracy_score(val_y, predictions)
Точность проверки составляет около 78%. очень хороший!
концевые сноски
Когда мы начинаем получать меньше обучающих данных, мы можем использовать методы увеличения изображения.
В этой статье мы познакомим вас с наиболее часто используемыми методами улучшения изображения. Мы научились вращать, перемещать и переворачивать изображения. Мы также узнали, как добавить случайный шум или размыть изображение. Затем мы обсудим основные рекомендации по выбору правильной техники аугментации.
Вы можете попробовать эти методы увеличения изображения для любой задачи классификации изображений и сравнить производительность с увеличением и без него. Не стесняйтесь делиться своими результатами в разделе комментариев ниже.
И, если вы новичок в глубоком обучении, компьютерном зрении и данных изображений, вам рекомендуются следующие курсы:
Оригинальная ссылка:Woohoo.Со слов аналитиков vi.com/blog/2019/1…