import numpy as np
import seaborn as sns
import pandas as pd
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt

# Load the dataset
csv_file_path = "garments_worker_productivity.csv"
df = pd.read_csv(csv_file_path)

# Inspect the distribution
print(df["actual_productivity"].describe())

#### Transform actual_productivity

# Transform ‘actual_productivity’ to a binary variable
threshold = 0.5
df["productivity_class"] = (df["actual_productivity"] >= threshold).astype(int)

# Check the transformation
print(df["productivity_class"].value_counts())

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

#### Normalize Features (Excluding the Target Variable)

# Define features and target
X = df.drop(["actual_productivity", "productivity_class"], axis=1)
y = df["productivity_class"]

# Convert categorical variables into dummies
X = pd.get_dummies(X)

# 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=42)

# Normalize - Fit StandardScaler on X_train and transform both X_train and X_test 
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# If needed, visualize the normalized training data (optional)
print(pd.DataFrame(X_train_scaled, columns=X_train.columns).head())

# Confirm the splitting
print(f"Training Set Size: {len(X_train)}")
print(f"Test Set Size: {len(X_test)}")
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

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

class NeuralNetwork:
    def init(self, x, y, hidden_neurons=20):
        self.input = x
        self.weights1 = np.random.rand(self.input.shape[1], hidden_neurons) * 0.01
        self.weights2 = np.random.rand(hidden_neurons, 1) * 0.01
        self.y = y
        self.output = np.zeros(y.shape)

    def feedforward(self):
        self.layer1 = sigmoid(np.dot(self.input, self.weights1))
        self.output = sigmoid(np.dot(self.layer1, self.weights2))

    def backprop(self):
        error = self.y - self.output
        d_weights2 = np.dot(self.layer1.T, (2 * error * sigmoid_derivative(self.output)))
        d_weights1 = np.dot(self.input.T,  (np.dot(2 * error * sigmoid_derivative(self.output), self.weights2.T) * sigmoid_derivative(self.layer1)))

        self.weights1 += d_weights1
        self.weights2 += d_weights2

    def train(self, epochs=1000):
        for epoch in range(epochs):
            self.feedforward()
            self.backprop()

    def predict(self, X):
        self.input = X
        self.feedforward()
        return self.output

# Function to create and train the network
def create_and_train_nn(X_train, y_train, hidden_neurons, epochs=1000):
    nn = NeuralNetwork(X_train, y_train[:, np.newaxis], hidden_neurons=hidden_neurons)
    nn.train(epochs)
    return nn

# Function to evaluate network performance
def evaluate_nn(nn, X_test, y_test):
    predictions = (nn.predict(X_test) > 0.5).astype(int)
    accuracy = accuracy_score(y_test, predictions)
    confusion_mat = confusion_matrix(y_test, predictions)
    classification_rep = classification_report(y_test, predictions)
    return accuracy, confusion_mat, classification_rep

# Initialize network configurations
hidden_neurons_configs = [10, 20, 30]
results = {}

for neurons in hidden_neurons_configs:
    nn = create_and_train_nn(X_train_scaled, y_train, hidden_neurons=neurons, epochs=1500)
    accuracy, confusion_mat, class_report = evaluate_nn(nn, X_test_scaled, y_test)
    results[neurons] = {
        "Neural Network": nn,
        "Accuracy": accuracy,
        "Confusion Matrix": confusion_mat,
        "Classification Report": class_report
    }

# Print results for each configuration
for config, result in results.items():
    print(f"Results for {config} Hidden Neurons:")
    print("Accuracy:", result["Accuracy"])
    print("Confusion Matrix:\n", result["Confusion Matrix"])
    print("Classification Report:\n", result["Classification Report"])
    print()

can you fix errors in this code please