Saltar navegación

Tensores con Pytorch

Librería Pytorch
Copilot. Librería Pytorch (CC BY-SA)

PyTorch é unha ferramenta moi usada en IA que traballa con tensores. Permíteche:

  • Crear tensores e aplicar operacións neles rapidamente.
  • Adestrar modelos de redes neuronais, onde cada capa da rede manipula tensores.
  • Aproveitar a potencia das tarxetas gráficas para realizar cálculos con miles ou millóns de valores ao mesmo tempo.

Os tensores son a base matemática detrás de moitos sistemas de intelixencia artificial, e PyTorch é unha ferramenta que facilita o traballo con eles

Que é un tensor?


Lembras que as máquinas só entenden números? Que calquera dato, xa sexan imaxes, vídeos, audios, texto...deben convertirse en números?

Pois, 

un tensor é simplemente unha forma de organizar eses números. Podes imaxinalo como unha extensión das matrices, que quizais coñezas xa en matemáticas.

Tensor
Copilot. Tensor (CC BY-SA)

  • Un número único é un escalar (por exemplo, 5).
  • Unha lista de números é un vector (por exemplo, [2, 4, 6]).
  • Unha táboa con filas e columnas é unha matriz (por exemplo, unha táboa de 3x3 con números).

Un tensor é unha extensión disto, podendo ter calquera número de dimensións. Os tensores son como caixas organizadas con números, que se poden mover, transformar e operar neles.

Na Intelixencia Artificial, especialmente en redes neuronais, traballamos con enormes cantidades de datos, como imaxes, textos e números. Estes datos organízanse en forma de tensores para que os computadores poidan procesalos de maneira rápida e eficiente.

Por exemplo:

  • Unha imaxe pode representarse como un tensor onde cada píxel ten valores de cor (vermelho, verde e azul).
  • Un texto pode transformarse nun tensor onde cada palabra se representa con números.

Usamos tensores porque permiten manipular grandes cantidades de información usando matemáticas avanzadas e computación eficiente.

Proba a visualizar o tensor dunha imaxe

Con este programa executado en Colab, podes subir o arquivo dunha imaxe e visualizar o tensor no que se traduce para que unha máquina poda traballar con ela.

Proba a visualizar o tensor dun texto

Con este programa executado en Colab, podes subir o arquivo dun texto e visualizar o tensor no que se traduce para que unha máquina poda traballar con el.

Explicación das saídas "tipo"

Imaxe

Dimensións do tensor: torch.Size([1, 96, 96]). O tensor que representa a imaxe ten tres dimensións:

  • 1: Indica que a imaxe ten unha soa canle, probablemente en escala de grises.
  • 96: Indica que a imaxe ten 96 píxeles de altura.
  • 96: Indica que a imaxe ten 96 píxeles de ancho.
  • O tensor describe unha imaxe de 96x96 en escala de grises.

Valores do tensor (Primeiros 10 números): tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]). Mostra os primeiros 10 valores numéricos do tensor.

  • Cada número representa a intensidade dun píxel da imaxe.
  • Neste caso, todos os valores son 0.0, o que significa que eses píxeles son completamente negros. A imaxe parece ter unha zona escura ao principio.

Todos os valores do tensor. Aquí ves os valores numéricos organizados como píxeles da imaxe. Cada número representa unha intensidade de cor entre 0.0 (negro) e 1.0 (branco).

Exemplos:

  • 0.0000 → Píxel negro.
  • 0.9608 → Píxel case branco.
  • 0.5686 → Píxel de cor intermedia.

Este tensor é a representación matemática da imaxe, útil para procesamento en IA. 

Texto

"Detectando a codificación do arquivo...". O programa está intentando descubrir en que formato está codificado o arquivo de texto. Se o texto usa UTF-8, poderá lerse sen problemas. Se UTF-8 non funciona, buscarase outra alternativa. 

"⚠️ Erro con UTF-8, probando con 'latin-1' como alternativa...". O programa tentou ler o texto en UTF-8, pero atopou caracteres que non poden decodificarse correctamente. Como alternativa, usa latin-1, que permite ler case calquera texto sen erros, aínda que pode modificar algúns caracteres especiais.

