Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
6 views

vertopal.com_3D_Convolutional_Autoencoder

Uploaded by

Boch
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

vertopal.com_3D_Convolutional_Autoencoder

Uploaded by

Boch
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

from google.

colab import drive


drive.mount('/content/drive')

Drive already mounted at /content/drive; to attempt to forcibly


remount, call drive.mount("/content/drive", force_remount=True).

gz_file_path ='/content/drive/MyDrive/UCSD_Anomaly_Dataset.tar.gz'

import tarfile

# Extract the .tar.gz file


with tarfile.open(gz_file_path, 'r:gz') as tar:
tar.extractall('/content/UCSD_Anomaly_Dataset')

!pip install tensorflow


!pip install opencv-python

Requirement already satisfied: tensorflow in


/usr/local/lib/python3.10/dist-packages (2.17.0)
Requirement already satisfied: absl-py>=1.0.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (1.4.0)
Requirement already satisfied: astunparse>=1.6.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (1.6.3)
Requirement already satisfied: flatbuffers>=24.3.25 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (24.3.25)
Requirement already satisfied: gast!=0.5.0,!=0.5.1,!=0.5.2,>=0.2.1
in /usr/local/lib/python3.10/dist-packages (from tensorflow) (0.6.0)
Requirement already satisfied: google-pasta>=0.1.1 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (0.2.0)
Requirement already satisfied: h5py>=3.10.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (3.12.1)
Requirement already satisfied: libclang>=13.0.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (18.1.1)
Requirement already satisfied: ml-dtypes<0.5.0,>=0.3.1 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (0.4.1)
Requirement already satisfied: opt-einsum>=2.3.2 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (3.4.0)
Requirement already satisfied: packaging in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (24.1)
Requirement already satisfied: protobuf!=4.21.0,!=4.21.1,!=4.21.2,!
=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.20.3 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (3.20.3)
Requirement already satisfied: requests<3,>=2.21.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (2.32.3)
Requirement already satisfied: setuptools in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (75.1.0)
Requirement already satisfied: six>=1.12.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (1.16.0)
Requirement already satisfied: termcolor>=1.1.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (2.5.0)
Requirement already satisfied: typing-extensions>=3.6.6 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (4.12.2)
Requirement already satisfied: wrapt>=1.11.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (1.16.0)
Requirement already satisfied: grpcio<2.0,>=1.24.3 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (1.64.1)
Requirement already satisfied: tensorboard<2.18,>=2.17 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (2.17.0)
Requirement already satisfied: keras>=3.2.0 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (3.4.1)
Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.23.1 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (0.37.1)
Requirement already satisfied: numpy<2.0.0,>=1.23.5 in
/usr/local/lib/python3.10/dist-packages (from tensorflow) (1.26.4)
Requirement already satisfied: wheel<1.0,>=0.23.0 in
/usr/local/lib/python3.10/dist-packages (from astunparse>=1.6.0-
>tensorflow) (0.44.0)
Requirement already satisfied: rich in /usr/local/lib/python3.10/dist-
packages (from keras>=3.2.0->tensorflow) (13.9.3)
Requirement already satisfied: namex in
/usr/local/lib/python3.10/dist-packages (from keras>=3.2.0-
>tensorflow) (0.0.8)
Requirement already satisfied: optree in
/usr/local/lib/python3.10/dist-packages (from keras>=3.2.0-
>tensorflow) (0.13.0)
Requirement already satisfied: charset-normalizer<4,>=2 in
/usr/local/lib/python3.10/dist-packages (from requests<3,>=2.21.0-
>tensorflow) (3.4.0)
Requirement already satisfied: idna<4,>=2.5 in
/usr/local/lib/python3.10/dist-packages (from requests<3,>=2.21.0-
>tensorflow) (3.10)
Requirement already satisfied: urllib3<3,>=1.21.1 in
/usr/local/lib/python3.10/dist-packages (from requests<3,>=2.21.0-
>tensorflow) (2.2.3)
Requirement already satisfied: certifi>=2017.4.17 in
/usr/local/lib/python3.10/dist-packages (from requests<3,>=2.21.0-
>tensorflow) (2024.8.30)
Requirement already satisfied: markdown>=2.6.8 in
/usr/local/lib/python3.10/dist-packages (from tensorboard<2.18,>=2.17-
>tensorflow) (3.7)
Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0
in /usr/local/lib/python3.10/dist-packages (from
tensorboard<2.18,>=2.17->tensorflow) (0.7.2)
Requirement already satisfied: werkzeug>=1.0.1 in
/usr/local/lib/python3.10/dist-packages (from tensorboard<2.18,>=2.17-
>tensorflow) (3.0.6)
Requirement already satisfied: MarkupSafe>=2.1.1 in
/usr/local/lib/python3.10/dist-packages (from werkzeug>=1.0.1-
>tensorboard<2.18,>=2.17->tensorflow) (3.0.2)
Requirement already satisfied: markdown-it-py>=2.2.0 in
/usr/local/lib/python3.10/dist-packages (from rich->keras>=3.2.0-
>tensorflow) (3.0.0)
Requirement already satisfied: pygments<3.0.0,>=2.13.0 in
/usr/local/lib/python3.10/dist-packages (from rich->keras>=3.2.0-
>tensorflow) (2.18.0)
Requirement already satisfied: mdurl~=0.1 in
/usr/local/lib/python3.10/dist-packages (from markdown-it-py>=2.2.0-
>rich->keras>=3.2.0->tensorflow) (0.1.2)
Requirement already satisfied: opencv-python in
/usr/local/lib/python3.10/dist-packages (4.10.0.84)
Requirement already satisfied: numpy>=1.21.2 in
/usr/local/lib/python3.10/dist-packages (from opencv-python) (1.26.4)

