#!/usr/bin/env python # coding: utf-8 # In[1]: import pandas as pd import joblib import os import numpy as np from tqdm import tqdm from sklearn.preprocessing import LabelBinarizer # In[2]: # get all the image folder paths all_paths = os.listdir(r'C:/Users/abdul/Desktop/Research/work/mhamad syrian/ziad/data') folder_paths = [x for x in all_paths if os.path.isdir('C:/Users/abdul/Desktop/Research/work/mhamad syrian/ziad/data/' + x)] print(f"Folder paths: {folder_paths}") print(f"Number of folders: {len(folder_paths)}") # In[3]: # we will create the data for the following labels, # add more to list to use those for creating the data as well create_labels = ['bend', 'jack', 'jump', 'pjump', 'walk', 'wave1', 'wave2'] # create a DataFrame data = pd.DataFrame() # In[4]: image_formats = ['jpg', 'JPG', 'PNG', 'png'] # we only want images that are in this format labels = [] counter = 0 for i, folder_path in tqdm(enumerate(folder_paths), total=len(folder_paths)): if folder_path not in create_labels: continue image_paths = os.listdir('C:/Users/abdul/Desktop/Research/work/mhamad syrian/ziad/data/'+folder_path) label = folder_path # save image paths in the DataFrame for image_path in image_paths: if image_path.split('.')[-1] in image_formats: data.loc[counter, 'image_path'] = f"C:/Users/abdul/Desktop/Research/work/mhamad syrian/ziad/data/{folder_path}/{image_path}" labels.append(label) counter += 1 # In[5]: labels = np.array(labels) # one-hot encode the labels lb = LabelBinarizer() labels = lb.fit_transform(labels) # In[6]: if len(labels[0]) == 1: for i in range(len(labels)): index = labels[i] data.loc[i, 'target'] = int(index) elif len(labels[0]) > 1: for i in range(len(labels)): index = np.argmax(labels[i]) data.loc[i, 'target'] = int(index) # In[7]: # shuffle the dataset data = data.sample(frac=1).reset_index(drop=True) print(f"Number of labels or classes: {len(lb.classes_)}") print(f"The first one hot encoded labels: {labels[0]}") print(f"Mapping the first one hot encoded label to its category: {lb.classes_[0]}") print(f"Total instances: {len(data)}") # save as CSV file data.to_csv('C:/Users/abdul/Desktop/Research/work/mhamad syrian/ziad/data.csv', index=False) # pickle the binarized labels print('Saving the binarized labels as pickled file') joblib.dump(lb, 'C:/Users/abdul/Desktop/Research/work/mhamad syrian/ziad/lb.pkl') print(data.head(5)) # In[8]: import torch import torch.nn as nn import torch.nn.functional as F import joblib # load the binarized labels file lb = joblib.load('C:/Users/abdul/Desktop/Research/work/mhamad syrian/ziad/lb.pkl') class CustomCNN(nn.Module): def __init__(self): super(CustomCNN, self).__init__() self.conv1 = nn.Conv2d(3, 16, 5) self.conv2 = nn.Conv2d(16, 32, 5) self.conv3 = nn.Conv2d(32, 64, 3) self.conv4 = nn.Conv2d(64, 128, 5) self.fc1 = nn.Linear(128, 256) self.fc2 = nn.Linear(256, len(lb.classes_)) self.pool = nn.MaxPool2d(2, 2) 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))) bs, _, _, _ = x.shape x = F.adaptive_avg_pool2d(x, 1).reshape(bs, -1) x = F.relu(self.fc1(x)) x = self.fc2(x) return x # In[9]: import torch import argparse import torch.nn as nn import torch.nn.functional as F import numpy as np import joblib import albumentations import torch.optim as optim import os # import cnn_models import matplotlib import matplotlib.pyplot as plt import time import pandas as pd matplotlib.style.use('ggplot') from imutils import paths from sklearn.preprocessing import LabelBinarizer from sklearn.model_selection import train_test_split from torch.utils.data import DataLoader, Dataset from tqdm import tqdm from PIL import Image # In[31]: # learning_parameters lr = 1e-3 epochs=100 batch_size = 64 device = 'cuda:0' print(f"Computation device: {device}\n") # In[ ]: # In[32]: # read the data.csv file and get the image paths and labels df = pd.read_csv('C:/Users/abdul/Desktop/Research/work/mhamad syrian/ziad/data.csv') X = df.image_path.values # image paths y = df.target.values # targets (xtrain, xtest, ytrain, ytest) = train_test_split(X, y, test_size=0.10, random_state=42) print(f"Training instances: {len(xtrain)}") print(f"Validation instances: {len(xtest)}") # In[33]: # custom dataset class ImageDataset(Dataset): def __init__(self, images, labels=None, tfms=None): self.X = images self.y = labels # apply augmentations if tfms == 0: # if validating self.aug = albumentations.Compose([ albumentations.Resize(224, 224, always_apply=True), ]) else: # if training self.aug = albumentations.Compose([ albumentations.Resize(224, 224, always_apply=True), albumentations.HorizontalFlip(p=0.5), albumentations.ShiftScaleRotate( shift_limit=0.3, scale_limit=0.3, rotate_limit=15, p=0.5 ), ]) def __len__(self): return (len(self.X)) def __getitem__(self, i): image = Image.open(self.X[i]) image = image.convert('RGB') image = self.aug(image=np.array(image))['image'] image = np.transpose(image, (2, 0, 1)).astype(np.float32) label = self.y[i] return (torch.tensor(image, dtype=torch.float), torch.tensor(label, dtype=torch.long)) # In[34]: train_data = ImageDataset(xtrain, ytrain, tfms=1) test_data = ImageDataset(xtest, ytest, tfms=0) # dataloaders trainloader = DataLoader(train_data, batch_size=batch_size, shuffle=True) testloader = DataLoader(test_data, batch_size=batch_size, shuffle=False) # In[35]: model = CustomCNN().to(device) print(model) # total parameters and trainable parameters total_params = sum(p.numel() for p in model.parameters()) print(f"{total_params:,} total parameters.") total_trainable_params = sum( p.numel() for p in model.parameters() if p.requires_grad) print(f"{total_trainable_params:,} training parameters.") # In[36]: # optimizer optimizer = optim.Adam(model.parameters(), lr=lr) # loss function criterion = nn.CrossEntropyLoss() # In[37]: scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau( optimizer, mode='min', patience=5, factor=0.5, min_lr=1e-6, verbose=True ) # In[38]: # training function def fit(model, train_dataloader): print('Training') model.train() train_running_loss = 0.0 train_running_correct = 0 for i, data in tqdm(enumerate(train_dataloader), total=int(len(train_data)/train_dataloader.batch_size)): data, target = data[0].to(device), data[1].to(device) optimizer.zero_grad() outputs = model(data) loss = criterion(outputs, target) train_running_loss += loss.item() _, preds = torch.max(outputs.data, 1) train_running_correct += (preds == target).sum().item() loss.backward() optimizer.step() train_loss = train_running_loss/len(train_dataloader.dataset) train_accuracy = 100. * train_running_correct/len(train_dataloader.dataset) print(f"Train Loss: {train_loss:.4f}, Train Acc: {train_accuracy:.2f}") return train_loss, train_accuracy # In[39]: #validation function def validate(model, test_dataloader): print('Validating') model.eval() val_running_loss = 0.0 val_running_correct = 0 with torch.no_grad(): for i, data in tqdm(enumerate(test_dataloader), total=int(len(test_data)/test_dataloader.batch_size)): data, target = data[0].to(device), data[1].to(device) outputs = model(data) loss = criterion(outputs, target) val_running_loss += loss.item() _, preds = torch.max(outputs.data, 1) val_running_correct += (preds == target).sum().item() val_loss = val_running_loss/len(test_dataloader.dataset) val_accuracy = 100. * val_running_correct/len(test_dataloader.dataset) print(f'Val Loss: {val_loss:.4f}, Val Acc: {val_accuracy:.2f}') return val_loss, val_accuracy # In[40]: train_loss , train_accuracy = [], [] val_loss , val_accuracy = [], [] start = time.time() for epoch in range(epochs): print(f"Epoch {epoch+1} of {epochs}") train_epoch_loss, train_epoch_accuracy = fit(model, trainloader) val_epoch_loss, val_epoch_accuracy = validate(model, testloader) train_loss.append(train_epoch_loss) train_accuracy.append(train_epoch_accuracy) val_loss.append(val_epoch_loss) val_accuracy.append(val_epoch_accuracy) scheduler.step(val_epoch_loss) end = time.time() print(f"{(end-start)/60:.3f} minutes") # In[42]: # accuracy plots plt.figure(figsize=(10, 7)) plt.plot(train_accuracy, color='green', label='train accuracy') plt.plot(val_accuracy, color='blue', label='validataion accuracy') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.legend() plt.savefig(r'C:\Users\abdul\Desktop\Research\work\mhamad syrian\ziad\accuracy.png') plt.show() # loss plots plt.figure(figsize=(10, 7)) plt.plot(train_loss, color='orange', label='train loss') plt.plot(val_loss, color='red', label='validataion loss') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.savefig(r'C:\Users\abdul\Desktop\Research\work\mhamad syrian\ziad\loss.png') plt.show() # serialize the model to disk print('Saving model...') torch.save(model.state_dict(), 'model') print('TRAINING COMPLETE')