import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from pandas import read_csv, merge
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import classification_report, confusion_matrixTo learn more about matplotlib click here
To learn more about Numpy click here
To learn more about sklearn click here
# Read in the focus/dose data with the first row (i.e., row 0) as the header
exp_data = read_csv('exposure_data.csv', header=0)
# Check for missing values
print("Total number of rows in DataFrame: " + str(exp_data.shape[0]))
print("Number of rows with missing values by column:")
print(exp_data.isnull().sum())Total number of rows in DataFrame: 1050
Number of rows with missing values by column:
Fab 0
LithoCell 0
Stage 0
Wafer 0
FieldX 0
FieldY 0
Lot 0
Date 0
Time 0
Focus 25
ExpDose 25
dtype: int64
# drop rows with missing values, printing the row counts before and after
exp_data.dropna(inplace=True)
# Check for missing values
print("Total number of rows in DataFrame: " + str(exp_data.shape[0]))
print("Number of rows with missing values by column:")
print(exp_data.isnull().sum())# Read in the inspection data
insp_data = read_csv('inspection_data.csv', header=0)
# Check for missing values
print("Total number of rows in dataframe: " + str(insp_data.shape[0]))
print("Number of rows with missing values by column:")
print(insp_data.isnull().sum())Total number of rows in dataframe: 1025
Number of rows with missing values by column:
Lot 0
Wafer 0
FieldX 0
FieldY 0
InspTool 0
Defect 25
dtype: int64
# drop rows with missing values, printing the row counts before and after
insp_data.dropna(inplace=True)
# Check for missing values
print("Total number of rows in dataframe: " + str(insp_data.shape[0]))
print("Number of rows with missing values by column:")
print(insp_data.isnull().sum())Total number of rows in dataframe: 1000
Number of rows with missing values by column:
Lot 0
Wafer 0
FieldX 0
FieldY 0
InspTool 0
Defect 0
dtype: int64
# merge data into a single DataFrame
merged_data = merge(exp_data, insp_data, how='inner', on=['Lot', 'Wafer', 'FieldX', 'FieldY'], sort=False)
# Print a few rows to see what the results look like
print(merged_data[0:5]) Fab LithoCell Stage Wafer FieldX FieldY Lot Date \
0 FAB_A LITH15 2 17 -7 -3 6V78TJ10 05/21/2017
1 FAB_A LITH06 2 2 -4 6 3JZX3ZUK 11/27/2017
2 FAB_A LITH02 2 20 7 -6 SKFPM6YR 05/16/2017
3 FAB_A LITH14 2 4 7 -1 VINI5MWO 08/10/2017
4 FAB_A LITH15 2 11 -5 -3 7SCWPT3O 09/05/2017
Time Focus ExpDose InspTool Defect
0 09:00 AM -39.736527 9.967321 INSP14C 1.0
1 07:40 PM -19.423390 9.466734 INSP14C 0.0
2 03:29 PM 77.052599 10.212761 INSP08A 1.0
3 12:14 PM -3.179968 9.748477 INSP12 0.0
4 05:53 AM -18.461324 10.645196 INSP11 0.0
data_array = merged_data.values
# Print a few rows for comparison with the DataFrame view in the previous step
print(data_array[0:4,:])
[['FAB_A' 'LITH15' 2 17 -7 -3 '6V78TJ10' '05/21/2017' '09:00 AM'
-39.73652744160897 9.967321151486813 'INSP14C' 1.0]
['FAB_A' 'LITH06' 2 2 -4 6 '3JZX3ZUK' '11/27/2017' '07:40 PM'
-19.42339018173626 9.4667337843247 'INSP14C' 0.0]
['FAB_A' 'LITH02' 2 20 7 -6 'SKFPM6YR' '05/16/2017' '03:29 PM'
77.05259896915155 10.212761264675525 'INSP08A' 1.0]
['FAB_A' 'LITH14' 2 4 7 -1 'VINI5MWO' '08/10/2017' '12:14 PM'
-3.179968221567368 9.748476954975498 'INSP12' 0.0]]
X = data_array[:,9:11].astype(float)
Y = data_array[:,12].astype(int)mask = Y.astype(bool)
a = 20*np.ones(mask.shape)
a_good = np.ma.masked_where(mask, a)
a_bad = np.ma.masked_where(np.logical_not(mask), a)
fig = plt.figure(figsize=(6,6), dpi=100)
axes = fig.add_axes([0.1, 0.1, 0.9, 0.9])
axes.scatter(X[:,0], X[:,1], s=a_good, color='green', label='No Defect')
axes.scatter(X[:,0], X[:,1], s=a_bad, color='red', label='Defect')
axes.set_xlabel('Focus [nm]')
axes.set_ylabel('Dose [mJ]')
axes.set_title('Raw Data');
axes.legend();
# Split the data into training and test sets
X_train, X_test, y_train, y_test = train_test_split(X,Y,test_size=0.2, random_state = 2018)# Create a 'StandardScaler' instance and adjust the normalization transforms to the training data
scaler = StandardScaler()
scaler.fit(X_train)
# Now apply the transformations to the the training and test sets
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)To learn more about standardScaler click here
# Define a multi-layer perceptron classifier with three hidden layers, each with 40 neurons
mlp = MLPClassifier(hidden_layer_sizes=(40,40,40), random_state = 2018)
# Fit the classifier to the training data
mlp.fit(X_train,y_train);/usr/local/lib/python3.10/dist-packages/sklearn/neural_network/_multilayer_perceptron.py:686: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (200) reached and the optimization hasn't converged yet.
warnings.warn(
predictions = mlp.predict(X_test)print(confusion_matrix(y_test,predictions))[[108 2]
[ 2 88]]
print(classification_report(y_test,predictions)) precision recall f1-score support
0 0.98 0.98 0.98 110
1 0.98 0.98 0.98 90
accuracy 0.98 200
macro avg 0.98 0.98 0.98 200
weighted avg 0.98 0.98 0.98 200