#!pip install matplotlib==3.4.3

import cv2
import numpy as np
import os
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv2D, MaxPooling2D,
UpSampling2D, Input
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error

from PIL import Image

def load_and_preprocess_frames(directory_path, frame_height=160,


frame_width=160):
all_videos = []

for video_folder in sorted(os.listdir(directory_path)):


video_path = os.path.join(directory_path, video_folder)

if os.path.isdir(video_path):
frames = []

for filename in sorted(os.listdir(video_path)):


frame_path = os.path.join(video_path, filename)

if filename.lower().endswith('.tif'):
# Open the image, resize, and convert to grayscale
if needed
with Image.open(frame_path) as img:
img = img.resize((frame_width, frame_height))
# Resize to (128, 128)
frame = np.array(img) # Convert to numpy
array
frame = np.expand_dims(frame, axis=-1) # Add
channel dimension for grayscale
frame = frame / 255.0 # Normalize to [0, 1]
frames.append(frame)

if frames:
all_videos.append(np.array(frames))

return all_videos

# Example usage
train_directory_ped1 =
'/content/UCSD_Anomaly_Dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped1/
Train'
train_directory_ped2 =
'/content/UCSD_Anomaly_Dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped2/
Train'

train_videos_ped1 = load_and_preprocess_frames(train_directory_ped1)
train_videos_ped2 = load_and_preprocess_frames(train_directory_ped2)
train_videos = train_videos_ped1 + train_videos_ped2

# Display a sample of frames to verify the loading process


def display_sample_frames(videos, num_frames=5):
for i, video_frames in enumerate(videos[:1]): # Display frames
from the first video only
plt.figure(figsize=(15, 5))
for j in range(min(num_frames, len(video_frames))):
plt.subplot(1, num_frames, j + 1)
plt.imshow(video_frames[j])
plt.axis('off')
plt.title(f"Video {i + 1} - Frame {j + 1}")
plt.show()

display_sample_frames(train_videos)
import numpy as np

def split_into_sequences(video_frames, sequence_length=16):


"""
Splits the frames of a video into sequences of a specified length.

Parameters:
- video_frames: np.array, the frames of a single video (e.g.,
shape (num_frames, height, width, channels))
- sequence_length: int, the number of frames per sequence

Returns:
- sequences: np.array, shape (num_sequences, sequence_length,
height, width, channels)
"""
num_frames = len(video_frames)
sequences = []

# Slide over frames to create sequences


for i in range(0, num_frames - sequence_length + 1,
sequence_length):
sequence = video_frames[i:i + sequence_length]
sequences.append(sequence)

return np.array(sequences)

# Define directories for both training datasets