"Convertendo cada caracter en números...". Cada letra, número ou símbolo do texto ten un código numérico ASCII. O programa está transformando cada caracter nun número para que poida ser procesado como un tensor.

Exemplo:

  • A letra "A" → 65
  • A letra "B" → 66
  • O espazo " " → 32

"Convertendo a lista de números nun tensor...". O texto xa foi convertido nunha lista de números. Agora esta lista transfórmase nun tensor, que é unha estrutura matemática usada en IA para procesamento eficiente.

"Dimensións do tensor: torch.Size([20389])". O tensor ten 20389 elementos, o que significa que o texto tiña 20389 caracteres. Isto indica que o documento era relativamente longo.

"Valores do tensor (Primeiros 10 números): tensor([80, 75, 3, 4, 20, 0, 0, 8, 0, 0], dtype=torch.int32)". O programa mostra os primeiros 10 números do tensor para que vexamos a transformación.
Estes valores corresponden aos caracteres iniciais do arquivo de texto. Interpretación: O número 80 representa P, 75 representa K... 

"Todos os valores do tensor..." Aquí podes ver a representación numérica completa do arquivo en forma de tensor. Como vemos na saída, aparecen números como 109, 105, 109, 101, 116, 121..., que parecen representar "mimetype", indicando que pode ser un arquivo binario e non un texto plano.

Código Python: Visualización do tensor dunha imaxe subida a colab

from google.colab import files  # Permite subir arquivos desde o ordenador a Google Colab
from PIL import Image  # Librería para abrir e manipular imaxes
import torch  # Biblioteca de IA e computación numérica
import torchvision.transforms as transforms  # Transformacións de imaxes para PyTorch
import matplotlib.pyplot as plt  # Librería para visualizar gráficos e imaxes

# 1️ Subir a imaxe
print(" Subindo unha imaxe desde o teu ordenador...")  
uploaded = files.upload()  # Abre un diálogo para que o usuario seleccione un arquivo

# 2️ Obter o nome do arquivo subido
image_path = list(uploaded.keys())[0]  # Gardamos o nome do arquivo subido
print(f" A túa imaxe '{image_path}' foi cargada correctamente!")

# 3️ Cargar e visualizar a imaxe
image = Image.open(image_path)  # Abrimos a imaxe usando PIL
plt.imshow(image)  # Mostramos a imaxe
plt.title(" Imaxe orixinal")  # Poñemos un título á imaxe
plt.axis("off")  # Eliminamos os eixos para mellor visualización
plt.show()  # Mostramos a imaxe na saída de Colab

# 4️ Converter a imaxe nun tensor
print(" Convertendo a imaxe nun tensor...")
transform = transforms.ToTensor()  # Transforma a imaxe nun tensor (numeros organizados en 3D)
tensor_image = transform(image)  # Aplicamos a transformación

# 5️ Mostrar información do tensor
print(" Dimensións do tensor:", tensor_image.shape)  # Mostra a forma do tensor (Canais, Alto, Ancho)
print(" Valores do tensor (Primeiros 10 números):", tensor_image.flatten()[:10])  # Mostra os primeiros valores do tensor

# 6️ Asegurarse de que se mostran todos os valores
torch.set_printoptions(profile="full")  # Configuramos PyTorch para que non acurte os valores ao imprimir

# 7️ Imprimir todos os valores do tensor
print(" Todos os valores do tensor:")
print(tensor_image)
    

Código Python: visualización do tensor dun texto subido a colab

from google.colab import files  # Librería para subir arquivos desde o ordenador a Google Colab
import torch  # Biblioteca de IA e computación numérica

# 1 Subir un arquivo de texto
print(" Subindo un arquivo de texto desde o teu ordenador...")  
uploaded = files.upload()  # Abre un diálogo para seleccionar un arquivo de texto

# 2 Obter o nome do arquivo subido
file_path = list(uploaded.keys())[0]  # Gardamos o nome do arquivo subido
print(f" O teu arquivo '{file_path}' foi cargado correctamente!")

import chardet  # Librería para detectar codificacións de texto

