Hello Juan,
thank you for your elaboration - most appreciated!
Yes, the task is feasable. After some execising, I can estimate the numbers myself. Of course: there is always room for improvement after the first guess.
The images come from high-resolution cameras (mirror-cameras). All taken under water. The two parameters are supposed the adapted the processing methods to the visibility conditions.
Other than that, there is little variation in the content of the images. That’s why I believe that 300 (representative) images should be sufficient.
I will do some more testing based on your input.
Would it make sense to post the source-code?
Thank you once again for your response.
Adding the code here:
import cv2
from torch.utils.data import Dataset
import pandas as pd
import os
import glob
from tqdm import tqdm
from PIL import Image, ImageFilter
import random
import torch
import torch.nn as nn
from torch.nn import MSELoss
from torch.optim.lr_scheduler import ReduceLROnPlateau
from torch.utils.data import DataLoader, random_split
import torchvision.transforms as transforms
import numpy as np
import torchvision.models as models
# from torchsummary import summary
from itertools import product, combinations
from random import randint
import torch.nn.functional as F
torch.manual_seed(0)
torch.cuda.empty_cache()
extensions = [".jpg", ".jpeg", ".JPG"]
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# device = 'cpu'
class CardDataset(Dataset):
def __init__(self, root_dir, data_file_path, transform=None):
self.Df = pd.read_csv(data_file_path)
print(self.Df)
self.root_dir = root_dir
self.transform = transform
def __len__(self):
return len(self.Df)
def __getitem__(self, index):
#img_path = os.path.join(self.root_dir, self.Df['Image Name'][index]+'.JPG')
#print('type img_path orig: ', type(img_path))
#print('img_path orig: ', img_path)
img_path = [f for f in glob.glob(os.path.join(self.root_dir, self.Df['Image Name'][index]+'*'), recursive=True) if os.path.splitext(f)[1] in extensions]
img_path = str(img_path)[2:-2]
#print('type img_path new: ', type(img_path))
#print('img_path new: ', img_path)
img = Image.open(img_path)
y_label = torch.tensor([float(self.Df['Iterations'][index]), float(self.Df['Threshold'][index])])
# y_label = torch.tensor( [float(self.Df['Threshold'][index])])
# img = Image.new('RGB',(400,200))
# img.paste(im1,(0,0))
# img.paste(im2,(200,0))
# label = y_label.item()
# print(label)
if self.transform is not None:
img = self.transform(img)
# print(img.size)
return img, y_label
transform_train = transforms.Compose(
[
transforms.ToTensor(),
transforms.Resize((1024, 1024)),
#transforms.RandomCrop(1024),
# transforms.RandomRotation(180),
# transforms.RandomPerspective(),
# transforms.ColorJitter(saturation=(0.8, 1.3), contrast=(0.8, 1.4), brightness=(0.8, 1.25)),
# transforms.RandomPerspective(distortion_scale=0.6, p=1.0)
# transforms.Resize(300),
# transforms.Normalize(mean=[0.485, 0.456, 0.406],
# std=[0.229, 0.224, 0.225]),
]
)
num_epochs = 600
learning_rate = 0.001
train_CNN = False
batch_size = 16
shuffle = True
pin_memory = True
num_workers = 2
print(learning_rate)
print(num_epochs)
train_set = CardDataset('all_days','all_days.csv',transform=transform_train)
train_set, validation_set = random_split(train_set, [int(0.85*len(train_set)), len(train_set)-int(0.85*len(train_set))])
#validation_set = CardDataset("hologram_classifier_dataset_splitted",'validation',transform=transform_val)
# train_set, validation_set = torch.utils.data.random_split(dataset,[train_size, val_size], generator=torch.Generator().manual_seed(2))
train_loader = DataLoader(dataset=train_set, shuffle=shuffle, batch_size=batch_size, num_workers=num_workers)
validation_loader = DataLoader(dataset=validation_set, shuffle=shuffle, batch_size=batch_size, num_workers=num_workers)
print(len(train_set))
class parameter_model(torch.nn.Module):
def __init__(self):
super().__init__()
self.Conv1 = torch.nn.Conv2d(3, 16, 3, padding = 'same')
self.Conv2 = torch.nn.Conv2d(16, 32, 3, padding = 'same')
self.Conv3 = torch.nn.Conv2d(32, 64, 3, padding = 'same')
self.Conv4 = torch.nn.Conv2d(64, 128, 3, padding = 'same')
self.pool = torch.nn.MaxPool2d(2,2)
self.fc1 = torch.nn.Linear(in_features = 128, out_features = 64)
self.fc2 = torch.nn.Linear(64, 2)
self.adaptive_pool = torch.nn.AdaptiveAvgPool2d(output_size=(1, 1))
def forward(self, x):
x = self.pool(F.relu(self.Conv1(x)))
x = self.pool(F.relu(self.Conv2(x)))
x = self.pool(F.relu(self.Conv3(x)))
x = self.pool(F.relu(self.Conv4(x)))
x = self.adaptive_pool(x)
x = torch.flatten(x, 1)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
return x
# # ct =0
# # # childern = model.children()
# # # print(childern)
# # for child in model.children():
# # ct += 1
# # # print(child)
# # if ct < 10:
# # for param in child.parameters():
# # param.requires_grad = False
# # # model.to(device)
# # print(ct)
model = parameter_model()
# print(model)
# from torch.nn.modules.conv import Conv2d
# model = models.resnet18(pretrained=False)
# model.fc = nn.Linear(in_features=512, out_features=1, bias=True)
# print(model)
if torch.cuda.is_available():
model.to(device)
# loss_weight = torch.Tensor([0.5, 1])
# loss_weight = loss_weight.to(device)
criterion = MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
scheduler = ReduceLROnPlateau(optimizer, 'min', patience=15)
def train():
# % % time
# keeping-track-of-losses
for epoch in range(1, num_epochs + 1):
# keep-track-of-training-and-validation-loss
# train_loss = 0.0
# training-the-model
model.train()
# i= 0
total_loss = []
for data, target in tqdm(train_loader):
# print('yes')
# i = i+1
# print(i)
# move-tensors-to-GPU
optimizer.zero_grad()
data = data.to(device)
target = target.to(device)
# target = target.long()
# clear-the-gradients-of-all-optimized-variables
# forward-pass: compute-predicted-outputs-by-passing-inputs-to-the-model
output = model(data)
# results = torch.max(output, 1).indices
# calculate-the-batch-loss
loss = criterion(output, target)
# backward-pass: compute-gradient-of-the-loss-wrt-model-parameters
loss.backward()
# perform-a-ingle-optimization-step (parameter-update)
optimizer.step()
#perform learning rate scheduler step
total_loss.append(loss)
# update-training-loss
# train_loss += loss.item() * data.size(0)
val_loss = 0
model.eval()
with torch.no_grad():
for data, target in tqdm(validation_loader):
# print('yes')
# i = i+1
# print(i)
# move-tensors-to-GPU
data = data.to(device)
target = target.to(device)
# target = target.long()
# clear-the-gradients-of-all-optimized-variables
# forward-pass: compute-predicted-outputs-by-passing-inputs-to-the-model
output = model(data)
# results = torch.max(output, 1).indices
# calculate-the-batch-loss
loss = criterion(output, target)
val_loss = val_loss + loss
scheduler.step(val_loss)
print(f'Epoch: {epoch}\t Train Loss: {sum(total_loss)/len(train_loader)}\t Validation Loss: {val_loss/len(validation_loader)}')
torch.save(model.state_dict(), "model_checkpoints/checkpoint_" + str(epoch) + ".pth")
print(learning_rate)
train()```