<jupyter_start><jupyter_text>Домашнее задание:- Получить точность 97.5% на валидации MNIST.- Реализовать морфинг автоэнкодером (без формальных критериев — просто получите красивую гифку).- Визуализировать MNIST автоэнкодером (обучить автоэнкодер с латентным пространством размерности 2 и вывести через scatter точки разного цвета). Линка на колаб с тетрадкой: [kaggle.com](https://www.kaggle.com/hashshes/training-mnist-97-val-accuracy)<jupyter_code># If running on colab

# ! pip install -qqq pytorch-lightning torch torchvision torchmetrics
import pytorch_lightning as pl
from torch.optim.lr_scheduler import StepLR
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
import torch.nn as nn
from torch.optim import Adam

from torchmetrics.classification import Accuracy

pl.seed_everything(0)
config = {
    'batch_size': 32,
    'lr': 0.00101017,
    'max_epochs': 30,
    'layer_1': 128,
    'layer_2': 64
}<jupyter_output><empty_output><jupyter_text>Defining the dataloader for mnist model<jupyter_code>default_transform = transforms.Compose([
    transforms.ToTensor(),
])

class MNISTDataloader(pl.LightningDataModule):
    def __init__(self, batch_size: int):
        super().__init__()
        self.batch_size = batch_size
        self.train_dataset = datasets.MNIST(root="../data/raw", download=True, train=True, transform=default_transform)
        self.test_dataset = datasets.MNIST(root="../data/raw", download=True, train=False, transform=default_transform)

    def train_dataloader(self):
        return DataLoader(dataset=self.train_dataset,
                          batch_size=self.batch_size,
                          shuffle=True,
                          num_workers=2)

    def val_dataloader(self):
        return DataLoader(dataset=self.test_dataset,
                          batch_size=self.batch_size,
                          shuffle=False,
                          num_workers=2)<jupyter_output><empty_output><jupyter_text>Defining the dense model for mnist model<jupyter_code>model = nn.Sequential(
    nn.Flatten(),
    nn.Linear(in_features=28 * 28, out_features=config['layer_1']),
    nn.ReLU(),

    nn.Linear(in_features=config['layer_1'], out_features=config['layer_2']),
    nn.ReLU(),

    nn.Linear(in_features=config['layer_2'], out_features=10)
)<jupyter_output><empty_output><jupyter_text>Defining training loop for our model<jupyter_code>class MNISTClassifier(pl.LightningModule):
    def __init__(self, _model: nn.Module, _config: dict):
        super().__init__()
        self.model = _model
        self.config = _config

        self.train_accuracy = Accuracy()
        self.val_accuracy = Accuracy()

        self.loss_fn = nn.CrossEntropyLoss()

        self.count_epoch = 0


    def training_step(self, batch, batch_idx):
        x, y = batch

        outputs = self.model(x)
        loss = self.loss_fn(outputs, y)

        self.log("train/loss_step", loss.item())
        self.log('train/acc_step', self.train_accuracy(outputs, y))

        return loss

    def training_epoch_end(self, outputs) -> None:
        self.count_epoch += 1
        print(f'Train accuracy on {self.count_epoch} epoch: {self.train_accuracy.compute()}')

    def validation_step(self, batch, batch_idx):
        x, y = batch
        outputs = self.model(x)
        self.log('val/acc_step', self.val_accuracy(outputs, y))

    def validation_epoch_end(self, outputs) -> None:
        print(f"Val accuracy on {self.count_epoch - 1} epoch: {self.val_accuracy.compute()}")


    def configure_optimizers(self):
        optimizer = Adam(self.parameters(), lr=self.config['lr'])

        return optimizer

def train(_config: dict):
    trainer = pl.Trainer(gpus=0, max_epochs=_config['max_epochs'],)

    data_loader = MNISTDataloader(batch_size=_config['batch_size'])
    classifier = MNISTClassifier(_model=model, _config=_config)
    trainer.fit(classifier, data_loader.train_dataloader(), data_loader.val_dataloader())
    trainer.save_checkpoint("../weights/mnist.ckpt", weights_only=True)

if __name__ == '__main__':
    train(config)<jupyter_output>GPU available: False, used: False
TPU available: False, using: 0 TPU cores
IPU available: False, using: 0 IPUs
/home/shamil/PycharmProjects/data-analysis-sklearn/venv/lib/python3.9/site-packages/torchvision/datasets/mnist.py:498: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at  ../torch/csrc/utils/tensor_numpy.cpp:180.)
  return torch.from_numpy(parsed.astype(m[2], copy=False)).view(*s)

  | Name           | Type             | Params
----------------------------------------------------
0 | model          | Sequential       | 109 K 
1 | train_accuracy | Accuracy         | 0     
2 | val_accuracy   | Accuracy         | 0     
3 | loss_f[...]
{'fraction_non_alphanumeric': 0.1156024214020699, 'fraction_numerical': 0.012302284710017574, 'mean_word_length': 3.3517417162276977, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 18, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '407123', 'license': 'MIT', 'n_tokens_mistral': 1710, 'n_tokens_neox': 1674, 'n_words': 366, 'path': 'jupyter-notebooks/achieving-97.6-val-acc-on-mnist.ipynb', 'repo_name': 'homomorfism/data-analysis', 'size': '5121'}