Potato
Potato
import numpy as np
import pandas as pd
import os
base_path = "/kaggle/input/potato-disease-detection-dataset/"
categories = ["Potato___Early_blight","Potato___Late_blight",
"Potato___healthy"]
image_paths = []
labels = []
df = pd.DataFrame({
"image_path": image_paths,
"label": labels
})
df.head()
image_path label
0 /kaggle/input/potato-disease-detection-dataset... Potato___Early_blight
1 /kaggle/input/potato-disease-detection-dataset... Potato___Early_blight
2 /kaggle/input/potato-disease-detection-dataset... Potato___Early_blight
3 /kaggle/input/potato-disease-detection-dataset... Potato___Early_blight
4 /kaggle/input/potato-disease-detection-dataset... Potato___Early_blight
df.tail()
image_path label
2147 /kaggle/input/potato-disease-detection-dataset... Potato___healthy
2148 /kaggle/input/potato-disease-detection-dataset... Potato___healthy
2149 /kaggle/input/potato-disease-detection-dataset... Potato___healthy
2150 /kaggle/input/potato-disease-detection-dataset... Potato___healthy
2151 /kaggle/input/potato-disease-detection-dataset... Potato___healthy
df.shape
(2152, 2)
df.columns
df.duplicated().sum()
df.isnull().sum()
image_path 0
label 0
dtype: int64
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2152 entries, 0 to 2151
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 image_path 2152 non-null object
1 label 2152 non-null object
dtypes: object(2)
memory usage: 33.8+ KB
df['label'].unique()
array(['Potato___Early_blight', 'Potato___Late_blight',
'Potato___healthy'], dtype=object)
df['label'].value_counts()
label
Potato___Early_blight 1000
Potato___Late_blight 1000
Potato___healthy 152
Name: count, dtype: int64
for p in ax.patches:
ax.annotate(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')
plt.show()
label_counts = df["label"].value_counts()
plt.show()
import cv2
num_images = 5
plt.figure(figsize=(15, 12))
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.tight_layout()
plt.show()
df['category_encoded'] = label_encoder.fit_transform(df['label'])
df = df[['image_path', 'category_encoded']]
max_count = df['category_encoded'].value_counts().max()
dfs = []
for category in df['category_encoded'].unique():
class_subset = df[df['category_encoded'] == category]
class_upsampled = resample(class_subset,
replace=True,
n_samples=max_count,
random_state=42)
dfs.append(class_upsampled)
df_balanced = pd.concat(dfs).sample(frac=1,
random_state=42).reset_index(drop=True)
df_balanced['category_encoded'].value_counts()
category_encoded
1 1000
0 1000
2 1000
Name: count, dtype: int64
df_resampled = df_balanced
df_resampled['category_encoded'] =
df_resampled['category_encoded'].astype(str)
import time
import shutil
import pathlib
import itertools
from PIL import Image
import cv2
import seaborn as sns
sns.set_style('darkgrid')
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, classification_report
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense,
Activation, Dropout, BatchNormalization
from tensorflow.keras import regularizers
import warnings
warnings.filterwarnings("ignore")
print ('check')
2025-06-04 12:50:59.118080: E
external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to
register cuFFT factory: Attempting to register factory for plugin cuFFT when
one has already been registered
WARNING: All log messages before absl::InitializeLog() is called are written
to STDERR
E0000 00:00:1749041459.595664 35 cuda_dnn.cc:8310] Unable to register
cuDNN factory: Attempting to register factory for plugin cuDNN when one has
already been registered
E0000 00:00:1749041459.728633 35 cuda_blas.cc:1418] Unable to register
cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has
already been registered
check
batch_size = 16
img_size = (224, 224)
channels = 3
img_shape = (img_size[0], img_size[1], channels)
tr_gen = ImageDataGenerator(
rescale=1./255
)
ts_gen = ImageDataGenerator(rescale=1./255)
train_gen_new = tr_gen.flow_from_dataframe(
train_df_new,
x_col='image_path',
y_col='category_encoded',
target_size=img_size,
class_mode='sparse',
color_mode='rgb',
shuffle=True,
batch_size=batch_size
)
valid_gen_new = ts_gen.flow_from_dataframe(
valid_df_new,
x_col='image_path',
y_col='category_encoded',
target_size=img_size,
class_mode='sparse',
color_mode='rgb',
shuffle=True,
batch_size=batch_size
)
test_gen_new = ts_gen.flow_from_dataframe(
test_df_new,
x_col='image_path',
y_col='category_encoded',
target_size=img_size,
class_mode='sparse',
color_mode='rgb',
shuffle=False,
batch_size=batch_size
)
gpus = tf.config.list_physical_devices('GPU')
if gpus:
try:
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
print("GPU is set for TensorFlow")
except RuntimeError as e:
print(e)
import tensorflow as tf
from tensorflow.keras.layers import (Input, Lambda, Conv2D, MaxPooling2D,
Flatten,
Dense, Reshape, Concatenate,
GlobalAveragePooling1D, Softmax, Multiply)
from tensorflow.keras.models import Model
def split_image(image):
upper_half = image[:, :img_size[0]//2, :, :]
lower_half = image[:, img_size[0]//2:, :, :]
return upper_half, lower_half
def flip_lower_half(lower_half):
return tf.image.flip_left_right(lower_half)
input_layer = Input(shape=img_shape)
similarity_scores = tf.keras.layers.Dot(axes=-1,
normalize=True)([upper_reshape, lower_reshape]) # (None, 1, 1)
attention_weights = Softmax(axis=1)(similarity_scores)
model.summary()
Model: "functional"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━
━━━━━━━━━━━━━━━━━━┓
┃ Layer (type) ┃ Output Shape ┃ Param # ┃
Connected to ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━
━━━━━━━━━━━━━━━━━━┩
│ input_layer (InputLayer) │ (None, 224, 224, 3) │ 0 │ -
│
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ lambda (Lambda) │ [(None, 112, 224, 3), │ 0 │
input_layer[0][0] │
│ │ (None, 112, 224, 3)] │ │
│
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ lambda_1 (Lambda) │ (None, 112, 224, 3) │ 0 │
lambda[0][1] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ conv2d (Conv2D) │ (None, 112, 224, 32) │ 896 │
lambda[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ conv2d_3 (Conv2D) │ (None, 112, 224, 32) │ 896 │
lambda_1[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ max_pooling2d │ (None, 56, 112, 32) │ 0 │
conv2d[0][0] │
│ (MaxPooling2D) │ │ │
│
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ max_pooling2d_3 │ (None, 56, 112, 32) │ 0 │
conv2d_3[0][0] │
│ (MaxPooling2D) │ │ │
│
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ conv2d_1 (Conv2D) │ (None, 56, 112, 64) │ 18,496 │
max_pooling2d[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ conv2d_4 (Conv2D) │ (None, 56, 112, 64) │ 18,496 │
max_pooling2d_3[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ max_pooling2d_1 │ (None, 28, 56, 64) │ 0 │
conv2d_1[0][0] │
│ (MaxPooling2D) │ │ │
│
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ max_pooling2d_4 │ (None, 28, 56, 64) │ 0 │
conv2d_4[0][0] │
│ (MaxPooling2D) │ │ │
│
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ conv2d_2 (Conv2D) │ (None, 28, 56, 128) │ 73,856 │
max_pooling2d_1[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ conv2d_5 (Conv2D) │ (None, 28, 56, 128) │ 73,856 │
max_pooling2d_4[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ max_pooling2d_2 │ (None, 14, 28, 128) │ 0 │
conv2d_2[0][0] │
│ (MaxPooling2D) │ │ │
│
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ max_pooling2d_5 │ (None, 14, 28, 128) │ 0 │
conv2d_5[0][0] │
│ (MaxPooling2D) │ │ │
│
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ flatten (Flatten) │ (None, 50176) │ 0 │
max_pooling2d_2[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ flatten_1 (Flatten) │ (None, 50176) │ 0 │
max_pooling2d_5[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ dense (Dense) │ (None, 512) │ 25,690,624 │
flatten[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ dense_1 (Dense) │ (None, 512) │ 25,690,624 │
flatten_1[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ reshape (Reshape) │ (None, 1, 512) │ 0 │
dense[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ reshape_1 (Reshape) │ (None, 1, 512) │ 0 │
dense_1[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ dot (Dot) │ (None, 1, 1) │ 0 │
reshape[0][0], │
│ │ │ │
reshape_1[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ softmax (Softmax) │ (None, 1, 1) │ 0 │
dot[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ multiply (Multiply) │ (None, 1, 512) │ 0 │
softmax[0][0], │
│ │ │ │
reshape[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ concatenate_1 │ (None, 1, 1024) │ 0 │
multiply[0][0], │
│ (Concatenate) │ │ │
reshape_1[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ reshape_2 (Reshape) │ (None, 1024) │ 0 │
concatenate_1[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ dense_2 (Dense) │ (None, 256) │ 262,400 │
reshape_2[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ dense_3 (Dense) │ (None, 128) │ 32,896 │
dense_2[0][0] │
├───────────────────────────┼────────────────────────┼────────────────┼──────
──────────────────┤
│ dense_4 (Dense) │ (None, 3) │ 387 │
dense_3[0][0] │
└───────────────────────────┴────────────────────────┴────────────────┴──────
──────────────────┘
plot_model(model,
to_file='/kaggle/working/model.png',
show_shapes=False,
show_dtype=False,
show_layer_names=False,
dpi=300)
history = model.fit(
train_gen_new,
validation_data=valid_gen_new,
epochs=3,
batch_size=batch_size
)
Epoch 1/3
WARNING: All log messages before absl::InitializeLog() is called are written
to STDERR
I0000 00:00:1749041902.649802 105 service.cc:148] XLA service
0x7b0678008160 initialized for platform CUDA (this does not guarantee that
XLA will be used). Devices:
I0000 00:00:1749041902.651550 105 service.cc:156] StreamExecutor device
(0): Tesla T4, Compute Capability 7.5
I0000 00:00:1749041902.651574 105 service.cc:156] StreamExecutor device
(1): Tesla T4, Compute Capability 7.5
I0000 00:00:1749041903.381011 105 cuda_dnn.cc:529] Loaded cuDNN version
90300
def plot_training_history(history):
plt.tight_layout()
plt.show()
plot_training_history(history)
test_loss, test_accuracy = model.evaluate(test_gen_new)
print(f"Test Accuracy: {test_accuracy:.4f}, Test Loss: {test_loss:.4f}")
test_gen_new.reset()
y_pred = model.predict(test_gen_new)
y_pred_classes = np.argmax(y_pred, axis=1)
y_true = test_gen_new.classes
class_names = list(test_gen_new.class_indices.keys())
cm = confusion_matrix(y_true, y_pred_classes)
plt.figure(figsize=(10, 8))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=class_names,
yticklabels=class_names)
plt.title('Confusion Matrix')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.show()
print("\nClassification Report:")
print(classification_report(y_true, y_pred_classes,
target_names=class_names))
Classification Report:
precision recall f1-score support