import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.metrics import accuracy_score
n_epoches = 1000
batch_size = 32
learning_rate = 0.1
X, y = load_breast_cancer(return_X_y=True)
poly = PolynomialFeatures(include_bias=False, degree=3, interaction_only=True)
X = poly.fit_transform(X)
scaler = StandardScaler()
X = scaler.fit_transform(X)
X = np.c_[np.ones(X.shape[0]), X]
y = y.reshape(-1, 1)
m, n = X.shape
theta = np.random.randn(n, 1)
best_loss = float('inf')
def sigmoid(z):
z = np.clip(z, -500, 500)
return 1 / (1 + np.exp(-z))
def compute_loss(theta, X, y):
y_hat = sigmoid(X @ theta)
epsilon = 1e-15
return -np.mean(y * np.log(y_hat + epsilon) + (1 - y) * np.log(1 - y_hat + epsilon))
for epoch in range(n_epoches):
indices = np.random.permutation(m)
X_shuffled = X[indices]
y_shuffled = y[indices]
for i in range(0, m, batch_size):
X_batch = X_shuffled[i:i + batch_size]
y_batch = y_shuffled[i:i + batch_size]
y_hat = sigmoid(X_batch @ theta)
gradient = X_batch.T @ (y_hat - y_batch) / batch_size
theta -= learning_rate * gradient
current_loss = compute_loss(theta, X, y)
learning_rate *= 0.995
if epoch > 10 and abs(best_loss - current_loss) < 1e-6:
break
if current_loss < best_loss:
best_loss = current_loss
if epoch % 50 == 0:
print(f"Epoch {epoch}: loss = {current_loss:.6f}")
y_pred = (sigmoid(X @ theta) > 0.5).astype(int)
accuracy = accuracy_score(y, y_pred)
print(f"\nFinal Accuracy:, {accuracy:.4f}")
print(f"Final Loss:, {best_loss:.4f}")