人脸表情识别实验——AffectNet

2019-05-19更新
发现国内做人脸表情识别的同学还蛮多的,这里提供一个平台给大家交流问题和心得。
人脸表情识别实验——AffectNet_第1张图片

2019-4-28更新
邮箱:[email protected]
申明:
1.请尽量通过申请官方授权下载。
2.仅提供给科研需要的同学,禁止商业用途,禁止牟利,禁止公开传播。
3.邮件中请说明所在科研机构或高校名称。
4.请使用学校邮箱(edu邮箱)或科研机构邮箱联系。


2018-11-29 13:43:21 更新
之前为了方便国内的同学科研,我私自提供了数据集的下载链接,违反了申请协议,现在真诚的向数据提供方致歉!我即刻删除所有数据集的下载链接,请有需要的同学自己申请。


2018年7月21日22:42:25更新
AffectNet数据集百度云下载链接,见文章末尾


Introduce

在做人脸表情时用到的数据集

Datasets

AffectNET
人脸表情识别实验——AffectNet_第2张图片

Experiment

torchvision.models中的网络的搭建方法很有参考价值,AlextNet的模型定义如下:

class AlexNet(nn.Module):

    def __init__(self, num_classes=1000):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(64, 192, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(192, 384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
        )
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes),
        )

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), 256 * 6 * 6)
        x = self.classifier(x)
        return x

imbalance

在不均衡数据集上训练20 epochs

# -*- coding: utf-8 -*-
from __future__ import print_function, division
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler
from torch.autograd import Variable
import torch.nn.functional as F 
from torchvision import datasets, transforms, models
import os
import time
import math

data_transforms = {
	'train': transforms.Compose([
		transforms.Resize(256),
		transforms.FiveCrop(224),
		transforms.Lambda(lambda crops: torch.stack([transforms.ToTensor()(transforms.RandomHorizontalFlip()(crop)) for crop in crops])),
		# transforms.ToTensor()
	]),
	'val': transforms.Compose([
		transforms.Resize(256),
		transforms.CenterCrop(224),
		transforms.ToTensor()
	])
}

batch_size = 256

data_dir = r'/home/zwx/Datasets/AffectNet/Manually_Annotated_Images_Classified'
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'val']}
dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=batch_size, shuffle=True, num_workers=4) for x in ['train', 'val']}
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
class_name = image_datasets['train'].classes

train_batch_num = math.ceil(dataset_sizes['train']/batch_size)
val_batch_num = math.ceil(dataset_sizes['val']/batch_size)

use_gpu = torch.cuda.is_available()

def test_model():
	model = models.alexnet(num_classes=11)
	print(model)
	input, target = next(iter(dataloaders['train']))
	bs, ncrops, c, h, w = input.size()
	print(bs, ncrops, c, h, w)
	input = input.view(-1, c, h, w)
	print(input.size())
	input = Variable(input)
	result = model(input)
	result_avg = result.view(bs, ncrops, -1).mean(1)
	print(result_avg)


def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
	since = time.time()

	best_model_wts = model.state_dict()
	best_acc = 0.0

	for epoch in range(num_epochs):
		print('Epoch {}/{}'.format(epoch, num_epochs - 1))
		print('-' * 10)

		for phase in ['train', 'val']:
			if phase == 'train':
				scheduler.step()
				model.train(True)
			else:
				model.train(False)

			running_loss = 0.0
			running_corrects = 0

			for i, data in enumerate(dataloaders[phase]):
				inputs, labels = data
				
				if phase == 'train':
					bs, ncrops, c, h, w = inputs.size()
					inputs = inputs.view(-1, c, h, w)
					if use_gpu:
						inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda())
					else:
						inputs, labels = Variable(inputs), Variable(labels)
					optimizer.zero_grad()
					result = model(inputs)
					outputs = result.view(bs, ncrops, -1).mean(1)
				elif phase == 'val':
					if use_gpu:
						inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda())
					else:
						inputs, labels = Variable(inputs), Variable(labels)
					outputs = model(inputs)

				_, preds = torch.max(outputs.data, 1)
				loss = criterion(outputs, labels)

				if phase == 'train':
					loss.backward()
					optimizer.step()
					print("batch {}/{} loss: {:04f} batch {}/{} corrects: {:04f}".format(i, train_batch_num, loss.data[0] / batch_size,
					 i, train_batch_num, torch.sum(preds == labels.data) / batch_size))

				running_loss += loss.data[0]
				running_corrects += torch.sum(preds == labels.data)

			epoch_loss = running_loss / dataset_sizes[phase]
			epoch_acc = running_corrects / dataset_sizes[phase]

			print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))

			if phase == 'val' and epoch_acc > best_acc:
				best_acc = epoch_acc
				best_model_wts = model.state_dict()

			print()

		time_elapsed = time.time() - since
		print('Training complete in {:0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
		print('Best val Acc: {:4f}'.format(best_acc))

		model.load_state_dict(best_model_wts)
		torch.save(model, 'best_model.pkl')
		torch.save(model.state_dict(), 'model_params.pkl')

if __name__ == '__main__':
	# test_model()
	model = models.alexnet(num_classes=11)
	if use_gpu:
		model = model.cuda()
	criterion = nn.CrossEntropyLoss()
	# optimizer = optim.Adam(model.parameters())
	optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
	exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=10000, gamma=0.1)
	train_model(model, criterion, optimizer, exp_lr_scheduler, num_epochs=20)

第20次迭代训练结果如下:

train Loss: 0.0036 Acc: 0.6902

val Loss: 0.0096 Acc: 0.3595

Training complete in 1243.000000m 56s
Best val Acc: 0.368612

你可能感兴趣的:(人脸表情识别实验——AffectNet)