22.1. Wytrenowanie sieci neuronowej na potrzeby klasyfikacji obrazów

# Wczytanie bibliotek.
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms

# Zdefiniowanie architektury splotowej sieci neuronowej.
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.dropout1 = nn.Dropout2d(0.25)
        self.dropout2 = nn.Dropout2d(0.5)
        self.fc1 = nn.Linear(64 * 14 * 14, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = nn.functional.relu(self.conv1(x))
        x = nn.functional.relu(self.conv2(x))
        x = nn.functional.max_pool2d(self.dropout1(x), 2)
        x = torch.flatten(x, 1)
        x = nn.functional.relu(self.fc1(self.dropout2(x)))
        x = self.fc2(x)
        return nn.functional.log_softmax(x, dim=1)

# Wskazanie urządzenia, w którym będzie działała ta sieć.
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Zdefiniowanie kroków mających na celu przygotowanie danych.
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,))
])

# Wczytanie zbioru danych MNIST.
train_dataset = datasets.MNIST('./data', train=True, download=True,
    transform=transform)
test_dataset = datasets.MNIST('./data', train=False, transform=transform)

# Zdefiniowanie procedur wczytywania danych.
batch_size = 64
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size,
    shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size,
    shuffle=True)

# Inicjalizacja modelu i optymalizatora.
model = Net().to(device)
optimizer = optim.Adam(model.parameters())

# Kompilacja modelu z użyciem optymalizatora torch 2.0.
model = torch.compile(model)

# Zdefiniowanie pętli uczenia.
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
    data, target = data.to(device), target.to(device)
    optimizer.zero_grad()
    output = model(data)
    loss = nn.functional.nll_loss(output, target)
    loss.backward()
    optimizer.step()

# Zdefiniowanie pętli testowania.
model.eval()
test_loss = 0
correct = 0
with torch.no_grad():
    for data, target in test_loader:
        data, target = data.to(device), target.to(device)
        output = model(data)

        # Pobranie indeksu maksymalnego prawdopodobieństwa.
        test_loss += nn.functional.nll_loss(
            output, target, reduction='sum'
        ).item()  # Podsumowanie straty w paczce.
        pred = output.argmax(dim=1, keepdim=True)
        correct += pred.eq(target.view_as(pred)).sum().item()

test_loss /= len(test_loader.dataset)





22.2. Wytrenowanie sieci neuronowej na potrzeby klasyfikacji tekstu

# Wczytanie bibliotek.
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# Wczytanie zbioru danych przedstawiającego 20 grup dyskusyjnych.
cats = ['alt.atheism', 'sci.space']
newsgroups_data = fetch_20newsgroups(subset='all', shuffle=True,
    random_state=42, categories=cats)

# Podział zbioru danych na zbiory uczący i testujący.
X_train, X_test, y_train, y_test = train_test_split(newsgroups_data.data,
    newsgroups_data.target, test_size=0.2, random_state=42)

# Wektoryzacja danych tekstowych za pomocą podejścia macierzy cech worka słów.
vectorizer = CountVectorizer(stop_words='english')
X_train = vectorizer.fit_transform(X_train).toarray()
X_test = vectorizer.transform(X_test).toarray()

# Konwersja danych na tensory PyTorch.
X_train = torch.tensor(X_train, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.long)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_test = torch.tensor(y_test, dtype=torch.long)

# Zdefiniowanie modelu.
class TextClassifier(nn.Module):
    def __init__(self, num_classes):
        super(TextClassifier, self).__init__()
        self.fc1 = nn.Linear(X_train.shape[1], 128)
        self.fc2 = nn.Linear(128, num_classes)

    def forward(self, x):
        x = nn.functional.relu(self.fc1(x))
        x = self.fc2(x)
        return nn.functional.log_softmax(x, dim=1)

# Utworzenie egzemplarza modelu oraz zdefiniowanie funkcji straty i optymalizatora.
model = TextClassifier(num_classes=len(cats))
loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# Kompilacja modelu z użyciem optymalizatora torch 2.0.
model = torch.compile(model)

# Wytrenowanie modelu.
num_epochs = 1
batch_size = 10
num_batches = len(X_train) // batch_size
for epoch in range(num_epochs):
    total_loss = 0.0
    for i in range(num_batches):
        # Przygotowanie danych wejściowych i danych docelowych dla bieżącej paczki.
        start_idx = i * batch_size
        end_idx = (i + 1) * batch_size
        inputs = X_train[start_idx:end_idx]
        targets = y_train[start_idx:end_idx]

        # Zero gradientów dla optymalizatora.
        optimizer.zero_grad()

        # Propagacja do przodu modelu oraz obliczanie straty.
        outputs = model(inputs)
        loss = loss_function(outputs, targets)

        # Wsteczna propagacja w modelu i uaktualnianie parametrów.
        loss.backward()
        optimizer.step()

        # Uaktualnienie straty całkowitej dla epoki.
        total_loss += loss.item()

    # Obliczenie dokładności w zbiorze testowym dla epoki.
    test_outputs = model(X_test)
    test_predictions = torch.argmax(test_outputs, dim=1)
    test_accuracy = accuracy_score(y_test, test_predictions)

    # Wyświetlenie numeru epoki, średniej straty i dokładności testu.
    print(f"Epoch: {epoch+1}, Loss: {total_loss/num_batches}, Test Accuracy:"
        "{test_accuracy}")





