[Машинное обучение] LIVENESS DETECTION — проверка идентификатора на принадлежность «живому» пользователю
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Технологией распознавания лиц уже никого не удивить. Крупные компании активно внедряют эту технологию в свои сервисы и конечно, мошенники пытаются использовать разные способы, в том числе подмену идентификатора лица с помощью маски, фото или записи для осуществления своих преступных действий. Такая атака называется спуфингом.
Хотим познакомить вас с технологией liveness detection, в задачу которой входит проверка идентификатора на принадлежность «живому» пользователю.Датасет можно скачать по ссылке.Для обучения в датасете есть 4 подкласса.
- real — «живое» лицо
- replay — кадры с видео
- printed — распечатанная фотография
- 2dmask — надетая 2d маска
Каждый образец представлен последовательностью из 5 картинок.СТРОИМ МОДЕЛЬДля решения задачи классификации изображений на принадлежность «живому» пользователю будем обучать нейронную сеть, используя фреймворк pytorch.Решение строится на работе с последовательностью картинок, а не с каждой картинкой отдельно. Используем небольшую претренированную сеть Resnet18 на каждую картинку из последовательности. Затем стакаем полученные фичи и применяем 1d свертку и далее fully connected слой на 1 класс.Таким образом, наша архитектура выглядит следующим образом:
class Empty(nn.Module):
def __init__(self):
super(Empty, self).__init__()
def forward(self, x):
return x
class SpoofModel(nn.Module):
def __init__(self):
super(SpoofModel, self).__init__()
self.encoder = torchvision.models.resnet18()
self.encoder.fc = Empty()
self.conv1d = nn.Conv1d(
in_channels=5,
out_channels=1,
kernel_size=(3),
stride=(2),
padding=(1))
self.fc = nn.Linear(in_features=256, out_features=1)
def forward(self, x):
vectors = []
for i in range(0, x.shape[1]):
v = self.encoder(x[:, i])
v = v.reshape(v.size(0), -1)
vectors.append(v)
vectors = torch.stack(vectors)
vectors = vectors.permute((1, 0, 2))
vectors = self.conv1d(vectors)
x = self.fc(vectors)
return x
Для примера мы будем тренировать нашу модель 5 эпох с батч сайзов 64, что займёт примерно 1 час с учетом валидации на одной 2080TI.На валидации смотрим 3 метрики: f1, accuracy и f2 score.Код для валидации:
def eval_metrics(outputs, labels, threshold=0.5):
return {
'f1': f1_score(y_true=labels, y_pred=(outputs > threshold).astype(int), average='macro'),
'accuracy': accuracy_score(y_true=labels, y_pred=(outputs > threshold).astype(int)),
'fbeta 2': fbeta_score(labels, y_pred=(outputs > threshold).astype(int), beta=2, average='weighted'),
'f1 weighted': f1_score(y_true=labels, y_pred=(outputs > threshold).astype(int), average='weighted')
}
def validation(model, val_loader):
model.eval()
metrics = []
batch_size = val_loader.batch_size
tq = tqdm(total=len(val_loader) * batch_size, position=0, leave=True)
with torch.no_grad():
for i, (inputs, labels) in enumerate(val_loader):
inputs = inputs.cuda()
labels = labels.cuda()
outputs = model(inputs).view(-1)
tq.update(batch_size)
metrics.append(eval_metrics(outputs.cpu().numpy(), labels.cpu().numpy()))
metrics_mean = mean_metrics(metrics)
tq.close()
return metrics_mean
В качестве оптимайзера используем SGD c learning rate = 0.001, а в качестве loss BCEWithLogitsLoss.Не будем использовать экзотических аугментаций. Делаем только Resize и RandomHorizontalFlip для изображений при обучении.Полный код функции для тренировки:
Итоговый ход тренировки выглядит так:def train():
path_data = 'data/'
checkpoints_path = 'model'
num_epochs = 5
batch_size = 64
val_batch_size = 32
lr = 0.001
weight_decay = 0.0000001
model = SpoofModel()
model.train()
model = model.cuda()
epoch = 0
if os.path.exists(os.path.join(checkpoints_path, 'model_.pt')):
epoch, model = load_model(model, os.path.join(checkpoints_path, 'model_.pt'))
optimizer = torch.optim.SGD(model.parameters(), lr=lr, weight_decay=weight_decay)
criterion = torch.nn.BCEWithLogitsLoss()
path_images = []
for label in ['2dmask', 'real', 'printed', 'replay']:
videos = os.listdir(os.path.join(path_data, label))
for video in videos:
path_images.append({
'path': os.path.join(path_data, label, video),
'label': int(label != 'real'),
})
split_on = int(len(path_images) * 0.7)
train_paths = path_images[:split_on]
val_paths = path_images[split_on:]
train_transform = torchvision.transforms.Compose([
torchvision.transforms.ToPILImage(),
torchvision.transforms.Resize(224),
torchvision.transforms.RandomHorizontalFlip(),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
[0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
val_transform = torchvision.transforms.Compose([
torchvision.transforms.ToPILImage(),
torchvision.transforms.Resize(224),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
[0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
train_dataset = AntispoofDataset(paths=train_paths, transform=train_transform)
train_loader = DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True,
num_workers=8,
drop_last=True)
val_dataset = AntispoofDataset(paths=val_paths, transform=val_transform)
val_loader = DataLoader(dataset=val_dataset,
batch_size=val_batch_size,
shuffle=True,
num_workers=8,
drop_last=False)
tq = None
try:
for epoch in range(epoch, num_epochs):
tq = tqdm(total=len(train_loader) * batch_size, position=0, leave=True)
tq.set_description(f'Epoch {epoch}, lr {lr}')
losses = []
for inputs, labels in train_loader:
inputs = inputs.cuda()
labels = labels.cuda()
optimizer.zero_grad()
with torch.set_grad_enabled(True):
outputs = model(inputs)
loss = criterion(outputs.view(-1), labels.float())
loss.backward()
optimizer.step()
optimizer.zero_grad()
tq.update(batch_size)
losses.append(loss.item())
intermediate_mean_loss = np.mean(losses[-10:])
tq.set_postfix(loss='{:.5f}'.format(intermediate_mean_loss))
epoch_loss = np.mean(losses)
epoch_metrics = validation(model, val_loader=val_loader)
tq.close()
print('\nLoss: {:.4f}\t Metrics: {}'.format(epoch_loss, epoch_metrics))
save_model(model, epoch, checkpoints_path, name_postfix=f'e{epoch}')
except KeyboardInterrupt:
tq.close()
print('\nCtrl+C, saving model...')
save_model(model, epoch, checkpoints_path)
Итоговый ход тренировки выглядит так:
В качестве модели для проверки используем веса с 3 эпохи.Для проверки у нас есть 10 примеров. Построим confusion matrix:
На 10 примерах мы достигли 100% точности. Конечно, для идеальной проверки модели требуется данных значительно больше.Таким образом, в своей статье я предложил один из вариантов реализации liveness detection с помощью классификации изображений нейронной сетью. Полный код размещен по ссылке
===========
Источник:
habr.com
===========
Похожие новости:
- [Машинное обучение, Изучение языков, IT-компании] Google рассказала об улучшении перевода речи в Google Translate
- [Машинное обучение, Искусственный интеллект] Примеры архитектур нейронных сетей для решения пяти прикладных задач
- [Высокая производительность, Серверное администрирование, Машинное обучение, Искусственный интеллект] Создание общей архитектуры для высокопроизводительных вычислений, искусственного интеллекта и анализа данных
- [Data Mining, Машинное обучение, Natural Language Processing] Сентимент-анализ. Определяем эмоциональные сообщения на Хабре
- [Программирование, Машинное обучение] Распознавание речи с помощью инструментов машинного обучения
- [Обработка изображений, Microsoft Azure, Машинное обучение, Разработка для интернета вещей] Azure Custom Vision без Azure, или «где у них маска». Как мы распознавали маску на лице (и других частях тела)
- [Алгоритмы, Apache, Машинное обучение, Hadoop] Масштабирование итеративных алгоритмов в Spark (перевод)
- [Python, Программирование, Алгоритмы, Машинное обучение, Искусственный интеллект] Нейронная Сеть CLIP от OpenAI: Классификатор, который не нужно обучать. Да здравствует Обучение без Обучения
- [Информационная безопасность, Машинное обучение] Как самому разработать систему обнаружения компьютерных атак на основе машинного обучения
- [Машинное обучение, Учебный процесс в IT, Образование за рубежом, Интервью] «Что послушать»: какие темы вошли в первый сезон подкаста о науке и технологиях «ITMO Research_»
Теги для поиска: #_mashinnoe_obuchenie (Машинное обучение), #_computer_vision, #_liveness_detection, #_mashinnoe_obuchenie (
Машинное обучение
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:30
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Технологией распознавания лиц уже никого не удивить. Крупные компании активно внедряют эту технологию в свои сервисы и конечно, мошенники пытаются использовать разные способы, в том числе подмену идентификатора лица с помощью маски, фото или записи для осуществления своих преступных действий. Такая атака называется спуфингом. Хотим познакомить вас с технологией liveness detection, в задачу которой входит проверка идентификатора на принадлежность «живому» пользователю.Датасет можно скачать по ссылке.Для обучения в датасете есть 4 подкласса.
Каждый образец представлен последовательностью из 5 картинок.СТРОИМ МОДЕЛЬДля решения задачи классификации изображений на принадлежность «живому» пользователю будем обучать нейронную сеть, используя фреймворк pytorch.Решение строится на работе с последовательностью картинок, а не с каждой картинкой отдельно. Используем небольшую претренированную сеть Resnet18 на каждую картинку из последовательности. Затем стакаем полученные фичи и применяем 1d свертку и далее fully connected слой на 1 класс.Таким образом, наша архитектура выглядит следующим образом: class Empty(nn.Module):
def __init__(self): super(Empty, self).__init__() def forward(self, x): return x class SpoofModel(nn.Module): def __init__(self): super(SpoofModel, self).__init__() self.encoder = torchvision.models.resnet18() self.encoder.fc = Empty() self.conv1d = nn.Conv1d( in_channels=5, out_channels=1, kernel_size=(3), stride=(2), padding=(1)) self.fc = nn.Linear(in_features=256, out_features=1) def forward(self, x): vectors = [] for i in range(0, x.shape[1]): v = self.encoder(x[:, i]) v = v.reshape(v.size(0), -1) vectors.append(v) vectors = torch.stack(vectors) vectors = vectors.permute((1, 0, 2)) vectors = self.conv1d(vectors) x = self.fc(vectors) return x def eval_metrics(outputs, labels, threshold=0.5):
return { 'f1': f1_score(y_true=labels, y_pred=(outputs > threshold).astype(int), average='macro'), 'accuracy': accuracy_score(y_true=labels, y_pred=(outputs > threshold).astype(int)), 'fbeta 2': fbeta_score(labels, y_pred=(outputs > threshold).astype(int), beta=2, average='weighted'), 'f1 weighted': f1_score(y_true=labels, y_pred=(outputs > threshold).astype(int), average='weighted') } def validation(model, val_loader): model.eval() metrics = [] batch_size = val_loader.batch_size tq = tqdm(total=len(val_loader) * batch_size, position=0, leave=True) with torch.no_grad(): for i, (inputs, labels) in enumerate(val_loader): inputs = inputs.cuda() labels = labels.cuda() outputs = model(inputs).view(-1) tq.update(batch_size) metrics.append(eval_metrics(outputs.cpu().numpy(), labels.cpu().numpy())) metrics_mean = mean_metrics(metrics) tq.close() return metrics_mean Итоговый ход тренировки выглядит так:def train():
path_data = 'data/' checkpoints_path = 'model' num_epochs = 5 batch_size = 64 val_batch_size = 32 lr = 0.001 weight_decay = 0.0000001 model = SpoofModel() model.train() model = model.cuda() epoch = 0 if os.path.exists(os.path.join(checkpoints_path, 'model_.pt')): epoch, model = load_model(model, os.path.join(checkpoints_path, 'model_.pt')) optimizer = torch.optim.SGD(model.parameters(), lr=lr, weight_decay=weight_decay) criterion = torch.nn.BCEWithLogitsLoss() path_images = [] for label in ['2dmask', 'real', 'printed', 'replay']: videos = os.listdir(os.path.join(path_data, label)) for video in videos: path_images.append({ 'path': os.path.join(path_data, label, video), 'label': int(label != 'real'), }) split_on = int(len(path_images) * 0.7) train_paths = path_images[:split_on] val_paths = path_images[split_on:] train_transform = torchvision.transforms.Compose([ torchvision.transforms.ToPILImage(), torchvision.transforms.Resize(224), torchvision.transforms.RandomHorizontalFlip(), torchvision.transforms.ToTensor(), torchvision.transforms.Normalize( [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]) val_transform = torchvision.transforms.Compose([ torchvision.transforms.ToPILImage(), torchvision.transforms.Resize(224), torchvision.transforms.ToTensor(), torchvision.transforms.Normalize( [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]) train_dataset = AntispoofDataset(paths=train_paths, transform=train_transform) train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True, num_workers=8, drop_last=True) val_dataset = AntispoofDataset(paths=val_paths, transform=val_transform) val_loader = DataLoader(dataset=val_dataset, batch_size=val_batch_size, shuffle=True, num_workers=8, drop_last=False) tq = None try: for epoch in range(epoch, num_epochs): tq = tqdm(total=len(train_loader) * batch_size, position=0, leave=True) tq.set_description(f'Epoch {epoch}, lr {lr}') losses = [] for inputs, labels in train_loader: inputs = inputs.cuda() labels = labels.cuda() optimizer.zero_grad() with torch.set_grad_enabled(True): outputs = model(inputs) loss = criterion(outputs.view(-1), labels.float()) loss.backward() optimizer.step() optimizer.zero_grad() tq.update(batch_size) losses.append(loss.item()) intermediate_mean_loss = np.mean(losses[-10:]) tq.set_postfix(loss='{:.5f}'.format(intermediate_mean_loss)) epoch_loss = np.mean(losses) epoch_metrics = validation(model, val_loader=val_loader) tq.close() print('\nLoss: {:.4f}\t Metrics: {}'.format(epoch_loss, epoch_metrics)) save_model(model, epoch, checkpoints_path, name_postfix=f'e{epoch}') except KeyboardInterrupt: tq.close() print('\nCtrl+C, saving model...') save_model(model, epoch, checkpoints_path) В качестве модели для проверки используем веса с 3 эпохи.Для проверки у нас есть 10 примеров. Построим confusion matrix: На 10 примерах мы достигли 100% точности. Конечно, для идеальной проверки модели требуется данных значительно больше.Таким образом, в своей статье я предложил один из вариантов реализации liveness detection с помощью классификации изображений нейронной сетью. Полный код размещен по ссылке =========== Источник: habr.com =========== Похожие новости:
Машинное обучение ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:30
Часовой пояс: UTC + 5