train_directory_ped1 =
'/content/UCSD_Anomaly_Dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped1/
Train'
train_directory_ped2 =
'/content/UCSD_Anomaly_Dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped2/
Train'

# Load both datasets


train_videos_ped1 = load_and_preprocess_frames(train_directory_ped1)
train_videos_ped2 = load_and_preprocess_frames(train_directory_ped2)

# Combine videos from both datasets


train_videos = train_videos_ped1 + train_videos_ped2

# Concatenate all sequences from all videos in both datasets


train_3d_data = np.concatenate([split_into_sequences(video,
sequence_length=16) for video in train_videos], axis=0)
print("Prepared training data shape:", train_3d_data.shape)

Prepared training data shape: (562, 16, 160, 160, 1)

from tensorflow.keras.models import Model


from tensorflow.keras.layers import Conv3D, MaxPooling3D,
UpSampling3D, Input, Activation
from tensorflow.keras.optimizers import Adam

# 3D CNN Autoencoder Model


def build_3d_cnn_autoencoder(input_shape=(16, 160, 160, 1)):
input_layer = Input(shape=input_shape)

# Encoder
x = Conv3D(32, (3, 3, 3), padding='same')(input_layer)
x = Activation('relu')(x)
x = MaxPooling3D((2, 2, 2), padding='same')(x)

x = Conv3D(32, (3, 3, 3), padding='same')(x)


x = Activation('relu')(x)
x = MaxPooling3D((2, 2, 2), padding='same')(x)

# Decoder
x = Conv3D(32, (3, 3, 3), padding='same')(x)
x = Activation('relu')(x)
x = UpSampling3D((2, 2, 2))(x)

x = Conv3D(32, (3, 3, 3), padding='same')(x)


x = Activation('relu')(x)
x = UpSampling3D((2, 2, 2))(x)

decoded = Conv3D(1, (3, 3, 3), activation='sigmoid',


padding='same')(x) # Final layer with sigmoid for [0, 1] range

# Autoencoder Model
autoencoder = Model(input_layer, decoded)
autoencoder.compile(optimizer=Adam(learning_rate=0.001),
loss='mse')

return autoencoder

# Example usage
input_shape = (16, 160, 160, 1) # 16 consecutive frames, 160x160
resolution, 1 channel (grayscale)
cnn_3d_autoencoder = build_3d_cnn_autoencoder(input_shape=input_shape)

# Encoder
# x = Conv3D(32, (3, 3, 3), activation='relu', padding='same')
(input_layer)
# x = MaxPooling3D((2, 2, 2), padding='same')(x)
# x = Conv3D(64, (3, 3, 3), activation='relu', padding='same')(x)
# x = MaxPooling3D((2, 2, 2), padding='same')(x)
# encoded = Conv3D(277, (3, 3, 3), activation='relu',
padding='same')(x)

# # Decoder
# x = UpSampling3D((2, 2, 2))(encoded)
# x = Conv3D(64, (3, 3, 3), activation='relu', padding='same')(x)
# x = UpSampling3D((2, 2, 2))(x)
# decoded = Conv3D(1, (3, 3, 3), activation='sigmoid',
padding='same')(x) # Single channel for grayscale output

# autoencoder = Model(input_layer, decoded)


# autoencoder.compile(optimizer=Adam(), loss='mse')
# return autoencoder

cnn_3d_autoencoder.compile(optimizer='adam', loss='mse')

# Assuming train_3d_data is your full dataset


train_size = int(0.8 * len(train_3d_data))
train_data = train_3d_data[:train_size]
val_data = train_3d_data[train_size:]

from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint

# Set up early stopping and model checkpoint to monitor validation


loss
early_stopping = EarlyStopping(monitor='val_loss', patience=3,
verbose=1)

cnn_3d_autoencoder.fit(
train_data, train_data,
epochs=10,
batch_size=2,
shuffle=True,
validation_data=(val_data, val_data),
callbacks=[early_stopping]
)

