{ "cells": [ { "cell_type": "markdown", "id": "e88ec0d9-3de0-4aa4-b028-d9e82ad9c455", "metadata": {}, "source": [ "# Neural network\n", "\n", "In this notebook we will see how tensor trains can be used to replace linear layers\n", "in neural networks. As we will see this can lead to high compression rates for fully\n", "connected layer." ] }, { "cell_type": "code", "execution_count": 1, "id": "e2f02d46-d970-4e73-a012-0256c7837d76", "metadata": {}, "outputs": [], "source": [ "from typing import Generator\n", "from copy import deepcopy\n", "from collections import deque\n", "import time\n", "\n", "import torch as tr\n", "import torch.nn as nn\n", "import torch.optim as optim\n", "import torchvision as tv\n", "from torch.utils.data import DataLoader\n", "\n", "from trainsum.torch import trainsum as ts\n", "from trainsum.typing import TrainShape, EinsumExpression, TensorTrain\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 2, "id": "d27ba58a-3355-4ab5-99c7-5662786bca62", "metadata": {}, "outputs": [], "source": [ "# create the datasets and data loaders\n", "transform = tv.transforms.Compose([\n", " tv.transforms.ToTensor(),\n", " tv.transforms.Normalize((0.1307,), (0.3081,)) # Normalize with MNIST mean and std\n", "])\n", "\n", "train_dataset = tv.datasets.MNIST(\n", " root='./data',\n", " train=True,\n", " download=True,\n", " transform=transform\n", ")\n", "\n", "test_dataset = tv.datasets.MNIST(\n", " root='./data',\n", " train=False,\n", " download=True,\n", " transform=transform\n", ")\n", "\n", "train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\n", "test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)" ] }, { "cell_type": "markdown", "id": "01a13613-c867-465f-b698-66d717464cdb", "metadata": {}, "source": [ "First we load a MNIST dataset (hand written numbers from 0 to 9) and save it in the\n", "folder ./data. The set is divided into a training set (train_loader) and testing set (test_loader)." ] }, { "cell_type": "code", "execution_count": 3, "id": "afb9ad76-2222-4d0f-b17d-0af4031f255b", "metadata": {}, "outputs": [], "source": [ "class LinearLayerNN(nn.Module):\n", " \"\"\"Simple neural network, which has three linear layer connected via relu activation funktions.\"\"\"\n", " def __init__(self, size: int):\n", " super(LinearLayerNN, self).__init__()\n", " self.flatten = nn.Flatten()\n", " self.relu = nn.ReLU()\n", " self.fc1 = nn.Linear(28*28, size)\n", " self.fc2 = nn.Linear(size, size)\n", " self.fc3 = nn.Linear(size, 10)\n", "\n", " def forward(self, x):\n", " x = self.flatten(x)\n", " x = self.fc1(x)\n", " x = self.relu(x)\n", " x = self.fc2(x)\n", " x = self.relu(x)\n", " x = self.fc3(x)\n", " return x" ] }, { "cell_type": "markdown", "id": "ca035f93-1c8a-4aba-be03-d9b5d847446d", "metadata": {}, "source": [ "Here we define the neural network that we will use to classify the numbers. We have three fully connected layer,\n", "that are combined with the ReLu activation function." ] }, { "cell_type": "code", "execution_count": 4, "id": "9edd52e2-6d8c-4c1d-9f66-a6cada507f80", "metadata": {}, "outputs": [], "source": [ "def training(train_loader: DataLoader, model: nn.Module, epochs: int) -> Generator[float]:\n", " \"\"\"Start the training loop for some data loader and a model.\"\"\"\n", " criterion = nn.CrossEntropyLoss()\n", " optimizer = optim.SGD(model.parameters(), lr=1e-2, momentum=0.9)\n", " scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9)\n", " running_loss = deque()\n", " for epoch in range(epochs):\n", " \n", " for i, (inputs, labels) in enumerate(train_loader):\n", " \n", " optimizer.zero_grad()\n", " outputs = model(inputs)\n", " loss = criterion(outputs, labels)\n", " loss.backward()\n", " optimizer.step()\n", "\n", " \n", " # Print statistics\n", " running_loss.append(loss.item())\n", " if len(running_loss) == 100:\n", " running_loss.popleft()\n", " print(f\"Epoch [{epoch+1}/{epochs}], Step [{i+1}/{len(train_loader)}],\", end=\"\")\n", " print(f\"Loss: {sum(running_loss)/len(running_loss):.4f}\", end=\"\\r\", flush=True)\n", " yield loss.item()\n", " \n", " scheduler.step()\n", " print()\n", " \n", "def eval_model(test_loader: DataLoader, model: nn.Module):\n", " \"\"\"Evaluate the model against a training set and print the result accuracy.\"\"\"\n", " model.eval()\n", " correct = 0\n", " total = 0\n", " \n", " t = time.time()\n", " with tr.no_grad():\n", " for images, labels in test_loader:\n", " outputs = model(images)\n", " _, predicted = tr.max(outputs.data, 1)\n", " total += labels.size(0)\n", " correct += (predicted == labels).sum().item()\n", " diff = time.time() - t\n", " \n", " accuracy = 100 * correct / total\n", " print(f'Accuracy on the test set is {accuracy:.2f}% and took {diff:.2f}s')\n", " \n", "def print_memory_savings(model: nn.Module, ref_model: nn.Module):\n", " \"\"\"Print the memory savings of some model in respect to a reference model\"\"\"\n", " model_numel = sum(param.numel() for param in model.parameters())\n", " ref_model_numel = sum(param.numel() for param in ref_model.parameters())\n", " perc = model_numel / ref_model_numel * 100\n", " print(f\"{100-perc:.0f}% memory savings in respect to the reference model\")" ] }, { "cell_type": "markdown", "id": "b0a5e225-7bf7-445a-8536-e082ffb9289e", "metadata": {}, "source": [ "The training is defined as a Generator object which returns the current loss at each step.\n", "The eval_model function evaluates the accuracy of the model in respect to the test dataset.\n", "The last function is a utility functions calculating the difference in the number of parameters\n", "of two models." ] }, { "cell_type": "code", "execution_count": 5, "id": "01ed452a-18e9-4bbe-b7a3-ac3d68d048fc", "metadata": {}, "outputs": [], "source": [ "from math import prod\n", "class TrainLayer(nn.Module):\n", " \"\"\"Tensor train layer as replacement for a Linear layer.\"\"\"\n", "\n", " _train: TensorTrain\n", " _exprs: dict[int, tuple[TrainShape | EinsumExpression]]\n", "\n", " def __init__(self, data: tr.Tensor, max_rank: int) -> None:\n", " \"\"\"Create a tensor train torch-layer by approximating data with a maximum rank.\"\"\"\n", " super().__init__()\n", " self._exprs = {}\n", "\n", " # convert the full input matrix to a tensor train\n", " data = data.T\n", " shape = ts.trainshape(*data.shape, mode=\"block\")\n", " with ts.variational(max_rank=max_rank, cutoff=1e-7, ncores=2, nsweeps=2):\n", " self._train = ts.tensortrain(shape, data)\n", "\n", " # attach the data of the tensor train cores as weights to the model\n", " self.weights = nn.ParameterList(nn.Parameter(core) for core in self._train.cores)\n", "\n", " def forward(self, data: tr.Tensor) -> tr.Tensor:\n", " \"\"\"Apply the linear map defined by the tensor train to data.\"\"\"\n", " # get rid of batch sizes 1\n", " data = data if data.shape[0] != 1 else data[0,:]\n", "\n", " # calculate the expression for the batch size if not present\n", " if data.shape[0] not in self._exprs:\n", " if len(data.shape) == 1:\n", " inp_dims = [self._train.tnshape.dims[0]]\n", " else:\n", " inp_dims = [ts.dimension([data.shape[0]]), self._train.shape.dims[0]]\n", " out_dims = [self._train.shape.dims[1]]\n", " inp_shape = ts.trainshape(*inp_dims, mode=\"full\")\n", " out_shape = ts.trainshape(*out_dims, mode=\"block\")\n", " with ts.exact(optimizer=\"random-greedy-128\"):\n", " expr = ts.einsum_expression(\"ai,ij->aj\", inp_shape, self._train.shape, result_shape=out_shape)\n", " self._exprs[data.shape[0]] = (inp_shape, expr)\n", "\n", " # create input without copying\n", " shape, expr = self._exprs[data.shape[0]]\n", " view = [1, *[d.base for dim in shape.dims for d in dim], 1]\n", " inp = ts.tensortrain(shape, [data.view(view)])\n", "\n", " # perform the mapping\n", " res = expr(inp, self._train)\n", "\n", " # convert the result to a tensor\n", " return res.to_tensor()\n", "\n", " def normalize(self, idx: int):\n", " self._train.normalize(idx)" ] }, { "cell_type": "markdown", "id": "fd3044b8-a3ed-4e5b-a043-9bb810d357e7", "metadata": {}, "source": [ "Since trainsum is a rather low level API, it does not include neural network layers. Here is a simple\n", "example how such a layer can be built. It is called TrainLayer and will upon initialization approximate\n", "some given data variationally with some maximum rank. The cores of the train are then interpreted as \n", "trainable neural network parameters. The only function that a nn.Module needs is the forward function\n", "that applies some operation to the data. In our case this is a linear map defined by the tensor train.\n", "Since the result needs to be a vector (not a tensor train) and therefore has no ranks we perform the \n", "operation exact. We try to cache the einsum expression for improved performance." ] }, { "cell_type": "code", "execution_count": 6, "id": "06de877d-4416-45a3-9691-03fd3c8d4bfd", "metadata": {}, "outputs": [], "source": [ "def normalization_sweeping(layer: TrainLayer) -> Generator[None]:\n", " \"\"\"\n", " Create a generator, which upen called normalizes the layer to a single core in a sweeping manner.\n", " The layer is altered so that only the normalized core is active.\n", " \"\"\"\n", " length = len(layer.weights)\n", " for i in range(length):\n", " layer.weights[i].requires_grad = False\n", " last_idx = 0\n", " while True:\n", " for i in range(length-1):\n", " layer.weights[last_idx].requires_grad = False\n", " layer.normalize(i)\n", " layer.weights[i].requires_grad = True\n", " last_idx = i\n", " yield\n", " for i in range(1, length)[::-1]:\n", " layer.weights[last_idx].requires_grad = False\n", " layer.normalize(i)\n", " layer.weights[i].requires_grad = True\n", " last_idx = i\n", " yield" ] }, { "cell_type": "markdown", "id": "7ea894aa-00b6-40f4-b1b4-806410fe2f3c", "metadata": {}, "source": [ "The normalization sweeping function brings the TrainLayer into a canonical format. The core that has been normalized onto \n", "is the only core with trainable parameters. The reason for this function is, that keeping all cores variable leads to a \n", "highly nonlinear behaviour, which might not be advantageous for the optimization (depends on the problem though)." ] }, { "cell_type": "code", "execution_count": 7, "id": "230770e3-2319-4831-babb-135312098fc4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch [2/2], Step [1875/1875],Loss: 0.0719\n", "Accuracy on the test set is 97.36% and took 3.18s\n" ] } ], "source": [ "# define the size of the linear layers\n", "size = 2**8\n", "\n", "#create the linear model\n", "ref_model = LinearLayerNN(size)\n", "\n", "# train the model\n", "model_loss = []\n", "train_gen = training(train_loader, ref_model, 2)\n", "for loss in train_gen:\n", " model_loss.append(loss)\n", "eval_model(test_loader, ref_model)" ] }, { "cell_type": "markdown", "id": "6553d68d-1cd0-4e36-a871-4361dc577cf1", "metadata": {}, "source": [ "After defining all layers we can start by training the normal neural network with a size of 256." ] }, { "cell_type": "code", "execution_count": 8, "id": "dcd619c4-cb59-4182-873f-1dd4b07fe06d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch [2/2], Step [1875/1875],Loss: 0.1179\n", "72% memory savings in respect to the reference model\n", "Accuracy on the test set is 96.34% and took 2.63s\n" ] } ], "source": [ "# create the tensorized model by approximating the first layer\n", "tn_model = deepcopy(ref_model)\n", "tn_model.fc1 = TrainLayer(ref_model.fc1.weight.data, 16)\n", "\n", "# start the training\n", "tn_model_loss = []\n", "training_gen = training(train_loader, tn_model, 2)\n", "norm_sweep = normalization_sweeping(tn_model.fc1)\n", "while True:\n", " try:\n", " next(norm_sweep)\n", " tn_model_loss.append(next(training_gen))\n", " except StopIteration:\n", " break\n", "\n", "print_memory_savings(tn_model, ref_model)\n", "eval_model(test_loader, tn_model)" ] }, { "cell_type": "code", "execution_count": 12, "id": "734864e3-a178-45b6-aebb-71ce851099f9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Accuracy on the test set is 97.36% and took 2.61s\n", "Accuracy on the test set is 96.34% and took 3.24s\n" ] } ], "source": [ "eval_model(test_loader, ref_model)\n", "eval_model(test_loader, tn_model)" ] }, { "cell_type": "markdown", "id": "8c31df2e-1c8b-465f-ae68-ab9bc8f0bb12", "metadata": {}, "source": [ "Using the pretrained model as input we can now approximate the first layer as a tensor train.\n", "By using the training generator and the normalization sweeping we train the newly created compressed model.\n", "In this example we get memory savings of 72% without a big loss of accuracy." ] }, { "cell_type": "code", "execution_count": 10, "id": "669c180b-f52e-41f7-a513-25be38858961", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure()\n", "plt.plot(model_loss, label=\"model loss\")\n", "plt.plot(tn_model_loss, label=\"tn model loss\")\n", "plt.legend()\n", "plt.xlabel(\"iteration\")\n", "plt.ylabel(\"loss\")\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.14.3" } }, "nbformat": 4, "nbformat_minor": 5 }