Introducción al Aprendizaje Automático - PyTorch | Original, traducido por IA

Home 2021.03

Este artículo fue escrito originalmente en chino. Ha sido traducido al inglés para facilitar su traducción a otros idiomas.


PyTorch

Vamos a instalarlo. Esto es compatible con la versión de Python 3.9.

$ pip install torch torchvision
Collecting torch
  Downloading torch-1.8.0-cp39-none-macosx_10_9_x86_64.whl (120.6 MB)
     |████████████████████████████████| 120.6 MB 224 kB/s
Collecting torchvision
  Downloading torchvision-0.9.0-cp39-cp39-macosx_10_9_x86_64.whl (13.1 MB)
     |████████████████████████████████| 13.1 MB 549 kB/s
Requirement already satisfied: numpy in /usr/local/lib/python3.9/site-packages (from torch) (1.20.1)
Collecting typing-extensions
  Downloading typing_extensions-3.7.4.3-py3-none-any.whl (22 kB)
Requirement already satisfied: pillow>=4.1.1 in /usr/local/lib/python3.9/site-packages (from torchvision) (8.0.1)
Installing collected packages: typing-extensions, torch, torchvision
Successfully installed torch-1.8.0 torchvision-0.9.0 typing-extensions-3.7.4.3

Vamos a verificarlo.

import torch
x = torch.rand(5, 3)
print(x)

Ocurrió un error.

Traceback (most recent call last):
  File "torch.py", line 1, in <module>
    import torch
  File "torch.py", line 2, in <module>
    x = torch.rand(5, 3)
AttributeError: partially initialized module 'torch' has no attribute 'rand' (most likely due to a circular import)

Después de buscar este mensaje de error en Google, resulta que nuestro archivo también se llamaba torch, lo que causaba un conflicto de nombres. Tras renombrarlo, funciona correctamente.

tensor([[0.5520, 0.9446, 0.5543],
        [0.6192, 0.0908, 0.8726],
        [0.0223, 0.7685, 0.9814],
        [0.4019, 0.5406, 0.3861],
        [0.5485, 0.6040, 0.2387]])

Vamos a buscar un ejemplo.

# -*- coding: utf-8 -*-

import torch
import math
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") # Descomenta esto para ejecutar en GPU

# Crear datos de entrada y salida aleatorios
x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype)
y = torch.sin(x)

# Inicializar aleatoriamente los pesos
a = torch.randn((), device=device, dtype=dtype)
b = torch.randn((), device=device, dtype=dtype)
c = torch.randn((), device=device, dtype=dtype)
d = torch.randn((), device=device, dtype=dtype)

learning_rate = 1e-6
for t in range(2000):
    # Paso hacia adelante: calcular y predicho
    y_pred = a + b * x + c * x ** 2 + d * x ** 3

    # Calcular e imprimir la pérdida
    loss = (y_pred - y).pow(2).sum().item()
    if t % 100 == 99:
        print(t, loss)

    # Retropropagación para calcular los gradientes de a, b, c, d con respecto a la pérdida
    grad_y_pred = 2.0 * (y_pred - y)
    grad_a = grad_y_pred.sum()
    grad_b = (grad_y_pred * x).sum()
    grad_c = (grad_y_pred * x ** 2).sum()
    grad_d = (grad_y_pred * x ** 3).sum()

    # Actualizar los pesos usando el descenso de gradiente
    a -= learning_rate * grad_a
    b -= learning_rate * grad_b
    c -= learning_rate * grad_c
    d -= learning_rate * grad_d
print(f'Resultado: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3')

Vamos a ejecutarlo.

99 1273.537353515625
199 849.24853515625
299 567.4786987304688
399 380.30291748046875
499 255.92752075195312
599 173.2559814453125
699 118.2861328125
799 81.72274780273438
899 57.39331817626953
999 41.198158264160156
1099 30.41307830810547
1199 23.227672576904297
1299 18.438262939453125
1399 15.244369506835938
1499 13.113286972045898
1599 11.690631866455078
1699 10.740333557128906
1799 10.105220794677734
1899 9.6804780960083
1999 9.39621353149414
Resultado: y = -0.011828352697193623 + 0.8360244631767273 x + 0.002040589228272438 x^2 + -0.09038365632295609 x^3

Veamos un código que usa solo la biblioteca numpy.

# -*- coding: utf-8 -*-
import numpy as np
import math

# Crear datos de entrada y salida aleatorios
x = np.linspace(-math.pi, math.pi, 2000)
y = np.sin(x)

# Inicializar aleatoriamente los pesos
a = np.random.randn()
b = np.random.randn()
c = np.random.randn()
d = np.random.randn()

learning_rate = 1e-6
for t in range(2000):
    # Paso hacia adelante: calcular y predicho
    # y = a + b x + c x^2 + d x^3
    y_pred = a + b * x + c * x ** 2 + d * x ** 3

    # Calcular e imprimir la pérdida
    loss = np.square(y_pred - y).sum()
    if t % 100 == 99:
        print(t, loss)

    # Retropropagación para calcular los gradientes de a, b, c, d con respecto a la pérdida
    grad_y_pred = 2.0 * (y_pred - y)
    grad_a = grad_y_pred.sum()
    grad_b = (grad_y_pred * x).sum()
    grad_c = (grad_y_pred * x ** 2).sum()
    grad_d = (grad_y_pred * x ** 3).sum()

    # Actualizar los pesos
    a -= learning_rate * grad_a
    b -= learning_rate * grad_b
    c -= learning_rate * grad_c
    d -= learning_rate * grad_d

print(f'Resultado: y = {a} + {b} x + {c} x^2 + {d} x^3')

Observa que estas son dos formas diferentes de realizar cálculos.

En estos ejemplos, primero se genera un conjunto de valores x e y. Luego, se asume que es una ecuación cúbica. A continuación, se utilizan algunos métodos para calcular iterativamente los coeficientes. ¿Qué algoritmos son estos? Observa que el bucle se repite 2000 veces, volviéndose más preciso en cada iteración. No profundizaremos en los detalles aquí.

Finalmente

Actualmente, no comprendemos cómo funcionan los cálculos de aprendizaje automático detrás de escena. Sin embargo, eso no es importante por ahora. Con los conocimientos anteriores, ya podemos hacer muchas cosas. El aprendizaje automático también se puede utilizar para procesar texto, audio y más. Después de explorar docenas de ejemplos, no será demasiado tarde para aprender la teoría.

Ejercicios


Back Donate