Iris Dataset¶
InĀ [1]:
Copied!
# Uncomment the following line to install GPU version with Cupy backend
#!pip install 'sorix @ git+https://github.com/Mitchell-Mirano/sorix.git@main'
# Uncomment the following line to install GPU version with Cupy backend
#!pip install 'sorix @ git+https://github.com/Mitchell-Mirano/sorix.git@main'
InĀ [2]:
Copied!
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from typing import Union
import sorix
from sorix.model_selection import train_test_split
from sorix.preprocessing import StandardScaler,MinMaxScaler,RobustScaler
from sorix.nn import Module
from sorix import tensor,Tensor
from sorix.nn import CrossEntropyLoss
from sorix.metrics import accuracy_score
from sorix.optim import RMSprop
from sorix.nn import Linear,ReLU
from sorix.metrics import confusion_matrix, classification_report
import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from typing import Union
import sorix
from sorix.model_selection import train_test_split
from sorix.preprocessing import StandardScaler,MinMaxScaler,RobustScaler
from sorix.nn import Module
from sorix import tensor,Tensor
from sorix.nn import CrossEntropyLoss
from sorix.metrics import accuracy_score
from sorix.optim import RMSprop
from sorix.nn import Linear,ReLU
from sorix.metrics import confusion_matrix, classification_report
import seaborn as sns
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'
InĀ [4]:
Copied!
df = pd.read_csv("../data/Iris.csv")
df.head()
df = pd.read_csv("../data/Iris.csv")
df.head()
Out[4]:
| Id | SepalLengthCm | SepalWidthCm | PetalLengthCm | PetalWidthCm | Species | |
|---|---|---|---|---|---|---|
| 0 | 1 | 5.1 | 3.5 | 1.4 | 0.2 | Iris-setosa |
| 1 | 2 | 4.9 | 3.0 | 1.4 | 0.2 | Iris-setosa |
| 2 | 3 | 4.7 | 3.2 | 1.3 | 0.2 | Iris-setosa |
| 3 | 4 | 4.6 | 3.1 | 1.5 | 0.2 | Iris-setosa |
| 4 | 5 | 5.0 | 3.6 | 1.4 | 0.2 | Iris-setosa |
InĀ [5]:
Copied!
labels = df["Species"].unique()
labels2id = {label: i for i, label in enumerate(labels)}
id2labels = {i: label for i, label in enumerate(labels)}
labels = df["Species"].unique()
labels2id = {label: i for i, label in enumerate(labels)}
id2labels = {i: label for i, label in enumerate(labels)}
InĀ [6]:
Copied!
df['labels'] = df['Species'].map(labels2id)
df.head()
df['labels'] = df['Species'].map(labels2id)
df.head()
Out[6]:
| Id | SepalLengthCm | SepalWidthCm | PetalLengthCm | PetalWidthCm | Species | labels | |
|---|---|---|---|---|---|---|---|
| 0 | 1 | 5.1 | 3.5 | 1.4 | 0.2 | Iris-setosa | 0 |
| 1 | 2 | 4.9 | 3.0 | 1.4 | 0.2 | Iris-setosa | 0 |
| 2 | 3 | 4.7 | 3.2 | 1.3 | 0.2 | Iris-setosa | 0 |
| 3 | 4 | 4.6 | 3.1 | 1.5 | 0.2 | Iris-setosa | 0 |
| 4 | 5 | 5.0 | 3.6 | 1.4 | 0.2 | Iris-setosa | 0 |
InĀ [7]:
Copied!
df_train, df_test = train_test_split(df, test_size=0.2, random_state=42)
df_train, df_test = train_test_split(df, test_size=0.2, random_state=42)
InĀ [8]:
Copied!
features = ["SepalLengthCm", "SepalWidthCm", "PetalLengthCm", "PetalWidthCm"]
labels = ["labels"]
X_train = df_train[features]
y_train = df_train[labels]
X_test = df_test[features]
y_test = df_test[labels]
features = ["SepalLengthCm", "SepalWidthCm", "PetalLengthCm", "PetalWidthCm"]
labels = ["labels"]
X_train = df_train[features]
y_train = df_train[labels]
X_test = df_test[features]
y_test = df_test[labels]
InĀ [9]:
Copied!
plt.scatter(X_train['SepalLengthCm'], X_train['SepalWidthCm'], c=y_train['labels'])
plt.scatter(X_train['SepalLengthCm'], X_train['SepalWidthCm'], c=y_train['labels'])
Out[9]:
<matplotlib.collections.PathCollection at 0x7f56b2b8c2f0>
InĀ [10]:
Copied!
scaler = StandardScaler()
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
scaler = StandardScaler()
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
InĀ [11]:
Copied!
X_train_scaled.shape, y_train.shape, X_test_scaled.shape, y_test.shape
X_train_scaled.shape, y_train.shape, X_test_scaled.shape, y_test.shape
Out[11]:
((120, 4), (120, 1), (30, 4), (30, 1))
InĀ [12]:
Copied!
X_train_tensor = tensor(X_train_scaled).to(device)
Y_train_tensor = tensor(y_train).to(device)
X_test_tensor = tensor(X_test_scaled).to(device)
Y_test_tensor = tensor(y_test).to(device)
print(f"X_train shape: {X_train_tensor.shape}, device: {X_train_tensor.device}")
print(f"Y_train shape: {Y_train_tensor.shape}, device: {Y_train_tensor.device}")
print(f"X_test shape: {X_test_tensor.shape}, device: {X_test_tensor.device}")
print(f"Y_test shape: {Y_test_tensor.shape}, device: {Y_test_tensor.device}")
X_train_tensor = tensor(X_train_scaled).to(device)
Y_train_tensor = tensor(y_train).to(device)
X_test_tensor = tensor(X_test_scaled).to(device)
Y_test_tensor = tensor(y_test).to(device)
print(f"X_train shape: {X_train_tensor.shape}, device: {X_train_tensor.device}")
print(f"Y_train shape: {Y_train_tensor.shape}, device: {Y_train_tensor.device}")
print(f"X_test shape: {X_test_tensor.shape}, device: {X_test_tensor.device}")
print(f"Y_test shape: {Y_test_tensor.shape}, device: {Y_test_tensor.device}")
X_train shape: sorix.Size([120, 4]), device: cuda:0 Y_train shape: sorix.Size([120, 1]), device: cuda:0 X_test shape: sorix.Size([30, 4]), device: cuda:0 Y_test shape: sorix.Size([30, 1]), device: cuda:0
InĀ [13]:
Copied!
class Net(Module):
def __init__(self):
super().__init__()
self.fc1 = Linear(4, 8)
self.fc2 = Linear(8, 4)
self.fc3 = Linear(4, 3)
self.relu = ReLU()
def forward(self, x: tensor) -> Tensor:
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
return x
net = Net().to(device)
criterion = CrossEntropyLoss()
optimizer = RMSprop(net.parameters(), lr=1e-2)
class Net(Module):
def __init__(self):
super().__init__()
self.fc1 = Linear(4, 8)
self.fc2 = Linear(8, 4)
self.fc3 = Linear(4, 3)
self.relu = ReLU()
def forward(self, x: tensor) -> Tensor:
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
return x
net = Net().to(device)
criterion = CrossEntropyLoss()
optimizer = RMSprop(net.parameters(), lr=1e-2)
InĀ [14]:
Copied!
logits = net(X_train_tensor)
logits
logits = net(X_train_tensor)
logits
Out[14]:
tensor([[ 3.18380770e-02, 5.91685631e-02, -7.86396504e-03],
[ 3.13370197e+00, 5.74086691e+00, -7.45613334e-01],
[-6.27524252e-02, -1.36923843e+00, 1.58636662e+00],
[ 3.68812375e-03, -3.08446122e-01, 4.18230142e-01],
[-2.65776979e-02, -2.79022078e-01, 2.54321886e-01],
[ 2.34201072e+00, 4.24755254e+00, -5.85250038e-01],
[ 8.82216808e-03, 2.42461865e-03, 1.40565934e-02],
[ 8.13916013e-02, -1.05761437e+00, 1.66882102e+00],
[-2.64715199e-02, -1.49514641e-01, 9.24898444e-02],
[-5.54242181e-04, -1.86377704e-02, -4.84749159e-02],
[ 3.60032830e-02, -8.28358602e-01, 1.21232245e+00],
[ 2.06400820e+00, 3.68548434e+00, -5.50437986e-01],
[ 2.88001819e+00, 5.23662302e+00, -7.55856685e-01],
[ 2.21337046e+00, 3.97225913e+00, -5.78986114e-01],
[ 3.18288505e+00, 5.80945838e+00, -6.86235603e-01],
[ 1.45123381e-02, -5.24926676e-01, 7.39887747e-01],
[ 2.46062169e-02, -1.00287913e+00, 1.40291056e+00],
[-5.21423812e-02, -1.27879173e-01, -4.72920072e-02],
[-5.65749397e-03, -3.95742734e-02, 3.27227844e-02],
[ 2.88399195e-02, -9.18760118e-01, 1.30674497e+00],
[ 2.19221991e+00, 3.93667524e+00, -5.17301622e-01],
[ 8.97614835e-03, -5.72666380e-01, 7.83763085e-01],
[ 2.29760228e+00, 4.15590958e+00, -5.26909164e-01],
[ 2.39446310e-02, -8.61873039e-01, 1.21521530e+00],
[-3.89442505e-02, -1.43634853e+00, 1.75593019e+00],
[ 6.55337450e-02, -1.01456623e+00, 1.55805238e+00],
[-5.04178076e-02, -6.63503494e-01, 7.00384973e-01],
[ 4.32010985e-02, -1.16846247e+00, 1.68417142e+00],
[ 1.77281707e+00, 3.15398165e+00, -4.43245852e-01],
[ 2.02470363e+00, 3.62813623e+00, -4.86150842e-01],
[ 3.13682903e+00, 5.67645254e+00, -7.30882150e-01],
[ 4.04362152e+00, 7.43207193e+00, -7.80373135e-01],
[-5.05755007e-02, -4.29726041e-01, 3.92407766e-01],
[ 2.54596961e+00, 4.60337048e+00, -5.74363675e-01],
[ 2.30134087e+00, 4.11463922e+00, -5.71982983e-01],
[ 2.10389747e-02, -6.10826781e-01, 8.75143434e-01],
[-9.43018398e-04, -4.67122438e-01, 6.11088082e-01],
[ 2.78381905e+00, 5.05903683e+00, -6.53340586e-01],
[ 2.97422700e+00, 5.40743424e+00, -6.47728008e-01],
[ 3.95251834e+00, 7.24417637e+00, -8.03992697e-01],
[-8.61208329e-03, -5.44252653e-01, 6.86330607e-01],
[-1.79378373e-03, -4.57687607e-01, 5.95774957e-01],
[-3.87303344e-02, -5.21625127e-01, 5.53716051e-01],
[ 3.30825152e+00, 6.05562187e+00, -7.02709854e-01],
[ 3.14721013e+00, 5.74610699e+00, -7.31635734e-01],
[-9.77670537e-02, -2.30847597e-01, -8.92878186e-02],
[-3.39432586e-02, -3.70475437e-01, 3.71288841e-01],
[ 6.65223663e-03, -7.32668999e-01, 9.86244692e-01],
[-4.89626813e-02, -3.82594034e-01, 3.35932843e-01],
[ 6.60773547e-02, -1.46109646e+00, 2.14713684e+00],
[-1.15041971e-02, -8.57852344e-02, 7.35272471e-02],
[-5.57455970e-02, -1.26605881e+00, 1.47460515e+00],
[-2.70143290e-02, -2.49851595e-01, 2.36320584e-01],
[ 2.80564147e+00, 5.09444191e+00, -6.36834297e-01],
[-9.94160128e-02, -1.16481896e+00, 1.19232601e+00],
[ 8.81469045e-02, 1.41017470e-01, -8.47095075e-02],
[ 2.64496766e+00, 4.79361724e+00, -6.51898193e-01],
[ 2.70862079e+00, 4.91054523e+00, -6.09610678e-01],
[ 2.91926941e+00, 5.33392086e+00, -6.28574545e-01],
[-5.69323871e-02, -1.83996163e-01, -4.85782950e-02],
[ 1.91095232e-02, -5.71609068e-01, 8.16979266e-01],
[ 2.44987675e+00, 4.43411215e+00, -5.48691117e-01],
[ 1.87454068e+00, 3.34866676e+00, -5.28320474e-01],
[ 1.95499250e+00, 3.52732934e+00, -4.56857253e-01],
[-1.39832846e-02, -3.81138219e-02, -1.24192564e-02],
[ 2.60212352e+00, 4.71550175e+00, -6.14193012e-01],
[-1.74164042e-03, -3.97214924e-03, -1.60025383e-03],
[ 8.84677919e-03, -1.56237158e+00, 2.08487385e+00],
[ 2.25639293e+00, 4.04456673e+00, -5.41551958e-01],
[-2.13781899e-02, -1.49540828e-01, 1.23650843e-01],
[ 1.83769871e-02, -4.92952115e-01, 7.11036506e-01],
[ 4.01361073e+00, 7.36482486e+00, -8.13147441e-01],
[ 5.43918374e-03, -5.39444581e-01, 7.27994249e-01],
[-8.61208329e-03, -5.44252653e-01, 6.86330607e-01],
[ 1.84389463e-01, 2.88705400e-01, -1.94539596e-01],
[-2.61323801e-02, -1.82796475e-01, 1.51148944e-01],
[ 1.42086436e-02, -1.02002889e+00, 1.38995515e+00],
[ 1.62906834e-02, -5.67155660e-05, 1.75329364e-02],
[ 3.15816858e+00, 5.78813885e+00, -6.55640220e-01],
[-7.37799912e-02, -2.10869806e-01, -6.48543265e-02],
[ 1.97121320e-02, -6.98977705e-01, 9.86538615e-01],
[ 2.45276126e+00, 4.42872696e+00, -5.85644883e-01],
[ 2.34624314e+00, 4.22006766e+00, -5.94801937e-01],
[-4.58528401e-02, -1.23924859e-01, -4.07969126e-02],
[-1.55761148e-02, -6.71523850e-01, 8.29920866e-01],
[ 2.21337046e+00, 3.97225913e+00, -5.78986114e-01],
[ 1.37889201e-02, -8.47158929e-01, 1.16118199e+00],
[ 2.59161266e+00, 4.69414655e+00, -5.87087276e-01],
[ 2.24495156e+00, 4.06386263e+00, -5.36941918e-01],
[-5.86844805e-03, -5.57119991e-01, 7.12622161e-01],
[-5.34681391e-02, -1.62438706e-01, -4.63365464e-02],
[ 5.75974294e-02, -1.15981793e+00, 1.72196818e+00],
[-7.66682471e-03, -3.74621636e-01, 4.66478519e-01],
[-1.93847917e-02, -1.35596971e-01, 1.12121085e-01],
[-1.66016791e-02, -1.43525842e+00, 1.83079905e+00],
[ 1.07662092e-02, -2.58287947e-03, 1.17626312e-02],
[ 1.71668511e+00, 3.02509832e+00, -4.54053266e-01],
[ 2.12903590e+00, 3.77705174e+00, -5.44621435e-01],
[-1.16346873e-02, -9.66011259e-02, 8.10755029e-02],
[-4.86084197e-02, -9.53046868e-01, 1.08734018e+00],
[ 2.04438529e+00, 3.65162275e+00, -4.99071343e-01],
[ 2.66797028e+00, 4.84329065e+00, -5.88822143e-01],
[ 1.93382898e+00, 3.42756963e+00, -4.99609979e-01],
[-3.85869265e-02, -2.69916254e-01, 2.23185687e-01],
[ 1.90211079e-02, -1.12409321e+00, 1.54324434e+00],
[ 2.50570150e+00, 4.51384544e+00, -6.00848088e-01],
[ 4.05301890e-02, -9.79425855e-01, 1.42644957e+00],
[ 1.15126805e-02, -1.21833120e+00, 1.64153374e+00],
[ 2.28844858e+00, 4.10618547e+00, -5.43055515e-01],
[-1.89513001e-02, -2.51221781e-01, 2.65658676e-01],
[-4.04414381e-02, -4.00419444e-01, 3.88475909e-01],
[ 2.39035689e-02, -5.41035522e-01, 7.93144484e-01],
[-7.62890172e-02, -5.34633177e-01, 4.42555595e-01],
[ 3.62928176e-02, -1.00766438e+00, 1.44911469e+00],
[ 3.26473531e+00, 5.96281259e+00, -6.88166431e-01],
[ 4.13973561e-02, -1.01511886e+00, 1.47635059e+00],
[ 5.31529751e-03, -2.65784310e-01, 3.67682955e-01],
[ 3.65343726e-02, -8.05372287e-01, 1.18390708e+00],
[-8.60919474e-02, -2.00252294e-01, -8.98781550e-02],
[-2.30541384e-02, -6.82638008e-02, -2.01015647e-02]], device='cuda:0', dtype=sorix.float64, requires_grad=True)
InĀ [15]:
Copied!
# Bucle de entrenamiento mejorado
for epoch in range(1000 + 1):
logits = net(X_train_tensor)
loss = criterion(logits, Y_train_tensor)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
preds = sorix.argmax(logits, axis=1, keepdims=True)
acc_train = (preds== Y_train_tensor).mean()
with sorix.no_grad():
logits = net(X_test_tensor)
preds = sorix.argmax(logits, axis=1, keepdims=True)
acc_test = (preds == Y_test_tensor).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.96: # Mejoramos el criterio de parada
print(f"Entrenamiento completado en {epoch} epochs!")
break
# Bucle de entrenamiento mejorado
for epoch in range(1000 + 1):
logits = net(X_train_tensor)
loss = criterion(logits, Y_train_tensor)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
preds = sorix.argmax(logits, axis=1, keepdims=True)
acc_train = (preds== Y_train_tensor).mean()
with sorix.no_grad():
logits = net(X_test_tensor)
preds = sorix.argmax(logits, axis=1, keepdims=True)
acc_test = (preds == Y_test_tensor).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.96: # Mejoramos el criterio de parada
print(f"Entrenamiento completado en {epoch} epochs!")
break
[cuda] Epoch 0 | Loss: 1.3640 | Acc Train: 34.17% | Acc Test: 63.33% [cuda] Epoch 10 | Loss: 0.2004 | Acc Train: 93.33% | Acc Test: 96.67% Entrenamiento completado en 10 epochs!
InĀ [16]:
Copied!
with sorix.no_grad():
logits = net(X_test_tensor)
preds = sorix.argmax(logits, axis=1, keepdims=True)
with sorix.no_grad():
logits = net(X_test_tensor)
preds = sorix.argmax(logits, axis=1, keepdims=True)
InĀ [17]:
Copied!
sns.heatmap(confusion_matrix(Y_test_tensor, preds), annot=True, cmap="Blues")
sns.heatmap(confusion_matrix(Y_test_tensor, preds), annot=True, cmap="Blues")
Out[17]:
<Axes: >
InĀ [18]:
Copied!
print(classification_report(Y_test_tensor, preds))
print(classification_report(Y_test_tensor, preds))
precision recall f1-score support 0 1.00 1.00 1.00 7 1 0.92 1.00 0.96 11 2 1.00 0.92 0.96 12 accuracy 0.97 30 macro avg 0.97 0.97 0.97 30 weighted avg 0.97 0.97 0.97 30