Epoch 1/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 27s 84ms/step - loss: 0.0158 - val_loss:
0.0013
Epoch 2/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 29s 58ms/step - loss: 0.0023 - val_loss:
9.8407e-04
Epoch 3/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 13s 58ms/step - loss: 0.0018 - val_loss:
8.5347e-04
Epoch 4/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 21s 59ms/step - loss: 0.0017 - val_loss:
7.8221e-04
Epoch 5/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 14s 61ms/step - loss: 0.0015 - val_loss:
7.4683e-04
Epoch 6/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 20s 60ms/step - loss: 0.0014 - val_loss:
7.0392e-04
Epoch 7/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 21s 61ms/step - loss: 0.0014 - val_loss:
7.2750e-04
Epoch 8/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 20s 61ms/step - loss: 0.0013 - val_loss:
6.5005e-04
Epoch 9/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 21s 61ms/step - loss: 0.0012 - val_loss:
6.2748e-04
Epoch 10/10
225/225 ━━━━━━━━━━━━━━━━━━━━ 14s 62ms/step - loss: 0.0012 - val_loss:
6.3976e-04

<keras.src.callbacks.history.History at 0x79e7ed803910>

import matplotlib.pyplot as plt


from PIL import Image
import numpy as np
import os

def load_and_preprocess_frames(directory_path, frame_height=160,


frame_width=160):
all_videos = []

for video_folder in sorted(os.listdir(directory_path)):


video_path = os.path.join(directory_path, video_folder)

if os.path.isdir(video_path):
frames = []

for filename in sorted(os.listdir(video_path)):


frame_path = os.path.join(video_path, filename)

if filename.lower().endswith('.tif'):
try:
# Attempt to open, resize, and normalize the
image
with Image.open(frame_path) as img:
img = img.resize((frame_width,
frame_height)) # Resize to (128, 128)
frame = np.array(img) # Convert to numpy
array
frame = np.expand_dims(frame, axis=-1) #
Add channel dimension for grayscale
frame = frame / 255.0 # Normalize to [0,
1]
frames.append(frame)
except Exception as e:
# Print an error message for any file that
fails to load
print(f"Error loading file {frame_path}: {e}")

if frames:
all_videos.append(np.array(frames))

return all_videos

# Example usage for loading the test set


test_directory_ped1 =
'/content/UCSD_Anomaly_Dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped1/
Test'
test_directory_ped2 =
'/content/UCSD_Anomaly_Dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped2/
Test'

test_videos_ped1 = load_and_preprocess_frames(test_directory_ped1)
test_videos_ped2 = load_and_preprocess_frames(test_directory_ped2)

test_videos = test_videos_ped1 + test_videos_ped2

Error loading file


/content/UCSD_Anomaly_Dataset/UCSD_Anomaly_Dataset.v1p2/UCSDped1/Test/
Test017/142.tif: -2

test_3d_data = np.concatenate([split_into_sequences(video,
sequence_length=16) for video in test_videos], axis=0)
print("Prepared test data shape:", test_3d_data.shape)

Prepared test data shape: (554, 16, 160, 160, 1)

reconstructed_test_data = cnn_3d_autoencoder.predict(test_3d_data)

18/18 ━━━━━━━━━━━━━━━━━━━━ 11s 326ms/step

from sklearn.metrics import mean_squared_error

# Calculate reconstruction error for each sequence


reconstruction_errors = [
mean_squared_error(original.flatten(), reconstructed.flatten())
for original, reconstructed in zip(test_3d_data,
reconstructed_test_data)
]

import numpy as np

threshold = np.percentile(reconstruction_errors, 30
)
print("Anomaly threshold:", threshold)

Anomaly threshold: 0.0011392208955404764


anomalies = [error > threshold for error in reconstruction_errors]

import matplotlib.pyplot as plt

plt.plot(reconstruction_errors, label='Reconstruction Error')


