Commit a9a57eb6 authored by jg5dev's avatar jg5dev 💬
Browse files

better

parent 6cbde2c2
Loading
Loading
Loading
Loading
+26 −24
Changes for src/apren/basics/ml_tensors.md: 26 added lines, 24 removed lines.
Original line number Diff line number Diff line
@@ -24,9 +24,9 @@ from torch import nn

```python
punts = [[0.5, 1.0], [2.0, -1.0], [0.0, 3.0], [1.5, 0.5]]  # 4 punts, 2 coordenades
X = torch.tensor(punts)
print(X)
print('shape:', X.shape, '| ndim:', X.ndim, '| dtype:', X.dtype)
X_t = torch.tensor(punts)
print(X_t)
print('shape:', X_t.shape, '| ndim:', X_t.ndim, '| dtype:', X_t.dtype)
```

```text
@@ -38,13 +38,15 @@ shape: torch.Size([4, 2]) | ndim: 2 | dtype: torch.float32
```

Les dades solen arribar en un array de NumPy, que `torch.tensor` també accepta. `dtype` en tria
el tipus, i `.numpy()` fa el camí invers:
el tipus, i `.numpy()` fa el camí invers. Quan tens les mateixes dades en tots dos formats, el
tensor porta el nom de l'array amb **`_t`** al final (`y` i `y_t`): així el nom diu sempre amb quina
biblioteca treballes.

```python
y_np = np.array([1, 0, 1, 0])
y = torch.tensor(y_np, dtype=torch.float32)
print(y_np.dtype, '→', y.dtype)
print(y.numpy())  # i de tornada a NumPy
y = np.array([1, 0, 1, 0])
y_t = torch.tensor(y, dtype=torch.float32)
print(y.dtype, '→', y_t.dtype)
print(y_t.numpy())  # i de tornada a NumPy
```

```text
@@ -58,9 +60,9 @@ Els pesos d'una capa de PyTorch són `float32`, i NumPy crea els decimals en `fl
dius el tipus en convertir, la capa no accepta les dades:

```python
X_np = np.array(punts)            # NumPy: float64 per defecte
X = np.array(punts)        # NumPy: float64 per defecte
neurona = nn.Linear(2, 1)  # els pesos de PyTorch: float32
neurona(torch.tensor(X_np))       # float64 contra float32
neurona(torch.tensor(X))   # float64 contra float32
```

```text
@@ -71,8 +73,8 @@ RuntimeError: mat1 and mat2 must have the same dtype, but got Double and Float
sempre amb `dtype=torch.float32`, etiquetes incloses:

```python
X = torch.tensor(X_np, dtype=torch.float32)
print(X.dtype)
X_t = torch.tensor(X, dtype=torch.float32)
print(X_t.dtype)
```

```text
@@ -87,9 +89,9 @@ Les operacions element a element, la indexació i les agregacions funcionen com
agregacions, l'eix es diu `dim` en lloc d'`axis`:

```python
print(X * 2)           # element a element
print(X[:, 0])         # la columna 0: totes les files
print(X.mean(dim=0))   # la mitjana de cada columna: dim fa el paper d'axis
print(X_t * 2)          # element a element
print(X_t[:, 0])        # la columna 0: totes les files
print(X_t.mean(dim=0))  # la mitjana de cada columna: dim fa el paper d'axis
```

```text
@@ -110,7 +112,7 @@ punts i un vector de pesos, és la **suma ponderada** d'una neurona,
```python
w = torch.tensor([2.0, -1.0])  # un pes per coordenada
b = 0.5
z = X @ w + b                  # la suma ponderada de la neurona, per als 4 punts alhora
z = X_t @ w + b                # la suma ponderada de la neurona, per als 4 punts alhora
print(z)
print(torch.sigmoid(z))        # les probabilitats
```
@@ -133,11 +135,11 @@ Les etiquetes, en canvi, solen arribar en fila. `.reshape(-1, 1)` les posa en co
els eixos de mida 1.

```python
print(y.shape)                    # una etiqueta per punt
print(y.reshape(-1, 1).shape)     # en columna: 4 files i 1 columna
print(y_t.shape)                 # una etiqueta per punt
print(y_t.reshape(-1, 1).shape)  # en columna: 4 files i 1 columna
torch.manual_seed(0)
neurona = nn.Linear(2, 1)
sortida = neurona(X)
sortida = neurona(X_t)
print(sortida.shape)             # la sortida d'una xarxa: sempre en columna
print(sortida.squeeze().shape)   # squeeze treu els eixos de mida 1
```
@@ -153,7 +155,7 @@ La funció de pèrdua compara la sortida i les etiquetes posició a posició, i

```python
loss_fn = nn.BCEWithLogitsLoss()
loss_fn(sortida, y)               # etiquetes en fila, sortida en columna
loss_fn(sortida, y_t)               # etiquetes en fila, sortida en columna
```

```text
@@ -161,7 +163,7 @@ ValueError: Target size (torch.Size([4])) must be the same as input size (torch.
```

```python
y_col = y.reshape(-1, 1)
y_col = y_t.reshape(-1, 1)
print(loss_fn(sortida, y_col))
```

@@ -218,8 +220,8 @@ que entrena les xarxes:

```python
w = torch.tensor([2.0, -1.0], requires_grad=True)  # PyTorch en seguirà les operacions
z = X @ w + 0.5
perdua = loss_fn(z, y)
z = X_t @ w + 0.5
perdua = loss_fn(z, y_t)
perdua.backward()                                  # calcula la derivada de la pèrdua respecte de w
print(w.grad)
```
@@ -250,7 +252,7 @@ seguir les operacions, i en sortir-ne tot torna a ser com abans:

```python
with torch.no_grad():
    z = X @ w + 0.5      # dins del bloc, PyTorch no segueix res
    z = X_t @ w + 0.5      # dins del bloc, PyTorch no segueix res
print(z.requires_grad)
```