Abdulkader's picture
Rename HumanMotionsClassificationZiad.py to Train.py
3899a9a
raw
history blame
9.91 kB
#!/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')