plt.axhline(y=threshold, color='r', linestyle='--', label='Anomaly
Threshold')
plt.xlabel("Sequence")
plt.ylabel("Reconstruction Error")
plt.title("Reconstruction Error on Test Data")
plt.legend()
plt.show()

# Define ground truth for UCSDped1


ground_truth_frames_ped1 = [
list(range(60, 153)),
list(range(50, 176)),
list(range(91, 201)),
list(range(31, 169)),
list(range(5, 91)) + list(range(140, 201)),
list(range(1, 101)) + list(range(110, 201)),
list(range(1, 176)),
list(range(1, 95)),
list(range(1, 49)),
list(range(1, 141)),
list(range(70, 166)),
list(range(130, 201)),
list(range(1, 157)),
list(range(1, 201)),
list(range(138, 201)),
list(range(123, 201)),
list(range(1, 48)),
list(range(54, 121)),
list(range(64, 139)),
list(range(45, 176)),
list(range(31, 201)),
list(range(16, 108)),
list(range(8, 166)),
list(range(50, 172)),
list(range(40, 136)),
list(range(77, 145)),
list(range(10, 123)),
list(range(105, 201)),
list(range(1, 16)) + list(range(45, 114)),
list(range(175, 201)),
list(range(1, 181)),
list(range(1, 53)) + list(range(65, 116)),
list(range(5, 166)),
list(range(1, 122)),
list(range(86, 201)),
list(range(15, 109))
]

# Define ground truth for UCSDped2


ground_truth_frames_ped2 = [
list(range(61, 180)),
list(range(95, 180)),
list(range(1, 146)),
list(range(31, 180)),
list(range(1, 129)),
list(range(1, 162)),
list(range(46, 180)),
list(range(1, 180)),
list(range(1, 120)),
list(range(1, 150)),
list(range(1, 180)),
list(range(88, 180))
]

# Combine both ground truth annotations


ground_truth_frames = ground_truth_frames_ped1 +
ground_truth_frames_ped2

# Convert reconstruction errors into binary predictions based on the


threshold
binary_predictions = [1 if error > threshold else 0 for error in
reconstruction_errors]

# Group predictions by video


sequence_length = 16
num_sequences_per_video = len(test_videos[0]) // sequence_length #
Assuming each video has the same number of frames

# Organize binary predictions by video


model_predictions = [
binary_predictions[i * num_sequences_per_video : (i + 1) *
num_sequences_per_video]
for i in range(len(test_videos))
]

from sklearn.metrics import precision_score, recall_score, f1_score

# Initialize lists to collect all ground truth labels and model


predictions
all_gt_labels = []
all_model_labels = []

# Iterate over each test video


for i, gt_frames in enumerate(ground_truth_frames):
# Get binary predictions for the current video, expanded to match
frame-level granularity
video_predictions = []
for seq_pred in model_predictions[i]:
video_predictions.extend([seq_pred] * sequence_length) #
Repeat each sequence prediction across its frames

# Generate ground truth labels for each frame in the video


gt_labels = [1 if frame in gt_frames else 0 for frame in
range(len(video_predictions))]

# Collect the ground truth and predictions for overall evaluation


all_gt_labels.extend(gt_labels)
all_model_labels.extend(video_predictions[:len(gt_labels)]) #
Ensure predictions align with gt labels length

# Calculate and display evaluation metrics


precision = precision_score(all_gt_labels, all_model_labels)
recall = recall_score(all_gt_labels, all_model_labels)
f1 = f1_score(all_gt_labels, all_model_labels)

print(f"Precision: {precision:.4f}")
print(f"Recall: {recall:.4f}")
print(f"F1 Score: {f1:.4f}")

Precision: 0.6432
Recall: 0.7471
F1 Score: 0.6912

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay


import matplotlib.pyplot as plt

# Assuming `all_gt_labels` are the ground truth labels and


`all_model_labels` are your final binary predictions
# Calculate the confusion matrix
cm = confusion_matrix(all_gt_labels, all_model_labels)

# Plot the confusion matrix


disp = ConfusionMatrixDisplay(confusion_matrix=cm,
display_labels=["Normal", "Anomaly"])
disp.plot(cmap="Blues")
plt.title("Confusion Matrix for Anomaly Detection")
plt.show()

Recall (0.7471): This moderately high recall indicates that the model successfully detects most
of the actual anomalies, although it may miss a few. A recall of 0.7471 means that the model is
generally effective in identifying anomalous sequences but may occasionally let some anomalies
go undetected.

Precision (0.6432): With a precision of 0.6432, the model is reasonably selective in identifying
anomalies. However, it does flag some normal sequences as anomalies, which suggests there
are still false positives. This precision level indicates a good balance where the model avoids
being overly sensitive, but it could still be improved if false alarms are a concern.

F1 Score (0.6912): The F1 score of 0.6912 reflects a solid balance between recall and precision.
This score indicates that the model is fairly good at both capturing actual anomalies and
avoiding false positives, making it a well-rounded choice for general anomaly detection.

You might also like