Spaces:
Runtime error
Runtime error
#!/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') | |