Regression¶
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 numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib
import sorix
from sorix.nn import ReLU,Linear
from sorix.optim import RMSprop
from sorix import tensor,Tensor
from sorix.nn import Module
from sorix.nn import MSELoss
from sorix.preprocessing import MinMaxScaler
from sorix.model_selection import train_test_split
from sorix.metrics import r2_score
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib
import sorix
from sorix.nn import ReLU,Linear
from sorix.optim import RMSprop
from sorix import tensor,Tensor
from sorix.nn import Module
from sorix.nn import MSELoss
from sorix.preprocessing import MinMaxScaler
from sorix.model_selection import train_test_split
from sorix.metrics import r2_score
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!
# Datos
points = 10000
x1 = np.linspace(1, 20*np.pi, points)
x2 = np.linspace(1, 20*np.pi, points)
# Definimos la salida
y = 20*np.log(x1+1) + -1*x2 + 3*np.random.randn(points)
data = pd.DataFrame({'x1': x1, 'x2': x2, 'y': y})
data.head()
plt.figure(figsize=(20,7))
plt.scatter(data['x2'], data['y'], s=20)
plt.show()
# Datos
points = 10000
x1 = np.linspace(1, 20*np.pi, points)
x2 = np.linspace(1, 20*np.pi, points)
# Definimos la salida
y = 20*np.log(x1+1) + -1*x2 + 3*np.random.randn(points)
data = pd.DataFrame({'x1': x1, 'x2': x2, 'y': y})
data.head()
plt.figure(figsize=(20,7))
plt.scatter(data['x2'], data['y'], s=20)
plt.show()
Preprocessing¶
In [5]:
Copied!
independent_variables = ['x1', 'x2']
dependent_variable = ['y']
independent_variables = ['x1', 'x2']
dependent_variable = ['y']
In [6]:
Copied!
# Train test split and normalization
df_train, df_test = train_test_split(data, test_size=0.2, random_state=42, shuffle=True)
X_train = df_train[independent_variables]
Y_train = df_train[dependent_variable]
X_test = df_test[independent_variables]
Y_test = df_test[dependent_variable]
X_train
# Train test split and normalization
df_train, df_test = train_test_split(data, test_size=0.2, random_state=42, shuffle=True)
X_train = df_train[independent_variables]
Y_train = df_train[dependent_variable]
X_test = df_test[independent_variables]
Y_test = df_test[dependent_variable]
X_train
Out[6]:
| x1 | x2 | |
|---|---|---|
| 6252 | 39.661141 | 39.661141 |
| 4684 | 29.964936 | 29.964936 |
| 1731 | 11.704164 | 11.704164 |
| 4742 | 30.323597 | 30.323597 |
| 4521 | 28.956976 | 28.956976 |
| ... | ... | ... |
| 1638 | 11.129070 | 11.129070 |
| 5891 | 37.428788 | 37.428788 |
| 7427 | 46.927110 | 46.927110 |
| 608 | 4.759753 | 4.759753 |
| 6907 | 43.711532 | 43.711532 |
8000 rows × 2 columns
In [7]:
Copied!
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
X_train
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
X_train
Out[7]:
array([[0.62526253, 0.62526253],
[0.46844684, 0.46844684],
[0.17311731, 0.17311731],
...,
[0.74277428, 0.74277428],
[0.06080608, 0.06080608],
[0.69076908, 0.69076908]], shape=(8000, 2))
In [8]:
Copied!
plt.Figure(figsize=(20,7))
plt.scatter(X_train[:,0], Y_train)
plt.show()
plt.Figure(figsize=(20,7))
plt.scatter(X_train[:,0], Y_train)
plt.show()
In [9]:
Copied!
X_train = tensor(X_train,dtype=sorix.float32,device=device)
Y_train = tensor(Y_train,dtype=sorix.float32,device=device)
X_test = tensor(X_test, dtype=sorix.float32,device=device)
Y_test = tensor(Y_test, dtype=sorix.float32,device=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 = tensor(X_train,dtype=sorix.float32,device=device)
Y_train = tensor(Y_train,dtype=sorix.float32,device=device)
X_test = tensor(X_test, dtype=sorix.float32,device=device)
Y_test = tensor(Y_test, dtype=sorix.float32,device=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([8000, 2]), device: cuda:0 Y_train shape: sorix.Size([8000, 1]). device: cuda:0 X_test shape: sorix.Size([2000, 2]), device: cuda:0 Y_test shape: sorix.Size([2000, 1]), device: cuda:0
In [10]:
Copied!
class Network(Module):
def __init__(self):
super().__init__()
self.fc1 = Linear(2, 64)
self.fc2 = Linear(64, 32)
self.fc3 = Linear(32, 1)
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 = Network()
net.to(device)
net
class Network(Module):
def __init__(self):
super().__init__()
self.fc1 = Linear(2, 64)
self.fc2 = Linear(64, 32)
self.fc3 = Linear(32, 1)
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 = Network()
net.to(device)
net
Out[10]:
Network( (fc1): Linear(in_features=2, out_features=64, bias=True) (fc2): Linear(in_features=64, out_features=32, bias=True) (fc3): Linear(in_features=32, out_features=1, bias=True) (relu): ReLU() )
In [11]:
Copied!
criterion = MSELoss()
optimizer = RMSprop(net.parameters(), lr=1e-2)
criterion = MSELoss()
optimizer = RMSprop(net.parameters(), lr=1e-2)
In [12]:
Copied!
Y_pred = net(X_train)
Y_pred
Y_pred = net(X_train)
Y_pred
Out[12]:
tensor([[0.6408244 ],
[0.48010576],
[0.17742594],
...,
[0.7612608 ],
[0.06231946],
[0.7079614 ]], device='cuda:0', requires_grad=True)
In [13]:
Copied!
# %%
# Bucle de entrenamiento mejorado
for epoch in range(1000 + 1):
Y_pred = net(X_train)
loss = criterion(Y_train,Y_pred)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
r2_train = r2_score(Y_pred, Y_train)
with sorix.no_grad():
Y_pred = net(X_test)
r2_test = r2_score(Y_test, Y_pred)
print(f"[{device}] Epoch {epoch:5d} | Loss: {loss.item():.4f} | R2_Train: {100*r2_train:5.2f} % | R2_Test: {100*r2_test:5.2f} %")
if r2_test > 0.95: # Mejoramos el criterio de parada
print(f"Entrenamiento completado en {epoch} epochs!")
break
# %%
# Bucle de entrenamiento mejorado
for epoch in range(1000 + 1):
Y_pred = net(X_train)
loss = criterion(Y_train,Y_pred)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
r2_train = r2_score(Y_pred, Y_train)
with sorix.no_grad():
Y_pred = net(X_test)
r2_test = r2_score(Y_test, Y_pred)
print(f"[{device}] Epoch {epoch:5d} | Loss: {loss.item():.4f} | R2_Train: {100*r2_train:5.2f} % | R2_Test: {100*r2_test:5.2f} %")
if r2_test > 0.95: # Mejoramos el criterio de parada
print(f"Entrenamiento completado en {epoch} epochs!")
break
[cuda] Epoch 0 | Loss: 1138.2170 | R2_Train: -1299164.94 % | R2_Test: -1290.38 % [cuda] Epoch 10 | Loss: 230.5616 | R2_Train: -193.14 % | R2_Test: -328.68 % [cuda] Epoch 20 | Loss: 144.2530 | R2_Train: -1230.48 % | R2_Test: -128.76 % [cuda] Epoch 30 | Loss: 68.2496 | R2_Train: -3519.27 % | R2_Test: -18.73 % [cuda] Epoch 40 | Loss: 38.1315 | R2_Train: -293.45 % | R2_Test: 31.66 % [cuda] Epoch 50 | Loss: 32.9292 | R2_Train: -124.56 % | R2_Test: 39.92 % [cuda] Epoch 60 | Loss: 31.2662 | R2_Train: -85.75 % | R2_Test: 43.11 % [cuda] Epoch 70 | Loss: 29.9982 | R2_Train: -65.42 % | R2_Test: 45.54 % [cuda] Epoch 80 | Loss: 29.1164 | R2_Train: -51.15 % | R2_Test: 47.27 %
[cuda] Epoch 90 | Loss: 28.3451 | R2_Train: -39.72 % | R2_Test: 48.87 % [cuda] Epoch 100 | Loss: 27.4177 | R2_Train: -29.33 % | R2_Test: 50.71 % [cuda] Epoch 110 | Loss: 26.5098 | R2_Train: -19.89 % | R2_Test: 52.44 % [cuda] Epoch 120 | Loss: 25.7088 | R2_Train: -11.50 % | R2_Test: 54.02 % [cuda] Epoch 130 | Loss: 24.8784 | R2_Train: -3.72 % | R2_Test: 55.65 % [cuda] Epoch 140 | Loss: 24.0457 | R2_Train: 3.50 % | R2_Test: 57.24 %
[cuda] Epoch 150 | Loss: 23.2410 | R2_Train: 10.08 % | R2_Test: 58.79 % [cuda] Epoch 160 | Loss: 22.4668 | R2_Train: 16.06 % | R2_Test: 60.28 % [cuda] Epoch 170 | Loss: 21.6908 | R2_Train: 21.51 % | R2_Test: 61.73 % [cuda] Epoch 180 | Loss: 20.9716 | R2_Train: 26.44 % | R2_Test: 63.02 % [cuda] Epoch 190 | Loss: 20.3757 | R2_Train: 30.61 % | R2_Test: 64.11 % [cuda] Epoch 200 | Loss: 19.8584 | R2_Train: 34.28 % | R2_Test: 64.95 % [cuda] Epoch 210 | Loss: 19.6084 | R2_Train: 36.92 % | R2_Test: 65.48 % [cuda] Epoch 220 | Loss: 19.1559 | R2_Train: 39.78 % | R2_Test: 66.30 % [cuda] Epoch 230 | Loss: 18.6410 | R2_Train: 42.66 % | R2_Test: 67.16 %
[cuda] Epoch 240 | Loss: 18.3535 | R2_Train: 44.79 % | R2_Test: 67.66 % [cuda] Epoch 250 | Loss: 18.0691 | R2_Train: 46.71 % | R2_Test: 68.22 % [cuda] Epoch 260 | Loss: 17.6551 | R2_Train: 48.88 % | R2_Test: 68.93 % [cuda] Epoch 270 | Loss: 17.2863 | R2_Train: 50.83 % | R2_Test: 69.58 % [cuda] Epoch 280 | Loss: 16.9279 | R2_Train: 52.59 % | R2_Test: 70.17 % [cuda] Epoch 290 | Loss: 16.6897 | R2_Train: 53.98 % | R2_Test: 70.53 %
[cuda] Epoch 300 | Loss: 16.5481 | R2_Train: 54.97 % | R2_Test: 70.81 % [cuda] Epoch 310 | Loss: 16.3107 | R2_Train: 56.14 % | R2_Test: 71.21 % [cuda] Epoch 320 | Loss: 16.0545 | R2_Train: 57.31 % | R2_Test: 71.63 % [cuda] Epoch 330 | Loss: 15.8544 | R2_Train: 58.31 % | R2_Test: 71.96 % [cuda] Epoch 340 | Loss: 15.6706 | R2_Train: 59.24 % | R2_Test: 72.28 % [cuda] Epoch 350 | Loss: 15.4655 | R2_Train: 60.16 % | R2_Test: 72.62 % [cuda] Epoch 360 | Loss: 15.2913 | R2_Train: 60.97 % | R2_Test: 72.93 % [cuda] Epoch 370 | Loss: 15.1512 | R2_Train: 61.65 % | R2_Test: 73.18 % [cuda] Epoch 380 | Loss: 14.9679 | R2_Train: 62.39 % | R2_Test: 73.51 % [cuda] Epoch 390 | Loss: 14.8025 | R2_Train: 63.08 % | R2_Test: 73.79 %
[cuda] Epoch 400 | Loss: 14.6873 | R2_Train: 63.61 % | R2_Test: 74.00 % [cuda] Epoch 410 | Loss: 14.5950 | R2_Train: 64.07 % | R2_Test: 74.19 % [cuda] Epoch 420 | Loss: 14.4725 | R2_Train: 64.57 % | R2_Test: 74.42 % [cuda] Epoch 430 | Loss: 14.3293 | R2_Train: 65.07 % | R2_Test: 74.66 % [cuda] Epoch 440 | Loss: 14.2447 | R2_Train: 65.44 % | R2_Test: 74.81 % [cuda] Epoch 450 | Loss: 14.1706 | R2_Train: 65.78 % | R2_Test: 74.94 %
[cuda] Epoch 460 | Loss: 14.0695 | R2_Train: 66.13 % | R2_Test: 75.11 % [cuda] Epoch 470 | Loss: 14.0022 | R2_Train: 66.44 % | R2_Test: 75.22 % [cuda] Epoch 480 | Loss: 13.9472 | R2_Train: 66.67 % | R2_Test: 75.32 % [cuda] Epoch 490 | Loss: 13.8502 | R2_Train: 66.99 % | R2_Test: 75.47 % [cuda] Epoch 500 | Loss: 13.7887 | R2_Train: 67.24 % | R2_Test: 75.57 % [cuda] Epoch 510 | Loss: 13.7137 | R2_Train: 67.49 % | R2_Test: 75.70 % [cuda] Epoch 520 | Loss: 13.6419 | R2_Train: 67.74 % | R2_Test: 75.81 % [cuda] Epoch 530 | Loss: 13.6320 | R2_Train: 67.86 % | R2_Test: 75.83 % [cuda] Epoch 540 | Loss: 13.5811 | R2_Train: 68.06 % | R2_Test: 75.93 % [cuda] Epoch 550 | Loss: 13.4861 | R2_Train: 68.35 % | R2_Test: 76.08 %
[cuda] Epoch 560 | Loss: 13.4519 | R2_Train: 68.49 % | R2_Test: 76.12 % [cuda] Epoch 570 | Loss: 13.4383 | R2_Train: 68.57 % | R2_Test: 76.15 % [cuda] Epoch 580 | Loss: 13.3743 | R2_Train: 68.77 % | R2_Test: 76.26 % [cuda] Epoch 590 | Loss: 13.3194 | R2_Train: 68.96 % | R2_Test: 76.34 % [cuda] Epoch 600 | Loss: 13.2899 | R2_Train: 69.08 % | R2_Test: 76.38 % [cuda] Epoch 610 | Loss: 13.2709 | R2_Train: 69.17 % | R2_Test: 76.42 %
[cuda] Epoch 620 | Loss: 13.2295 | R2_Train: 69.30 % | R2_Test: 76.48 % [cuda] Epoch 630 | Loss: 13.1972 | R2_Train: 69.41 % | R2_Test: 76.52 % [cuda] Epoch 640 | Loss: 13.1793 | R2_Train: 69.49 % | R2_Test: 76.55 % [cuda] Epoch 650 | Loss: 13.1401 | R2_Train: 69.61 % | R2_Test: 76.61 % [cuda] Epoch 660 | Loss: 13.1257 | R2_Train: 69.68 % | R2_Test: 76.62 % [cuda] Epoch 670 | Loss: 13.1126 | R2_Train: 69.73 % | R2_Test: 76.64 % [cuda] Epoch 680 | Loss: 13.0777 | R2_Train: 69.83 % | R2_Test: 76.68 % [cuda] Epoch 690 | Loss: 13.0393 | R2_Train: 69.94 % | R2_Test: 76.73 % [cuda] Epoch 700 | Loss: 13.0217 | R2_Train: 69.99 % | R2_Test: 76.75 % [cuda] Epoch 710 | Loss: 12.9973 | R2_Train: 70.05 % | R2_Test: 76.80 %
[cuda] Epoch 720 | Loss: 12.9261 | R2_Train: 70.22 % | R2_Test: 76.90 % [cuda] Epoch 730 | Loss: 12.9143 | R2_Train: 70.27 % | R2_Test: 76.92 % [cuda] Epoch 740 | Loss: 12.9069 | R2_Train: 70.29 % | R2_Test: 76.94 % [cuda] Epoch 750 | Loss: 12.8627 | R2_Train: 70.39 % | R2_Test: 77.01 % [cuda] Epoch 760 | Loss: 12.8309 | R2_Train: 70.48 % | R2_Test: 77.06 % [cuda] Epoch 770 | Loss: 12.8003 | R2_Train: 70.56 % | R2_Test: 77.11 % [cuda] Epoch 780 | Loss: 12.7696 | R2_Train: 70.66 % | R2_Test: 77.15 %
[cuda] Epoch 790 | Loss: 12.7614 | R2_Train: 70.70 % | R2_Test: 77.15 % [cuda] Epoch 800 | Loss: 12.7570 | R2_Train: 70.72 % | R2_Test: 77.16 % [cuda] Epoch 810 | Loss: 12.7207 | R2_Train: 70.81 % | R2_Test: 77.22 % [cuda] Epoch 820 | Loss: 12.6721 | R2_Train: 70.93 % | R2_Test: 77.29 % [cuda] Epoch 830 | Loss: 12.6652 | R2_Train: 70.97 % | R2_Test: 77.29 % [cuda] Epoch 840 | Loss: 12.6596 | R2_Train: 71.00 % | R2_Test: 77.30 % [cuda] Epoch 850 | Loss: 12.6378 | R2_Train: 71.07 % | R2_Test: 77.33 % [cuda] Epoch 860 | Loss: 12.6008 | R2_Train: 71.17 % | R2_Test: 77.39 % [cuda] Epoch 870 | Loss: 12.5677 | R2_Train: 71.25 % | R2_Test: 77.43 % [cuda] Epoch 880 | Loss: 12.5590 | R2_Train: 71.28 % | R2_Test: 77.44 %
[cuda] Epoch 890 | Loss: 12.5430 | R2_Train: 71.33 % | R2_Test: 77.47 % [cuda] Epoch 900 | Loss: 12.5062 | R2_Train: 71.42 % | R2_Test: 77.52 % [cuda] Epoch 910 | Loss: 12.5019 | R2_Train: 71.45 % | R2_Test: 77.53 % [cuda] Epoch 920 | Loss: 12.4937 | R2_Train: 71.48 % | R2_Test: 77.54 % [cuda] Epoch 930 | Loss: 12.4858 | R2_Train: 71.51 % | R2_Test: 77.55 % [cuda] Epoch 940 | Loss: 12.4581 | R2_Train: 71.58 % | R2_Test: 77.60 % [cuda] Epoch 950 | Loss: 12.4267 | R2_Train: 71.66 % | R2_Test: 77.64 %
[cuda] Epoch 960 | Loss: 12.3972 | R2_Train: 71.74 % | R2_Test: 77.68 % [cuda] Epoch 970 | Loss: 12.3896 | R2_Train: 71.76 % | R2_Test: 77.68 % [cuda] Epoch 980 | Loss: 12.3948 | R2_Train: 71.76 % | R2_Test: 77.68 % [cuda] Epoch 990 | Loss: 12.3813 | R2_Train: 71.81 % | R2_Test: 77.70 % [cuda] Epoch 1000 | Loss: 12.3444 | R2_Train: 71.90 % | R2_Test: 77.76 %
In [14]:
Copied!
# %%
# Visualización final
with sorix.no_grad():
y_pred = net(X_test)
r2 = r2_score(Y_test, y_pred)
plt.figure(figsize=(20,8))
plt.scatter(X_test[:,0],Y_test,s=50)
plt.scatter(X_test[:,0],y_pred)
plt.title(f'Polinomic Regression on Test Data(Accuracy:{r2*100:.2f}%)')
# %%
# Visualización final
with sorix.no_grad():
y_pred = net(X_test)
r2 = r2_score(Y_test, y_pred)
plt.figure(figsize=(20,8))
plt.scatter(X_test[:,0],Y_test,s=50)
plt.scatter(X_test[:,0],y_pred)
plt.title(f'Polinomic Regression on Test Data(Accuracy:{r2*100:.2f}%)')
Out[14]:
Text(0.5, 1.0, 'Polinomic Regression on Test Data(Accuracy:77.76%)')
Save and Load Model¶
In [15]:
Copied!
sorix.save(net.state_dict(),"regression_weights.sor")
sorix.save(net.state_dict(),"regression_weights.sor")
CPU¶
In [16]:
Copied!
net2 = Network()
net2.load_state_dict(sorix.load("regression_weights.sor"))
if X_test.device == 'cpu':
out = net2(X_test)
if X_test.device == 'cuda':
out = net2(X_test.to('cpu'))
out
net2 = Network()
net2.load_state_dict(sorix.load("regression_weights.sor"))
if X_test.device == 'cpu':
out = net2(X_test)
if X_test.device == 'cuda':
out = net2(X_test.to('cpu'))
out
Out[16]:
tensor([[27.23454 ],
[33.00465 ],
[35.701096],
...,
[38.732765],
[34.634453],
[32.91391 ]], requires_grad=True)
GPU¶
In [17]:
Copied!
net2 = Network()
net2.load_state_dict(sorix.load("regression_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("regression_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[17]:
tensor([[27.234539],
[33.00465 ],
[35.701096],
...,
[38.732765],
[34.634453],
[32.91391 ]], device='cuda:0')