Chest X-Ray Classification
using Vedic Calculus
(No GPUs Required)
import pandas as pd
import numpy as np
import os
base_path = "/kaggle/input/chest-x-ray-dataset-4-categories/Chest X_Ray
Dataset/"
categories = ["COVID19", "NORMAL", "PNEUMONIA", "TURBERCULOSIS"]
image_paths = []
labels = []
for category in categories:
category_path = [Link](base_path, category)
for image_name in [Link](category_path):
image_path = [Link](category_path, image_name)
image_paths.append(image_path)
[Link](category)
df = [Link]({
"image_path": image_paths,
"label": labels
})
[Link]()
image_path label
0 /kaggle/input/chest-x-ray-dataset-4-categories... COVID19
1 /kaggle/input/chest-x-ray-dataset-4-categories... COVID19
2 /kaggle/input/chest-x-ray-dataset-4-categories... COVID19
3 /kaggle/input/chest-x-ray-dataset-4-categories... COVID19
4 /kaggle/input/chest-x-ray-dataset-4-categories... COVID19
[Link]()
image_path label
7127 /kaggle/input/chest-x-ray-dataset-4-categories... TURBERCULOSIS
7128 /kaggle/input/chest-x-ray-dataset-4-categories... TURBERCULOSIS
7129 /kaggle/input/chest-x-ray-dataset-4-categories... TURBERCULOSIS
7130 /kaggle/input/chest-x-ray-dataset-4-categories... TURBERCULOSIS
7131 /kaggle/input/chest-x-ray-dataset-4-categories... TURBERCULOSIS
[Link]
(7132, 2)
[Link]
Index(['image_path', 'label'], dtype='object')
[Link]().sum()
[Link]().sum()
image_path 0
label 0
dtype: int64
[Link]()
<class '[Link]'>
RangeIndex: 7132 entries, 0 to 7131
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 image_path 7132 non-null object
1 label 7132 non-null object
dtypes: object(2)
memory usage: 111.6+ KB
df['label'].unique()
array(['COVID19', 'NORMAL', 'PNEUMONIA', 'TURBERCULOSIS'], dtype=object)
df['label'].value_counts()
label
PNEUMONIA 4273
NORMAL 1583
TURBERCULOSIS 700
COVID19 576
Name: count, dtype: int64
import seaborn as sns
import [Link] as plt
sns.set_style("whitegrid")
fig, ax = [Link](figsize=(8, 6))
[Link](data=df, x="label", palette="viridis", ax=ax)
ax.set_title("Distribution of Disease Types", fontsize=14, fontweight='bold')
ax.set_xlabel("Tumor Type", fontsize=12)
ax.set_ylabel("Count", fontsize=12)
for p in [Link]:
[Link](f'{int(p.get_height())}',
(p.get_x() + p.get_width() / 2., p.get_height()),
ha='center', va='bottom', fontsize=11, color='black',
xytext=(0, 5), textcoords='offset points')
[Link]()
label_counts = df["label"].value_counts()
fig, ax = [Link](figsize=(8, 6))
colors = sns.color_palette("viridis", len(label_counts))
[Link](label_counts, labels=label_counts.index, autopct='%1.1f%%',
startangle=140, colors=colors, textprops={'fontsize': 12, 'weight':
'bold'},
wedgeprops={'edgecolor': 'black', 'linewidth': 1})
ax.set_title("Distribution of Disease Types - Pie Chart", fontsize=14,
fontweight='bold')
[Link]()
import cv2
num_images = 5
[Link](figsize=(15, 12))
for i, category in enumerate(categories):
category_images = df[df['label'] ==
category]['image_path'].iloc[:num_images]
for j, img_path in enumerate(category_images):
img = [Link](img_path)
img = [Link](img, cv2.COLOR_BGR2RGB)
[Link](len(categories), num_images, i * num_images + j + 1)
[Link](img)
[Link]('off')
[Link](category)
plt.tight_layout()
[Link]()
import warnings
[Link]('ignore')
import torch
import [Link] as nn
import [Link] as optim
from [Link] import Dataset, DataLoader
from torchvision import transforms, models
from PIL import Image
import [Link] as plt
import seaborn as sns
from [Link] import confusion_matrix
from sklearn.model_selection import train_test_split
train_df, val_df = train_test_split(df, test_size=0.2, stratify=df['label'],
random_state=42)
max_samples = train_df['label'].value_counts().max()
balanced_train_df = train_df.groupby('label', group_keys=False).apply(
lambda x: [Link](n=max_samples, replace=True, random_state=42)
).reset_index(drop=True)
balanced_train_df = balanced_train_df[['image_path', 'label']]
import torch
import [Link] as nn
import [Link] as optim
from [Link] import Dataset, DataLoader
from torchvision import transforms, models
from PIL import Image
import [Link] as plt
import seaborn as sns
from [Link] import confusion_matrix, classification_report
from sklearn.model_selection import train_test_split
import random
label_map = {'COVID19': 0, 'NORMAL': 1, 'PNEUMONIA': 2, 'TURBERCULOSIS': 3}
import torch
import [Link] as nn
from [Link] import Dataset, DataLoader
from torchvision import transforms, models
from PIL import Image
import [Link] as plt
import seaborn as sns
from [Link] import confusion_matrix, classification_report
from sklearn.model_selection import train_test_split
from tqdm import tqdm
train_df, val_df = train_test_split(balanced_train_df, test_size=0.2,
random_state=42, stratify=balanced_train_df['label'])
transform = [Link]([
[Link]((128, 128)),
[Link](),
[Link](mean=[0.485, 0.456, 0.406], std=[0.229, 0.224,
0.225])
])
class ChestXRayDataset(Dataset):
def __init__(self, dataframe, transform=None):
[Link] = dataframe
[Link] = transform
self.label_map = {cat: i for i, cat in enumerate(categories)}
def __len__(self):
return len([Link])
def __getitem__(self, idx):
img_path = [Link][idx]['image_path']
image = [Link](img_path).convert('RGB')
label = self.label_map[[Link][idx]['label']]
if [Link]:
image = [Link](image)
return image, label
train_loader = DataLoader(ChestXRayDataset(train_df, transform),
batch_size=32, shuffle=True)
val_loader = DataLoader(ChestXRayDataset(val_df, transform), batch_size=32)
class VedicChestNet([Link]):
def __init__(self, num_classes=4):
super(VedicChestNet, self).__init__()
[Link] = [Link]()
self.fc1 = [Link](3 * 128 * 128, 512)
self.fc2 = [Link](512, num_classes)
[Link].xavier_uniform_([Link])
[Link].xavier_uniform_([Link])
def forward(self, x):
x = [Link](x)
self.feat1 = [Link](self.fc1(x))
return self.fc2(self.feat1)
def vedic_step(model, images, targets, lr):
outputs = model(images)
error = outputs - targets
with torch.no_grad():
grad_fc2 = [Link](error.t(), model.feat1)
grad_fc2 = [Link](grad_fc2, -1.0, 1.0)
[Link] -= lr * grad_fc2
[Link] -= lr * [Link]([Link](dim=0), -1.0, 1.0)
back_err = [Link](error, [Link])
back_err[model.feat1 <= 0] = 0
grad_fc1 = [Link](back_err.t(), [Link]([Link](0), -
1))
grad_fc1 = [Link](grad_fc1, -1.0, 1.0)
[Link] -= lr * grad_fc1
[Link] -= lr * [Link](back_err.sum(dim=0), -1.0, 1.0)
device = [Link]("cuda" if [Link].is_available() else "cpu")
model = VedicChestNet(num_classes=len(categories)).to(device)
lr = 1e-5
history = {'train_loss': [], 'val_acc': []}
for epoch in range(5):
[Link]()
loop = tqdm(train_loader, total=len(train_loader))
epoch_loss = 0
for images, labels in loop:
images = [Link](device)
targets = [Link].one_hot(labels,
num_classes=4).float().to(device)
vedic_step(model, images, targets, lr)
outputs = model(images)
loss = [Link]((outputs - targets)**2)
if [Link](loss):
continue
epoch_loss += [Link]()
loop.set_description(f"Epoch {epoch+1}/5")
loop.set_postfix(loss=[Link]())
history['train_loss'].append(epoch_loss / len(train_loader))
[Link]()
correct, total = 0, 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = [Link](device), [Link](device)
outputs = model(images)
_, pred = [Link](outputs, 1)
total += [Link](0)
correct += (pred == labels).sum().item()
history['val_acc'].append(100 * correct / total)
[Link](figsize=(12, 4))
[Link](1, 2, 1); [Link](history['train_loss']); [Link]('Vedic Loss
Path')
[Link](1, 2, 2); [Link](history['val_acc']); [Link]('Vedic Accuracy
Path')
[Link]()
[Link]()
y_true, y_pred = [], []
with torch.no_grad():
for images, labels in val_loader:
images, labels = [Link](device), [Link](device)
outputs = model(images)
_, predicted = [Link](outputs, 1)
y_true.extend([Link]().numpy())
y_pred.extend([Link]().numpy())
print("\nClassification Report:\n", classification_report(y_true, y_pred,
target_names=categories))
cm = confusion_matrix(y_true, y_pred)
[Link](figsize=(8, 6))
[Link](cm, annot=True, fmt='d', xticklabels=categories,
yticklabels=categories)
[Link]('Vedic Confusion Matrix')
[Link]()
Epoch 1/5: 100%|██████████| 342/342 [04:51<00:00, 1.17it/s, loss=0.184]
Epoch 2/5: 100%|██████████| 342/342 [04:20<00:00, 1.31it/s, loss=0.0548]
Epoch 3/5: 100%|██████████| 342/342 [04:21<00:00, 1.31it/s, loss=0.0341]
Epoch 4/5: 100%|██████████| 342/342 [04:06<00:00, 1.39it/s, loss=0.0245]
Epoch 5/5: 100%|██████████| 342/342 [04:17<00:00, 1.33it/s, loss=0.0156]
Classification Report:
precision recall f1-score support
COVID19 0.98 1.00 0.99 684
NORMAL 0.94 0.92 0.93 683
PNEUMONIA 0.93 0.94 0.94 684
TURBERCULOSIS 0.99 1.00 0.99 684
accuracy 0.96 2735
macro avg 0.96 0.96 0.96 2735
weighted avg 0.96 0.96 0.96 2735