# 3 Ler o contido do arquivo en modo binario
print(" Detectando a codificación do arquivo...")
with open(file_path, "rb") as f:
    raw_data = f.read()  # Lemos os datos en formato binario

# Tentamos decodificar o texto en UTF-8 primeiro
try:
    text = raw_data.decode("utf-8")  
    print(" O texto foi decodificado correctamente en UTF-8.")
except UnicodeDecodeError:
    print("⚠️ Erro con UTF-8, probando con 'latin-1' como alternativa...")
    text = raw_data.decode("latin-1")  # Decodificación alternativa en caso de erro

# 4 Converter o texto en números (codificación ASCII)
print(" Convertendo cada caracter en números...")
text_encoded = [ord(char) for char in text]  # Cada caracter transfórmase no seu código numérico

# 5 Convertir a lista nun tensor de números
print(" Convertendo a lista de números nun tensor...")
text_tensor = torch.tensor(text_encoded, dtype=torch.int32)  # Tensor de números enteros

# 6 Mostrar información do tensor
print(" Dimensións do tensor:", text_tensor.shape)  # Indica o tamaño do tensor
print(" Valores do tensor (Primeiros 10 números):", text_tensor[:10])  # Mostra os primeiros números para facilitar a visualización
print(" Todos os valores do tensor:")
print(text_tensor)  # Mostra todos os valores do tensor

    

Actividades de aprendizaxe

Actividade 1: Descargar e manipular dataset MNIST

Obxectivo: Aprender a descargar e manipular o dataset mnist.
Instrución: Descargar o dataset MNIST, visualizar as imaxes dato e separar 25 para probas posteriores.

Código Python: Descarga, visualización e separación de 25 imaxes de proba en MNIST

'''Este programa descarga os datos de adestramento de MNIST e visualiza os 5 primeiros
   logo os de validación e gárda os 25 primeiros coma imaxes png'''

import torchvision # Importa a biblioteca para traballar con visión por computador
import torchvision.datasets as datasets # Biblioteca para descargar conxuntos de datos de visión por computador import torchvision.transforms as transforms # Módulo para aplicar transformacións a imaxes import torch # Biblioteca para traballar con tensores en intelixencia artificial import matplotlib.pyplot as plt # Librería para visualizar imaxes e gráficos from PIL import Image # Librería para manipular imaxes en formato PIL # 1️ Descargar o dataset de adestramento MNIST dataset = torchvision.datasets.MNIST( root="./data", # Indica o directorio onde se almacenarán os datos descargados train=True, # Especifica que queremos o conxunto de datos de adestramento (non o de test) transform=transforms.ToTensor(), # Convértese cada imaxe nun tensor de PyTorch para facilitar o procesamento download=True # Se os datos non están presentes, descárgaos automaticamente desde internet ) # 2️ Mostrar unha mensaxe para indicar que a descarga completouse print(" Descarga completada!") # 3 Explorar os datos do dataset MNIST print(f" Forma dos datos: {dataset.data.shape}") # Mostra as dimensións do dataset -> (60000, 28, 28) # Isto significa que temos 60.000 imaxes de números, cada unha de 28x28 píxeles print(f" Etiquetas dispoñibles: {dataset.targets.unique()}") # Mostra os valores das etiquetas (0-9) # Estes son os números que pode recoñecer o modelo de IA # 4 Visualizar algunhas imaxes do dataset de adestramento fig, axes = plt.subplots(1, 5, figsize=(10, 3)) # Creamos unha figura con 5 subgráficos nunha fila # figsize=(10,3) determina o tamaño do gráfico for i in range(5): # Iteramos sobre as primeiras 5 imaxes axes[i].imshow(dataset.data[i], cmap="gray") # Mostramos a imaxe en escala de grises (cmap="gray") axes[i].set_title(f"Etiqueta: {dataset.targets[i].item()}") # Poñemos un título con o número que representa cada imaxe axes[i].axis("off") # Eliminamos os eixos para unha mellor visualización plt.show() # Mostramos a figura coas imaxes # 5 Descargar o dataset MNIST de proba (test) mnist_val = datasets.MNIST( root="./data", # Directorio onde se gardará o dataset train=False, # Indica que queremos o conxunto de proba (non o de adestramento) download=True, # Se o dataset non está na carpeta, descárgao automaticamente transform=transforms.ToTensor() # Convértese a imaxe nun tensor de PyTorch (valores entre 0 e 1) ) # 6 Gardar as primeiras 25 imaxes en formato PNG for i in range(25): image, label = mnist_val[i] # Obtén a imaxe e a etiqueta correspondente image = image.squeeze(0) * 255 # Escala os valores de 0-1 a 0-255 (para converter en imaxe estándar) # Converter o tensor a imaxe en formato PIL image = Image.fromarray(image.numpy().astype("uint8")) # Gardar a imaxe cun nome descritivo image.save(f"mnist_digit_{label}_{i}.png") # 7 Mostrar unha mensaxe para indicar que a descarga completouse print(" Descarga de imaxes de proba completada!")

