aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ipynb_checkpoints/transformer_shortest_paths-checkpoint.ipynb717
-rw-r--r--README.md137
-rw-r--r--images/ink_img001.pngbin0 -> 228445 bytes
-rw-r--r--images/ink_img001.svg76
-rw-r--r--transformer_shortest_paths.ipynb2
5 files changed, 914 insertions, 18 deletions
diff --git a/.ipynb_checkpoints/transformer_shortest_paths-checkpoint.ipynb b/.ipynb_checkpoints/transformer_shortest_paths-checkpoint.ipynb
new file mode 100644
index 0000000..ee844fb
--- /dev/null
+++ b/.ipynb_checkpoints/transformer_shortest_paths-checkpoint.ipynb
@@ -0,0 +1,717 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "LPphBnKR-aWF"
+ },
+ "source": [
+ "# Step 0: Imports"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "ge5QvElvhCOw",
+ "outputId": "c7cdaefa-d6dc-44ad-c258-e4fb2aca97a5"
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "imports complete\n"
+ ]
+ }
+ ],
+ "source": [
+ "# imports\n",
+ "import numpy as np\n",
+ "from collections import deque\n",
+ "import pickle\n",
+ "from tqdm import tqdm\n",
+ "np.random.seed(42)\n",
+ "\n",
+ "import torch\n",
+ "import torch.nn as nn\n",
+ "import pickle\n",
+ "from math import sqrt\n",
+ "from torch.utils.data import DataLoader, TensorDataset\n",
+ "import matplotlib.pyplot as plt\n",
+ "torch.manual_seed(42)\n",
+ "\n",
+ "import os\n",
+ "\n",
+ "print(\"imports complete\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "id": "lylOX2POPwFL"
+ },
+ "outputs": [],
+ "source": [
+ "SEQ_LEN = 32\n",
+ "\n",
+ "PAD_TOKEN = 0\n",
+ "AVG_DEG = 2\n",
+ "MAX_VTXS = SEQ_LEN//AVG_DEG - 1\n",
+ "# vertices are labelled 1,2,...,63\n",
+ "# we also have a padding token which is 0.\n",
+ "\n",
+ "INF = MAX_VTXS # represents unreachability"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "gKt-yIpDebF1"
+ },
+ "source": [
+ "# Step 1: Generate synthetic data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "1IbzGIWseK3E",
+ "outputId": "a3cbc233-358c-4e17-ea6e-f4e9349d886b"
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|██████████| 1/1 [00:14<00:00, 14.42s/it]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# original task data\n",
+ "NTRAIN1 = 100_000\n",
+ "# the data will be edge lists\n",
+ "# like this: [1 3 1 5 2 4 0 0 0 0]\n",
+ "# this represents edges (1,3), (1,5) (2,4)\n",
+ "# (the zeros are just padding tokens)\n",
+ "\n",
+ "# the label is the shortest distance from vtx 1 to vtx 2\n",
+ "# or \"INF\" if no path exists\n",
+ "\n",
+ "# fine tuning data\n",
+ "NTRAIN2 = 2000\n",
+ "# I haven't totally figured out how to do the fine tuning yet.\n",
+ "# So don't worry about this yet.\n",
+ "\n",
+ "def random_graph(n):\n",
+ " edge_list = []\n",
+ " adjacencies = [set() for _ in range(n+1)]\n",
+ " indices = np.random.randint(n, size=(AVG_DEG*(n-1)))+1\n",
+ " for i in range(0, len(indices), 2):\n",
+ " u = indices[i]\n",
+ " v = indices[i + 1]\n",
+ " if u != v:\n",
+ " edge_list += [u,v]\n",
+ " adjacencies[u].add(v)\n",
+ " adjacencies[v].add(u)\n",
+ "\n",
+ " if np.random.random() < 0.25:\n",
+ " edge_list += [1,2]\n",
+ " adjacencies[1].add(2)\n",
+ " adjacencies[2].add(1)\n",
+ "\n",
+ " edge_list += [PAD_TOKEN]*(SEQ_LEN-len(edge_list))\n",
+ " return edge_list, adjacencies\n",
+ "\n",
+ "\"\"\"\n",
+ "input: G, represented as an adjacency list\n",
+ "output: [INF]+[d(1,i) for i in range(n)] if target=None\n",
+ "if target is set to some value, then we instead just output that specific distance\n",
+ "\"\"\"\n",
+ "def SSSP(G, target=None):\n",
+ " dist = [INF for _ in G]\n",
+ " dist[1] = 0\n",
+ " frontier = deque()\n",
+ " frontier.append(1)\n",
+ " while len(frontier) > 0:\n",
+ " vtx = frontier.popleft()\n",
+ " for x in G[vtx]:\n",
+ " if dist[x] == INF:\n",
+ " dist[x] = 1 + dist[vtx]\n",
+ " frontier.append(x)\n",
+ " if x == target:\n",
+ " return dist[target]\n",
+ " if target is not None:\n",
+ " return dist[target]\n",
+ " else:\n",
+ " return dist\n",
+ "\n",
+ "def fake_SSSP(G, target=None):\n",
+ " return 2 in G[1]\n",
+ "\n",
+ "graphs1 = []\n",
+ "distance1 = []\n",
+ "\n",
+ "graphs2 = []\n",
+ "distances2 = []\n",
+ "\n",
+ "for n in tqdm(range(MAX_VTXS-1, MAX_VTXS)):\n",
+ " # for _ in range(NTRAIN1//MAX_VTXS):\n",
+ " for _ in range(NTRAIN1):\n",
+ " edge_list, adj_list = random_graph(n)\n",
+ " dist = SSSP(adj_list, target=2)\n",
+ "\n",
+ " graphs1.append(edge_list)\n",
+ " distance1.append(dist)\n",
+ "\n",
+ "# for n in range(8, MAX_VTXS//4):\n",
+ "# for _ in range(NTRAIN2//MAX_VTXS):\n",
+ "# edge_list, adj_list = random_graph(n)\n",
+ "# distances = SSSP(adj_list)\n",
+ "# graphs2.append(edge_list)\n",
+ "# distances2.append(distances)\n",
+ "\n",
+ "split1 = int(len(graphs1)*3/4)\n",
+ "split2 = int(len(graphs2)*3/4)\n",
+ "\n",
+ "all1 = list(zip(graphs1, distance1))\n",
+ "np.random.shuffle(all1)\n",
+ "graphs1, distance1 = zip(*all1)\n",
+ "\n",
+ "data = {\n",
+ " \"train1-data\": graphs1[:split1],\n",
+ " \"train1-labels\": distance1[:split1],\n",
+ " \"test1-data\": graphs1[split1:],\n",
+ " \"test1-labels\": distance1[split1:]\n",
+ " # \"train2-data\": graphs2[:split2],\n",
+ " # \"train2-labels\": distances2[:split2],\n",
+ " # \"test2-data\": graphs2[split2:],\n",
+ " # \"test2-labels\": distances2[split2:]\n",
+ "}\n",
+ "\n",
+ "with open('data.pkl', 'wb') as file:\n",
+ " pickle.dump(data, file)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 74,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "torch.Size([75000, 32])\n",
+ "DONE\n"
+ ]
+ }
+ ],
+ "source": [
+ "NTRAIN1 = 100000\n",
+ "\n",
+ "graphs1 = torch.randint(1, MAX_VTXS, (NTRAIN1, SEQ_LEN))\n",
+ "\n",
+ "# check if token 1 is in the graph\n",
+ "def silly_distance(graph):\n",
+ " return int(1 in graph)\n",
+ "\n",
+ "# check if both token 1 and token 2 are in the graph\n",
+ "def silly_distance2(graph):\n",
+ " return int(1 in graph and 2 in graph and 3 in graph and 4 in graph and 5 in graph)\n",
+ "\n",
+ "def silly_distance3(graph):\n",
+ " for i in range(len(graph)//2):\n",
+ " if graph[2*i] + graph[2*i+1] == 3:\n",
+ " return 1\n",
+ " return 0\n",
+ "\n",
+ "distance1 = [silly_distance3(graph) for graph in graphs1]\n",
+ "\n",
+ "split1 = int(len(graphs1)*3/4)\n",
+ "\n",
+ "data = {\n",
+ " \"train1-data\": graphs1[:split1],\n",
+ " \"train1-labels\": distance1[:split1],\n",
+ " \"test1-data\": graphs1[split1:],\n",
+ " \"test1-labels\": distance1[split1:]\n",
+ "}\n",
+ "\n",
+ "print(data[\"train1-data\"].shape)\n",
+ "\n",
+ "with open('data.pkl', 'wb') as file:\n",
+ " pickle.dump(data, file)\n",
+ "\n",
+ "print(\"DONE\")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 76,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.1518"
+ ]
+ },
+ "execution_count": 76,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "0.1518"
+ ]
+ },
+ "execution_count": 75,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sum(distance1)/len(distance1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 77,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "EpDBxcgaIPpJ",
+ "outputId": "37cf9577-8cd8-444c-ec1a-c6f4b6061b7f"
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "dataset size = 49MB\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(f\"dataset size = {os.path.getsize('data.pkl')//(1024*1024)}MB\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Q3Cg_8UQep8g"
+ },
+ "source": [
+ "# Step 2: Define Transformer Model"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 107,
+ "metadata": {
+ "id": "tLOWhg_CeWzH"
+ },
+ "outputs": [],
+ "source": [
+ "class TransformerModel(nn.Module):\n",
+ " def __init__(self, input_dim, model_dim, output_dim, num_heads, num_layers, seq_len, device, dropout=0.1):\n",
+ " super().__init__()\n",
+ " self.embedding = nn.Embedding(input_dim, model_dim//2)\n",
+ " self.model_dim = model_dim\n",
+ " self.seq_len = seq_len\n",
+ " self.device = device\n",
+ "\n",
+ " encoder_layer = nn.TransformerEncoderLayer(d_model=model_dim, nhead=num_heads,\n",
+ " dim_feedforward=model_dim*4,\n",
+ " dropout=dropout, batch_first=True)\n",
+ " self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_layers)\n",
+ "\n",
+ " self.fc_out = nn.Linear(model_dim*seq_len, output_dim)\n",
+ " self.fancy_encoding = torch.repeat_interleave(torch.rand((1,SEQ_LEN // 2, model_dim // 2), device=device), 2, dim=1)\n",
+ " \n",
+ " def positional_encoding(self, batch_size):\n",
+ " position = torch.arange(self.seq_len, dtype=torch.float, device=self.device).unsqueeze(1)\n",
+ " div_term = torch.exp(torch.arange(0, self.model_dim, 2, dtype=torch.float, device=self.device) *\n",
+ " -(torch.log(torch.tensor(500.0)) / self.model_dim))\n",
+ "\n",
+ " pos_encoding = torch.zeros(self.seq_len, self.model_dim, device=self.device)\n",
+ " pos_encoding[:, 0::2] = torch.sin(position * div_term)\n",
+ " pos_encoding[:, 1::2] = torch.cos(position * div_term)\n",
+ " pos_encoding = pos_encoding.unsqueeze(0).repeat(batch_size, 1, 1)\n",
+ " return pos_encoding\n",
+ "\n",
+ " def forward(self, src, key_padding_mask):\n",
+ " batch_size, src_len = src.size(0), src.size(1)\n",
+ " # src_pos = self.positional_encoding(batch_size)\n",
+ " embed = self.embedding(src)\n",
+ " src = torch.cat((embed * sqrt(self.model_dim), torch.Tensor.repeat(self.fancy_encoding, (batch_size, 1, 1))), dim=2)\n",
+ "\n",
+ " output = self.transformer_encoder(src, None, src_key_padding_mask=key_padding_mask)\n",
+ " flat_output = torch.flatten(output, start_dim=1, end_dim=2)\n",
+ " output = self.fc_out(flat_output)\n",
+ " return output\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "bpIeg86S-hBb"
+ },
+ "source": [
+ "# Step 3: Load Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 121,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "kWXvJRDYgFVP",
+ "outputId": "c13adb9d-6565-43b5-8437-20cef3dc0d16"
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Trainable parameters in the model: 102K\n",
+ "train BASELINEs: 0.1290\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/tmp/ipykernel_390590/1991115476.py:23: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
+ " train_data_tensor = torch.tensor(train_data1, dtype=torch.long, device=device)\n",
+ "/tmp/ipykernel_390590/1991115476.py:31: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
+ " test_data_tensor = torch.tensor(test_data1, dtype=torch.long, device=device)\n"
+ ]
+ }
+ ],
+ "source": [
+ "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
+ "assert device.type == 'cuda', \"CUDA is not available. Please check your GPU setup.\"\n",
+ "\n",
+ "# PARAMS\n",
+ "VOCAB_SIZE = 1+MAX_VTXS # one more than the max number of vertices\n",
+ "MODEL_DIM = 64 # Dimension of model (embedding and transformer)\n",
+ "NEPOCHS = 50\n",
+ "BSZ = 512\n",
+ "LR = 0.001\n",
+ "NHEADS = 4\n",
+ "NLAYERS = 2\n",
+ "PAD_TOKEN = 0\n",
+ "model = TransformerModel(input_dim=VOCAB_SIZE, model_dim=MODEL_DIM,\n",
+ " output_dim=1, num_heads=NHEADS,\n",
+ " num_layers=NLAYERS, seq_len=SEQ_LEN,\n",
+ " device=device).to(device)\n",
+ "\n",
+ "with open(\"data.pkl\", \"rb\") as f:\n",
+ " data = pickle.load(f)\n",
+ "\n",
+ "train_data1 = data[\"train1-data\"]\n",
+ "train_label1 = data[\"train1-labels\"]\n",
+ "train_data_tensor = torch.tensor(train_data1, dtype=torch.long, device=device)\n",
+ "train_label_tensor = torch.tensor(train_label1, dtype=torch.float, device=device)\n",
+ "train_padding_mask = (train_data_tensor == PAD_TOKEN).bool().to(device)\n",
+ "train_dataset = TensorDataset(train_data_tensor, train_label_tensor, train_padding_mask)\n",
+ "train_loader = DataLoader(train_dataset, batch_size=BSZ, shuffle=True)\n",
+ "\n",
+ "test_data1 = data[\"test1-data\"]\n",
+ "test_label1 = data[\"test1-labels\"]\n",
+ "test_data_tensor = torch.tensor(test_data1, dtype=torch.long, device=device)\n",
+ "test_label_tensor = torch.tensor(test_label1, dtype=torch.float, device=device)\n",
+ "test_padding_mask = (test_data_tensor == PAD_TOKEN).bool().to(device)\n",
+ "test_dataset = TensorDataset(test_data_tensor, test_label_tensor, test_padding_mask)\n",
+ "test_loader = DataLoader(test_dataset, batch_size=BSZ, shuffle=True)\n",
+ "\n",
+ "criterion = nn.MSELoss()\n",
+ "optimizer = torch.optim.Adam(model.parameters(), lr=LR)\n",
+ "\n",
+ "train_err = []\n",
+ "test_err = []\n",
+ "\n",
+ "trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
+ "print(f\"Trainable parameters in the model: {trainable_params//1000}K\")\n",
+ "\n",
+ "train_baseline = ((train_label_tensor - train_label_tensor.mean())**2).mean().item()\n",
+ "print(f\"train BASELINEs: {train_baseline:.4f}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "f8Zn33m7CxL5"
+ },
+ "source": [
+ "# Step 4: Train the Model for the first task"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 122,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 486
+ },
+ "id": "pvTfzGmCeXU4",
+ "outputId": "0d3a20f3-23be-4c19-9eb6-46bfe11a48b1"
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch 1/50 \t Train Err: 0.1621 \t Test Err: 0.1208 \t baseline err: 0.1290\n",
+ "Epoch 2/50 \t Train Err: 0.1266 \t Test Err: 0.1201 \t baseline err: 0.1290\n",
+ "Epoch 3/50 \t Train Err: 0.1224 \t Test Err: 0.1199 \t baseline err: 0.1290\n",
+ "Epoch 4/50 \t Train Err: 0.1190 \t Test Err: 0.1214 \t baseline err: 0.1290\n",
+ "Epoch 5/50 \t Train Err: 0.1167 \t Test Err: 0.1164 \t baseline err: 0.1290\n",
+ "Epoch 6/50 \t Train Err: 0.1154 \t Test Err: 0.1156 \t baseline err: 0.1290\n",
+ "Epoch 7/50 \t Train Err: 0.1146 \t Test Err: 0.1131 \t baseline err: 0.1290\n",
+ "Epoch 8/50 \t Train Err: 0.1140 \t Test Err: 0.1145 \t baseline err: 0.1290\n",
+ "Epoch 9/50 \t Train Err: 0.1135 \t Test Err: 0.1144 \t baseline err: 0.1290\n",
+ "Epoch 10/50 \t Train Err: 0.1134 \t Test Err: 0.1160 \t baseline err: 0.1290\n",
+ "Epoch 11/50 \t Train Err: 0.1134 \t Test Err: 0.1160 \t baseline err: 0.1290\n",
+ "Epoch 12/50 \t Train Err: 0.1129 \t Test Err: 0.1137 \t baseline err: 0.1290\n",
+ "Epoch 13/50 \t Train Err: 0.1131 \t Test Err: 0.1122 \t baseline err: 0.1290\n",
+ "Epoch 14/50 \t Train Err: 0.1125 \t Test Err: 0.1133 \t baseline err: 0.1290\n",
+ "Epoch 15/50 \t Train Err: 0.1121 \t Test Err: 0.1119 \t baseline err: 0.1290\n",
+ "Epoch 16/50 \t Train Err: 0.1120 \t Test Err: 0.1129 \t baseline err: 0.1290\n",
+ "Epoch 17/50 \t Train Err: 0.1123 \t Test Err: 0.1123 \t baseline err: 0.1290\n",
+ "Epoch 18/50 \t Train Err: 0.1120 \t Test Err: 0.1119 \t baseline err: 0.1290\n",
+ "Epoch 19/50 \t Train Err: 0.1117 \t Test Err: 0.1148 \t baseline err: 0.1290\n",
+ "Epoch 20/50 \t Train Err: 0.1119 \t Test Err: 0.1136 \t baseline err: 0.1290\n",
+ "Epoch 21/50 \t Train Err: 0.1117 \t Test Err: 0.1120 \t baseline err: 0.1290\n",
+ "Epoch 22/50 \t Train Err: 0.1114 \t Test Err: 0.1123 \t baseline err: 0.1290\n",
+ "Epoch 23/50 \t Train Err: 0.1111 \t Test Err: 0.1121 \t baseline err: 0.1290\n",
+ "Epoch 24/50 \t Train Err: 0.1093 \t Test Err: 0.1061 \t baseline err: 0.1290\n",
+ "Epoch 25/50 \t Train Err: 0.1044 \t Test Err: 0.1012 \t baseline err: 0.1290\n",
+ "Epoch 26/50 \t Train Err: 0.1012 \t Test Err: 0.1003 \t baseline err: 0.1290\n",
+ "Epoch 27/50 \t Train Err: 0.0985 \t Test Err: 0.0964 \t baseline err: 0.1290\n",
+ "Epoch 28/50 \t Train Err: 0.0957 \t Test Err: 0.0942 \t baseline err: 0.1290\n",
+ "Epoch 29/50 \t Train Err: 0.0947 \t Test Err: 0.0935 \t baseline err: 0.1290\n",
+ "Epoch 30/50 \t Train Err: 0.0931 \t Test Err: 0.0941 \t baseline err: 0.1290\n",
+ "Epoch 31/50 \t Train Err: 0.0920 \t Test Err: 0.0916 \t baseline err: 0.1290\n",
+ "Epoch 32/50 \t Train Err: 0.0893 \t Test Err: 0.0857 \t baseline err: 0.1290\n",
+ "Epoch 33/50 \t Train Err: 0.0868 \t Test Err: 0.0814 \t baseline err: 0.1290\n",
+ "Epoch 34/50 \t Train Err: 0.0827 \t Test Err: 0.0785 \t baseline err: 0.1290\n",
+ "Epoch 35/50 \t Train Err: 0.0770 \t Test Err: 0.0720 \t baseline err: 0.1290\n",
+ "Epoch 36/50 \t Train Err: 0.0713 \t Test Err: 0.0646 \t baseline err: 0.1290\n",
+ "Epoch 37/50 \t Train Err: 0.0642 \t Test Err: 0.0540 \t baseline err: 0.1290\n",
+ "Epoch 38/50 \t Train Err: 0.0588 \t Test Err: 0.0501 \t baseline err: 0.1290\n",
+ "Epoch 39/50 \t Train Err: 0.0543 \t Test Err: 0.0456 \t baseline err: 0.1290\n",
+ "Epoch 40/50 \t Train Err: 0.0488 \t Test Err: 0.0366 \t baseline err: 0.1290\n",
+ "Epoch 41/50 \t Train Err: 0.0416 \t Test Err: 0.0315 \t baseline err: 0.1290\n",
+ "Epoch 42/50 \t Train Err: 0.0360 \t Test Err: 0.0214 \t baseline err: 0.1290\n",
+ "Epoch 43/50 \t Train Err: 0.0305 \t Test Err: 0.0172 \t baseline err: 0.1290\n",
+ "Epoch 44/50 \t Train Err: 0.0239 \t Test Err: 0.0116 \t baseline err: 0.1290\n",
+ "Epoch 45/50 \t Train Err: 0.0205 \t Test Err: 0.0117 \t baseline err: 0.1290\n",
+ "Epoch 46/50 \t Train Err: 0.0181 \t Test Err: 0.0092 \t baseline err: 0.1290\n",
+ "Epoch 47/50 \t Train Err: 0.0164 \t Test Err: 0.0100 \t baseline err: 0.1290\n",
+ "Epoch 48/50 \t Train Err: 0.0155 \t Test Err: 0.0081 \t baseline err: 0.1290\n",
+ "Epoch 49/50 \t Train Err: 0.0141 \t Test Err: 0.0074 \t baseline err: 0.1290\n",
+ "Epoch 50/50 \t Train Err: 0.0129 \t Test Err: 0.0075 \t baseline err: 0.1290\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1cAAAHWCAYAAACbsXOkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAACL8ElEQVR4nOzde3yO9R/H8dd972hjc5ht5jSnHMKcj0UJK+V87kD4UbJSK0UHh04kpKKUIoqIIiEZhYqcZg7lTM5zKIyNbbb798fXxtqw2b3dO7yfj8f1uO/7ur/XdX2uu+/Pz8f3e32+FpvNZkNEREREREQyxeroAERERERERPICJVciIiIiIiJ2oORKRERERETEDpRciYiIiIiI2IGSKxERERERETtQciUiIiIiImIHSq5ERERERETsQMmViIiIiIiIHSi5EhERERERsQMlVyIiIpKmL774AovFwqZNmxwdiohIrqDkSkQkH/joo4+wWCw0bNjQ0aHIdZKSlxttf/zxh6NDFBGRDHB2dAAiIpL1Zs2aRWBgIBs2bGDfvn1UrFjR0SHJdV5//XXKlSuXar/+O4mI5C5KrkRE8riDBw+ydu1avvvuO5544glmzZrFiBEjHB1WmqKjo/H09HR0GNnugQceoF69eo4OQ0REMknTAkVE8rhZs2ZRpEgRHnzwQbp06cKsWbPSbHfu3Dmee+45AgMDcXNzo1SpUvTq1YszZ84kt7l8+TIjR47kjjvuwN3dnRIlStCpUyf2798PwKpVq7BYLKxatSrFuf/++28sFgtffPFF8r7HH3+cggULsn//ftq0aUOhQoV45JFHAPj111/p2rUrZcqUwc3NjdKlS/Pcc89x6dKlVHHv2rWLbt26Ubx4cQoUKEDlypV55ZVXAPjll1+wWCwsWLAg1XGzZ8/GYrGwbt26NH+PTZs2YbFYmDFjRqrvfvrpJywWC4sXLwbgwoULPPvss8m/na+vL61atSI8PPwG/1UyJun3GzduHO+99x5ly5alQIECNG/enB07dqRq//PPP3P33Xfj6elJ4cKFad++PTt37kzV7tixY/Tr14+AgADc3NwoV64cAwcOJC4uLkW72NhYQkNDKV68OJ6ennTs2JHTp0+naLNp0yaCg4Px8fGhQIEClCtXjr59+9rl/kVEcguNXImI5HGzZs2iU6dOuLq60rNnTz7++GM2btxI/fr1k9tcvHiRu+++m507d9K3b1/q1KnDmTNnWLRoEUePHsXHx4eEhAQeeughVq5cSY8ePRg8eDAXLlwgLCyMHTt2UKFChQzHduXKFYKDg7nrrrsYN24cHh4eAMybN4+YmBgGDhxIsWLF2LBhAx9++CFHjx5l3rx5ycdv27aNu+++GxcXFwYMGEBgYCD79+/nhx9+4K233uKee+6hdOnSzJo1i44dO6b6XSpUqEDjxo3TjK1evXqUL1+eb775ht69e6f4bu7cuRQpUoTg4GAAnnzySebPn09ISAjVqlXjn3/+4bfffmPnzp3UqVPnlr/D+fPnUySxABaLhWLFiqXYN3PmTC5cuMCgQYO4fPky77//Pi1atGD79u34+fkBsGLFCh544AHKly/PyJEjuXTpEh9++CFNmzYlPDycwMBAAI4fP06DBg04d+4cAwYMoEqVKhw7doz58+cTExODq6tr8nWffvppihQpwogRI/j777+ZOHEiISEhzJ07F4BTp07RunVrihcvztChQylcuDB///0333333S3vXUQkT7GJiEietWnTJhtgCwsLs9lsNltiYqKtVKlStsGDB6doN3z4cBtg++6771KdIzEx0Waz2WzTpk2zAbYJEybcsM0vv/xiA2y//PJLiu8PHjxoA2zTp09P3te7d28bYBs6dGiq88XExKTaN3r0aJvFYrEdOnQoeV+zZs1shQoVSrHv+nhsNptt2LBhNjc3N9u5c+eS9506dcrm7OxsGzFiRKrrXG/YsGE2FxcX27///pu8LzY21la4cGFb3759k/d5e3vbBg0adNNzpWX69Ok2IM3Nzc0tuV3S71egQAHb0aNHk/evX7/eBtiee+655H21atWy+fr62v7555/kfVu3brVZrVZbr169kvf16tXLZrVabRs3bkwVV9LvlxRfy5YtU/ymzz33nM3JySn5N12wYIENSPNcIiL5iaYFiojkYbNmzcLPz497770Xro6GdO/enTlz5pCQkJDc7ttvvyUoKCjV6E7SMUltfHx8ePrpp2/Y5nYMHDgw1b4CBQokv4+OjubMmTM0adIEm83Gli1bADh9+jRr1qyhb9++lClT5obx9OrVi9jYWObPn5+8b+7cuVy5coVHH330prF1796d+Pj4FCMwy5cv59y5c3Tv3j15X+HChVm/fj3Hjx/P8P0DTJ48mbCw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m5vN19fX9tBDD9k2bdqUod9ZRCS3s9gyOvYvIiKSC125coWAgADatm3L559/7uhwMuTvv/+mXLlyvPvuu7zwwguODkdERG5Az1yJiEi+sHDhQk6fPk2vXr0cHYqIiORReuZKRETytPXr17Nt2zbeeOMNateunbxeloiIiL1p5EpERPK0jz/+mIEDB+Lr68vMmTMdHY6IiORheuZKRERERETEDjRyJSIiIiIiYgdKrkREREREROxABS3SkJiYyPHjxylUqBAWi8XR4YiIiIiIiIPYbDYuXLhAQEBAikXk06LkKg3Hjx+ndOnSjg5DRERERERyiCNHjlCqVKmbtlFylYZChQrB1R/Qy8vLobHEx8ezfPlyWrdujYuLi0NjkdxH/UcyQ/1HMkP9RzJD/UduV1b0naioKEqXLp2cI9yMkqs0JE0F9PLyyhHJlYeHB15eXvrDRTJM/UcyQ/1HMkP9RzJD/UduV1b2nfQ8LqSCFiIiIiIiInag5EpERERERMQOlFyJiIiIiIjYgZ65EhERERHJxRISEoiPj3d0GDlCfHw8zs7OXL58mYSEhHQd4+TkhLOzs12WYFJyJSIiIiKSS128eJGjR49is9kcHUqOYLPZ8Pf358iRIxlKljw8PChRogSurq6Zur6SKxERERGRXCghIYGjR4/i4eFB8eLF7TLyktslJiZy8eJFChYseMsFf7majMXFxXH69GkOHjxIpUqV0nXcjSi5EhERERHJheLj47HZbBQvXpwCBQo4OpwcITExkbi4ONzd3dOdJBUoUAAXFxcOHTqUfOztUkELEREREZFcTCNWmZeZ0aoU57HLWURERERERPI5JVciIiIiIiJ2oORKRERERETEDpRciYiIiIhItrBYLDfdRo4cmalzL1y40K7xZpSqBYqIiIiISLY4ceJE8vu5c+cyfPhwdu/enbyvYMGCDorMPjRylcMNHWrlySfv44cfVAVGRERERG7CZoPoaMds6VzE2N/fP3nz9vbGYrGk2DdnzhyqVq2Ku7s7VapU4aOPPko+Ni4ujpCQEEqUKIG7uztly5Zl9OjRAAQGBgLQuXNnihQpQvny5bPoR745jVzlcKdOWYiMLMi2bQl06uToaEREREQkx4qJAUeN/Fy8CJ6emTrFrFmzGD58OJMmTaJ27dps2bKF/v374+npSe/evfnggw9YtGgR33zz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K2YtrDffNOsUi0jedlvJFVerBvbu3ZuAgADGjx9PixYt+OMmc5FFREREcq1CheDHH6F+ffjnHzM0tXPnDZu7upqq7i+9ZD6/9ho8+aRJtkQk78pQchUZGcmYMWOoVKkSXbt2xcvLi9jYWBYuXMiYMWOoX79+1kUqIiIi4kje3vDTT1C7Npw6BS1awJ49N2xutaZcC+vTT01lQa2FJZJ3pTu5atu2LZUrV2bbtm1MnDiR48eP8+GHH2ZtdCIiIiI5SZEiEBYGNWpAZKRJsA4duukh16+F9cMP5pDTp7MtYhHJRulOrn788Uf69evHqFGjePDBB3FycsrayERERERyomLFTNXAatXg2DF48EFT7OImrl8La/16aNoUDh7MtohFJJukO7n67bffuHDhAnXr1qVhw4ZMmjSJM1qCXERERPIjX19YtgxKlIA//4SuXSE+/qaH/HctrJYt4eTJbItYRLJBupOrRo0aMXXqVE6cOMETTzzBnDlzCAgIIDExkbCwMC5cuJC1kYqIiIjkJKVLw+LFpppgWBg89dQtSwImrYVVvjwcOGAGvS5ezLaIRSSLZbhaoKenJ3379uW3335j+/btPP/884wZMwZfX1/atWuXNVGKiIiI5ER16sCcOaZ6xWefwdixtzwkIMAMevn4wObN6Rr0EpFc4rZLsQNUrlyZsWPHcvToUb7++mv7RSUiIiKSWzz0EEycaN4PHQrffHPLQypVMoNeBQqYRGvAAK2DJZIXZCq5SuLk5ESHDh1YtGiRPU4nIiIikrs8/TQMHmze9+pl5v7dQsOGJg+zWuGLL2D48KwPU0Syll2SKxEREZF8b/x4aNcOYmPN64EDtzzkoYdgyhTz/s034ZNPsj5MEck6Sq5ERERE7MHJCWbPNs9hnTkDbdrAv//e8rD+/a+NWj31FGgikEjupeRKRERExF48Pc1KwaVLw+7dZoGruLhbHjZyJPTtC4mJ0KNHumYVikgOpORKRERExJ4CAmDJEihUCFavhv/975bVKiwWMz2wTRu4dAnatjW5mYjkLkquREREROytRg2YN89MFfzyS3jjjVse4uJiClzUrw///AP33w+RkdkSrYjYiZIrERERkawQHAwffWTejxgBX311y0M8PU2J9goV4O+/zSLDFy5kfagiYh9KrkRERESyyoAB8OKL5n3fvrBmzS0P8fU1a18V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Bwe1YsUKZWVl6dSpU2pqatLnn38e1zw1NDQoEolo3bp16ujo0MGDBzV37ty499i+fbuefPJJffPNN3r00UcVCoX0yy+/WO//7bff6siRI+rs7FRDQ4NycnL+5W8BAHCrOYwxxu4iAAD4p9asWaO9e/dq2rRpceNbt27V1q1b5XA4tH79ejU0NFhzS5Ys0aJFi/T222/r3Xff1QsvvKCLFy8qPT1dknT48GGtXLlSPT098ng8mj17ttauXasdO3bctAaHw6EXX3xRL7/8sjTSsE2fPl1HjhxRRUWFHn/8ceXk5Gj37t239LsAANiLe64AAJPeQw89FNc8SVJ2dra17vf74+b8fr+i0agkqbOzUyUlJVZjJUlLly5VLBZTV1eXHA6Henp6FAgExqxh4cKF1np6erpmzJihvr4+SdLzzz+vqqoqnT59Wo888ogqKyt1//33T/BTAwCSDc0VAGDSS09PH3WZXqK43e5x7Zeamhq37XA4FIvFJEnBYFA//vijDh8+rJaWFgUCAUUiEb366qu3pGYAgD245woAcNs7efLkqO158+ZJkubNm6czZ85ocHDQmj9+/LimTJmi4uJiZWRk6K677lJra+uEasjNzVU4HNbevXu1a9cuvfPOOxN6PQBA8uHMFQBg0hsaGlJvb2/cWEpKivXQiKamJpWVlemBBx7Qhx9+qK+//lrvv/++JCkUCqm+vl7hcFjbtm3Tzz//rJqaGj3zzDPyeDySpG3btmn9+vW64447FAwG1d/fr+PHj6umpmZc9b300ksqLS3VggULNDQ0pEOHDlnNHQDg9kFzBQCY9D799FP5fL64seLiYp07d04aeZJfY2OjNmzYIJ/Pp/3792v+/PmSpLS0NB09elS1tbW67777lJaWpqqqKr322mvWa4XDYV27dk2vv/66Nm/erJycHD3xxBPjrs/pdGrLli364Ycf5Ha7tWzZMjU2Nibs8wMAkgNPCwQA3NYcDoeam5tVWVlpdykAgNsc91wBAAAAQALQXAEAAABAAnDPFQDgtsbV7wCAfwtnrgAAAAAgAWiuAAAAACABaK4AAAAAIAForgAAAAAgAWiuAAAAACABaK4AAAAAIAForgAAAAAgAWiuAAAAACAB/gdKrnXNcDZxbwAAAABJRU5ErkJggg==",
+ "text/plain": [
+ "<Figure size 1000x500 with 1 Axes>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "for epoch in range(NEPOCHS):\n",
+ " model.train() # set to training mode\n",
+ " train_loss = 0\n",
+ "\n",
+ " for batch_src, batch_labels, batch_padding_mask in train_loader:\n",
+ " optimizer.zero_grad()\n",
+ " output = model(batch_src, batch_padding_mask)\n",
+ " loss = criterion(output.squeeze(1), batch_labels)\n",
+ " train_loss += loss.item()/len(train_loader)\n",
+ " loss.backward()\n",
+ " optimizer.step()\n",
+ "\n",
+ " # Evaluate performance\n",
+ " model.eval()\n",
+ " test_loss = 0\n",
+ "\n",
+ " with torch.no_grad():\n",
+ " for batch_src, batch_labels, batch_padding_mask in test_loader:\n",
+ " output = model(batch_src, batch_padding_mask)\n",
+ " loss = criterion(output.squeeze(1), batch_labels)\n",
+ " test_loss += loss.item()/len(test_loader)\n",
+ "\n",
+ " test_err.append(test_loss)\n",
+ " train_err.append(train_loss)\n",
+ " print(f\"Epoch {epoch + 1}/{NEPOCHS} \\t Train Err: {train_loss:.4f} \\t Test Err: {test_loss:.4f} \\t baseline err: {train_baseline:.4f}\")\n",
+ "\n",
+ "plt.figure(figsize=(10, 5))\n",
+ "plt.plot(test_err, label='Test', color='red')\n",
+ "plt.plot(train_err, label='Train', color='blue')\n",
+ "plt.title('Accuracy vs Epochs')\n",
+ "plt.xlabel('Epochs'); plt.ylabel('Accuracy')\n",
+ "plt.legend(); plt.grid()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "v1hCiItHDWxJ"
+ },
+ "outputs": [],
+ "source": [
+ "## Q: why is this not working so well?\n",
+ "\n",
+ "## maybe first try a simpler problem: just give it points for distinguishing between distance 1 or not"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 47,
+ "metadata": {
+ "id": "LoGEmM5lH7_A"
+ },
+ "outputs": [],
+ "source": [
+ "batch_src, batch_labels, batch_padding_mask = next(iter(train_loader))\n",
+ "output = model(batch_src, batch_padding_mask)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "hO8AhX3G7vF8",
+ "outputId": "8f4a3ca6-db47-434d-95a4-4631bc73de62"
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "0 \t nan\n",
+ "0 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "0 \t nan\n",
+ "1 \t nan\n",
+ "0 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "0 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "0 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n",
+ "1 \t nan\n"
+ ]
+ }
+ ],
+ "source": [
+ "for x,y in zip(batch_labels.tolist(), output.squeeze(1).tolist()):\n",
+ " print(f\"{int(x)} \\t {y:.1f}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "dRdUGbFmkPtK"
+ },
+ "outputs": [],
+ "source": [
+ "batch_src[2]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "LC6Xv3YfC0Rm"
+ },
+ "source": [
+ "# Step 5: Fine Tune"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "JtTLXn4zC1z_"
+ },
+ "source": [
+ "# Step 6: Test generalization"
+ ]
+ }
+ ],
+ "metadata": {
+ "colab": {
+ "gpuType": "T4",
+ "provenance": []
+ },
+ "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.10.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/README.md b/README.md
index 56866df..5e9fc09 100644
--- a/README.md
+++ b/README.md
@@ -1,32 +1,135 @@
-1. Submit proposal [10 of grade] (Due: November 14, 11:59pm): Submit a pro- posal as a one page pdf. Provide an outline of your plan for the project and questions you will investigate / analysis you’ll conduct in the course of it. It may help to define a set of hypotheses you will test. An integral aspect of the proposal is to define a project idea that is both realistic and ambitious in scope. We recommend that you use the project proposal stage to get feedback from the teaching staff on the project’s feasibility and whether the proposal satisfies the project expectations of the class.
+Alek Westover, Anthony Wang, Kevin Zhao
+MIT Deep Learning Final Project
-Specify architecture stuff
+"Investigating Off-Distribution Generalization of Transformers"
-Specify the training data generation process
+In this project we hope to further the community's understanding of *when* off-distribution generalization happens. Paul Christiano proposed an experiment [here](https://www.alignmentforum.org/posts/BxersHYN2qcFoonwg/experimentally-evaluating-whether-honesty-generalizes?commentId=dsDA2BWpHPdgLvaXX) to investigate this; our project is essentially to implement Christiano's proposed experiment. To the best of our knowledge no one has done this yet.
-undirected graph
+## Motivation
-[XY == write out how we're gonna generate data]
-PRE-train data
+It is generally desirable for LLMs to output true statements.
+One current approach for ensuring truthfulness of LLM outputs is having
+a human in the loop that rewards a model for true outputs (e.g.,
+RLHF).
+One drawback of this approach is that sometimes humans may be
+poor judges of truthfulness.
+Humans enjoy many cognitive biases and might employ superficial
+heuristics when judging truthfulness.
+A further challenge is that as LLMs become more capable, there
+might not even exist experts that are good judges of whether the
+models outputs are truthful.
+For instance, most Task Rabbit workers would probably be hard
+pressed to evaluate whether a difficult mathematical proof
+produced by an LLM is true. The entire mathematical community has
+been known on occasion to believe [false statements for many years](https://en.wikipedia.org/wiki/Grunwald%E2%80%93Wang_theorem).
-Fine-tune data
+One approach to solving this problem is to reward an LLM for
+truthful behavior on simple inputs, and then hope that the LLM
+generalizes to truthful behavior on more complex inputs where
+humans are unable to give helpful labels.
+Deep learning models often perform remarkable feats of
+off-distribution generalization -- for instance, a model trained
+to transform hand drawn cats into images of cats might be
+able to handle a "cat" with three eyes in an intuitive way.
+We might hope that generalizing truthfully is simple, and thus
+promoted by "Occam's Razor". We hope that our experiments in this
+project can shed light on whether this is likely to happen.
-validation data
-- hypothesis 1 -- transformers can learn shortest paths without too much GPUs
+## Plan
-mathemetical motivation for why this is possible with a not super deep transfomer.
+We will use a synthetic task to test our hypothesis that models
+will generalize truthfully off-distribution.
+The synthetic task is computing the distance between various
+vertices in an input graph. Our experiment will have three parts:
-- hypothesis 2 -- pre-training on 1-2 shortest path should make fine-tuning for other shortest paths which are prefix of the shortest 1-2 path faster
+1. Pre-train a transformer to predict the distance between two
+ fixed vertices $s,t$ on graphs with $n\in [16, 64]$ vertices.
+2. Fine-tune a transformer to predict the distances between
+ $s,t'$ for any $t'$ which is on the shortest path from $s$ to
+ $t$. Only do the fine-tuning on graphs with $n\in [16,32]$
+ vertices.
+3. Test whether the transformer can accurately predict the
+ distances between $s,t'$ for any $t'$ on the shortest path
+ from $s$ to $t$ for graphs with $n\in [16,64]$ vertices.
-we believe this because the info should be sitting somewhere inside the model
+## Data
-- hypothesis 3 -- training for lots of sizes of 1-2 paths, and fine tuning on small graphs, it'll generalize to large graphs.
+To represent an $n$ vertex, $m$ edge graph we will use a sequence
+$[a_1,b_1,a_2,b_2,\ldots,a_m,b_m] \in \{1,2,\ldots,n\}^{2m}$. We
+will use the token $0$ as a padding token and pad all the
+sequences to be the same length.
+This sequence represents an unweighted, undirected graph on vertex set
+$\{1,\ldots,n\}$ with edges $\{(a_i,b_i)\}$.
-we hope that this is like Occam's razor
+The full input to our model will have one more token (after
+adding the padding tokens), which is the target vertex. The value
+that the model is tasked with predicting is the distance between
+vertex $1$ and the target vertex $t$. In the case that there is
+no path from $1$ to $t$ we set this distance to be one larger
+than the maximum possible number of vertices -- this represents
+infinity.
-train on erdos renyi graphs, does it generalize to arbitrary graphs?
+So in summary, an input output pair for our model could look like
+this:
+
+> Input: [1, 3, 3, 2, 0, 0, 0, 0, 2]. Output: 2
+
+![ink_img001](images/ink_img001.png)
+
+We have three separate datasets.
+
+**Pre-train data**
+
+For each $n\in [16,64]$ we will generate several graphs on $n$
+vertices. We generate these graphs by inserting $2n$ random edges into the graph.
+We always set the target vertex to be $2$ here.
+
+**Fine-tune data**
+For each $n\in [16,32]$ we will generate several graphs on $n$
+vertices. We generate these graphs by inserting $2n$ random edges into the graph.
+We select the target vertex to be a random vertex on the shortest
+path from $1$ to $2$.
+
+**Generalization testing data**
+The same as the fine-tune data, except we sample $n\in [32,64]$
+instead.
+
+As a side note, we're also curious whether the transformer
+learns to generalize to different distributions of graphs, e.g.,
+denser graphs or graphs with different properties. Time
+permitting we'll investigate this as well.
+
+## Architecture
+
+We plan to use a standard transformer architecture. We will
+ensure that the number of layers in our transformer is at least
+the diameter of the graph. By doing this, we ensure that there is
+an extremely simple circuit --- namely BFS --- that the transformer
+could in theory learn to perform the task.
+Note that if the transformer actually learns a simple circuit to
+perform this task, then it seems more likely to generalize well.
+This is also our intuition for why it should be possible to fine
+tune on a small amount of data for finding shortest paths to
+other vertices besides $2$ -- it seems like the model should be
+computing these other distances as intermediate values in its
+computation to find the distance to vertex $2$.
+
+## Positional Encodings
+
+In order to facilitate performing this task with limited
+computational resources, we plan to use custom-made positional
+encodings that tell the model extra information about the
+structure of the problem, rather than the traditional sine/cosine
+positional encodings (although we're open to experimenting to see
+if our custom positional encodings actually are any better than
+the sine/cosine positional encodings).
+Specifically, our positional encodings will be
+$v_1,v_1,v_2,v_2,\ldots,v_m,v_m,v_{m+1}$ where these are all
+random independent vectors.
+We will concatenate these with the token encodings rather than
+adding them.
+This should let the model easily have large attention scores between
+vertices corresponding to a single edge.
-Inspiration for project
-Here, I implement an experiment proposed by Paul Christiano [here](https://www.alignmentforum.org/posts/BxersHYN2qcFoonwg/experimentally-evaluating-whether-honesty-generalizes?commentId=dsDA2BWpHPdgLvaXX)
diff --git a/images/ink_img001.png b/images/ink_img001.png
new file mode 100644
index 0000000..0c7ed4d
--- /dev/null
+++ b/images/ink_img001.png
Binary files differ
diff --git a/images/ink_img001.svg b/images/ink_img001.svg
new file mode 100644
index 0000000..8978e13
--- /dev/null
+++ b/images/ink_img001.svg
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="1000mm"
+ height="700mm"
+ viewBox="0 0 1000 700"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
+ sodipodi:docname="ink_img001.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#cccccc"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="1"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="mm"
+ showgrid="false"
+ inkscape:zoom="0.2102413"
+ inkscape:cx="1752.7479"
+ inkscape:cy="1217.6485"
+ inkscape:window-width="1440"
+ inkscape:window-height="836"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1"
+ inkscape:lockguides="false" />
+ <defs
+ id="defs2" />
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:#1a1a1a;stroke:#642bdb;stroke-width:0"
+ id="path11"
+ d="m 177.98764,92.216612 c -6.10806,-2.182889 -12.46322,-3.366135 -18.96535,-2.655353 -5.47965,0.599011 -10.90529,2.599507 -16.07037,4.405593 -11.22884,4.655423 -20.94749,11.884488 -30.00106,19.861518 -7.84516,7.33308 -14.492087,16.03098 -19.157752,25.73494 -0.765876,1.59292 -1.381739,3.2537 -2.072606,4.88056 -4.526558,12.03859 -6.164834,24.83122 -7.969464,37.48367 -0.270735,2.23249 -0.553662,4.46353 -0.81221,6.69746 -0.50007,4.3208 -0.750747,5.97889 -0.786926,10.21123 -0.04467,5.2248 0.307295,10.47015 0.458562,15.69204 0.07967,7.1876 1.631432,13.80766 3.688244,20.63771 1.629193,4.40424 2.648786,9.17868 5.005075,13.29523 1.243539,2.17252 2.433908,3.3858 4.06326,5.31249 5.321097,5.92178 10.517677,11.94776 15.747137,17.94907 5.02957,6.06237 12.43588,8.53741 19.64991,10.99558 7.48418,2.52185 15.1016,4.51239 22.95477,5.39276 8.10767,-0.0682 16.25788,-0.27569 24.30528,-1.329 7.03871,-0.78237 14.10221,-1.40401 21.11558,-2.39451 6.31053,-1.13747 12.64564,-2.17781 18.89647,-3.61666 0.84257,-0.29285 1.69707,-0.55335 2.52769,-0.87853 3.60607,-1.41168 1.78479,-0.99547 5.49919,-2.15241 2.55275,-0.79513 4.91776,-1.44698 7.36195,-2.55992 3.4138,-2.20866 7.0813,-4.0789 10.33559,-6.53148 0.90293,-0.68048 2.94514,-2.51952 3.88191,-3.35153 3.48463,-3.05946 7.25112,-5.76736 11.05147,-8.42429 5.37348,-2.54019 8.55388,-7.44864 11.70009,-12.24833 2.69997,-3.65646 4.73816,-7.31053 5.7866,-11.72364 0.88424,-3.62067 2.32722,-7.06443 3.36508,-10.63924 0.67818,-4.00523 -0.0662,-8.05455 -0.0581,-12.09177 0.12266,-4.70224 0.0889,-9.4059 0.0723,-14.10906 -0.01,-4.47581 0.003,-8.95163 0.003,-13.42745 -0.67583,-3.92678 -0.89781,-7.90263 -1.59092,-11.82655 -0.42481,-2.44877 -1.86594,-4.57531 -2.51277,-6.94656 -0.28792,-1.05548 -0.34335,-2.16098 -0.5107,-3.24214 -0.69646,-3.49052 -2.18437,-6.74629 -3.50322,-10.03115 -1.47785,-3.21268 -2.19196,-6.68457 -3.70448,-9.87581 -2.18982,-3.26782 -4.45075,-6.48385 -6.60671,-9.77568 -1.84358,-2.9542 -3.84775,-5.81603 -6.30869,-8.28804 -2.18236,-2.27864 -4.11014,-4.74799 -6.3988,-6.94497 -2.44945,-1.9206 -4.13196,-4.48697 -6.12854,-6.81382 -2.6017,-2.33372 -4.63851,-5.17225 -7.07334,-7.66682 -2.25736,-2.401199 -5.17215,-3.757562 -8.24763,-4.780092 -3.72256,-0.718285 -6.94312,-2.599298 -10.37263,-4.074474 -0.6994,-0.20582 -1.3918,-0.437074 -2.09819,-0.617461 -0.90743,-0.200089 -3.52182,-0.766821 -4.47267,-1.01287 -1.74191,-0.450747 -3.35569,-1.071473 -5.12264,-1.425932 -3.99878,0.127685 -7.97889,0.343879 -11.98948,0.288483 -5.56819,-0.444828 -10.83305,1.35536 -16.06706,2.957295 -2.28017,0.783797 -4.60161,1.582217 -6.72733,2.723978 -0.2962,0.224512 -0.5924,0.449027 -0.88861,0.673539 0,0 1.22686,1.579499 1.22686,1.579499 v 0 c 0.20565,-0.165293 0.4113,-0.330586 0.61695,-0.495879 1.99467,-1.100532 4.2152,-1.811591 6.35747,-2.56871 5.03604,-1.541441 10.09425,-3.308141 15.4542,-2.869911 3.89103,0.05334 7.75692,-0.09259 11.63515,-0.325083 1.74153,0.326064 3.33557,0.967012 5.05071,1.410562 4.54543,1.175491 -0.2576,-0.169034 4.36837,0.985589 0.6285,0.156869 1.24548,0.356735 1.86823,0.535104 3.48293,1.487749 6.75733,3.404044 10.53257,4.135083 2.77745,0.91364 5.41245,2.10636 7.44552,4.27931 2.40865,2.46018 4.41116,5.27614 6.98824,7.5741 2.04573,2.36463 3.76029,4.99423 6.25925,6.95173 2.27946,2.18552 4.18899,4.65117 6.36865,6.91543 2.37394,2.36591 4.27113,5.13962 6.05035,7.97016 2.10773,3.21807 4.30048,6.37405 6.47664,9.54512 1.52506,3.13352 2.15151,6.60152 3.65175,9.75604 1.26325,3.1435 2.69116,6.25784 3.38267,9.59178 0.0967,0.62391 0.46083,3.07656 0.61603,3.64239 0.61807,2.25341 1.96948,4.27609 2.41483,6.59068 0.68318,3.80709 0.86598,7.67066 1.55998,11.47612 1.1e-4,4.47815 -0.0114,8.95629 -0.003,13.43443 0.0164,4.69974 0.0501,9.39996 -0.0723,14.09879 -0.005,3.85332 0.66236,7.71077 0.13703,11.53869 -1.04196,3.60762 -2.51275,7.07778 -3.39022,10.7348 -0.98721,4.18526 -2.95357,7.61907 -5.51317,11.08816 -3.01419,4.60062 -6.00691,9.29156 -11.17354,11.70562 -3.86245,2.7021 -7.69044,5.45844 -11.23356,8.56805 -0.76291,0.67793 -2.95775,2.6491 -3.67633,3.1916 -3.16445,2.38898 -6.73637,4.19981 -10.04597,6.36836 -2.38438,1.10001 -4.6964,1.70945 -7.19379,2.49193 -3.78327,1.18539 -1.9953,0.76539 -5.49512,2.15101 -0.7611,0.30133 -1.54386,0.5448 -2.31578,0.81722 -6.19453,1.42819 -12.47424,2.45385 -18.72761,3.58531 -7.00627,0.99261 -14.06409,1.60753 -21.0958,2.39184 -7.88848,1.03886 -15.87671,1.22372 -23.82439,1.32416 -7.71113,-0.8463 -15.18206,-2.83562 -22.53075,-5.29823 -6.87995,-2.34027 -13.98415,-4.6378 -18.78671,-10.4163 -5.22425,-5.99398 -10.41365,-12.01443 -15.729671,-17.92875 -1.361943,-1.60071 -2.721417,-3.02748 -3.772358,-4.85643 -2.316922,-4.03215 -3.303151,-8.7198 -4.906237,-13.03453 -2.007979,-6.66251 -3.531529,-13.10434 -3.604067,-20.11872 -0.150016,-5.17604 -0.49874,-10.37516 -0.45933,-15.55407 0.03172,-4.16805 0.279077,-5.77229 0.773993,-10.05056 0.256816,-2.22002 0.537808,-4.43718 0.806712,-6.65577 1.780186,-12.48144 3.38514,-25.10335 7.830976,-36.98571 0.665073,-1.57286 1.256985,-3.17871 1.995218,-4.71859 4.551654,-9.4943 11.049404,-18.00243 18.716194,-25.17696 8.85697,-7.81103 18.3602,-14.89517 29.33943,-19.474182 4.96155,-1.739427 10.19278,-3.692028 15.45417,-4.293738 6.2398,-0.713605 12.33544,0.426969 18.19898,2.521109 z" />
+ <path
+ style="fill:#1a1a1a;stroke:#642bdb;stroke-width:0"
+ id="path12"
+ d="m 165.19489,135.52808 c 0.33185,6.67891 1.79328,13.19978 2.17786,19.87373 -0.35083,4.65019 0.46856,9.23172 0.51072,13.87226 -0.44419,4.4761 0.56211,8.86968 0.58999,13.33359 -0.12614,3.10644 -0.19957,6.21147 -0.14151,9.31988 0.023,2.36261 2.1e-4,4.72533 -5.3e-4,7.088 -0.053,1.07192 0.0192,0.97492 0.82465,1.98742 0,0 0.93121,-1.76999 0.93121,-1.76999 v 0 c 0.53709,1.59413 0.1283,0.21845 0.24414,-0.21685 8e-4,-2.37532 0.0237,-4.75069 1.4e-4,-7.12595 -0.058,-3.101 0.0191,-6.19839 0.1418,-9.2975 -0.0387,-4.46755 -1.01988,-8.85958 -0.59003,-13.33816 -0.0488,-4.67435 -0.85946,-9.28537 -0.51402,-13.96918 -0.39551,-6.70116 -1.83674,-13.25114 -2.18439,-19.95626 z" />
+ <path
+ style="fill:#1a1a1a;stroke:#642bdb;stroke-width:0"
+ id="path18"
+ d="m 285.13542,174.3942 c 1.35776,-0.0967 2.7201,-0.14255 4.07326,-0.29015 4.20987,-0.45923 8.19925,-1.23438 12.46992,-1.14821 4.32321,0.0872 9.54754,0.67423 13.78159,1.07445 15.83669,1.73569 31.70957,3.02843 47.64543,2.93415 9.99294,-0.13406 19.99488,-0.55243 29.99046,-0.33699 0.8975,0.0193 14.01564,0.59742 15.1552,0.64722 13.28635,0.0495 26.54676,0.39617 39.78746,1.53321 13.83147,1.49329 27.79297,1.31869 41.69191,1.40973 14.337,-0.0559 28.67371,-0.0955 43.01082,-0.0779 13.83409,0.002 27.66558,-0.81736 41.47254,-1.65042 11.90117,-0.45849 23.79964,-0.98437 35.68951,-1.67922 12.49635,-0.59511 24.98593,-1.408 37.46699,-2.30271 2.20744,-0.19705 4.41161,-0.43491 6.62233,-0.59117 4.34991,-0.30746 8.71212,-0.41143 13.06457,-0.68098 5.96792,-0.3696 11.9036,-1.00523 17.87178,-1.37003 7.53605,-0.14197 14.99931,-1.39526 22.51893,-1.73688 2.70899,-0.12307 5.42285,-0.11211 8.13223,-0.22681 7.35539,0.0437 14.67194,-0.85295 22.0235,-0.81104 5.80286,0.19756 11.60856,0.15633 17.41336,0.12057 3.49512,-0.27492 6.93219,-1.11732 10.43117,-1.29178 1.23989,0.0487 2.45388,0.19355 3.69473,0.1517 0.78943,-0.0175 0.39137,-0.0117 1.19422,-0.0173 0,0 -0.0145,-1.99995 -0.0145,-1.99995 v 0 c -0.84072,0.006 -0.4249,-3e-5 -1.24746,0.0185 -1.25254,0.0427 -2.47748,-0.13556 -3.732,-0.15009 -3.46835,0.19073 -6.87845,0.9675 -10.33849,1.28905 -5.7971,0.0357 -11.59507,0.0766 -17.39027,-0.12057 -7.38375,-0.0375 -14.73168,0.85054 -22.11906,0.81281 -2.7297,0.11611 -5.46394,0.10576 -8.19327,0.23033 -7.51173,0.34287 -14.96716,1.59236 -22.49533,1.7353 -5.96214,0.36573 -11.89198,0.99978 -17.85389,1.36901 -0.24144,0.0149 -13.02023,0.67786 -13.1381,0.68619 -2.19908,0.15538 -4.39166,0.39224 -6.58749,0.58836 -12.47227,0.89455 -24.95307,1.70699 -37.44068,2.301 -11.89112,0.69548 -23.79086,1.22005 -35.69327,1.67944 -13.76601,0.83116 -27.55657,1.64784 -41.34959,1.64679 -14.33359,-0.0176 -28.66676,0.0218 -43.00019,0.0779 -13.84628,-0.0905 -27.755,0.0862 -41.53397,-1.40244 -13.26857,-1.13822 -26.55684,-1.49179 -39.87118,-1.53863 -1.27404,-0.0557 -14.24027,-0.62762 -15.23965,-0.64913 -10.00054,-0.21526 -20.00742,0.20219 -30.00534,0.33702 -15.86905,0.0967 -31.67504,-1.19943 -47.44537,-2.92532 -4.39986,-0.4151 -9.55887,-0.99852 -14.02961,-1.08241 -4.30009,-0.0807 -8.3166,0.68463 -12.55332,1.15245 -1.30545,0.14415 -2.6199,0.19001 -3.92988,0.28501 z" />
+ <path
+ style="fill:#1a1a1a;stroke:#642bdb;stroke-width:0"
+ id="path19"
+ d="m 852.43103,87.584821 c -11.23831,2.992327 -22.36317,6.541016 -32.49671,12.367194 -4.55308,2.617745 -9.12294,5.987995 -13.41501,9.024715 -9.14844,7.07108 -18.09946,14.51421 -25.97536,23.01191 -1.63335,1.76232 -3.12013,3.65505 -4.68019,5.48257 -1.0877,1.84555 -2.36503,3.59176 -3.26308,5.53665 -1.53292,3.31976 -2.86713,8.90536 -3.65572,12.42061 -1.21685,5.42434 -2.06727,10.86202 -2.72357,16.37631 -0.5439,13.84683 0.44014,27.71865 2.22213,41.44547 1.21185,7.24509 2.5754,14.46217 3.82709,21.70039 0.3982,2.30268 0.67157,4.63006 1.18724,6.90932 1.14985,5.08251 2.06222,6.78853 3.99799,11.57927 5.2307,8.87981 10.07583,18.30357 17.22675,25.85544 1.65746,1.75037 3.48192,3.3347 5.22288,5.00208 6.99791,6.07234 14.2064,12.09055 22.5992,16.15868 4.79232,2.32294 7.23196,3.01136 12.28058,4.77951 6.62427,2.2642 13.56029,3.14998 20.45973,4.07824 5.89169,0.79266 11.69738,1.5471 17.63339,1.85221 9.55291,-0.29265 19.81404,-1.25184 29.0671,-3.74507 7.51033,-3.52427 14.97015,-7.55279 21.63612,-12.53468 1.56371,-1.16867 3.0295,-2.46296 4.54427,-3.69443 8.49106,-8.46373 16.69912,-17.39519 23.68148,-27.17112 1.32315,-1.85254 2.49764,-3.80687 3.74647,-5.7103 0.97843,-1.89921 2.01861,-3.76787 2.93529,-5.69763 0.88008,-1.85268 4.10845,-9.58065 4.93818,-11.45366 1.02275,-2.30877 4.28675,-9.20433 5.21221,-11.55272 0.79441,-2.01585 1.42134,-4.09373 2.13201,-6.1406 3.00138,-9.92924 4.8473,-20.14027 4.91123,-30.53381 0.0114,-1.86573 -0.15172,-3.72843 -0.22757,-5.59265 -0.86199,-10.12522 -4.50895,-19.61823 -8.95768,-28.65931 -2.96413,-6.0906 -5.74855,-12.33312 -9.64549,-17.91131 -3.14921,-4.50784 -4.12843,-5.22265 -7.93816,-9.20638 -5.20698,-4.80898 -10.26578,-9.89107 -16.46751,-13.44063 -2.23584,-1.27969 -8.51898,-4.2663 -10.73629,-5.33875 -5.81343,-2.85118 -10.93639,-6.88474 -16.58139,-10.01886 -3.17746,-1.76414 -4.45542,-2.18579 -7.81367,-3.585972 -7.19624,-2.787761 -14.83064,-3.476384 -22.4159,-4.37203 -6.05041,-0.858806 -12.06746,-1.87388 -18.19529,-1.232123 -2.91764,0.30556 -5.72905,0.987436 -8.58723,1.60377 -7.48499,1.434814 -14.31428,3.628638 -18.16907,10.695345 0,0 1.7668,0.9372 1.7668,0.9372 v 0 c 3.22898,-6.30964 10.28595,-8.476871 16.82449,-9.677621 2.70751,-0.585722 5.51458,-1.264148 8.2741,-1.561669 6.01173,-0.648163 11.91453,0.393028 17.85168,1.221301 7.40179,0.873924 14.85418,1.527379 21.88183,4.232249 3.19022,1.32571 4.52618,1.77407 7.54073,3.44694 5.70209,3.1643 10.87414,7.2434 16.75215,10.11197 1.98959,0.96211 8.45558,4.04081 10.52266,5.21874 6.07301,3.46074 11.00723,8.44958 16.1077,13.14371 3.65996,3.81339 4.66088,4.55817 7.68398,8.87898 3.86347,5.5219 6.61223,11.70875 9.5499,17.73925 4.33652,8.78544 7.8903,18.01742 8.75337,27.85802 0.52096,12.33877 -0.89141,23.56502 -4.57507,35.38868 -0.69014,1.99479 -1.2967,4.0205 -2.07042,5.98439 -0.91003,2.3099 -4.22587,9.32663 -5.22327,11.57807 -0.73988,1.67015 -4.07683,9.63287 -4.87773,11.32507 -0.88394,1.8677 -1.88616,3.67709 -2.82927,5.51563 -1.21928,1.86192 -2.36463,3.77438 -3.65784,5.58574 -6.89141,9.65273 -14.99441,18.46783 -23.35993,26.84094 -1.47179,1.1993 -2.89546,2.4602 -4.41536,3.59788 -6.48624,4.85505 -13.74659,8.75308 -21.02565,12.25201 -4.16597,1.13586 -8.34495,1.73538 -12.62454,2.33111 -3.13293,0.43611 -7.71231,1.06225 -10.91176,1.25151 -1.63277,0.0966 -3.27062,0.0636 -4.90593,0.0954 -5.87899,-0.2966 -11.62955,-1.05254 -17.46448,-1.8364 -6.76698,-0.90908 -13.57172,-1.76657 -20.06997,-3.98446 -4.92419,-1.72054 -7.3179,-2.39567 -11.98861,-4.65037 -8.23894,-3.97719 -15.29922,-9.89878 -22.16934,-15.8455 -1.69251,-1.61584 -3.46635,-3.15058 -5.07753,-4.84754 -7.01683,-7.39031 -11.74274,-16.63478 -16.90064,-25.31535 -1.84877,-4.55263 -2.7881,-6.33639 -3.88056,-11.1671 -0.51578,-2.28065 -0.78949,-4.60937 -1.18795,-6.91341 -1.24688,-7.20997 -2.60366,-14.39913 -3.81418,-21.61536 -1.76477,-13.56343 -2.73164,-27.26928 -2.21938,-40.952 0.64294,-5.43296 1.4855,-10.78871 2.67943,-16.13353 0.70827,-3.17078 2.05624,-8.85043 3.43924,-11.88776 0.83934,-1.84337 2.03954,-3.50006 3.0593,-5.2501 1.52535,-1.78984 2.97783,-3.64442 4.57602,-5.36954 7.79627,-8.41554 16.65798,-15.78545 25.71322,-22.7903 4.15255,-2.93961 8.77474,-6.34438 13.17148,-8.87721 10.01311,-5.768205 21.01406,-9.262624 32.12301,-12.220985 z" />
+ <path
+ style="fill:#1a1a1a;stroke:#642bdb;stroke-width:0"
+ id="path20"
+ d="m 832.47692,162.59548 c 12.68762,-0.0911 25.22551,-1.89425 37.71773,-3.92831 4.03651,-1.00969 7.78822,-0.96867 11.07157,1.77233 0.0246,0.0389 0.48739,0.729 0.4676,0.84314 -0.03,0.17284 -0.25001,0.25465 -0.32735,0.4121 -1.78183,3.62708 0.0719,0.90497 -2.83461,5.72855 -0.99219,1.64658 -2.11026,3.21393 -3.1654,4.8209 -5.5142,7.77265 -12.45713,14.50792 -19.81575,20.53698 -0.22633,0.18545 -4.97385,3.66309 -5.72453,4.21355 -1.47246,1.60605 -3.67435,4.03565 -3.02731,6.50179 0.22958,0.87504 0.73946,1.65131 1.10919,2.47697 6.23636,7.78599 15.76636,11.82652 24.95357,15.06229 2.74606,0.68783 4.82973,2.38043 6.73751,4.38085 1.29026,4.40531 -1.80613,9.36393 -4.48988,12.564 -1.52879,1.82293 -3.37423,3.35494 -5.06134,5.03241 -2.21009,1.46998 -4.29041,3.15678 -6.63025,4.40993 -7.29152,3.90506 -15.51284,5.48836 -23.50632,7.21312 -3.09192,0.66714 -11.11473,2.28823 -14.17881,2.91111 -7.61413,1.45511 -15.19344,3.05398 -22.7384,4.82969 0,0 0.45831,1.94679 0.45831,1.94679 v 0 c 7.52486,-1.77192 15.08458,-3.36458 22.6785,-4.81657 3.05392,-0.62082 11.14001,-2.2547 14.2168,-2.91921 8.24084,-1.77984 16.681,-3.44108 24.18154,-7.50232 2.4484,-1.3257 4.62203,-3.10568 6.93304,-4.65853 1.77419,-1.78483 3.71771,-3.41599 5.32257,-5.35448 3.22855,-3.89975 6.72078,-9.95711 4.25775,-15.04023 -2.12434,-2.20494 -4.48612,-4.10378 -7.51742,-4.88327 -8.70567,-3.05749 -17.74322,-6.85185 -23.82282,-14.05893 -0.3012,-0.53723 -0.7017,-1.02983 -0.90363,-1.6117 -0.62645,-1.80516 1.20801,-3.6692 2.21009,-4.87086 9.77535,-7.16824 19.0042,-15.30391 26.03024,-25.26691 1.75146,-2.67606 6.7302,-9.30812 6.44043,-12.95865 -0.0282,-0.35525 -0.86733,-1.33263 -0.9961,-1.49795 -3.97637,-3.13737 -7.79796,-3.32883 -12.65023,-2.1909 -12.43706,2.02524 -24.91859,3.82043 -37.55049,3.90828 z" />
+ <path
+ style="fill:#1a1a1a;stroke:#642bdb;stroke-width:0"
+ id="path21"
+ d="m 793.71194,307.06917 c -6.74772,2.40583 -13.23337,5.48563 -19.40917,9.11063 -9.82729,5.76834 -1.2246,1.24024 -11.46312,6.98993 -2.16406,1.21528 -4.38121,2.33344 -6.57183,3.50014 -9.40475,4.87238 -19.42859,8.43862 -28.94693,13.05515 -6.92644,3.35944 -9.31425,5.04434 -15.99162,9.11453 -2.9432,1.73646 -5.86415,3.51126 -8.82963,5.20941 -9.12246,5.22388 -9.16225,4.87309 -18.26947,10.33502 -9.59059,5.75177 -18.87339,11.99406 -28.14733,18.23564 -10.69401,7.27633 -21.93166,13.69406 -32.69165,20.86501 -14.7306,9.81713 -0.50597,0.66029 -13.99561,9.25222 -2.08085,1.21216 -4.15878,2.42937 -6.24258,3.63643 -6.58958,3.81706 -7.07848,3.90686 -13.46809,8.23214 -9.36553,6.33971 -3.19429,2.40072 -12.02507,9.0292 -1.8637,1.3989 -3.80738,2.68795 -5.71106,4.0319 -1.88857,1.05773 -3.74716,2.1708 -5.66571,3.17312 -4.31575,2.2547 -6.0919,2.74614 -10.27054,5.06995 -5.56258,3.09343 -10.56079,7.03241 -15.63799,10.83921 -1.87896,1.37459 -3.75137,2.7582 -5.63687,4.1238 -3.83905,2.78048 -5.30987,3.9366 -9.3427,6.24064 -5.90825,3.3755 -4.83872,2.40385 -11.0966,5.62653 -1.97104,1.01502 -3.89294,2.12272 -5.8394,3.1841 -6.4942,3.80307 -11.80164,9.23856 -18.15219,13.24687 -2.86145,1.80607 -5.80366,3.19002 -8.81962,4.69987 -5.09289,2.2012 -9.41957,5.64322 -14.2308,8.33937 -1.6718,0.73002 -2.89854,2.0819 -4.34785,3.12873 -0.80198,0.57928 -1.74318,0.92755 -2.60654,1.40216 -1.02121,0.32514 -1.89151,1.00777 -2.73624,1.64457 0,0 1.21121,1.59155 1.21121,1.59155 v 0 c 0.77097,-0.59354 1.55416,-1.19277 2.49354,-1.48627 1.08701,-0.60651 0.47831,-0.28991 1.83869,-0.92507 1.84759,-1.01425 3.1727,-2.75119 5.12495,-3.61098 4.78526,-2.682 9.08831,-6.09922 14.14881,-8.29587 3.1831,-1.59557 6.04528,-2.93709 9.07142,-4.85006 6.2856,-3.97343 11.55362,-9.33256 17.96238,-13.12912 1.91807,-1.04675 3.81151,-2.13987 5.75419,-3.14021 6.32841,-3.25877 5.27883,-2.29224 11.27511,-5.72463 4.0867,-2.33931 5.59787,-3.52166 9.47256,-6.32804 1.89185,-1.37022 3.77052,-2.75855 5.65578,-4.13785 4.98047,-3.73496 9.88359,-7.61859 15.34049,-10.65442 4.11245,-2.28785 6.08706,-2.87803 10.34693,-5.11067 1.97829,-1.03685 3.8939,-2.18911 5.84084,-3.28369 1.93397,-1.36668 3.90795,-2.67845 5.80191,-4.10003 8.79375,-6.60051 2.52325,-2.58657 11.86582,-8.91485 6.35043,-4.30154 6.81104,-4.37221 13.38951,-8.18388 2.10653,-1.22055 4.20685,-2.45179 6.31026,-3.67768 13.57905,-8.65132 -0.69046,0.53721 14.01326,-9.26359 10.76756,-7.1772 22.01523,-13.5976 32.71615,-20.88126 9.23483,-6.21559 18.47813,-12.43343 28.02821,-18.16143 9.03888,-5.42136 9.20938,-5.14664 18.28819,-10.34589 2.97386,-1.70307 5.90309,-3.48295 8.85462,-5.22441 6.53145,-3.98476 8.98242,-5.70595 15.75819,-8.99247 9.56238,-4.63815 19.63359,-8.21942 29.07948,-13.11966 2.21755,-1.18187 4.4618,-2.31492 6.6526,-3.5456 10.33793,-5.80724 1.63637,-1.21536 11.40696,-6.95775 6.10444,-3.58772 12.51725,-6.63183 19.1906,-9.00697 z" />
+ <path
+ style="fill:#1a1a1a;stroke:#642bdb;stroke-width:0"
+ id="path22"
+ d="m 318.12314,438.74012 c -8.56202,2.22729 -17.33349,4.73747 -24.93354,9.43877 -5.22348,3.23117 -6.2262,4.78071 -10.44966,9.10926 -8.46733,10.68406 -18.3364,20.2142 -26.02595,31.51717 -1.65943,2.43919 -3.10232,5.01888 -4.65348,7.52835 -1.27342,2.58141 -2.62928,5.12376 -3.82026,7.74425 -1.15468,2.54055 -2.12666,5.16032 -3.21308,7.73083 -3.86554,9.14596 -7.81898,18.16759 -11.1537,27.52672 -4.24638,14.20884 -6.14297,29.07265 -6.54113,43.86821 0.12124,8.48894 0.15746,17.13764 3.02532,25.24829 0.56525,1.59858 1.3226,3.12258 1.98389,4.68389 3.89631,8.09604 9.44705,15.20774 15.98479,21.31954 9.54659,6.87634 20.77771,10.98193 31.73816,15.03442 12.83954,4.32969 26.42346,5.69754 39.83077,7.09845 9.04658,0.49877 18.19979,0.53549 27.18723,-0.7752 2.4642,-0.35938 11.78349,-2.21353 14.06726,-2.65999 14.57119,-2.60612 28.29682,-8.23187 42.27042,-12.91368 14.31938,-4.23788 26.25211,-13.15233 37.56877,-22.56337 6.11349,-5.09932 12.35596,-10.1895 17.45041,-16.35734 3.04466,-3.68615 4.47532,-6.17614 6.99685,-10.12899 4.29154,-7.75806 8.20989,-15.85264 10.45975,-24.47091 0.44508,-1.70498 0.69955,-3.45411 1.04933,-5.18115 1.59367,-10.80749 -0.0556,-21.6254 -2.46578,-32.17191 -2.18834,-7.09551 -4.35227,-14.3415 -7.86212,-20.92875 -2.20163,-4.13197 -3.05464,-4.987 -5.87926,-8.82372 -5.39104,-6.6198 -10.73213,-13.31257 -16.94238,-19.19907 -3.84376,-3.64342 -4.95472,-4.3439 -9.17657,-7.63992 -7.34226,-4.64974 -13.8158,-10.59992 -21.22048,-15.15473 -3.55484,-2.18664 -7.68054,-4.07469 -11.42918,-5.89293 -10.2811,-4.87352 -21.24472,-8.30678 -32.35407,-10.69631 -9.88319,-2.25711 -19.99067,-2.92227 -30.03732,-4.02987 -1.30427,-0.0849 -2.60581,-0.26024 -3.91282,-0.25463 -3.05843,0.0132 -6.14172,0.52649 -9.14739,1.00049 -4.40415,0.69453 -8.79824,1.47781 -13.18411,2.27918 -6.85972,1.17633 -13.65207,3.20402 -19.81266,6.52531 -2.11571,1.14062 -4.07725,2.54659 -6.11587,3.81987 -7.57795,6.02932 -4.09474,3.15097 -10.48954,8.5866 0,0 1.29543,1.52376 1.29543,1.52376 v 0 c 6.28817,-5.34688 2.88118,-2.52764 10.25581,-8.41541 1.95834,-1.23034 3.84066,-2.59091 5.87502,-3.69102 6.01577,-3.25319 12.64806,-5.23875 19.35133,-6.3817 4.36301,-0.79737 8.73416,-1.57355 13.11489,-2.26777 2.71603,-0.43042 5.93799,-0.9684 8.72773,-0.98351 1.27699,-0.007 2.54871,0.16455 3.82307,0.24681 9.97945,1.09958 20.01962,1.75619 29.83683,3.99737 10.95475,2.34501 21.76309,5.74366 31.90115,10.54047 3.53201,1.71162 7.8131,3.67811 11.1632,5.73763 7.37349,4.533 13.81659,10.4608 21.12875,15.08725 4.12435,3.21535 5.23303,3.91642 8.98774,7.47242 6.1419,5.81684 11.41857,12.43576 16.75185,18.97684 2.71132,3.66924 3.56854,4.53739 5.68071,8.49135 3.44893,6.45634 5.56408,13.56609 7.72076,20.52064 2.35841,10.26726 3.97435,20.80421 2.45467,31.33039 -0.33187,1.65756 -0.56957,3.33677 -0.99555,4.97266 -2.20078,8.45164 -6.04036,16.388 -10.23951,23.99935 -2.41339,3.79021 -3.87509,6.32407 -6.78214,9.8498 -5.03269,6.10381 -11.21373,11.12996 -17.25748,16.17382 -11.1248,9.25537 -22.84166,18.04406 -36.92522,22.20463 -13.89129,4.65442 -27.53458,10.25194 -42.01879,12.84721 -2.10283,0.41114 -11.57418,2.29336 -13.90426,2.63504 -8.84483,1.29696 -17.85463,1.25624 -26.75871,0.77383 -13.24139,-1.38242 -26.66029,-2.72415 -39.34508,-6.98524 -10.71517,-3.9602 -21.68997,-7.97015 -31.06747,-14.62103 -6.34676,-5.90529 -11.7132,-12.81298 -15.50855,-20.63996 -0.63302,-1.48093 -1.35982,-2.92521 -1.89906,-4.44278 -2.81331,-7.91742 -2.8253,-16.36435 -2.95123,-24.65327 0.383,-14.58534 2.26061,-29.23923 6.4259,-43.2503 3.3209,-9.32749 7.26644,-18.31562 11.11667,-27.43065 1.06927,-2.5314 2.02538,-5.1114 3.16014,-7.61412 1.16239,-2.56363 2.48522,-5.05145 3.72782,-7.57719 1.51962,-2.4629 2.93215,-4.99518 4.55887,-7.3887 7.63435,-11.233 17.45052,-20.6914 25.85295,-31.31363 3.9592,-4.08852 5.01179,-5.67393 9.92251,-8.72077 7.43013,-4.61002 16.01295,-7.06398 24.38659,-9.25401 z" />
+ <path
+ style="fill:#1a1a1a;stroke:#642bdb;stroke-width:0"
+ id="path23"
+ d="m 322.05136,513.00252 c 5.25822,-4.02756 10.75735,-7.77192 16.8675,-10.4105 6.42422,-2.77424 13.36175,-4.36666 20.14403,-5.95583 6.83106,-1.04267 14.04892,-4.20674 21.06623,-3.31618 1.91585,0.24315 3.30644,0.97758 5.027,1.72538 1.90363,0.85807 4.35232,1.3848 5.71723,3.14325 2.64427,3.40664 3.10581,8.31225 3.84987,12.34522 0.0938,1.99681 0.36983,3.99335 0.28154,5.99037 -0.19224,4.34848 -1.27587,8.15176 -2.60212,12.27609 -2.19231,6.81765 -4.9892,13.24218 -8.21936,19.61565 -5.4346,8.50913 -11.55396,16.93135 -19.16399,23.66222 -4.09831,3.62484 -6.03792,4.47185 -10.6078,7.12877 -7.26639,2.61125 -15.35391,6.61331 -23.2377,6.10317 -0.61412,-0.18709 -1.25124,-0.31086 -1.84239,-0.56129 -0.72639,-0.30771 -2.96241,-1.93892 -3.39186,-2.64914 -0.0578,-0.0956 0.0477,-0.21828 0.0715,-0.32742 0.39209,-4.09718 1.23219,-8.48138 3.81781,-11.83928 0.5828,-0.7569 1.37951,-1.32181 2.06928,-1.98271 5.75791,-4.01585 11.89627,-4.42891 18.65942,-3.5015 5.52262,1.82695 10.08303,5.485 14.75793,8.81073 4.95038,3.52174 3.23726,2.26727 7.89646,5.89423 6.08164,4.71033 8.25606,12.19743 11.42902,18.87646 1.74329,3.66962 4.56626,8.94549 6.42946,12.48979 5.34736,9.22713 2.57521,4.99491 8.18348,12.78266 0,0 1.62213,-1.16994 1.62213,-1.16994 v 0 c -5.4873,-7.59605 -2.76076,-3.44612 -8.03534,-12.54336 -1.80295,-3.42937 -4.68024,-8.80989 -6.37352,-12.37457 -3.31404,-6.97671 -5.64838,-14.74192 -12.02695,-19.63943 -3.9501,-3.07295 -7.98587,-5.98668 -12.08792,-8.85402 -3.17129,-2.21673 -4.39147,-3.24644 -7.83058,-4.83389 -1.19906,-0.55345 -2.46554,-0.94726 -3.69832,-1.42089 -7.58457,-0.99623 -13.92168,-0.49162 -20.32772,4.05784 -0.80111,0.80544 -1.71969,1.50907 -2.40334,2.41636 -2.83666,3.76454 -3.89285,8.75398 -4.00971,13.36175 0.171,0.42611 0.26985,0.88886 0.513,1.27836 0.0793,0.127 1.42756,1.24235 1.46365,1.27248 1.50878,1.2609 2.97952,2.17403 4.99734,2.45335 0.87707,0.0469 1.75355,0.17383 2.63126,0.14063 2.93642,-0.11105 3.91953,-0.51721 6.80182,-1.3245 5.07995,-1.42285 10.09007,-3.06838 14.9292,-5.18811 4.79041,-2.80083 6.71859,-3.6349 11.01968,-7.44742 7.75856,-6.87718 14.00387,-15.47053 19.52911,-24.16804 3.28208,-6.49153 6.14307,-13.03229 8.36054,-19.9784 1.40557,-4.40298 2.4856,-8.27841 2.6742,-12.91357 0.0849,-2.08759 -0.20873,-4.1734 -0.31311,-6.26009 -0.86185,-4.57425 -1.42891,-9.76316 -4.54157,-13.51997 -1.5453,-1.86508 -4.08969,-2.53082 -6.203,-3.4398 -2.08235,-0.88326 -3.43366,-1.61031 -5.77196,-1.88693 -7.30126,-0.86378 -14.48004,2.24512 -21.56659,3.36854 -6.94386,1.63021 -14.0272,3.27271 -20.60093,6.12384 -6.21065,2.69364 -11.80849,6.49642 -17.15802,10.59272 z" />
+ </g>
+</svg>
diff --git a/transformer_shortest_paths.ipynb b/transformer_shortest_paths.ipynb
index 2303603..ee844fb 100644
--- a/transformer_shortest_paths.ipynb
+++ b/transformer_shortest_paths.ipynb
@@ -709,7 +709,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.12.6"
+ "version": "3.10.12"
}
},
"nbformat": 4,