X_train.shape[1]

25150





22.3. Dostrajanie wytrenowanego modelu na potrzeby klasyfikacji obrazu

# Wczytanie bibliotek.
import torch
from torchvision.transforms import(
    RandomResizedCrop, Compose, Normalize, ToTensor
    )
from transformers import Trainer, TrainingArguments, DefaultDataCollator
from transformers import ViTFeatureExtractor, ViTForImageClassification
from datasets import load_dataset, load_metric, Image

# Zdefiniowanie funkcji pomocniczej przeprowadzającej konwersję obrazu na postać RGB.
def transforms(examples):
    examples["pixel_values"] = [_transforms(img.convert("RGB")) for img in
        examples["image"]]
    del examples["image"]
    return examples

# Zdefiniowanie funkcji pomocniczej przeprowadzającej obliczenie wskaźników.
def compute_metrics(p):
    return metric.compute(predictions=np.argmax(p.predictions, axis=1),
        references=p.label_ids)

# Wczytanie zbioru danych fashion mnist.
dataset = load_dataset("fashion_mnist")

# Wczytanie procesora z modelu ViT.
image_processor = ViTFeatureExtractor.from_pretrained(
    "google/vit-base-patch16-224-in21k"
)

# Ustawienie etykiet pochodzących ze zbioru danych.
labels = dataset['train'].features['label'].names

# Wczytanie wcześniej wytrenowanego modelu.
model = ViTForImageClassification.from_pretrained(
    "google/vit-base-patch16-224-in21k",
    num_labels=len(labels),
    id2label={str(i): c for i, c in enumerate(labels)},
    label2id={c: str(i) for i, c in enumerate(labels)}
)

# Zdefiniowanie obiektów Collator, Normalize i Transform.
collate_fn = DefaultDataCollator()
normalize = Normalize(mean=image_processor.image_mean,
    std=image_processor.image_std)
size = (
    image_processor.size["shortest_edge"]
    if "shortest_edge" in image_processor.size
    else (image_processor.size["height"], image_processor.size["width"])
)
_transforms = Compose([RandomResizedCrop(size), ToTensor(), normalize])

# Wczytanie zbioru danych, który będzie używany razem z transformacjami.
dataset = dataset.with_transform(transforms)

# Użycie dokładności jako wskaźnika.
metric = load_metric("accuracy")

# Określenie argumentów uczących.
training_args = TrainingArguments(
    output_dir="fashion_mnist_model",
    remove_unused_columns=False,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    learning_rate=0.01,
    per_device_train_batch_size=16,
    gradient_accumulation_steps=4,
    per_device_eval_batch_size=16,
    num_train_epochs=1,
    warmup_ratio=0.1,
    logging_steps=10,
    load_best_model_at_end=True,
    metric_for_best_model="accuracy",
    push_to_hub=False,
)

# Utworzenie egzemplarza uczącego.
trainer = Trainer(
    model=model,
    args=training_args,
    data_collator=collate_fn,
    compute_metrics=compute_metrics,
    train_dataset=dataset["train"],
    eval_dataset=dataset["test"],
    tokenizer=image_processor,
)

# Wytrenowanie modelu, zarejestrowanie i zapisanie wskaźników.
train_results = trainer.train()
trainer.save_model()
trainer.log_metrics("train", train_results.metrics)
trainer.save_metrics("train", train_results.metrics)
trainer.save_state()





22.4. Dostrajanie wytrenowanego modelu na potrzeby klasyfikacji tekstu

# Wczytanie bibliotek.
from datasets import load_dataset
from transformers import AutoTokenizer, DataCollatorWithPadding
from transformers import (
    AutoModelForSequenceClassification, TrainingArguments, Trainer
    )
import evaluate
import numpy as np

# Wczytanie zbioru danych imdb.
imdb = load_dataset("imdb")

# Utworzenie obiektów Tokenizer i Collator.
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

# Podział na tokeny zbioru danych imdb.
tokenized_imdb = imdb.map(
    lambda example: tokenizer(
        example["text"], padding="max_length", truncation=True
    ),
    batched=True,
)

# Użycie dokładności jako wskaźnika.
accuracy = evaluate.load("accuracy")

# Zdefiniowanie funkcji pomocniczej przeprowadzającej obliczenie wskaźników.
def compute_metrics(eval_pred):
    predictions, labels = eval_pred
    predictions = np.argmax(predictions, axis=1)
    return accuracy.compute(predictions=predictions, references=labels)

# Utworzenie słowników do mapowania indeksów na etykiety i na odwrót.
id2label = {0: "NEGATIVE", 1: "POSITIVE"}
label2id = {"NEGATIVE": 0, "POSITIVE": 1}

# Wczytanie wcześniej wytrenowanego modelu.
model = AutoModelForSequenceClassification.from_pretrained(
    "distilbert-base-uncased", num_labels=2, id2label=id2label,
        label2id=label2id
)

# Określenie argumentów uczących.
training_args = TrainingArguments(
    output_dir="my_awesome_model",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=2,
    weight_decay=0.01,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
)

# Utworzenie egzemplarza uczącego.
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_imdb["train"],
    eval_dataset=tokenized_imdb["test"],
    tokenizer=tokenizer,
    data_collator=data_collator,
    compute_metrics=compute_metrics,
)

# Wytrenowanie modelu.
trainer.train()