Actividade 2: Rede neuronal e adestramento

Obxectivo: Aprender o funcionamento de Pytorch na creación de redes neuronais
Instrución: Crear unha rede neuronal de 2 capas e adestrala para recoñecer díxitos 0-9 con MINST

Código Python: Creación e adestramento dunha rede neuronal simple con Pytorch

import torch  # Biblioteca para computación numérica e IA
import torch.nn as nn  # Módulo de redes neuronais
import torch.optim as optim  # Optimización para adestrar modelos
import torchvision  # Biblioteca para manipular datos visuais
import torchvision.transforms as transforms  # Transformacións de imaxe
import matplotlib.pyplot as plt  # Librería para visualizar gráficos

# 1️ Cargar o dataset MNIST xa descargado en Colab
transform = transforms.Compose([
    transforms.ToTensor(),  # Convértese a imaxe nun tensor con valores entre 0 e 1
])

# Cargamos os datos de adestramento
train_dataset = torchvision.datasets.MNIST(root="./data", train=True, transform=transform, download=False)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)

# Cargamos os datos de validación
test_dataset = torchvision.datasets.MNIST(root="./data", train=False, transform=transform, download=False)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False)

print("Datos cargados correctamente!")

# 2️ Definir a rede neuronal
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(28*28, 128)  # Capa totalmente conectada con 128 neuronas
        self.fc2 = nn.Linear(128, 10)  # Saída con 10 neuronas (unha por cada díxito 0-9)

    def forward(self, x):
        x = x.view(-1, 28*28)  # Aplanamos a imaxe de 28x28 a un vector de 784 elementos
        x = torch.relu(self.fc1(x))  # Aplicamos a activación ReLU
        x = self.fc2(x)  # Última capa para obter as predicións
        return x

# Crear o modelo
model = SimpleNN()
print(" Modelo creado:")
print(model)

# 3️ Definir a función de perda e o optimizador
criterion = nn.CrossEntropyLoss()  # Función de perda para clasificación multiclase(temos 10 clases)
optimizer = optim.SGD(model.parameters(), lr=0.01)  # Optimización con Gradiente Estocástico (SGD)

# 4️ Adestrar a rede neuronal
epochs = 5  # Número de épocas
losses = []  # Lista para gardar os valores da perda
accuracies = []  # Lista para gardar as precisións

print(" Comezando o adestramento...")

iteracions=0

for epoch in range(epochs):
    correct = 0
    total = 0
    print(model.fc1.weight.grad) #para ver como os gradientes cambian en cada iteración.
    for images, labels in train_loader:  # Iterar sobre os datos de adestramento
        iteracions+= 1  #Contar iteracións
        optimizer.zero_grad()  # Reiniciar gradientes
        outputs = model(images)  # Pasar as imaxes polo modelo
        loss = criterion(outputs, labels)  # Calcular a perda
        loss.backward()  # Retropropagar os erros
        optimizer.step()  # Actualizar os parámetros do modelo

        losses.append(loss.item())  # Gardar a perda

        # Calcular a precisión
        predictions = torch.argmax(outputs, dim=1)
        correct += (predictions == labels).sum().item()
        total += labels.size(0)

    accuracy = correct / total  # Calcular precisión
    accuracies.append(accuracy)  # Gardar a precisión
    print(f" Época {epoch+1}: Perda = {loss.item():.4f}, Precisión = {accuracy:.4f}")

