Spaces:
Runtime error
Runtime error
Update
Browse files- augment.py +0 -1
- combine_dats.py +42 -0
- configs.py +6 -5
- eda.py +103 -0
- eval.py +25 -5
- test.py +39 -0
- tuning.py +1 -1
augment.py
CHANGED
@@ -39,7 +39,6 @@ for task in ["1"]:
|
|
39 |
output_directory=f"{class_label}/",
|
40 |
save_format="png",
|
41 |
)
|
42 |
-
p.rotate(probability=0.8, max_left_rotation=5, max_right_rotation=5)
|
43 |
p.flip_left_right(probability=0.8)
|
44 |
p.zoom_random(probability=0.8, percentage_area=0.8)
|
45 |
p.flip_top_bottom(probability=0.8)
|
|
|
39 |
output_directory=f"{class_label}/",
|
40 |
save_format="png",
|
41 |
)
|
|
|
42 |
p.flip_left_right(probability=0.8)
|
43 |
p.zoom_random(probability=0.8, percentage_area=0.8)
|
44 |
p.flip_top_bottom(probability=0.8)
|
combine_dats.py
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copy the all the data from external, augmented and raw folders to combined folder
|
2 |
+
import os
|
3 |
+
import shutil
|
4 |
+
import uuid
|
5 |
+
|
6 |
+
from configs import *
|
7 |
+
|
8 |
+
for disease in CLASSES:
|
9 |
+
# check if the original folder exists
|
10 |
+
if os.path.exists(RAW_DATA_DIR + '1/' + disease):
|
11 |
+
print("Copying raw data for disease: ", disease)
|
12 |
+
if not os.path.exists(COMBINED_DATA_DIR + '1/' + disease):
|
13 |
+
os.makedirs(COMBINED_DATA_DIR + '1/' + disease)
|
14 |
+
for file in os.listdir(RAW_DATA_DIR + '1/' + disease):
|
15 |
+
random_name = str(uuid.uuid4()) + ".png"
|
16 |
+
shutil.copy(
|
17 |
+
RAW_DATA_DIR + '1/' + disease + '/' + file,
|
18 |
+
COMBINED_DATA_DIR + '1/' + disease + '/' + random_name,
|
19 |
+
)
|
20 |
+
|
21 |
+
if os.path.exists(EXTERNAL_DATA_DIR + '1/' + disease):
|
22 |
+
print("Copying external data for disease: ", disease)
|
23 |
+
if not os.path.exists(COMBINED_DATA_DIR + '1/' + disease):
|
24 |
+
os.makedirs(COMBINED_DATA_DIR + '1/' + disease)
|
25 |
+
for file in os.listdir(EXTERNAL_DATA_DIR + '1/' + disease):
|
26 |
+
random_name = str(uuid.uuid4()) + ".png"
|
27 |
+
shutil.copy(
|
28 |
+
EXTERNAL_DATA_DIR + '1/' + disease + '/' + file,
|
29 |
+
COMBINED_DATA_DIR + '1/' + disease + '/' + random_name,
|
30 |
+
)
|
31 |
+
|
32 |
+
if os.path.exists(AUG_DATA_DIR + '1/' + disease):
|
33 |
+
print("Copying augmented data for disease: ", disease)
|
34 |
+
if not os.path.exists(COMBINED_DATA_DIR + '1/' + disease):
|
35 |
+
os.makedirs(COMBINED_DATA_DIR + '1/' + disease)
|
36 |
+
for file in os.listdir(AUG_DATA_DIR + '1/' + disease):
|
37 |
+
random_name = str(uuid.uuid4()) + ".png"
|
38 |
+
shutil.copy(
|
39 |
+
AUG_DATA_DIR + '1/' + disease + '/' + file,
|
40 |
+
COMBINED_DATA_DIR + '1/' + disease + '/' + random_name,
|
41 |
+
)
|
42 |
+
|
configs.py
CHANGED
@@ -14,17 +14,18 @@ from torchvision.models import squeezenet1_0
|
|
14 |
|
15 |
# Constants
|
16 |
RANDOM_SEED = 123
|
17 |
-
BATCH_SIZE =
|
18 |
NUM_EPOCHS = 100
|
19 |
-
LEARNING_RATE =
|
20 |
STEP_SIZE = 10
|
21 |
-
GAMMA = 0.
|
22 |
DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
23 |
NUM_PRINT = 100
|
24 |
TASK = 1
|
25 |
RAW_DATA_DIR = r"data/train/raw/Task "
|
26 |
AUG_DATA_DIR = r"data/train/augmented/Task "
|
27 |
EXTERNAL_DATA_DIR = r"data/train/external/Task "
|
|
|
28 |
TEMP_DATA_DIR = "data/temp/"
|
29 |
NUM_CLASSES = 7
|
30 |
EARLY_STOPPING_PATIENCE = 20
|
@@ -108,7 +109,7 @@ class ResNet18WithNorm(nn.Module):
|
|
108 |
nn.AdaptiveAvgPool2d((1, 1)),
|
109 |
nn.Flatten(),
|
110 |
nn.Linear(512, num_classes),
|
111 |
-
nn.
|
112 |
)
|
113 |
|
114 |
def forward(self, x):
|
@@ -123,7 +124,7 @@ print(CLASSES)
|
|
123 |
|
124 |
preprocess = transforms.Compose(
|
125 |
[
|
126 |
-
transforms.Resize((
|
127 |
transforms.ToTensor(), # Convert to tensor
|
128 |
transforms.Grayscale(num_output_channels=3), # Convert to 3 channels
|
129 |
# Normalize 3 channels
|
|
|
14 |
|
15 |
# Constants
|
16 |
RANDOM_SEED = 123
|
17 |
+
BATCH_SIZE = 64
|
18 |
NUM_EPOCHS = 100
|
19 |
+
LEARNING_RATE = 0.00016633192288673592
|
20 |
STEP_SIZE = 10
|
21 |
+
GAMMA = 0.9
|
22 |
DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
23 |
NUM_PRINT = 100
|
24 |
TASK = 1
|
25 |
RAW_DATA_DIR = r"data/train/raw/Task "
|
26 |
AUG_DATA_DIR = r"data/train/augmented/Task "
|
27 |
EXTERNAL_DATA_DIR = r"data/train/external/Task "
|
28 |
+
COMBINED_DATA_DIR = r"data/train/combined/Task "
|
29 |
TEMP_DATA_DIR = "data/temp/"
|
30 |
NUM_CLASSES = 7
|
31 |
EARLY_STOPPING_PATIENCE = 20
|
|
|
109 |
nn.AdaptiveAvgPool2d((1, 1)),
|
110 |
nn.Flatten(),
|
111 |
nn.Linear(512, num_classes),
|
112 |
+
nn.BatchNorm1d(num_classes), # Add batch normalization
|
113 |
)
|
114 |
|
115 |
def forward(self, x):
|
|
|
124 |
|
125 |
preprocess = transforms.Compose(
|
126 |
[
|
127 |
+
transforms.Resize((112, 112)), # Resize to 112x112
|
128 |
transforms.ToTensor(), # Convert to tensor
|
129 |
transforms.Grayscale(num_output_channels=3), # Convert to 3 channels
|
130 |
# Normalize 3 channels
|
eda.py
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import pandas as pd
|
3 |
+
import numpy as np
|
4 |
+
import matplotlib.pyplot as plt
|
5 |
+
import seaborn as sns
|
6 |
+
from matplotlib import rcParams
|
7 |
+
|
8 |
+
rcParams['font.family'] = 'Times New Roman'
|
9 |
+
|
10 |
+
# Define the directory where your dataset is located
|
11 |
+
dataset_directory = 'data/train/combined/Task 1/'
|
12 |
+
|
13 |
+
# Create a list of class labels based on subdirectories in the dataset directory
|
14 |
+
class_labels = os.listdir(dataset_directory)
|
15 |
+
|
16 |
+
# Initialize lists to store data for EDA
|
17 |
+
num_samples_per_class = []
|
18 |
+
class_labels_processed = []
|
19 |
+
|
20 |
+
# Initialize an empty DataFrame to store image dimensions
|
21 |
+
image_dimensions_df = pd.DataFrame(columns=['Height', 'Width'])
|
22 |
+
|
23 |
+
# Initialize a dictionary to store a random sample of images from each class
|
24 |
+
sampled_images = {label: [] for label in class_labels}
|
25 |
+
|
26 |
+
# Iterate through class labels and count the number of samples per class
|
27 |
+
for label in class_labels:
|
28 |
+
if label != ".DS_Store":
|
29 |
+
class_directory = os.path.join(dataset_directory, label)
|
30 |
+
num_samples = len(os.listdir(class_directory))
|
31 |
+
num_samples_per_class.append(num_samples)
|
32 |
+
class_labels_processed.append(label)
|
33 |
+
|
34 |
+
# Extract image dimensions and add them to the DataFrame
|
35 |
+
for image_file in os.listdir(class_directory):
|
36 |
+
image_path = os.path.join(class_directory, image_file)
|
37 |
+
image = plt.imread(image_path)
|
38 |
+
height, width, _ = image.shape
|
39 |
+
image_dimensions_df = image_dimensions_df._append({'Height': height, 'Width': width}, ignore_index=True)
|
40 |
+
|
41 |
+
# Randomly sample 5 images from each class for visualization
|
42 |
+
if len(sampled_images[label]) < 5:
|
43 |
+
sampled_images[label].append(image)
|
44 |
+
|
45 |
+
# Create a Pandas DataFrame for EDA
|
46 |
+
eda_data = pd.DataFrame({'Class Label': class_labels_processed, 'Number of Samples': num_samples_per_class})
|
47 |
+
|
48 |
+
# Plot the number of samples per class
|
49 |
+
plt.figure(figsize=(10, 6))
|
50 |
+
sns.barplot(x='Class Label', y='Number of Samples', data=eda_data)
|
51 |
+
plt.title('Number of Samples per Class')
|
52 |
+
plt.xticks(rotation=45)
|
53 |
+
plt.xlabel('Class Label')
|
54 |
+
plt.ylabel('Number of Samples')
|
55 |
+
plt.savefig('docs/eda/Number of Samples per Class.png')
|
56 |
+
plt.show()
|
57 |
+
|
58 |
+
# Calculate and plot the distribution of sample sizes (image dimensions)
|
59 |
+
plt.figure(figsize=(10, 6))
|
60 |
+
plt.scatter(image_dimensions_df['Width'], image_dimensions_df['Height'], alpha=0.5)
|
61 |
+
plt.title('Distribution of Sample Sizes (Image Dimensions)')
|
62 |
+
plt.xlabel('Width (Pixels)')
|
63 |
+
plt.ylabel('Height (Pixels)')
|
64 |
+
plt.savefig('docs/eda/Distribution of Sample Sizes (Image Dimensions).png')
|
65 |
+
plt.show()
|
66 |
+
|
67 |
+
# Plot a random sample of images from each class
|
68 |
+
for label, images in sampled_images.items():
|
69 |
+
plt.figure(figsize=(15, 5))
|
70 |
+
plt.suptitle(f'Random Sample of Images from Class: {label}')
|
71 |
+
for i, image in enumerate(images, start=1):
|
72 |
+
plt.subplot(1, 5, i)
|
73 |
+
plt.imshow(image)
|
74 |
+
plt.axis('off')
|
75 |
+
plt.title(f'Sample {i}')
|
76 |
+
plt.savefig(f'docs/eda/Random Sample of Images from Class {label}.png')
|
77 |
+
plt.show()
|
78 |
+
|
79 |
+
# Calculate and plot the correlation matrix for image dimensions
|
80 |
+
correlation_matrix = image_dimensions_df.corr()
|
81 |
+
plt.figure(figsize=(8, 6))
|
82 |
+
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', linewidths=0.5)
|
83 |
+
plt.title('Correlation Matrix of Image Dimensions')
|
84 |
+
plt.savefig('docs/eda/Correlation Matrix of Image Dimensions.png')
|
85 |
+
plt.show()
|
86 |
+
|
87 |
+
# Plot the distribution of image widths
|
88 |
+
plt.figure(figsize=(10, 6))
|
89 |
+
sns.histplot(image_dimensions_df['Width'], bins=20, kde=True)
|
90 |
+
plt.title('Distribution of Image Widths')
|
91 |
+
plt.xlabel('Width (Pixels)')
|
92 |
+
plt.ylabel('Frequency')
|
93 |
+
plt.savefig('docs/eda/Distribution of Image Widths.png')
|
94 |
+
plt.show()
|
95 |
+
|
96 |
+
# Plot the distribution of image heights
|
97 |
+
plt.figure(figsize=(10, 6))
|
98 |
+
sns.histplot(image_dimensions_df['Height'], bins=20, kde=True)
|
99 |
+
plt.title('Distribution of Image Heights')
|
100 |
+
plt.xlabel('Height (Pixels)')
|
101 |
+
plt.ylabel('Frequency')
|
102 |
+
plt.savefig('docs/eda/Distribution of Image Heights.png')
|
103 |
+
plt.show()
|
eval.py
CHANGED
@@ -5,17 +5,23 @@ import pathlib
|
|
5 |
from PIL import Image
|
6 |
from torchmetrics import ConfusionMatrix, Accuracy, F1Score
|
7 |
import matplotlib.pyplot as plt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
from configs import *
|
9 |
from data_loader import load_data # Import the load_data function
|
10 |
-
|
11 |
-
image_path = "data/test/Task 1/"
|
12 |
|
13 |
# Constants
|
14 |
DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
15 |
|
16 |
# Load the model
|
17 |
MODEL = MODEL.to(DEVICE)
|
18 |
-
MODEL.load_state_dict(torch.load(
|
19 |
MODEL.eval()
|
20 |
|
21 |
|
@@ -30,6 +36,7 @@ def predict_image(image_path, model, transform):
|
|
30 |
|
31 |
true_classes = []
|
32 |
predicted_labels = []
|
|
|
33 |
|
34 |
accuracy_metric = Accuracy(num_classes=NUM_CLASSES, task="multiclass")
|
35 |
f1_metric = F1Score(num_classes=NUM_CLASSES, task="multiclass")
|
@@ -51,6 +58,9 @@ def predict_image(image_path, model, transform):
|
|
51 |
# Append true and predicted labels to their respective lists
|
52 |
true_classes.append(true_class)
|
53 |
predicted_labels.append(predicted_class)
|
|
|
|
|
|
|
54 |
|
55 |
# Check if the prediction is correct
|
56 |
if predicted_class == true_class:
|
@@ -73,8 +83,18 @@ def predict_image(image_path, model, transform):
|
|
73 |
# Plot the confusion matrix
|
74 |
conf_matrix.compute()
|
75 |
conf_matrix.plot()
|
|
|
76 |
plt.show()
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
-
# Call predict_image function
|
80 |
-
predict_image(
|
|
|
5 |
from PIL import Image
|
6 |
from torchmetrics import ConfusionMatrix, Accuracy, F1Score
|
7 |
import matplotlib.pyplot as plt
|
8 |
+
from sklearn.metrics import (
|
9 |
+
classification_report,
|
10 |
+
precision_recall_curve,
|
11 |
+
roc_curve,
|
12 |
+
auc,
|
13 |
+
confusion_matrix,
|
14 |
+
)
|
15 |
from configs import *
|
16 |
from data_loader import load_data # Import the load_data function
|
17 |
+
import numpy as np
|
|
|
18 |
|
19 |
# Constants
|
20 |
DEVICE = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
21 |
|
22 |
# Load the model
|
23 |
MODEL = MODEL.to(DEVICE)
|
24 |
+
MODEL.load_state_dict(torch.load(r"C:\Users\User\Documents\Flutter-test\handetect\assets\model.pt", map_location=DEVICE))
|
25 |
MODEL.eval()
|
26 |
|
27 |
|
|
|
36 |
|
37 |
true_classes = []
|
38 |
predicted_labels = []
|
39 |
+
predicted_scores = [] # To store predicted class probabilities
|
40 |
|
41 |
accuracy_metric = Accuracy(num_classes=NUM_CLASSES, task="multiclass")
|
42 |
f1_metric = F1Score(num_classes=NUM_CLASSES, task="multiclass")
|
|
|
58 |
# Append true and predicted labels to their respective lists
|
59 |
true_classes.append(true_class)
|
60 |
predicted_labels.append(predicted_class)
|
61 |
+
predicted_scores.append(
|
62 |
+
output.softmax(dim=1).cpu().numpy()
|
63 |
+
) # Store predicted class probabilities
|
64 |
|
65 |
# Check if the prediction is correct
|
66 |
if predicted_class == true_class:
|
|
|
83 |
# Plot the confusion matrix
|
84 |
conf_matrix.compute()
|
85 |
conf_matrix.plot()
|
86 |
+
plt.title("Confusion Matrix")
|
87 |
plt.show()
|
88 |
|
89 |
+
# Classification report
|
90 |
+
class_names = [str(cls) for cls in range(NUM_CLASSES)]
|
91 |
+
report = classification_report(
|
92 |
+
true_classes, predicted_labels, target_names=class_names
|
93 |
+
)
|
94 |
+
print("Classification Report:\n", report)
|
95 |
+
|
96 |
+
|
97 |
+
|
98 |
|
99 |
+
# Call predict_image function with your image path
|
100 |
+
predict_image("data/test/Task 1/", MODEL, preprocess)
|
test.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import torch.optim as optim
|
3 |
+
import torchvision.models as models
|
4 |
+
import torchvision.transforms as transforms
|
5 |
+
from configs import *
|
6 |
+
|
7 |
+
# Load a pre-trained model (e.g., VGG16)
|
8 |
+
MODEL = MODEL.to(DEVICE)
|
9 |
+
MODEL.load_state_dict(torch.load(MODEL_SAVE_PATH, map_location=DEVICE))
|
10 |
+
MODEL.eval()
|
11 |
+
|
12 |
+
# Prepare an initial image (e.g., a random noise image)
|
13 |
+
image = torch.randn(1, 3, 224, 224, requires_grad=True).cuda()
|
14 |
+
|
15 |
+
# Define a loss function to maximize a specific layer or neuron's activation
|
16 |
+
loss_function = torch.nn.CrossEntropyLoss()
|
17 |
+
|
18 |
+
# Create an optimizer (e.g., Adam) for updating the image
|
19 |
+
optimizer = optim.Adam([image], lr=0.01)
|
20 |
+
|
21 |
+
# Optimization loop
|
22 |
+
for _ in range(1000):
|
23 |
+
optimizer.zero_grad()
|
24 |
+
output = MODEL(image)
|
25 |
+
loss = -output[0, 'Healthy'] # Maximize the activation of a specific class
|
26 |
+
loss.backward()
|
27 |
+
optimizer.step()
|
28 |
+
|
29 |
+
# Visualize the optimized image
|
30 |
+
import matplotlib.pyplot as plt
|
31 |
+
import torchvision.transforms as transforms
|
32 |
+
|
33 |
+
# Convert the tensor to an image
|
34 |
+
image = transforms.ToPILImage()(image.squeeze())
|
35 |
+
|
36 |
+
# Display the generated image
|
37 |
+
plt.imshow(image)
|
38 |
+
plt.axis('off')
|
39 |
+
plt.show()
|
tuning.py
CHANGED
@@ -12,7 +12,7 @@ from torch.utils.tensorboard import SummaryWriter
|
|
12 |
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
13 |
EPOCHS = 10
|
14 |
N_TRIALS = 1000
|
15 |
-
TIMEOUT =
|
16 |
|
17 |
# Create a TensorBoard writer
|
18 |
writer = SummaryWriter(log_dir="output/tensorboard/tuning")
|
|
|
12 |
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
13 |
EPOCHS = 10
|
14 |
N_TRIALS = 1000
|
15 |
+
TIMEOUT = 1800
|
16 |
|
17 |
# Create a TensorBoard writer
|
18 |
writer = SummaryWriter(log_dir="output/tensorboard/tuning")
|