Wafer Defect Prediction

Load data and Models

import numpy as np
import tensorflow as tf

# Load Data
data_path = "../data/mixedtype-wafer-defect-datasets/Wafer_Map_Datasets.npz"
data = np.load(data_path)
images = data["arr_0"]
labels = data["arr_1"]
print("✓ Data loaded")

# Load the Phase 2 models
MODELS_DIR = "phase2_models"
model_p2_cnn = tf.keras.models.load_model(f"{MODELS_DIR}/model_p2_cnn.keras")
model_p2_tl = tf.keras.models.load_model(f"{MODELS_DIR}/model_p2_tl.keras")
print("✓ Models loaded")
✓ Data loaded
✓ Models loaded

Data Cleansing

# Default pixels with 3 to 0
images[images == 3] = 0
# String Label Mapping
label_mapping = {
    "00000000": "Normal",
    "10000000": "Center",
    "01000000": "Donut",
    "00100000": "Edge_Loc",
    "00010000": "Edge_Ring",
    "00001000": "Loc",
    "00000100": "Near_Full",
    "00000010": "Scratch",
    "00000001": "Random",
    "10100000": "Center+Edge_Loc",
    "10010000": "Center+Edge_Ring",
    "10001000": "Center+Loc",
    "10000010": "Center+Scratch",
    "01100000": "Donut+Edge_Loc",
    "01010000": "Donut+Edge_Ring",
    "01001000": "Donut+Loc",
    "01000010": "Donut+Scratch",
    "00101000": "Edge_Loc+Loc",
    "00100010": "Edge_Loc+Scratch",
    "00011000": "Edge_Ring+Loc",
    "00010010": "Edge_Ring+Scratch",
    "00001010": "Loc+Scratch",
    "10101000": "Center+Edge_Loc+Loc",
    "10100010": "Center+Edge_Loc+Scratch",
    "10011000": "Center+Edge_Ring+Loc",
    "10010010": "Center+Edge_Ring+Scratch",
    "10001010": "Center+Loc+Scratch",
    "01101000": "Donut+Edge_Loc+Loc",
    "01100010": "Donut+Edge_Loc+Scratch",
    "01011000": "Donut+Edge_Ring+Loc",
    "01010010": "Donut+Edge_Ring+Scratch",
    "01001010": "Donut+Loc+Scratch",
    "00101010": "Edge_Loc+Loc+Scratch",
    "00011010": "Edge_Ring+Loc+Scratch",
    "10101010": "Center+Edge_Loc+Loc+Scratch",
    "10011010": "Center+Edge_Ring+Loc+Scratch",
    "01101010": "Donut+Edge_Loc+Loc+Scratch",
    "01011010": "Donut+Edge_Ring+Loc+Scratch",
}


unique_patterns = sorted(label_mapping.keys())
pattern_to_id = {pattern: idx for idx, pattern in enumerate(unique_patterns)}
id_to_pattern = {idx: label_mapping[pattern] for pattern, idx in pattern_to_id.items()}
label_str_arr = np.array(["".join(map(str, map(int, row))) for row in labels])

X_test = np.eye(3, dtype=np.float32)[images.astype(int)]  # Shape: (52, 52, 3)
y_class_test = np.array([pattern_to_id[s] for s in label_str_arr])

Predict Wafer Defect

# Pick a random wafer map from test set
random_idx = np.random.randint(0, len(X_test))
random_wafer = X_test[random_idx : random_idx + 1]
true_class_id = y_class_test[random_idx]
true_pattern_name = id_to_pattern[true_class_id]

print(f"Random wafer shape: {random_wafer.shape}")
print(f"True defect pattern: {true_pattern_name}")

# Make predictions
pred_cnn = model_p2_cnn.predict(random_wafer, verbose=0)  # Shape: (1, 38)
pred_tl = model_p2_tl.predict(random_wafer, verbose=0)  # Shape: (1, 38)

# Get predicted class IDs (argmax)
pred_class_cnn = pred_cnn[0].argmax()
pred_class_tl = pred_tl[0].argmax()

# Get predicted pattern names
pred_pattern_cnn = id_to_pattern[pred_class_cnn]
pred_pattern_tl = id_to_pattern[pred_class_tl]

# Get confidence scores
conf_cnn = pred_cnn[0, pred_class_cnn]
conf_tl = pred_tl[0, pred_class_tl]

print("\nPredictions:")
print(f"  Custom CNN:   {pred_pattern_cnn} (confidence: {conf_cnn:.2%})")
print(f"  MobileNetV2:  {pred_pattern_tl} (confidence: {conf_tl:.2%})")
print(f"  Match: {'✓' if pred_class_cnn == true_class_id else '✗'} (Custom CNN)")
print(f"  Match: {'✓' if pred_class_tl == true_class_id else '✗'} (MobileNetV2)")
Random wafer shape: (1, 52, 52, 3)
True defect pattern: Loc+Scratch

Predictions:
  Custom CNN:   Loc+Scratch (confidence: 99.89%)
  MobileNetV2:  Loc+Scratch (confidence: 98.48%)
  Match: ✓ (Custom CNN)
  Match: ✓ (MobileNetV2)