According to the following task is my code correct. 1.	Background and Dataset
The garment industry is one of the key examples of the industrial globalization of this modern era. There are many manual operations in this business, which requires a lot of effort. Employee performance in terms of production and delivery in clothing manufacturing enterprises is a major factor in meeting the enormous demand for textile products around the world. Hence, monitoring, evaluating, and forecasting the productivity performance of the factory work teams is highly desired by the decision-makers in the garment business.
In this study, you will use Productivity Prediction of Garment Employees dataset to classify it as satisfactory or unsatisfactory productivity.
The dataset consists of 1197 instances and 15 features. For dataset description see UCI Machine Learning Library at:
 https://archive.ics.uci.edu/dataset/597/productivity+prediction+of+garment+employees
This study consists of two parts:
•	Part 1 is about implementing and training a multilayer feedforward neural network to classify productivity data as satisfactory or unsatisfactory.
•	Part 2 is about applying computational intelligence techniques to classify the data based on various features. 
2.	Part 1 Tasks
A.	Dataset Preparation
2.1	The original class label (actual_productivity) is a continuous variable. You must first transform it to a discrete variable so that you can apply Binary Classification on it. Visualize the distribution of features and classes, normalize the data, and divide it into training and test sets.
B.	Developing ANN from Scratch
2.2	Construct a 3-layers feedforward network with X input neurons, 20 hidden neurons, and Y output neurons. You must identify the values of X and Y yourself (Hint: Lecture # 3 ANN architecture design). Identify an appropriate activation function and justify your choice.
2.3	Write a computer program using a high-level programming language of your choice (Python with NumPy or C/C++ or Java) to train and test the neural network using the Backpropagation algorithm from scratch WITHOUT using any machine learning library. 
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.impute import SimpleImputer

# Load the dataset
dataset_path =  'garments_worker_productivity.csv'
df = pd.read_csv(dataset_path)

# Define a threshold for satisfactory vs. unsatisfactory productivity
threshold_productivity = 0.75
df['productivity_class'] = (df['actual_productivity'] >= threshold_productivity).astype(int)
                            
# Visualize the distribution of actual productivity
sns.histplot(df['actual_productivity'], kde=True)
plt.title('Distribution of Actual Productivity')
plt.show()

# Visualize the binary classes distribution
sns.countplot(x='productivity_class', data=df)
plt.title('Distribution of Productivity Classes')
plt.show()

# Convert date to datetime and extract components if the ‘date’ column exists
if 'date' in df.columns:
    df['date'] = pd.to_datetime(df['date'])
    df['year'] = df['date'].dt.year
    df['month'] = df['date'].dt.month
    df['day'] = df['date'].dt.day
    df.drop('date', axis=1, inplace=True)

# One-hot encode other categorical data if they exist; adjust the column names as necessary
for cat_column in ['quarter', 'department']:
    if cat_column in df.columns:
        df = pd.get_dummies(df, columns=[cat_column], drop_first=True)

# Ensure all other pre-processing steps here, such as handling missing values or other non-numeric columns
imputer_mean = SimpleImputer(missing_values=np.nan, strategy='mean')

df['wip'] = imputer_mean.fit_transform(df[['wip']])

# Select features (excluding target variables and any non-features if those exist)
features = df.drop(['actual_productivity', 'productivity_class'], axis=1, errors='ignore')

# Normalize the features
scaler = StandardScaler()
features_normalized = scaler.fit_transform(features)

# Prepare the feature matrix (X) and target vector (y)
X = features_normalized
y = df['productivity_class'].values

# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

print(f"Training samples: {X_train.shape[0]}, Test samples: {X_test.shape[0]}")

# Activation functions
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def relu(x):
    return np.maximum(0, x)

def relu_derivative(x):
    return (x > 0).astype(x.dtype)

# Correct dimensions and initializations
n_inputs = X_train.shape[1]  # Correct number of input features
n_hidden_units = 20  # Specified number of neurons in the hidden layer
n_outputs = 1  # Specified number of output neurons for binary classification

np.random.seed(42)  # For reproducibility

# Correctly initialize weights with the corrected dimensions
weights_input_hidden = np.random.normal(0, 0.1, (n_inputs, n_hidden_units))
weights_hidden_output = np.random.normal(0, 0.1, (n_hidden_units, n_outputs))

# Correctly initialize biases for the hidden and output layer
bias_hidden = np.zeros((1, n_hidden_units))
bias_output = np.zeros((1, n_outputs))

# Forward pass function
def forward_pass(X):
    # Input to Hidden Layer
    hidden_layer_input = np.dot(X, weights_input_hidden) + bias_hidden
    hidden_layer_output = relu(hidden_layer_input)
    
    # Hidden Layer to Output Layer
    output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output
    predicted_output = sigmoid(output_layer_input)
    
    return predicted_output, hidden_layer_output

# Example usage: Predicted output for the first 2 samples in the training dataset
predicted_output, hidden_layer_output = forward_pass(X_train[:2])

print("Predicted output (first 2 samples):", predicted_output)


# Sigmoid activation function and its derivative
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return x * (1 - x)

# Input datasets
inputs = np.array([[0,0],[0,1],[1,0],[1,1]])
expected_output = np.array([[0],[1],[1],[0]])

# Hyperparameters
epochs = 10000
learning_rate = 0.1
inputLayerNeurons, hiddenLayerNeurons, outputLayerNeurons = 2, 2, 1

# Random weights and bias initialization
hidden_weights = np.random.uniform(size=(inputLayerNeurons, hiddenLayerNeurons))
hidden_bias = np.random.uniform(size=(1, hiddenLayerNeurons))
output_weights = np.random.uniform(size=(hiddenLayerNeurons, outputLayerNeurons))
output_bias = np.random.uniform(size=(1, outputLayerNeurons))

# Training algorithm
for _ in range(epochs):
    # Forward Propagation
    hidden_layer_activation = np.dot(inputs, hidden_weights)
    hidden_layer_activation += hidden_bias
    hidden_layer_output = sigmoid(hidden_layer_activation)

    output_layer_activation = np.dot(hidden_layer_output, output_weights)
    output_layer_activation += output_bias
    predicted_output = sigmoid(output_layer_activation)

    # Backpropagation
    error = expected_output - predicted_output
    d_predicted_output = error * sigmoid_derivative(predicted_output)
    
    error_hidden_layer = d_predicted_output.dot(output_weights.T)
    d_hidden_layer = error_hidden_layer * sigmoid_derivative(hidden_layer_output)

    # Updating Weights and Biases
    output_weights += hidden_layer_output.T.dot(d_predicted_output) * learning_rate
    output_bias += np.sum(d_predicted_output,axis=0,keepdims=True) * learning_rate
    hidden_weights += inputs.T.dot(d_hidden_layer) * learning_rate
    hidden_bias += np.sum(d_hidden_layer,axis=0,keepdims=True) * learning_rate

# Displaying results after training
print("Final hidden weights: ", hidden_weights)
print("Final hidden bias: ", hidden_bias)
print("Final output weights: ", output_weights)
print("Final output bias: ", output_bias)
print("\nOutput from neural network after 10,000 epochs: ", predicted_output)