{ "cells": [ { "cell_type": "code", "execution_count": 7, "id": "ae9d73b0-9e7a-4259-aa04-2d3176864d40", "metadata": {}, "outputs": [], "source": [ "import torch\n", "from torch import nn, optim\n", "from torch.utils.data import DataLoader\n", "import numpy as np\n", "from collections import Counter\n", "import regex as re\n", "import itertools\n", "from itertools import islice" ] }, { "cell_type": "code", "execution_count": 21, "id": "ae22808c-8957-4d38-94bc-8f9cfc5f8b99", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CUDA Available: True\n", "CUDA Device Name: NVIDIA GeForce RTX 3050\n" ] } ], "source": [ "import torch\n", "\n", "cuda_available = torch.cuda.is_available()\n", "print(f\"CUDA Available: {cuda_available}\")\n", "if cuda_available:\n", " print(f\"CUDA Device Name: {torch.cuda.get_device_name(0)}\")" ] }, { "cell_type": "code", "execution_count": 22, "id": "41daea76-75a5-4098-b5ae-b770d3aa9e1b", "metadata": {}, "outputs": [], "source": [ "device = 'cuda'" ] }, { "cell_type": "code", "execution_count": 8, "id": "fa76fb6d-c5cf-4711-a65e-8ec004e3b6fc", "metadata": {}, "outputs": [], "source": [ "train_path = \"C:/Users/Mauri/Desktop/UAM - 3 semestr/modelowanie języka/gap_pred/challenging-america-word-gap-prediction/train/train.txt\"" ] }, { "cell_type": "code", "execution_count": 9, "id": "e40859e9-88e4-4ff5-a78c-bb11b3822fd3", "metadata": {}, "outputs": [], "source": [ "class Dataset(torch.utils.data.Dataset):\n", " def __init__(\n", " self,\n", " sequence_length,\n", " train_path,\n", " max_vocab_size=20000\n", " ):\n", " self.sequence_length = sequence_length\n", " self.train_path = train_path\n", " self.max_vocab_size = max_vocab_size\n", "\n", " self.words = self.load()\n", " self.uniq_words = self.get_uniq_words()\n", "\n", " self.index_to_word = {index: word for index, word in enumerate(self.uniq_words)}\n", " self.index_to_word[len(self.index_to_word)] = ''\n", " self.word_to_index = {word: index for index, word in enumerate(self.uniq_words)}\n", " self.word_to_index[''] = len(self.word_to_index)\n", "\n", " self.words_indexes = [self.word_to_index.get(w, self.word_to_index['']) for w in self.words]\n", "\n", " def load(self):\n", " with open(self.train_path, 'r', encoding='utf-8') as f_in:\n", " text = [x.rstrip() for x in f_in.readlines() if x.strip()]\n", " text = ' '.join(text).lower()\n", " text = text.replace('-\\\\\\\\n', '').replace('\\\\\\\\n', ' ').replace('\\\\\\\\t', ' ')\n", " text = re.sub(r'\\n', ' ', text)\n", " text = re.sub(r'(?<=\\w)[,-](?=\\w)', '', text)\n", " text = re.sub(r'\\s+', ' ', text)\n", " text = re.sub(r'\\p{P}', '', text)\n", " text = text.split(' ')\n", " return text\n", "\n", " def get_uniq_words(self):\n", " word_counts = Counter(self.words)\n", " most_common_words = word_counts.most_common(self.max_vocab_size)\n", " return [word for word, _ in most_common_words]\n", "\n", " def __len__(self):\n", " return len(self.words_indexes) - self.sequence_length\n", "\n", " def __getitem__(self, index):\n", " # Get the sequence\n", " sequence = self.words_indexes[index:index+self.sequence_length]\n", " # Split the sequence into x and y\n", " x = sequence[:2] + sequence[-2:]\n", " y = sequence[len(sequence) // 2]\n", " return torch.tensor(x), torch.tensor(y)" ] }, { "cell_type": "code", "execution_count": 10, "id": "bf0efaba-86a2-4368-a31d-de7d08a759a0", "metadata": {}, "outputs": [], "source": [ "train_dataset = Dataset(5, train_path)" ] }, { "cell_type": "code", "execution_count": 51, "id": "7aa7bd72-5978-484e-b541-36f737f22b0d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(tensor([ 14, 110, 3, 28]), tensor(208))" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_dataset[420]" ] }, { "cell_type": "code", "execution_count": 53, "id": "2a13298c-e0dd-4181-9093-7cec414b5b79", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['at', 'last', 'to', 'tho']" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[train_dataset.index_to_word[x] for x in [ 14, 110, 3, 28]]" ] }, { "cell_type": "code", "execution_count": 54, "id": "192c4d6d-3fc1-4687-9ce4-b1a8cbea7d82", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['come']" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[train_dataset.index_to_word[208]]" ] }, { "cell_type": "code", "execution_count": 52, "id": "3f0cd5b3-3937-4ad8-a9f8-766d27ad9d70", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(tensor([ 218, 104, 8207, 3121]), tensor(20000))" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_dataset[21237]" ] }, { "cell_type": "code", "execution_count": 12, "id": "b1302c90-d77e-49e4-8b9d-9a8aeca675b0", "metadata": {}, "outputs": [], "source": [ "import torch\n", "import torch.nn as nn\n", "\n", "class Model(nn.Module):\n", " def __init__(self, vocab_size, lstm_size=128, embedding_dim=128, num_layers=3, dropout=0.2):\n", " super(Model, self).__init__()\n", " self.lstm_size = lstm_size\n", " self.embedding_dim = embedding_dim\n", " self.num_layers = num_layers\n", " self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", "\n", " self.embedding = nn.Embedding(\n", " num_embeddings=vocab_size,\n", " embedding_dim=self.embedding_dim,\n", " )\n", " self.lstm = nn.LSTM(\n", " input_size=self.embedding_dim,\n", " hidden_size=self.lstm_size,\n", " num_layers=self.num_layers,\n", " dropout=dropout,\n", " )\n", " self.fc1 = nn.Linear(self.lstm_size, 256) \n", " self.fc2 = nn.Linear(256, vocab_size)\n", " self.softmax = nn.Softmax(dim=1)\n", " \n", " def forward(self, x, prev_state=None):\n", " x = x.to(self.device)\n", " embed = self.embedding(x)\n", " embed = embed.transpose(0, 1)\n", " \n", " if prev_state is None:\n", " prev_state = self.init_state(x.size(0))\n", " \n", " output, state = self.lstm(embed, prev_state)\n", " logits = self.fc1(output[-1])\n", " logits = self.fc2(logits)\n", " probabilities = self.softmax(logits)\n", " return probabilities\n", "\n", " def init_state(self, batch_size):\n", " return (torch.zeros(self.num_layers, batch_size, self.lstm_size).to(self.device),\n", " torch.zeros(self.num_layers, batch_size, self.lstm_size).to(self.device))\n" ] }, { "cell_type": "code", "execution_count": 105, "id": "93a29618-3283-4ad5-881f-48c84839ceeb", "metadata": {}, "outputs": [], "source": [ "def train(dataset, model, max_epochs, batch_size):\n", " model.train()\n", "\n", " dataloader = DataLoader(dataset, batch_size=batch_size, pin_memory=True)\n", " criterion = nn.CrossEntropyLoss()\n", " optimizer = optim.Adam(model.parameters())\n", "\n", " for epoch in range(max_epochs):\n", " for batch, (x, y) in enumerate(dataloader):\n", " optimizer.zero_grad()\n", " x = x.to(device, non_blocking=True)\n", " y = y.to(device, non_blocking=True)\n", "\n", " y_pred = model(x)\n", " loss = criterion(torch.log(y_pred), y)\n", "\n", " loss.backward()\n", " optimizer.step()\n", "\n", " if batch % 500 == 0:\n", " print({ 'epoch': epoch, 'update in batch': batch, '/' : len(dataloader), 'loss': loss.item() })" ] }, { "cell_type": "code", "execution_count": 106, "id": "2315e67d-a315-44b5-bddf-5ab4bed1e727", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'epoch': 0, 'update in batch': 0, '/': 16679, 'loss': 9.917818069458008}\n", "{'epoch': 0, 'update in batch': 500, '/': 16679, 'loss': 6.078440189361572}\n", "{'epoch': 0, 'update in batch': 1000, '/': 16679, 'loss': 5.651369571685791}\n", "{'epoch': 0, 'update in batch': 1500, '/': 16679, 'loss': 5.4341654777526855}\n", "{'epoch': 0, 'update in batch': 2000, '/': 16679, 'loss': 5.383695602416992}\n", "{'epoch': 0, 'update in batch': 2500, '/': 16679, 'loss': 5.225739479064941}\n", "{'epoch': 0, 'update in batch': 3000, '/': 16679, 'loss': 5.282474517822266}\n", "{'epoch': 0, 'update in batch': 3500, '/': 16679, 'loss': 5.092397689819336}\n", "{'epoch': 0, 'update in batch': 4000, '/': 16679, 'loss': 4.940906047821045}\n", "{'epoch': 0, 'update in batch': 4500, '/': 16679, 'loss': 4.908115863800049}\n", "{'epoch': 0, 'update in batch': 5000, '/': 16679, 'loss': 5.092423439025879}\n", "{'epoch': 0, 'update in batch': 5500, '/': 16679, 'loss': 4.979565620422363}\n", "{'epoch': 0, 'update in batch': 6000, '/': 16679, 'loss': 4.8268022537231445}\n", "{'epoch': 0, 'update in batch': 6500, '/': 16679, 'loss': 4.7172017097473145}\n", "{'epoch': 0, 'update in batch': 7000, '/': 16679, 'loss': 4.781315326690674}\n", "{'epoch': 0, 'update in batch': 7500, '/': 16679, 'loss': 5.0033040046691895}\n", "{'epoch': 0, 'update in batch': 8000, '/': 16679, 'loss': 4.663774013519287}\n", "{'epoch': 0, 'update in batch': 8500, '/': 16679, 'loss': 4.710158348083496}\n", "{'epoch': 0, 'update in batch': 9000, '/': 16679, 'loss': 4.817586898803711}\n", "{'epoch': 0, 'update in batch': 9500, '/': 16679, 'loss': 4.655371189117432}\n", "{'epoch': 0, 'update in batch': 10000, '/': 16679, 'loss': 4.679412841796875}\n", "{'epoch': 0, 'update in batch': 10500, '/': 16679, 'loss': 4.544621467590332}\n", "{'epoch': 0, 'update in batch': 11000, '/': 16679, 'loss': 4.816493511199951}\n", "{'epoch': 0, 'update in batch': 11500, '/': 16679, 'loss': 4.627770900726318}\n", "{'epoch': 0, 'update in batch': 12000, '/': 16679, 'loss': 4.525866985321045}\n", "{'epoch': 0, 'update in batch': 12500, '/': 16679, 'loss': 4.739295959472656}\n", "{'epoch': 0, 'update in batch': 13000, '/': 16679, 'loss': 4.6095709800720215}\n", "{'epoch': 0, 'update in batch': 13500, '/': 16679, 'loss': 4.7243266105651855}\n", "{'epoch': 0, 'update in batch': 14000, '/': 16679, 'loss': 4.557321071624756}\n", "{'epoch': 0, 'update in batch': 14500, '/': 16679, 'loss': 4.830319404602051}\n", "{'epoch': 0, 'update in batch': 15000, '/': 16679, 'loss': 4.536618709564209}\n", "{'epoch': 0, 'update in batch': 15500, '/': 16679, 'loss': 4.605734825134277}\n", "{'epoch': 0, 'update in batch': 16000, '/': 16679, 'loss': 4.605676651000977}\n", "{'epoch': 0, 'update in batch': 16500, '/': 16679, 'loss': 4.614283084869385}\n" ] } ], "source": [ "model = Model(vocab_size = len(train_dataset.uniq_words) + 1).to(device)\n", "train(train_dataset, model, 1, 8192)" ] }, { "cell_type": "code", "execution_count": 107, "id": "8acf3dc2-f3fe-4a2a-bdf9-82a18acb1bd1", "metadata": {}, "outputs": [], "source": [ "torch.save(model.state_dict(), 'model.pth')" ] }, { "cell_type": "code", "execution_count": 23, "id": "5e60d5b3-019d-4d63-b794-59e1356bc45e", "metadata": {}, "outputs": [], "source": [ "model = Model(20001).to(device)" ] }, { "cell_type": "code", "execution_count": 24, "id": "7e55b0b2-cdda-4c37-8979-0400f9973461", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.load_state_dict(torch.load('model.pth'))" ] }, { "cell_type": "code", "execution_count": 2, "id": "e842b192-8e10-438c-b8ee-781a4a7a875c", "metadata": {}, "outputs": [], "source": [ "def clean(text):\n", " text = text.replace('-\\\\\\\\n', '').replace('\\\\\\\\n', ' ').replace('\\\\\\\\t', ' ')\n", " text = re.sub(r'\\n', ' ', text)\n", " text = re.sub(r'(?<=\\w)[,-](?=\\w)', '', text)\n", " text = re.sub(r'\\s+', ' ', text)\n", " text = re.sub(r'\\p{P}', '', text)\n", " text = text.strip()\n", " return text" ] }, { "cell_type": "code", "execution_count": 3, "id": "f20f8fdc-194e-415a-8343-6f590abe1166", "metadata": {}, "outputs": [], "source": [ "def get_words(words, model, dataset, n=20):\n", " ixs = [dataset.word_to_index.get(word, dataset.word_to_index['']) for word in words]\n", " ixs = torch.tensor(ixs).unsqueeze(0).to(model.device)\n", "\n", " out = model(ixs)\n", " top = torch.topk(out[0], n)\n", " top_indices = top.indices.tolist()\n", " top_probs = top.values.tolist()\n", " top_words = [dataset.index_to_word[idx] for idx in top_indices]\n", " return list(zip(top_words, top_probs))" ] }, { "cell_type": "code", "execution_count": 4, "id": "22ebafa5-d21f-4208-9aad-a4c4d90134c4", "metadata": {}, "outputs": [], "source": [ "def f_out(left, right, model, dataset):\n", " left = clean(left)\n", " right = clean(right)\n", " words = left.split(' ')[-2:] + right.split(' ')[:2]\n", " words = get_words(words, model, dataset)\n", "\n", " probs_sum = 0\n", " output = ''\n", " for word, prob in words:\n", " if word == \"\":\n", " continue\n", " probs_sum += prob\n", " output += f\"{word}:{prob} \"\n", " output += f\":{1-probs_sum}\"\n", "\n", " return output" ] }, { "cell_type": "code", "execution_count": 6, "id": "1dc64cee-a9a5-44d4-92da-82e1b7f8fdc4", "metadata": {}, "outputs": [], "source": [ "def create_out(input_path, model, dataset, output_path):\n", " lines = []\n", " with open(input_path, encoding='utf-8') as f:\n", " for line in f:\n", " columns = line.split('\\t')\n", " left = columns[6]\n", " right = columns[7]\n", " lines.append((left, right))\n", "\n", " with open(output_path, 'w', encoding='utf-8') as output_file:\n", " for left, right in lines:\n", " result = f_out(left, right, model, dataset)\n", " output_file.write(result + '\\n')" ] }, { "cell_type": "code", "execution_count": 19, "id": "348a77c1-8ff1-40bb-a243-3b702c119c2c", "metadata": {}, "outputs": [], "source": [ "dev_path = \"C:/Users/Mauri/Desktop/UAM - 3 semestr/modelowanie języka/gap_pred/challenging-america-word-gap-prediction/dev-0/in.tsv\"" ] }, { "cell_type": "code", "execution_count": 25, "id": "9377c725-3309-4590-89d2-444057ae2b80", "metadata": {}, "outputs": [], "source": [ "create_out(dev_path, model, train_dataset, output_path='C:/Users/Mauri/Desktop/UAM - 3 semestr/modelowanie języka/gap_pred/challenging-america-word-gap-prediction/dev-0/out.tsv')" ] }, { "cell_type": "code", "execution_count": 26, "id": "50f47d4a-762f-48b2-9c19-f385d9822886", "metadata": {}, "outputs": [], "source": [ "test_path = \"C:/Users/Mauri/Desktop/UAM - 3 semestr/modelowanie języka/gap_pred/challenging-america-word-gap-prediction/test-A/in.tsv\"" ] }, { "cell_type": "code", "execution_count": 27, "id": "18aa1059-88ed-4c32-af88-80a4de4be6c9", "metadata": {}, "outputs": [], "source": [ "create_out(test_path, model, train_dataset, output_path='C:/Users/Mauri/Desktop/UAM - 3 semestr/modelowanie języka/gap_pred/challenging-america-word-gap-prediction/test-A/out.tsv')" ] }, { "cell_type": "code", "execution_count": 2, "id": "426de26f-b72e-41dc-a63c-a7956d3b1655", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import Image\n", "Image(filename='C:/Users/Mauri/Desktop/Zrzut ekranu 2024-05-27 134020.png')" ] } ], "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.11.9" } }, "nbformat": 4, "nbformat_minor": 5 }