Classification Binary¶
In [1]:
Copied!
# Uncomment the next line and run this cell to install sorix
#!pip install 'sorix @ git+https://github.com/Mitchell-Mirano/sorix.git@main'
# Uncomment the next line and run this cell to install sorix
#!pip install 'sorix @ git+https://github.com/Mitchell-Mirano/sorix.git@main'
In [2]:
Copied!
import joblib
import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sorix
from sorix.nn import ReLU,Linear,Sigmoid
from sorix.optim import SGDMomentum,RMSprop,Adam,SGD
from sorix import tensor,Tensor
from sorix.nn import Module
from sorix.nn import BCEWithLogitsLoss
from sorix.metrics import confusion_matrix,classification_report
from sorix.model_selection import train_test_split
import joblib
import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sorix
from sorix.nn import ReLU,Linear,Sigmoid
from sorix.optim import SGDMomentum,RMSprop,Adam,SGD
from sorix import tensor,Tensor
from sorix.nn import Module
from sorix.nn import BCEWithLogitsLoss
from sorix.metrics import confusion_matrix,classification_report
from sorix.model_selection import train_test_split
In [3]:
Copied!
device = 'cuda' if sorix.cuda.is_available() else 'cpu'
device
device = 'cuda' if sorix.cuda.is_available() else 'cpu'
device
✅ GPU basic operation passed ✅ GPU available: NVIDIA GeForce RTX 4070 Laptop GPU CUDA runtime version: 13000 CuPy version: 13.6.0
Out[3]:
'cuda'
Datos¶
In [4]:
Copied!
r1 = 0.5
r2 = 1.5
num_points = 10000
thetas = np.linspace(0, 2 * np.pi, num_points)
x1 = r1 * np.cos(thetas) + 0.1 * np.random.randn(num_points)
y1 = r1 * np.sin(thetas) + 0.1 * np.random.randn(num_points)
x2 = r2 * np.cos(thetas) + 0.1 * np.random.randn(num_points)
y2 = r2 * np.sin(thetas) + 0.1 * np.random.randn(num_points)
plt.figure(figsize=(8, 7))
plt.scatter(x1, y1, s=50, label="Clase A", alpha=0.8) # Puntos de la Clase A
plt.scatter(x2, y2, s=50, label="Clase B", alpha=0.8) # Puntos de la Clase B
plt.xlabel("Característica X")
plt.ylabel("Característica Y")
plt.title("Dataset de Círculos con 3 Clases")
plt.legend()
plt.grid(True, linestyle='--', alpha=0.6)
plt.axis('equal')
plt.show()
r1 = 0.5
r2 = 1.5
num_points = 10000
thetas = np.linspace(0, 2 * np.pi, num_points)
x1 = r1 * np.cos(thetas) + 0.1 * np.random.randn(num_points)
y1 = r1 * np.sin(thetas) + 0.1 * np.random.randn(num_points)
x2 = r2 * np.cos(thetas) + 0.1 * np.random.randn(num_points)
y2 = r2 * np.sin(thetas) + 0.1 * np.random.randn(num_points)
plt.figure(figsize=(8, 7))
plt.scatter(x1, y1, s=50, label="Clase A", alpha=0.8) # Puntos de la Clase A
plt.scatter(x2, y2, s=50, label="Clase B", alpha=0.8) # Puntos de la Clase B
plt.xlabel("Característica X")
plt.ylabel("Característica Y")
plt.title("Dataset de Círculos con 3 Clases")
plt.legend()
plt.grid(True, linestyle='--', alpha=0.6)
plt.axis('equal')
plt.show()
In [5]:
Copied!
df = pd.DataFrame(
{"x": x1.tolist()+x2.tolist(),
"y": y1.tolist()+ y2.tolist(),
"labels":['A' for _ in range(num_points)]+['B' for _ in range(num_points)]
})
labels = df["labels"].unique()
labels2id = {label: i for i, label in enumerate(labels)}
id2labels = {v: k for k, v in labels2id.items()}
df["labels"] = df["labels"].map(labels2id)
df.head()
df = pd.DataFrame(
{"x": x1.tolist()+x2.tolist(),
"y": y1.tolist()+ y2.tolist(),
"labels":['A' for _ in range(num_points)]+['B' for _ in range(num_points)]
})
labels = df["labels"].unique()
labels2id = {label: i for i, label in enumerate(labels)}
id2labels = {v: k for k, v in labels2id.items()}
df["labels"] = df["labels"].map(labels2id)
df.head()
Out[5]:
| x | y | labels | |
|---|---|---|---|
| 0 | 0.569368 | -0.010504 | 0 |
| 1 | 0.505318 | -0.098828 | 0 |
| 2 | 0.576423 | 0.041205 | 0 |
| 3 | 0.475242 | 0.000298 | 0 |
| 4 | 0.377815 | 0.049446 | 0 |
In [6]:
Copied!
df_train, df_test = train_test_split(df, test_size=0.2, random_state=42)
X_train = tensor(df_train[["x","y"]].values).to(device)
Y_train = tensor(df_train[["labels"]].values).to(device)
X_test = tensor(df_test[["x","y"]].values).to(device)
Y_test = tensor(df_test[["labels"]].values).to(device)
print(f"X_train shape: {X_train.shape}, device: {X_train.device}")
print(f"Y_train shape: {Y_train.shape}, device: {Y_train.device}")
print(f"X_test shape: {X_test.shape}, device: {X_test.device}")
print(f"Y_test shape: {Y_test.shape}, device: {Y_test.device}")
df_train, df_test = train_test_split(df, test_size=0.2, random_state=42)
X_train = tensor(df_train[["x","y"]].values).to(device)
Y_train = tensor(df_train[["labels"]].values).to(device)
X_test = tensor(df_test[["x","y"]].values).to(device)
Y_test = tensor(df_test[["labels"]].values).to(device)
print(f"X_train shape: {X_train.shape}, device: {X_train.device}")
print(f"Y_train shape: {Y_train.shape}, device: {Y_train.device}")
print(f"X_test shape: {X_test.shape}, device: {X_test.device}")
print(f"Y_test shape: {Y_test.shape}, device: {Y_test.device}")
X_train shape: sorix.Size([16000, 2]), device: cuda:0 Y_train shape: sorix.Size([16000, 1]), device: cuda:0 X_test shape: sorix.Size([4000, 2]), device: cuda:0 Y_test shape: sorix.Size([4000, 1]), device: cuda:0
In [7]:
Copied!
class Network(Module):
def __init__(self):
super().__init__()
self.fc1 = Linear(2, 4)
self.relu = ReLU()
self.fc2 = Linear(4, 1)
def forward(self, x: tensor) -> Tensor:
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
net = Network().to(device)
net.parameters()
class Network(Module):
def __init__(self):
super().__init__()
self.fc1 = Linear(2, 4)
self.relu = ReLU()
self.fc2 = Linear(4, 1)
def forward(self, x: tensor) -> Tensor:
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
net = Network().to(device)
net.parameters()
Out[7]:
[tensor([[-0.17466629, -1.1154755 , -0.40821883, -0.16068657],
[-1.3185993 , 1.0869352 , 0.5690863 , -1.0485913 ]], device='cuda:0', requires_grad=True),
tensor([[0., 0., 0., 0.]], device='cuda:0', requires_grad=True),
tensor([[-1.2580953 ],
[ 0.507598 ],
[-1.1620189 ],
[ 0.05934924]], device='cuda:0', requires_grad=True),
tensor([[0.]], device='cuda:0', requires_grad=True)]
In [8]:
Copied!
criterion = BCEWithLogitsLoss()
optimizer = RMSprop(net.parameters(), lr=1e-2)
criterion = BCEWithLogitsLoss()
optimizer = RMSprop(net.parameters(), lr=1e-2)
In [9]:
Copied!
logits = net(X_train)
logits
logits = net(X_train)
logits
Out[9]:
tensor([[ 0. ],
[-0.04924323],
[-0.26874777],
...,
[ 0. ],
[-2.39560962],
[-0.08795738]], device='cuda:0', dtype=sorix.float64, requires_grad=True)
Training¶
In [10]:
Copied!
# Bucle de entrenamiento mejorado
for epoch in range(1000 + 1):
logits = net(X_train)
loss = criterion(logits, Y_train)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
probs = sorix.sigmoid(logits)
preds = (probs > 0.5).astype('uint8')
acc_train = (preds == Y_train).mean()
with sorix.no_grad():
logits = net(X_test)
probs = sorix.sigmoid(logits)
preds = (probs > 0.5).astype('uint8')
acc_test = (preds == Y_test).mean()
# Usamos una f-string para formatear y alinear la salida
print(f"[{device}] Epoch {epoch:5d} | Loss: {loss.item():.4f} | Acc Train: {acc_train.item()*100:.2f}% | Acc Test: {acc_test.item()*100:.2f}%")
if acc_test.item() > 0.98:
break
# Bucle de entrenamiento mejorado
for epoch in range(1000 + 1):
logits = net(X_train)
loss = criterion(logits, Y_train)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
probs = sorix.sigmoid(logits)
preds = (probs > 0.5).astype('uint8')
acc_train = (preds == Y_train).mean()
with sorix.no_grad():
logits = net(X_test)
probs = sorix.sigmoid(logits)
preds = (probs > 0.5).astype('uint8')
acc_test = (preds == Y_test).mean()
# Usamos una f-string para formatear y alinear la salida
print(f"[{device}] Epoch {epoch:5d} | Loss: {loss.item():.4f} | Acc Train: {acc_train.item()*100:.2f}% | Acc Test: {acc_test.item()*100:.2f}%")
if acc_test.item() > 0.98:
break
[cuda] Epoch 0 | Loss: 0.9076 | Acc Train: 50.42% | Acc Test: 45.67% [cuda] Epoch 10 | Loss: 0.5728 | Acc Train: 81.23% | Acc Test: 82.30% [cuda] Epoch 20 | Loss: 0.4563 | Acc Train: 86.44% | Acc Test: 85.08% [cuda] Epoch 30 | Loss: 0.3810 | Acc Train: 86.71% | Acc Test: 85.28% [cuda] Epoch 40 | Loss: 0.3274 | Acc Train: 86.63% | Acc Test: 85.32% [cuda] Epoch 50 | Loss: 0.2847 | Acc Train: 96.57% | Acc Test: 96.95% [cuda] Epoch 60 | Loss: 0.2492 | Acc Train: 97.72% | Acc Test: 97.92% [cuda] Epoch 70 | Loss: 0.2193 | Acc Train: 98.47% | Acc Test: 98.52%
Prediction¶
In [11]:
Copied!
with sorix.no_grad():
logits = net(X_test)
probs = sorix.sigmoid(logits)
preds = (probs > 0.5).astype('uint8')
acc_test = (preds == Y_test).mean()
y_pred_labels = [id2labels[y.item()] for y in preds]
df_test['pred_labels'] = y_pred_labels
for label in df_test['pred_labels'].unique():
x = df_test[df_test['pred_labels'] == label]['x']
y = df_test[df_test['pred_labels'] == label]['y']
plt.scatter(x,y,s=50,label=label)
plt.title(f"Circles Tetst Dataset: Accuracy: {100*acc_test.item():.2f}%")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
with sorix.no_grad():
logits = net(X_test)
probs = sorix.sigmoid(logits)
preds = (probs > 0.5).astype('uint8')
acc_test = (preds == Y_test).mean()
y_pred_labels = [id2labels[y.item()] for y in preds]
df_test['pred_labels'] = y_pred_labels
for label in df_test['pred_labels'].unique():
x = df_test[df_test['pred_labels'] == label]['x']
y = df_test[df_test['pred_labels'] == label]['y']
plt.scatter(x,y,s=50,label=label)
plt.title(f"Circles Tetst Dataset: Accuracy: {100*acc_test.item():.2f}%")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
Out[11]:
<matplotlib.legend.Legend at 0x7fc00e9ba350>
In [12]:
Copied!
sns.heatmap(confusion_matrix(Y_test, preds), annot=True, cmap="Blues", fmt=".0f")
sns.heatmap(confusion_matrix(Y_test, preds), annot=True, cmap="Blues", fmt=".0f")
Out[12]:
<Axes: >
In [13]:
Copied!
print(classification_report(Y_test, preds))
print(classification_report(Y_test, preds))
precision recall f1-score support 0 0.97 1.00 0.99 1956 1 1.00 0.97 0.99 2044 accuracy 0.99 4000 macro avg 0.99 0.99 0.99 4000 weighted avg 0.99 0.99 0.99 4000
Save and Load Model¶
In [14]:
Copied!
sorix.save(net.state_dict(),"model_weights.sor")
sorix.save(net.state_dict(),"model_weights.sor")
CPU¶
In [15]:
Copied!
net2 = Network()
net2.load_state_dict(sorix.load("model_weights.sor"))
if X_test.device == 'cpu':
with sorix.no_grad():
out = net2(X_test)
if X_test.device == 'cuda':
with sorix.no_grad():
out = net2(X_test.to('cpu'))
out
net2 = Network()
net2.load_state_dict(sorix.load("model_weights.sor"))
if X_test.device == 'cpu':
with sorix.no_grad():
out = net2(X_test)
if X_test.device == 'cuda':
with sorix.no_grad():
out = net2(X_test.to('cpu'))
out
Out[15]:
tensor([[-1.69789311],
[ 0.39547288],
[-2.11016996],
...,
[-2.38632162],
[-1.58028176],
[ 1.35286509]], dtype=sorix.float64)
GPU¶
In [16]:
Copied!
net2 = Network()
net2.load_state_dict(sorix.load("model_weights.sor"))
net2.to('cuda')
if X_test.device == 'cpu':
with sorix.no_grad():
out = net2(X_test.to('cuda'))
if X_test.device == 'cuda':
with sorix.no_grad():
out = net2(X_test)
out
net2 = Network()
net2.load_state_dict(sorix.load("model_weights.sor"))
net2.to('cuda')
if X_test.device == 'cpu':
with sorix.no_grad():
out = net2(X_test.to('cuda'))
if X_test.device == 'cuda':
with sorix.no_grad():
out = net2(X_test)
out
Out[16]:
tensor([[-1.69789311],
[ 0.39547288],
[-2.11016996],
...,
[-2.38632162],
[-1.58028176],
[ 1.35286509]], device='cuda:0', dtype=sorix.float64)