print(f" Total de iteracións no adestramento: {iteracions}")
print(" Adestramento completado!")

# 5️ Visualizar as curvas de aprendizaxe
plt.figure(figsize=(10, 4))

# Gráfica da perda ao longo das épocas
plt.subplot(1, 2, 1)
plt.plot(losses, label="Perda")
plt.xlabel("Iteracións") # nº de iteracións=cantidade de datos/lotes de datos=6000/64=938 aprox
plt.ylabel("Valor da perda")
plt.title("Curva de perda")
plt.legend()

# Gráfica da precisión ao longo das épocas
plt.subplot(1, 2, 2)
plt.plot(accuracies, label="Precisión", marker='o')
plt.xlabel("Épocas")
plt.ylabel("Precisión")
plt.title("Curva de precisión")
plt.legend()

plt.show()
print("Gráficas de perda e precisión xeradas!")

    

Actividade 3: Proba do modelo

Obxectivo: Comprender como o modelo predí o novo díxito.
Instrución: Prepara as 25 imaxes de validación gardadas para predecir e proba o modelo.

Código Python: Proba do modelo para recoñecer imaxes de díxitos a man do 0 ó 9

import torchvision.transforms as transforms  # Biblioteca para transformar imaxes
from PIL import Image  # Manipulación de imaxes en formato PIL
import matplotlib.pyplot as plt  # Librería para visualizar imaxes
import torch  # Biblioteca de computación numérica e intelixencia artificial
from google.colab import files  # Permite subir arquivos en Google Colab

# 1️ Subir unha imaxe dun díxito
print(" Sube unha imaxe dun díxito (formato PNG ou JPG)...")
uploaded = files.upload()  # Abre un diálogo para seleccionar a imaxe

# 2️ Obter o nome do ficheiro subido
filename = list(uploaded.keys())[0]  # Gardamos o nome do ficheiro subido
print(f" Imaxe '{filename}' cargada correctamente!")

# 3️ Cargar a imaxe
image = Image.open(filename).convert("L")  # Converte a imaxe a escala de grises


# 4️ Transformar a imaxe para a predición
print(" Transformando a imaxe para adaptala ao modelo MNIST...")
transform = transforms.Compose([
    transforms.Resize((28, 28)),  # Redimensionar a imaxe ao formato de MNIST (28x28 píxeles)
    transforms.ToTensor(),  # Converter a imaxe nun tensor
    transforms.Normalize((0.5,), (0.5,))  # Normalizar os valores para mellor predición
])

image_tensor = transform(image).unsqueeze(0)  # Engadimos unha dimensión de lote
print(" Imaxe transformada lista para predición!")

#5 Visualizar ambas imaxes
plt.figure(figsize=(10, 4))  # Define o tamaño da figura

plt.subplot(1, 2, 1)  # Primeira imaxe
plt.imshow(image, cmap="gray")
plt.title(" Díxito subido")
plt.axis("off")

plt.subplot(1, 2, 2)  # Segunda imaxe
plt.imshow(image_tensor.squeeze(0).squeeze(0), cmap="gray")
plt.title(" Díxito transformado")
plt.axis("off")
plt.show()  # Mostrar ambas imaxes á vez na mesma fila


# 6 Predición co modelo adestrado
print(" Realizando a predición co modelo MNIST...")
model.eval()  # Poñemos o modelo en modo avaliación (desactiva o adestramento)
with torch.no_grad():  # Desactivamos o cálculo de gradientes para a predición
    output = model(image_tensor)  # Predición do modelo

# 7 Obter os 3 díxitos máis probables
probabilities = torch.softmax(output, dim=1)  # Aplicamos Softmax para obter probabilidades
top3 = torch.topk(probabilities, 3)  # Obtemos os 3 valores máis altos

print(" Predicións do modelo:")
for i in range(3):
    predicted_digit = top3.indices[0][i].item()  # Díxito predicido
    probability = top3.values[0][i].item()  # Probabilidade asociada
    print(f" Díxito: {predicted_digit}, Probabilidade: {probability*100:.4f} %")

print(" Predición completada!")