played around with CASIA-WEB-FACE
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,6 +7,7 @@ include/
|
|||||||
|
|
||||||
# Data and Models
|
# Data and Models
|
||||||
data/
|
data/
|
||||||
|
datasets/
|
||||||
trained_models/
|
trained_models/
|
||||||
|
|
||||||
# Python cache
|
# Python cache
|
||||||
|
|||||||
9
Data.py
9
Data.py
@@ -2,6 +2,7 @@ from torchvision import datasets, transforms, models
|
|||||||
import torch
|
import torch
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
# train set transform
|
# train set transform
|
||||||
def train_transform(res):
|
def train_transform(res):
|
||||||
return transforms.Compose([
|
return transforms.Compose([
|
||||||
@@ -25,7 +26,6 @@ def train_transform(res):
|
|||||||
# test set transform
|
# test set transform
|
||||||
def test_transform(res):
|
def test_transform(res):
|
||||||
return transforms.Compose([
|
return transforms.Compose([
|
||||||
# Just standard resize to 224x224
|
|
||||||
transforms.Resize((res, res)),
|
transforms.Resize((res, res)),
|
||||||
transforms.ToTensor(),
|
transforms.ToTensor(),
|
||||||
transforms.Normalize(
|
transforms.Normalize(
|
||||||
@@ -67,7 +67,7 @@ def select_ids( dataset, sample_size, class_size):
|
|||||||
return np.random.choice(eligible_ids, class_size, replace=False)
|
return np.random.choice(eligible_ids, class_size, replace=False)
|
||||||
|
|
||||||
# optional function to get max amount of samples per class
|
# optional function to get max amount of samples per class
|
||||||
def select_balanced_ids(dataset, class_size):
|
def select_top_ids(dataset, class_size):
|
||||||
ids, counts = get_ids_and_counts(dataset=dataset)
|
ids, counts = get_ids_and_counts(dataset=dataset)
|
||||||
|
|
||||||
# sort by number of images (descending)
|
# sort by number of images (descending)
|
||||||
@@ -79,11 +79,12 @@ def select_balanced_ids(dataset, class_size):
|
|||||||
|
|
||||||
|
|
||||||
# split class images to train and test set.
|
# split class images to train and test set.
|
||||||
def get_indices(dataset, identities, split_at):
|
def get_indices(dataset, identities, split_at, size = 30):
|
||||||
train_indices = []
|
train_indices = []
|
||||||
test_indices = []
|
test_indices = []
|
||||||
|
|
||||||
#training_sample = int(sample_size * training_ratio)
|
#training_sample = int(sample_size * training_ratio)
|
||||||
|
np.random.seed(42)
|
||||||
for person_id in identities:
|
for person_id in identities:
|
||||||
# Get all indices for this specific person
|
# Get all indices for this specific person
|
||||||
indices = torch.where(dataset.identity == person_id)[0].numpy()
|
indices = torch.where(dataset.identity == person_id)[0].numpy()
|
||||||
@@ -93,6 +94,6 @@ def get_indices(dataset, identities, split_at):
|
|||||||
|
|
||||||
# split data to testing and training
|
# split data to testing and training
|
||||||
train_indices.extend(indices[:split_at])
|
train_indices.extend(indices[:split_at])
|
||||||
test_indices.extend(indices[split_at:])
|
test_indices.extend(indices[split_at:size])
|
||||||
|
|
||||||
return train_indices, test_indices
|
return train_indices, test_indices
|
||||||
|
|||||||
50
DataAnalyser.py
Normal file
50
DataAnalyser.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
#from Data import *
|
||||||
|
from datasets.Casia import *
|
||||||
|
|
||||||
|
'''
|
||||||
|
Because the size of samples per class had the biggest impact
|
||||||
|
on training outcome, I decided to check the maximum amount of data
|
||||||
|
I can get from a class.
|
||||||
|
The highest I can get is
|
||||||
|
Rank | Identity ID |Count
|
||||||
|
-----------------------------------
|
||||||
|
1 | 3782 | 35
|
||||||
|
2 | 2820 | 35
|
||||||
|
3 | 3227 | 35
|
||||||
|
4 | 3745 | 34
|
||||||
|
5 | 3699 | 34
|
||||||
|
6 | 8968 | 32
|
||||||
|
7 | 9152 | 32
|
||||||
|
8 | 9256 | 32
|
||||||
|
9 | 2114 | 31
|
||||||
|
... | ... | ...
|
||||||
|
17 | 4126 | 31
|
||||||
|
18 | 3185 | 30
|
||||||
|
... | ... | ...
|
||||||
|
50 | 3186 | 30
|
||||||
|
|
||||||
|
as can be seen, 3 classes have 35, 2 have 34, 3 have 32 and the rest have 30.
|
||||||
|
'''
|
||||||
|
def print_top_identity_stats(dataset, top_n=50):
|
||||||
|
# we get data
|
||||||
|
ids, counts = get_ids_and_counts(dataset)
|
||||||
|
# sort in descending order
|
||||||
|
sorted_counts, sorted_indices = torch.sort(counts, descending=True)
|
||||||
|
|
||||||
|
# coresponding sorted ids
|
||||||
|
sorted_ids = ids[sorted_indices]
|
||||||
|
|
||||||
|
# 4. Slice the first 'top_n' and print
|
||||||
|
print(f"{'Rank':<8} | {'Identity ID':<12} | {'Image Count':<12}")
|
||||||
|
print("-" * 35)
|
||||||
|
|
||||||
|
for i in range(top_n):
|
||||||
|
identity_id = sorted_ids[i].item()
|
||||||
|
count = sorted_counts[i].item()
|
||||||
|
print(f"{i+1:<8} | {identity_id:<12} | {count:<12}")
|
||||||
|
|
||||||
|
# Usage:
|
||||||
|
dataset = get_set()
|
||||||
|
print_top_identity_stats(dataset, 50)
|
||||||
|
|
||||||
26
Tune.py
26
Tune.py
@@ -1,16 +1,21 @@
|
|||||||
import torch
|
# Finetuning a selected model
|
||||||
|
# on a selected dataset
|
||||||
|
# using selected parameters
|
||||||
|
|
||||||
from torch.utils.data import DataLoader
|
from torch.utils.data import DataLoader
|
||||||
from sklearn.metrics import classification_report
|
from sklearn.metrics import classification_report
|
||||||
import SetUp
|
import SetUp
|
||||||
from Data import *
|
from Data import *
|
||||||
from IdentitySubset import IdentitySubset
|
#from datasets.Casia import *
|
||||||
|
#from IdentitySubset import IdentitySubset
|
||||||
|
from datasets.UniversalIdentitySubset import UniversalIdentitySubset as IdentitySubset
|
||||||
# models
|
# models
|
||||||
from architectures.Model import Model, Architecture
|
from architectures.Model import Model, Architecture
|
||||||
|
|
||||||
# numbre of classes
|
# numbre of classes
|
||||||
CLASS_SIZE = 20
|
CLASS_SIZE = 20
|
||||||
# batch
|
# batch
|
||||||
BATCH_SIZE = 16
|
BATCH_SIZE = 32
|
||||||
|
|
||||||
# size of images per class trainset + testset
|
# size of images per class trainset + testset
|
||||||
# 30 works best, more than that and we dont have enough data
|
# 30 works best, more than that and we dont have enough data
|
||||||
@@ -21,7 +26,7 @@ TRAINING_SMPLE = 28
|
|||||||
|
|
||||||
# learning rate
|
# learning rate
|
||||||
LR_RATE = 0.0001
|
LR_RATE = 0.0001
|
||||||
EPOCHS = 16
|
EPOCHS = 20
|
||||||
|
|
||||||
# depends on model architecture
|
# depends on model architecture
|
||||||
# ResNet, DenseNet = 224
|
# ResNet, DenseNet = 224
|
||||||
@@ -42,10 +47,17 @@ arch = Architecture.RESNET50
|
|||||||
# load data set and prepare
|
# load data set and prepare
|
||||||
dataset = get_set()
|
dataset = get_set()
|
||||||
# select identities for experiment
|
# select identities for experiment
|
||||||
selected_identities = select_ids(
|
#selected_identities = select_ids(
|
||||||
|
# dataset = dataset,
|
||||||
|
# sample_size = SAMPLE_SIZE,
|
||||||
|
# class_size = CLASS_SIZE
|
||||||
|
# )
|
||||||
|
|
||||||
|
# this selects the top 50 based on sample size
|
||||||
|
# that way repeated calls return the same classes
|
||||||
|
selected_identities = select_top_ids(
|
||||||
dataset=dataset,
|
dataset=dataset,
|
||||||
sample_size = SAMPLE_SIZE,
|
class_size= CLASS_SIZE,
|
||||||
class_size = CLASS_SIZE
|
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f'> Selected {CLASS_SIZE} random identity classes from CelebA dataset.')
|
print(f'> Selected {CLASS_SIZE} random identity classes from CelebA dataset.')
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ class ResNet18(Model):
|
|||||||
m = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
|
m = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
|
||||||
|
|
||||||
# freez all layers
|
# freez all layers
|
||||||
for param in m.parameters():
|
#for param in m.parameters():
|
||||||
param.requires_grad = False
|
# param.requires_grad = False
|
||||||
|
|
||||||
# unfreez the last two
|
# unfreez the last two
|
||||||
for param in m.layer3.parameters(): param.requires_grad = True
|
#for param in m.layer3.parameters(): param.requires_grad = True
|
||||||
for param in m.layer4.parameters(): param.requires_grad = True
|
#for param in m.layer4.parameters(): param.requires_grad = True
|
||||||
|
|
||||||
m.fc = nn.Linear(m.fc.in_features, self.size)
|
m.fc = nn.Linear(m.fc.in_features, self.size)
|
||||||
return m
|
return m
|
||||||
@@ -3,3 +3,4 @@ torchvision
|
|||||||
gdown
|
gdown
|
||||||
numpy
|
numpy
|
||||||
scikit-learn
|
scikit-learn
|
||||||
|
kagglehub
|
||||||
Reference in New Issue
Block a user