人臉表情識別實驗——AffectNet

2018年7月21日22:42:25更新
AffectNet數據集百度雲下載鏈接,見文章末尾


Introduce

本篇博客是我畢業論文實驗的相關記錄。

Datasets

AffectNET

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

下載鏈接:https://pan.baidu.com/s/1hp-U7U2xkn0smuKPN2jecQ 密碼:b5dy

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章