chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:45:52 +08:00
commit aa6c9c0720
43 changed files with 5178 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: Python application
on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install py2ipynb==0.0.5
- name: Test with py2ipynb
run: |
py2ipynb '*/*.py'
- name: Commit changes
uses: EndBug/add-and-commit@v4
with:
author_name: graykode
author_email: nlkey2022@gmail.com
message: "Automatic convert from py to ipynb"
add: "*/*.ipynb"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1
View File
@@ -0,0 +1 @@
.idea
+111
View File
@@ -0,0 +1,111 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung @graykode\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"\n",
"def make_batch():\n",
" input_batch = []\n",
" target_batch = []\n",
"\n",
" for sen in sentences:\n",
" word = sen.split() # space tokenizer\n",
" input = [word_dict[n] for n in word[:-1]] # create (1~n-1) as input\n",
" target = word_dict[word[-1]] # create (n) as target, We usually call this 'casual language model'\n",
"\n",
" input_batch.append(input)\n",
" target_batch.append(target)\n",
"\n",
" return input_batch, target_batch\n",
"\n",
"# Model\n",
"class NNLM(nn.Module):\n",
" def __init__(self):\n",
" super(NNLM, self).__init__()\n",
" self.C = nn.Embedding(n_class, m)\n",
" self.H = nn.Linear(n_step * m, n_hidden, bias=False)\n",
" self.d = nn.Parameter(torch.ones(n_hidden))\n",
" self.U = nn.Linear(n_hidden, n_class, bias=False)\n",
" self.W = nn.Linear(n_step * m, n_class, bias=False)\n",
" self.b = nn.Parameter(torch.ones(n_class))\n",
"\n",
" def forward(self, X):\n",
" X = self.C(X) # X : [batch_size, n_step, m]\n",
" X = X.view(-1, n_step * m) # [batch_size, n_step * m]\n",
" tanh = torch.tanh(self.d + self.H(X)) # [batch_size, n_hidden]\n",
" output = self.b + self.W(X) + self.U(tanh) # [batch_size, n_class]\n",
" return output\n",
"\n",
"if __name__ == '__main__':\n",
" n_step = 2 # number of steps, n-1 in paper\n",
" n_hidden = 2 # number of hidden size, h in paper\n",
" m = 2 # embedding size, m in paper\n",
"\n",
" sentences = [\"i like dog\", \"i love coffee\", \"i hate milk\"]\n",
"\n",
" word_list = \" \".join(sentences).split()\n",
" word_list = list(set(word_list))\n",
" word_dict = {w: i for i, w in enumerate(word_list)}\n",
" number_dict = {i: w for i, w in enumerate(word_list)}\n",
" n_class = len(word_dict) # number of Vocabulary\n",
"\n",
" model = NNLM()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" input_batch, target_batch = make_batch()\n",
" input_batch = torch.LongTensor(input_batch)\n",
" target_batch = torch.LongTensor(target_batch)\n",
"\n",
" # Training\n",
" for epoch in range(5000):\n",
" optimizer.zero_grad()\n",
" output = model(input_batch)\n",
"\n",
" # output : [batch_size, n_class], target_batch : [batch_size]\n",
" loss = criterion(output, target_batch)\n",
" if (epoch + 1) % 1000 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Predict\n",
" predict = model(input_batch).data.max(1, keepdim=True)[1]\n",
"\n",
" # Test\n",
" print([sen.split()[:2] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+78
View File
@@ -0,0 +1,78 @@
# %%
# code by Tae Hwan Jung @graykode
import torch
import torch.nn as nn
import torch.optim as optim
def make_batch():
input_batch = []
target_batch = []
for sen in sentences:
word = sen.split() # space tokenizer
input = [word_dict[n] for n in word[:-1]] # create (1~n-1) as input
target = word_dict[word[-1]] # create (n) as target, We usually call this 'casual language model'
input_batch.append(input)
target_batch.append(target)
return input_batch, target_batch
# Model
class NNLM(nn.Module):
def __init__(self):
super(NNLM, self).__init__()
self.C = nn.Embedding(n_class, m)
self.H = nn.Linear(n_step * m, n_hidden, bias=False)
self.d = nn.Parameter(torch.ones(n_hidden))
self.U = nn.Linear(n_hidden, n_class, bias=False)
self.W = nn.Linear(n_step * m, n_class, bias=False)
self.b = nn.Parameter(torch.ones(n_class))
def forward(self, X):
X = self.C(X) # X : [batch_size, n_step, m]
X = X.view(-1, n_step * m) # [batch_size, n_step * m]
tanh = torch.tanh(self.d + self.H(X)) # [batch_size, n_hidden]
output = self.b + self.W(X) + self.U(tanh) # [batch_size, n_class]
return output
if __name__ == '__main__':
n_step = 2 # number of steps, n-1 in paper
n_hidden = 2 # number of hidden size, h in paper
m = 2 # embedding size, m in paper
sentences = ["i like dog", "i love coffee", "i hate milk"]
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict) # number of Vocabulary
model = NNLM()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
input_batch, target_batch = make_batch()
input_batch = torch.LongTensor(input_batch)
target_batch = torch.LongTensor(target_batch)
# Training
for epoch in range(5000):
optimizer.zero_grad()
output = model(input_batch)
# output : [batch_size, n_class], target_batch : [batch_size]
loss = criterion(output, target_batch)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Predict
predict = model(input_batch).data.max(1, keepdim=True)[1]
# Test
print([sen.split()[:2] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])
@@ -0,0 +1,115 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung @graykode\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"import matplotlib.pyplot as plt\n",
"\n",
"def random_batch():\n",
" random_inputs = []\n",
" random_labels = []\n",
" random_index = np.random.choice(range(len(skip_grams)), batch_size, replace=False)\n",
"\n",
" for i in random_index:\n",
" random_inputs.append(np.eye(voc_size)[skip_grams[i][0]]) # target\n",
" random_labels.append(skip_grams[i][1]) # context word\n",
"\n",
" return random_inputs, random_labels\n",
"\n",
"# Model\n",
"class Word2Vec(nn.Module):\n",
" def __init__(self):\n",
" super(Word2Vec, self).__init__()\n",
" # W and WT is not Traspose relationship\n",
" self.W = nn.Linear(voc_size, embedding_size, bias=False) # voc_size > embedding_size Weight\n",
" self.WT = nn.Linear(embedding_size, voc_size, bias=False) # embedding_size > voc_size Weight\n",
"\n",
" def forward(self, X):\n",
" # X : [batch_size, voc_size]\n",
" hidden_layer = self.W(X) # hidden_layer : [batch_size, embedding_size]\n",
" output_layer = self.WT(hidden_layer) # output_layer : [batch_size, voc_size]\n",
" return output_layer\n",
"\n",
"if __name__ == '__main__':\n",
" batch_size = 2 # mini-batch size\n",
" embedding_size = 2 # embedding size\n",
"\n",
" sentences = [\"apple banana fruit\", \"banana orange fruit\", \"orange banana fruit\",\n",
" \"dog cat animal\", \"cat monkey animal\", \"monkey dog animal\"]\n",
"\n",
" word_sequence = \" \".join(sentences).split()\n",
" word_list = \" \".join(sentences).split()\n",
" word_list = list(set(word_list))\n",
" word_dict = {w: i for i, w in enumerate(word_list)}\n",
" voc_size = len(word_list)\n",
"\n",
" # Make skip gram of one size window\n",
" skip_grams = []\n",
" for i in range(1, len(word_sequence) - 1):\n",
" target = word_dict[word_sequence[i]]\n",
" context = [word_dict[word_sequence[i - 1]], word_dict[word_sequence[i + 1]]]\n",
" for w in context:\n",
" skip_grams.append([target, w])\n",
"\n",
" model = Word2Vec()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" # Training\n",
" for epoch in range(5000):\n",
" input_batch, target_batch = random_batch()\n",
" input_batch = torch.Tensor(input_batch)\n",
" target_batch = torch.LongTensor(target_batch)\n",
"\n",
" optimizer.zero_grad()\n",
" output = model(input_batch)\n",
"\n",
" # output : [batch_size, voc_size], target_batch : [batch_size] (LongTensor, not one-hot)\n",
" loss = criterion(output, target_batch)\n",
" if (epoch + 1) % 1000 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" for i, label in enumerate(word_list):\n",
" W, WT = model.parameters()\n",
" x, y = W[0][i].item(), W[1][i].item()\n",
" plt.scatter(x, y)\n",
" plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')\n",
" plt.show()\n"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
@@ -0,0 +1,82 @@
# %%
# code by Tae Hwan Jung @graykode
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
def random_batch():
random_inputs = []
random_labels = []
random_index = np.random.choice(range(len(skip_grams)), batch_size, replace=False)
for i in random_index:
random_inputs.append(np.eye(voc_size)[skip_grams[i][0]]) # target
random_labels.append(skip_grams[i][1]) # context word
return random_inputs, random_labels
# Model
class Word2Vec(nn.Module):
def __init__(self):
super(Word2Vec, self).__init__()
# W and WT is not Traspose relationship
self.W = nn.Linear(voc_size, embedding_size, bias=False) # voc_size > embedding_size Weight
self.WT = nn.Linear(embedding_size, voc_size, bias=False) # embedding_size > voc_size Weight
def forward(self, X):
# X : [batch_size, voc_size]
hidden_layer = self.W(X) # hidden_layer : [batch_size, embedding_size]
output_layer = self.WT(hidden_layer) # output_layer : [batch_size, voc_size]
return output_layer
if __name__ == '__main__':
batch_size = 2 # mini-batch size
embedding_size = 2 # embedding size
sentences = ["apple banana fruit", "banana orange fruit", "orange banana fruit",
"dog cat animal", "cat monkey animal", "monkey dog animal"]
word_sequence = " ".join(sentences).split()
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
voc_size = len(word_list)
# Make skip gram of one size window
skip_grams = []
for i in range(1, len(word_sequence) - 1):
target = word_dict[word_sequence[i]]
context = [word_dict[word_sequence[i - 1]], word_dict[word_sequence[i + 1]]]
for w in context:
skip_grams.append([target, w])
model = Word2Vec()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Training
for epoch in range(5000):
input_batch, target_batch = random_batch()
input_batch = torch.Tensor(input_batch)
target_batch = torch.LongTensor(target_batch)
optimizer.zero_grad()
output = model(input_batch)
# output : [batch_size, voc_size], target_batch : [batch_size] (LongTensor, not one-hot)
loss = criterion(output, target_batch)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
for i, label in enumerate(word_list):
W, WT = model.parameters()
x, y = W[0][i].item(), W[1][i].item()
plt.scatter(x, y)
plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
plt.show()
+755
View File
@@ -0,0 +1,755 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "FastText.ipynb",
"version": "0.3.2",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"accelerator": "GPU"
},
"cells": [
{
"metadata": {
"id": "kg9kgMnGqYkU",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## Install [FastText](https://fasttext.cc/docs/en/supervised-tutorial.html)"
]
},
{
"metadata": {
"id": "3Iod5UKTqZnC",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 11051
},
"outputId": "b10c85c0-c4cf-4f0b-a30e-2207ae4512b2"
},
"cell_type": "code",
"source": [
"!wget https://github.com/facebookresearch/fastText/archive/0.2.0.zip\n",
"!unzip 0.2.0.zip\n",
"%cd fastText-0.2.0\n",
"!make"
],
"execution_count": 1,
"outputs": [
{
"output_type": "stream",
"text": [
"--2019-02-02 14:43:56-- https://github.com/facebookresearch/fastText/archive/0.2.0.zip\n",
"Resolving github.com (github.com)... 140.82.118.3, 140.82.118.4\n",
"Connecting to github.com (github.com)|140.82.118.3|:443... connected.\n",
"HTTP request sent, awaiting response... 302 Found\n",
"Location: https://codeload.github.com/facebookresearch/fastText/zip/0.2.0 [following]\n",
"--2019-02-02 14:43:56-- https://codeload.github.com/facebookresearch/fastText/zip/0.2.0\n",
"Resolving codeload.github.com (codeload.github.com)... 192.30.253.121, 192.30.253.120\n",
"Connecting to codeload.github.com (codeload.github.com)|192.30.253.121|:443... connected.\n",
"HTTP request sent, awaiting response... 200 OK\n",
"Length: unspecified [application/zip]\n",
"Saving to: 0.2.0.zip\n",
"\n",
"0.2.0.zip [ <=> ] 4.10M 6.17MB/s in 0.7s \n",
"\n",
"2019-02-02 14:43:57 (6.17 MB/s) - 0.2.0.zip saved [4304799]\n",
"\n",
"Archive: 0.2.0.zip\n",
"7842495a4d64c7a3bb4339d45d6e64321d002ed8\n",
" creating: fastText-0.2.0/\n",
" creating: fastText-0.2.0/.circleci/\n",
" inflating: fastText-0.2.0/.circleci/cmake_test.sh \n",
" inflating: fastText-0.2.0/.circleci/config.yml \n",
" inflating: fastText-0.2.0/.circleci/gcc_test.sh \n",
" inflating: fastText-0.2.0/.circleci/pip_test.sh \n",
" inflating: fastText-0.2.0/.circleci/pull_data.sh \n",
" inflating: fastText-0.2.0/.circleci/python_test.sh \n",
" inflating: fastText-0.2.0/.circleci/run_locally.sh \n",
" inflating: fastText-0.2.0/.circleci/setup_circleimg.sh \n",
" inflating: fastText-0.2.0/.circleci/setup_debian.sh \n",
" inflating: fastText-0.2.0/.gitignore \n",
" inflating: fastText-0.2.0/CMakeLists.txt \n",
" inflating: fastText-0.2.0/CONTRIBUTING.md \n",
" inflating: fastText-0.2.0/LICENSE \n",
" inflating: fastText-0.2.0/MANIFEST.in \n",
" inflating: fastText-0.2.0/Makefile \n",
" inflating: fastText-0.2.0/README.md \n",
" creating: fastText-0.2.0/alignment/\n",
" inflating: fastText-0.2.0/alignment/README.md \n",
" inflating: fastText-0.2.0/alignment/align.py \n",
" inflating: fastText-0.2.0/alignment/eval.py \n",
" inflating: fastText-0.2.0/alignment/example.sh \n",
" inflating: fastText-0.2.0/alignment/utils.py \n",
" inflating: fastText-0.2.0/classification-example.sh \n",
" inflating: fastText-0.2.0/classification-results.sh \n",
" creating: fastText-0.2.0/docs/\n",
" inflating: fastText-0.2.0/docs/aligned-vectors.md \n",
" inflating: fastText-0.2.0/docs/api.md \n",
" inflating: fastText-0.2.0/docs/cheatsheet.md \n",
" inflating: fastText-0.2.0/docs/crawl-vectors.md \n",
" inflating: fastText-0.2.0/docs/dataset.md \n",
" inflating: fastText-0.2.0/docs/english-vectors.md \n",
" inflating: fastText-0.2.0/docs/faqs.md \n",
" inflating: fastText-0.2.0/docs/language-identification.md \n",
" inflating: fastText-0.2.0/docs/options.md \n",
" inflating: fastText-0.2.0/docs/pretrained-vectors.md \n",
" inflating: fastText-0.2.0/docs/references.md \n",
" inflating: fastText-0.2.0/docs/supervised-models.md \n",
" inflating: fastText-0.2.0/docs/supervised-tutorial.md \n",
" inflating: fastText-0.2.0/docs/support.md \n",
" inflating: fastText-0.2.0/docs/unsupervised-tutorials.md \n",
" inflating: fastText-0.2.0/eval.py \n",
" inflating: fastText-0.2.0/get-wikimedia.sh \n",
" inflating: fastText-0.2.0/pretrained-vectors.md \n",
" creating: fastText-0.2.0/python/\n",
" inflating: fastText-0.2.0/python/README.md \n",
" inflating: fastText-0.2.0/python/README.rst \n",
" creating: fastText-0.2.0/python/benchmarks/\n",
" inflating: fastText-0.2.0/python/benchmarks/README.rst \n",
" inflating: fastText-0.2.0/python/benchmarks/get_word_vector.py \n",
" creating: fastText-0.2.0/python/doc/\n",
" creating: fastText-0.2.0/python/doc/examples/\n",
" inflating: fastText-0.2.0/python/doc/examples/FastTextEmbeddingBag.py \n",
" inflating: fastText-0.2.0/python/doc/examples/bin_to_vec.py \n",
" inflating: fastText-0.2.0/python/doc/examples/compute_accuracy.py \n",
" inflating: fastText-0.2.0/python/doc/examples/get_vocab.py \n",
" inflating: fastText-0.2.0/python/doc/examples/train_supervised.py \n",
" inflating: fastText-0.2.0/python/doc/examples/train_unsupervised.py \n",
" creating: fastText-0.2.0/python/fastText/\n",
" inflating: fastText-0.2.0/python/fastText/FastText.py \n",
" inflating: fastText-0.2.0/python/fastText/__init__.py \n",
" creating: fastText-0.2.0/python/fastText/pybind/\n",
" inflating: fastText-0.2.0/python/fastText/pybind/fasttext_pybind.cc \n",
" creating: fastText-0.2.0/python/fastText/tests/\n",
" inflating: fastText-0.2.0/python/fastText/tests/__init__.py \n",
" inflating: fastText-0.2.0/python/fastText/tests/test_configurations.py \n",
" inflating: fastText-0.2.0/python/fastText/tests/test_script.py \n",
" creating: fastText-0.2.0/python/fastText/util/\n",
" inflating: fastText-0.2.0/python/fastText/util/__init__.py \n",
" inflating: fastText-0.2.0/python/fastText/util/util.py \n",
" inflating: fastText-0.2.0/quantization-example.sh \n",
" inflating: fastText-0.2.0/runtests.py \n",
" creating: fastText-0.2.0/scripts/\n",
" creating: fastText-0.2.0/scripts/kbcompletion/\n",
" inflating: fastText-0.2.0/scripts/kbcompletion/README.md \n",
" inflating: fastText-0.2.0/scripts/kbcompletion/data.sh \n",
" inflating: fastText-0.2.0/scripts/kbcompletion/eval.cpp \n",
" inflating: fastText-0.2.0/scripts/kbcompletion/fb15k.sh \n",
" inflating: fastText-0.2.0/scripts/kbcompletion/fb15k237.sh \n",
" inflating: fastText-0.2.0/scripts/kbcompletion/svo.sh \n",
" inflating: fastText-0.2.0/scripts/kbcompletion/wn18.sh \n",
" creating: fastText-0.2.0/scripts/quantization/\n",
" inflating: fastText-0.2.0/scripts/quantization/quantization-results.sh \n",
" extracting: fastText-0.2.0/setup.cfg \n",
" inflating: fastText-0.2.0/setup.py \n",
" creating: fastText-0.2.0/src/\n",
" inflating: fastText-0.2.0/src/args.cc \n",
" inflating: fastText-0.2.0/src/args.h \n",
" inflating: fastText-0.2.0/src/dictionary.cc \n",
" inflating: fastText-0.2.0/src/dictionary.h \n",
" inflating: fastText-0.2.0/src/fasttext.cc \n",
" inflating: fastText-0.2.0/src/fasttext.h \n",
" inflating: fastText-0.2.0/src/main.cc \n",
" inflating: fastText-0.2.0/src/matrix.cc \n",
" inflating: fastText-0.2.0/src/matrix.h \n",
" inflating: fastText-0.2.0/src/meter.cc \n",
" inflating: fastText-0.2.0/src/meter.h \n",
" inflating: fastText-0.2.0/src/model.cc \n",
" inflating: fastText-0.2.0/src/model.h \n",
" inflating: fastText-0.2.0/src/productquantizer.cc \n",
" inflating: fastText-0.2.0/src/productquantizer.h \n",
" inflating: fastText-0.2.0/src/qmatrix.cc \n",
" inflating: fastText-0.2.0/src/qmatrix.h \n",
" inflating: fastText-0.2.0/src/real.h \n",
" inflating: fastText-0.2.0/src/utils.cc \n",
" inflating: fastText-0.2.0/src/utils.h \n",
" inflating: fastText-0.2.0/src/vector.cc \n",
" inflating: fastText-0.2.0/src/vector.h \n",
" creating: fastText-0.2.0/tests/\n",
" inflating: fastText-0.2.0/tests/fetch_test_data.sh \n",
" creating: fastText-0.2.0/website/\n",
" inflating: fastText-0.2.0/website/README.md \n",
" creating: fastText-0.2.0/website/blog/\n",
" inflating: fastText-0.2.0/website/blog/2016-08-18-blog-post.md \n",
" inflating: fastText-0.2.0/website/blog/2017-05-02-blog-post.md \n",
" inflating: fastText-0.2.0/website/blog/2017-10-02-blog-post.md \n",
" creating: fastText-0.2.0/website/core/\n",
" inflating: fastText-0.2.0/website/core/Footer.js \n",
" inflating: fastText-0.2.0/website/package.json \n",
" creating: fastText-0.2.0/website/pages/\n",
" creating: fastText-0.2.0/website/pages/en/\n",
" inflating: fastText-0.2.0/website/pages/en/index.js \n",
" inflating: fastText-0.2.0/website/sidebars.json \n",
" inflating: fastText-0.2.0/website/siteConfig.js \n",
" creating: fastText-0.2.0/website/static/\n",
" creating: fastText-0.2.0/website/static/docs/\n",
" creating: fastText-0.2.0/website/static/docs/en/\n",
" creating: fastText-0.2.0/website/static/docs/en/html/\n",
" extracting: fastText-0.2.0/website/static/docs/en/html/.classfasttext_1_1QMatrix-members.html.i4eKqy \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/annotated.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/annotated_dup.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/args_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/args_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/args_8h.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/args_8h_source.html \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/bc_s.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/bdwn.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classes.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Args-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Args.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Args.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Dictionary-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Dictionary.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Dictionary.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1FastText-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1FastText.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1FastText.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Matrix-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Matrix.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Matrix.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Model-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Model.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Model.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1ProductQuantizer-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1ProductQuantizer.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1ProductQuantizer.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1QMatrix-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1QMatrix.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1QMatrix.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Vector-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Vector.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/classfasttext_1_1Vector.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/closed.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/dictionary_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/dictionary_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/dictionary_8h.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/dictionary_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/dir_68267d1309a1af8e8297ef4c3efbcdba.js \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/doc.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/doxygen.css \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/doxygen.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/dynsections.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/fasttext_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/fasttext_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/fasttext_8h.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/fasttext_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/favicon.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/files.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/files.js \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/folderclosed.png \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/folderopen.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_0x7e.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_b.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_c.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_d.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_dup.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_e.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_f.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_func.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_g.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_i.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_k.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_l.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_m.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_n.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_o.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_p.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_q.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_r.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_s.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_t.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_u.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_v.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_vars.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_w.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/functions_z.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/globals.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/globals_defs.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/globals_func.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/index.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/jquery.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/main_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/main_8cc.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/matrix_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/matrix_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/matrix_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/menu.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/menudata.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/model_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/model_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/model_8h.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/model_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespacefasttext.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespacefasttext.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespacefasttext_1_1utils.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespacemembers.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespacemembers_enum.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespacemembers_func.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespacemembers_type.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespaces.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/namespaces.js \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/nav_f.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/nav_g.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/nav_h.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/navtree.css \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/navtree.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/navtreedata.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/navtreeindex0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/navtreeindex1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/open.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/productquantizer_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/productquantizer_8cc.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/productquantizer_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/productquantizer_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/qmatrix_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/qmatrix_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/qmatrix_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/real_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/real_8h.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/real_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/resize.js \n",
" creating: fastText-0.2.0/website/static/docs/en/html/search/\n",
" extracting: fastText-0.2.0/website/static/docs/en/html/search/.files_7.html.StRRNc \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/search/.variables_a.html.1MGQ27 \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_10.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_10.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_11.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_11.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_12.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_12.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_13.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_13.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_14.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_14.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_15.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_15.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_16.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_16.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_17.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_17.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_2.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_2.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_3.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_3.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_4.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_4.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_5.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_5.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_6.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_6.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_7.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_7.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_8.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_8.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_9.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_9.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_a.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_a.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_b.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_b.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_c.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_c.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_d.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_d.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_e.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_e.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_f.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/all_f.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_2.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_2.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_3.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_3.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_4.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_4.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_5.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_5.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_6.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_6.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_7.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_7.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_8.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/classes_8.js \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/search/close.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/defines_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/defines_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/defines_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/defines_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/defines_2.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/defines_2.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/defines_3.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/defines_3.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enums_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enums_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enums_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enums_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enums_2.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enums_2.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_2.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_2.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_3.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_3.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_4.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_4.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_5.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/enumvalues_5.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_2.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_2.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_3.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_3.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_4.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_4.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_5.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_5.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_6.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_6.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_7.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_7.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_8.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/files_8.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_10.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_10.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_11.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_11.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_12.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_12.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_13.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_13.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_14.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_14.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_15.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_15.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_16.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_16.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_17.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_17.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_2.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_2.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_3.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_3.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_4.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_4.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_5.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_5.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_6.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_6.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_7.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_7.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_8.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_8.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_9.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_9.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_a.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_a.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_b.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_b.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_c.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_c.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_d.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_d.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_e.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_e.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_f.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/functions_f.js \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/search/mag_sel.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/namespaces_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/namespaces_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/nomatches.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/search.css \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/search.js \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/search/search_l.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/search_m.png \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/search/search_r.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/searchdata.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/typedefs_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/typedefs_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/typedefs_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/typedefs_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_0.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_0.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_1.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_1.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_10.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_10.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_11.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_11.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_12.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_12.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_13.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_13.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_2.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_2.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_3.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_3.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_4.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_4.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_5.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_5.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_6.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_6.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_7.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_7.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_8.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_8.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_9.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_9.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_a.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_a.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_b.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_b.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_c.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_c.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_d.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_d.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_e.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_e.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_f.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/search/variables_f.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/splitbar.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/structfasttext_1_1Node-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/structfasttext_1_1Node.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/structfasttext_1_1Node.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/structfasttext_1_1entry-members.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/structfasttext_1_1entry.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/structfasttext_1_1entry.js \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/sync_off.png \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/sync_on.png \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/tab_a.png \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/tab_b.png \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/tab_h.png \n",
" extracting: fastText-0.2.0/website/static/docs/en/html/tab_s.png \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/tabs.css \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/utils_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/utils_8cc.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/utils_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/utils_8h.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/utils_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/vector_8cc.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/vector_8cc.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/vector_8h.html \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/vector_8h.js \n",
" inflating: fastText-0.2.0/website/static/docs/en/html/vector_8h_source.html \n",
" inflating: fastText-0.2.0/website/static/fasttext.css \n",
" creating: fastText-0.2.0/website/static/img/\n",
" creating: fastText-0.2.0/website/static/img/authors/\n",
" inflating: fastText-0.2.0/website/static/img/authors/armand_joulin.jpg \n",
" inflating: fastText-0.2.0/website/static/img/authors/christian_puhrsch.png \n",
" inflating: fastText-0.2.0/website/static/img/authors/edouard_grave.jpeg \n",
" inflating: fastText-0.2.0/website/static/img/authors/piotr_bojanowski.jpg \n",
" inflating: fastText-0.2.0/website/static/img/authors/tomas_mikolov.jpg \n",
" creating: fastText-0.2.0/website/static/img/blog/\n",
" inflating: fastText-0.2.0/website/static/img/blog/2016-08-18-blog-post-img1.png \n",
" inflating: fastText-0.2.0/website/static/img/blog/2016-08-18-blog-post-img2.png \n",
" inflating: fastText-0.2.0/website/static/img/blog/2017-05-02-blog-post-img1.jpg \n",
" inflating: fastText-0.2.0/website/static/img/blog/2017-05-02-blog-post-img2.jpg \n",
" inflating: fastText-0.2.0/website/static/img/blog/2017-10-02-blog-post-img1.png \n",
" inflating: fastText-0.2.0/website/static/img/cbo_vs_skipgram.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-icon-api.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-icon-bg-web.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-icon-color-square.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-icon-color-web.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-icon-faq.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-icon-tutorial.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-icon-white-web.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-logo-color-web.png \n",
" inflating: fastText-0.2.0/website/static/img/fasttext-logo-white-web.png \n",
" inflating: fastText-0.2.0/website/static/img/logo-color.png \n",
" inflating: fastText-0.2.0/website/static/img/model-black.png \n",
" inflating: fastText-0.2.0/website/static/img/model-blue.png \n",
" inflating: fastText-0.2.0/website/static/img/model-red.png \n",
" inflating: fastText-0.2.0/website/static/img/ogimage.png \n",
" inflating: fastText-0.2.0/website/static/img/oss_logo.png \n",
" inflating: fastText-0.2.0/wikifil.pl \n",
" inflating: fastText-0.2.0/word-vector-example.sh \n",
"/content/fastText-0.2.0\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/args.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/dictionary.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/productquantizer.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/matrix.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/qmatrix.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/vector.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/model.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/utils.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/meter.cc\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/fasttext.cc\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:\u001b[m\u001b[K In member function \u001b[01m\u001b[Kvoid fasttext::FastText::quantize(const fasttext::Args&)\u001b[m\u001b[K:\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:302:45:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[K\u001b[01m\u001b[Kstd::vector<int> fasttext::FastText::selectEmbeddings(int32_t) const\u001b[m\u001b[K is deprecated: selectEmbeddings is being deprecated. [\u001b[01;35m\u001b[K-Wdeprecated-declarations\u001b[m\u001b[K]\n",
" auto idx = selectEmbeddings(qargs.cutoff\u001b[01;35m\u001b[K)\u001b[m\u001b[K;\n",
" \u001b[01;35m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:279:22:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kdeclared here\n",
" std::vector<int32_t> \u001b[01;36m\u001b[KFastText\u001b[m\u001b[K::selectEmbeddings(int32_t cutoff) const {\n",
" \u001b[01;36m\u001b[K^~~~~~~~\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:\u001b[m\u001b[K In member function \u001b[01m\u001b[Kvoid fasttext::FastText::lazyComputeWordVectors()\u001b[m\u001b[K:\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:531:40:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[K\u001b[01m\u001b[Kvoid fasttext::FastText::precomputeWordVectors(fasttext::Matrix&)\u001b[m\u001b[K is deprecated: precomputeWordVectors is being deprecated. [\u001b[01;35m\u001b[K-Wdeprecated-declarations\u001b[m\u001b[K]\n",
" precomputeWordVectors(*wordVectors_\u001b[01;35m\u001b[K)\u001b[m\u001b[K;\n",
" \u001b[01;35m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:514:6:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kdeclared here\n",
" void \u001b[01;36m\u001b[KFastText\u001b[m\u001b[K::precomputeWordVectors(Matrix& wordVectors) {\n",
" \u001b[01;36m\u001b[K^~~~~~~~\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:\u001b[m\u001b[K In member function \u001b[01m\u001b[Kvoid fasttext::FastText::trainThread(int32_t)\u001b[m\u001b[K:\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:650:41:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[K\u001b[01m\u001b[Kvoid fasttext::FastText::supervised(fasttext::Model&, fasttext::real, const std::vector<int>&, const std::vector<int>&)\u001b[m\u001b[K is deprecated: supervised is being deprecated. [\u001b[01;35m\u001b[K-Wdeprecated-declarations\u001b[m\u001b[K]\n",
" supervised(model, lr, line, labels\u001b[01;35m\u001b[K)\u001b[m\u001b[K;\n",
" \u001b[01;35m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:338:6:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kdeclared here\n",
" void \u001b[01;36m\u001b[KFastText\u001b[m\u001b[K::supervised(\n",
" \u001b[01;36m\u001b[K^~~~~~~~\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:653:27:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[K\u001b[01m\u001b[Kvoid fasttext::FastText::cbow(fasttext::Model&, fasttext::real, const std::vector<int>&)\u001b[m\u001b[K is deprecated: cbow is being deprecated. [\u001b[01;35m\u001b[K-Wdeprecated-declarations\u001b[m\u001b[K]\n",
" cbow(model, lr, line\u001b[01;35m\u001b[K)\u001b[m\u001b[K;\n",
" \u001b[01;35m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:355:6:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kdeclared here\n",
" void \u001b[01;36m\u001b[KFastText\u001b[m\u001b[K::cbow(Model& model, real lr, const std::vector<int32_t>& line) {\n",
" \u001b[01;36m\u001b[K^~~~~~~~\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:656:31:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[K\u001b[01m\u001b[Kvoid fasttext::FastText::skipgram(fasttext::Model&, fasttext::real, const std::vector<int>&)\u001b[m\u001b[K is deprecated: skipgram is being deprecated. [\u001b[01;35m\u001b[K-Wdeprecated-declarations\u001b[m\u001b[K]\n",
" skipgram(model, lr, line\u001b[01;35m\u001b[K)\u001b[m\u001b[K;\n",
" \u001b[01;35m\u001b[K^\u001b[m\u001b[K\n",
"\u001b[01m\u001b[Ksrc/fasttext.cc:371:6:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kdeclared here\n",
" void \u001b[01;36m\u001b[KFastText\u001b[m\u001b[K::skipgram(\n",
" \u001b[01;36m\u001b[K^~~~~~~~\u001b[m\u001b[K\n",
"c++ -pthread -std=c++0x -march=native -O3 -funroll-loops args.o dictionary.o productquantizer.o matrix.o qmatrix.o vector.o model.o utils.o meter.o fasttext.o src/main.cc -o fasttext\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "5JauDviyqqL-",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## Make simple dataset"
]
},
{
"metadata": {
"id": "ALMQ3gjFqqZS",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# 1 is positive, 0 is negative\n",
"f = open('train.txt', 'w')\n",
"f.write('__label__1 i love you\\n')\n",
"f.write('__label__1 he loves me\\n')\n",
"f.write('__label__1 she likes baseball\\n')\n",
"f.write('__label__0 i hate you\\n')\n",
"f.write('__label__0 sorry for that\\n')\n",
"f.write('__label__0 this is awful')\n",
"f.close()\n",
"\n",
"f = open('test.txt', 'w')\n",
"f.write('sorry hate you')\n",
"f.close()"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "i3_PpexwsN_a",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## Training"
]
},
{
"metadata": {
"id": "q06m76JusOQ8",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 92
},
"outputId": "4ed3502d-4aec-4d06-cb02-b8392978ce14"
},
"cell_type": "code",
"source": [
"!./fasttext supervised -input train.txt -output model -dim 2"
],
"execution_count": 18,
"outputs": [
{
"output_type": "stream",
"text": [
"\rRead 0M words\n",
"Number of words: 17\n",
"Number of labels: 2\n",
"\rProgress: 100.0% words/sec/thread: 17608 lr: 0.000000 loss: 0.672308 ETA: 0h 0m\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "C77MXO-GsOpi",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## Predict"
]
},
{
"metadata": {
"id": "y1yDPCjVsO6x",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 36
},
"outputId": "8963d7bd-01c8-40b9-e1ee-1446cb1b3454"
},
"cell_type": "code",
"source": [
"!cat test.txt\n",
"!./fasttext predict model.bin test.txt"
],
"execution_count": 22,
"outputs": [
{
"output_type": "stream",
"text": [
"sorry hate you__label__0\n"
],
"name": "stdout"
}
]
}
]
}
+1
View File
@@ -0,0 +1 @@
sorry hate you
+6
View File
@@ -0,0 +1,6 @@
__label__1 i love you
__label__1 he loves me
__label__1 she likes baseball
__label__0 i hate you
__label__0 sorry for that
__label__0 this is awful
+117
View File
@@ -0,0 +1,117 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung @graykode\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"import torch.nn.functional as F\n",
"\n",
"class TextCNN(nn.Module):\n",
" def __init__(self):\n",
" super(TextCNN, self).__init__()\n",
" self.num_filters_total = num_filters * len(filter_sizes)\n",
" self.W = nn.Embedding(vocab_size, embedding_size)\n",
" self.Weight = nn.Linear(self.num_filters_total, num_classes, bias=False)\n",
" self.Bias = nn.Parameter(torch.ones([num_classes]))\n",
" self.filter_list = nn.ModuleList([nn.Conv2d(1, num_filters, (size, embedding_size)) for size in filter_sizes])\n",
"\n",
" def forward(self, X):\n",
" embedded_chars = self.W(X) # [batch_size, sequence_length, sequence_length]\n",
" embedded_chars = embedded_chars.unsqueeze(1) # add channel(=1) [batch, channel(=1), sequence_length, embedding_size]\n",
"\n",
" pooled_outputs = []\n",
" for i, conv in enumerate(self.filter_list):\n",
" # conv : [input_channel(=1), output_channel(=3), (filter_height, filter_width), bias_option]\n",
" h = F.relu(conv(embedded_chars))\n",
" # mp : ((filter_height, filter_width))\n",
" mp = nn.MaxPool2d((sequence_length - filter_sizes[i] + 1, 1))\n",
" # pooled : [batch_size(=6), output_height(=1), output_width(=1), output_channel(=3)]\n",
" pooled = mp(h).permute(0, 3, 2, 1)\n",
" pooled_outputs.append(pooled)\n",
"\n",
" h_pool = torch.cat(pooled_outputs, len(filter_sizes)) # [batch_size(=6), output_height(=1), output_width(=1), output_channel(=3) * 3]\n",
" h_pool_flat = torch.reshape(h_pool, [-1, self.num_filters_total]) # [batch_size(=6), output_height * output_width * (output_channel * 3)]\n",
" model = self.Weight(h_pool_flat) + self.Bias # [batch_size, num_classes]\n",
" return model\n",
"\n",
"if __name__ == '__main__':\n",
" embedding_size = 2 # embedding size\n",
" sequence_length = 3 # sequence length\n",
" num_classes = 2 # number of classes\n",
" filter_sizes = [2, 2, 2] # n-gram windows\n",
" num_filters = 3 # number of filters\n",
"\n",
" # 3 words sentences (=sequence_length is 3)\n",
" sentences = [\"i love you\", \"he loves me\", \"she likes baseball\", \"i hate you\", \"sorry for that\", \"this is awful\"]\n",
" labels = [1, 1, 1, 0, 0, 0] # 1 is good, 0 is not good.\n",
"\n",
" word_list = \" \".join(sentences).split()\n",
" word_list = list(set(word_list))\n",
" word_dict = {w: i for i, w in enumerate(word_list)}\n",
" vocab_size = len(word_dict)\n",
"\n",
" model = TextCNN()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" inputs = torch.LongTensor([np.asarray([word_dict[n] for n in sen.split()]) for sen in sentences])\n",
" targets = torch.LongTensor([out for out in labels]) # To using Torch Softmax Loss function\n",
"\n",
" # Training\n",
" for epoch in range(5000):\n",
" optimizer.zero_grad()\n",
" output = model(inputs)\n",
"\n",
" # output : [batch_size, num_classes], target_batch : [batch_size] (LongTensor, not one-hot)\n",
" loss = criterion(output, targets)\n",
" if (epoch + 1) % 1000 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Test\n",
" test_text = 'sorry hate you'\n",
" tests = [np.asarray([word_dict[n] for n in test_text.split()])]\n",
" test_batch = torch.LongTensor(tests)\n",
"\n",
" # Predict\n",
" predict = model(test_batch).data.max(1, keepdim=True)[1]\n",
" if predict[0][0] == 0:\n",
" print(test_text,\"is Bad Mean...\")\n",
" else:\n",
" print(test_text,\"is Good Mean!!\")"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+84
View File
@@ -0,0 +1,84 @@
# %%
# code by Tae Hwan Jung @graykode
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
class TextCNN(nn.Module):
def __init__(self):
super(TextCNN, self).__init__()
self.num_filters_total = num_filters * len(filter_sizes)
self.W = nn.Embedding(vocab_size, embedding_size)
self.Weight = nn.Linear(self.num_filters_total, num_classes, bias=False)
self.Bias = nn.Parameter(torch.ones([num_classes]))
self.filter_list = nn.ModuleList([nn.Conv2d(1, num_filters, (size, embedding_size)) for size in filter_sizes])
def forward(self, X):
embedded_chars = self.W(X) # [batch_size, sequence_length, sequence_length]
embedded_chars = embedded_chars.unsqueeze(1) # add channel(=1) [batch, channel(=1), sequence_length, embedding_size]
pooled_outputs = []
for i, conv in enumerate(self.filter_list):
# conv : [input_channel(=1), output_channel(=3), (filter_height, filter_width), bias_option]
h = F.relu(conv(embedded_chars))
# mp : ((filter_height, filter_width))
mp = nn.MaxPool2d((sequence_length - filter_sizes[i] + 1, 1))
# pooled : [batch_size(=6), output_height(=1), output_width(=1), output_channel(=3)]
pooled = mp(h).permute(0, 3, 2, 1)
pooled_outputs.append(pooled)
h_pool = torch.cat(pooled_outputs, len(filter_sizes)) # [batch_size(=6), output_height(=1), output_width(=1), output_channel(=3) * 3]
h_pool_flat = torch.reshape(h_pool, [-1, self.num_filters_total]) # [batch_size(=6), output_height * output_width * (output_channel * 3)]
model = self.Weight(h_pool_flat) + self.Bias # [batch_size, num_classes]
return model
if __name__ == '__main__':
embedding_size = 2 # embedding size
sequence_length = 3 # sequence length
num_classes = 2 # number of classes
filter_sizes = [2, 2, 2] # n-gram windows
num_filters = 3 # number of filters
# 3 words sentences (=sequence_length is 3)
sentences = ["i love you", "he loves me", "she likes baseball", "i hate you", "sorry for that", "this is awful"]
labels = [1, 1, 1, 0, 0, 0] # 1 is good, 0 is not good.
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
vocab_size = len(word_dict)
model = TextCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
inputs = torch.LongTensor([np.asarray([word_dict[n] for n in sen.split()]) for sen in sentences])
targets = torch.LongTensor([out for out in labels]) # To using Torch Softmax Loss function
# Training
for epoch in range(5000):
optimizer.zero_grad()
output = model(inputs)
# output : [batch_size, num_classes], target_batch : [batch_size] (LongTensor, not one-hot)
loss = criterion(output, targets)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Test
test_text = 'sorry hate you'
tests = [np.asarray([word_dict[n] for n in test_text.split()])]
test_batch = torch.LongTensor(tests)
# Predict
predict = model(test_batch).data.max(1, keepdim=True)[1]
if predict[0][0] == 0:
print(test_text,"is Bad Mean...")
else:
print(test_text,"is Good Mean!!")
+115
View File
@@ -0,0 +1,115 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung @graykode\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"\n",
"def make_batch():\n",
" input_batch = []\n",
" target_batch = []\n",
"\n",
" for sen in sentences:\n",
" word = sen.split() # space tokenizer\n",
" input = [word_dict[n] for n in word[:-1]] # create (1~n-1) as input\n",
" target = word_dict[word[-1]] # create (n) as target, We usually call this 'casual language model'\n",
"\n",
" input_batch.append(np.eye(n_class)[input])\n",
" target_batch.append(target)\n",
"\n",
" return input_batch, target_batch\n",
"\n",
"class TextRNN(nn.Module):\n",
" def __init__(self):\n",
" super(TextRNN, self).__init__()\n",
" self.rnn = nn.RNN(input_size=n_class, hidden_size=n_hidden)\n",
" self.W = nn.Linear(n_hidden, n_class, bias=False)\n",
" self.b = nn.Parameter(torch.ones([n_class]))\n",
"\n",
" def forward(self, hidden, X):\n",
" X = X.transpose(0, 1) # X : [n_step, batch_size, n_class]\n",
" outputs, hidden = self.rnn(X, hidden)\n",
" # outputs : [n_step, batch_size, num_directions(=1) * n_hidden]\n",
" # hidden : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]\n",
" outputs = outputs[-1] # [batch_size, num_directions(=1) * n_hidden]\n",
" model = self.W(outputs) + self.b # model : [batch_size, n_class]\n",
" return model\n",
"\n",
"if __name__ == '__main__':\n",
" n_step = 2 # number of cells(= number of Step)\n",
" n_hidden = 5 # number of hidden units in one cell\n",
"\n",
" sentences = [\"i like dog\", \"i love coffee\", \"i hate milk\"]\n",
"\n",
" word_list = \" \".join(sentences).split()\n",
" word_list = list(set(word_list))\n",
" word_dict = {w: i for i, w in enumerate(word_list)}\n",
" number_dict = {i: w for i, w in enumerate(word_list)}\n",
" n_class = len(word_dict)\n",
" batch_size = len(sentences)\n",
"\n",
" model = TextRNN()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" input_batch, target_batch = make_batch()\n",
" input_batch = torch.FloatTensor(input_batch)\n",
" target_batch = torch.LongTensor(target_batch)\n",
"\n",
" # Training\n",
" for epoch in range(5000):\n",
" optimizer.zero_grad()\n",
"\n",
" # hidden : [num_layers * num_directions, batch, hidden_size]\n",
" hidden = torch.zeros(1, batch_size, n_hidden)\n",
" # input_batch : [batch_size, n_step, n_class]\n",
" output = model(hidden, input_batch)\n",
"\n",
" # output : [batch_size, n_class], target_batch : [batch_size] (LongTensor, not one-hot)\n",
" loss = criterion(output, target_batch)\n",
" if (epoch + 1) % 1000 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" input = [sen.split()[:2] for sen in sentences]\n",
"\n",
" # Predict\n",
" hidden = torch.zeros(1, batch_size, n_hidden)\n",
" predict = model(hidden, input_batch).data.max(1, keepdim=True)[1]\n",
" print([sen.split()[:2] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+82
View File
@@ -0,0 +1,82 @@
# %%
# code by Tae Hwan Jung @graykode
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
def make_batch():
input_batch = []
target_batch = []
for sen in sentences:
word = sen.split() # space tokenizer
input = [word_dict[n] for n in word[:-1]] # create (1~n-1) as input
target = word_dict[word[-1]] # create (n) as target, We usually call this 'casual language model'
input_batch.append(np.eye(n_class)[input])
target_batch.append(target)
return input_batch, target_batch
class TextRNN(nn.Module):
def __init__(self):
super(TextRNN, self).__init__()
self.rnn = nn.RNN(input_size=n_class, hidden_size=n_hidden)
self.W = nn.Linear(n_hidden, n_class, bias=False)
self.b = nn.Parameter(torch.ones([n_class]))
def forward(self, hidden, X):
X = X.transpose(0, 1) # X : [n_step, batch_size, n_class]
outputs, hidden = self.rnn(X, hidden)
# outputs : [n_step, batch_size, num_directions(=1) * n_hidden]
# hidden : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]
outputs = outputs[-1] # [batch_size, num_directions(=1) * n_hidden]
model = self.W(outputs) + self.b # model : [batch_size, n_class]
return model
if __name__ == '__main__':
n_step = 2 # number of cells(= number of Step)
n_hidden = 5 # number of hidden units in one cell
sentences = ["i like dog", "i love coffee", "i hate milk"]
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict)
batch_size = len(sentences)
model = TextRNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
input_batch, target_batch = make_batch()
input_batch = torch.FloatTensor(input_batch)
target_batch = torch.LongTensor(target_batch)
# Training
for epoch in range(5000):
optimizer.zero_grad()
# hidden : [num_layers * num_directions, batch, hidden_size]
hidden = torch.zeros(1, batch_size, n_hidden)
# input_batch : [batch_size, n_step, n_class]
output = model(hidden, input_batch)
# output : [batch_size, n_class], target_batch : [batch_size] (LongTensor, not one-hot)
loss = criterion(output, target_batch)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
input = [sen.split()[:2] for sen in sentences]
# Predict
hidden = torch.zeros(1, batch_size, n_hidden)
predict = model(hidden, input_batch).data.max(1, keepdim=True)[1]
print([sen.split()[:2] for sen in sentences], '->', [number_dict[n.item()] for n in predict.squeeze()])
+106
View File
@@ -0,0 +1,106 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung @graykode\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"\n",
"def make_batch():\n",
" input_batch, target_batch = [], []\n",
"\n",
" for seq in seq_data:\n",
" input = [word_dict[n] for n in seq[:-1]] # 'm', 'a' , 'k' is input\n",
" target = word_dict[seq[-1]] # 'e' is target\n",
" input_batch.append(np.eye(n_class)[input])\n",
" target_batch.append(target)\n",
"\n",
" return input_batch, target_batch\n",
"\n",
"class TextLSTM(nn.Module):\n",
" def __init__(self):\n",
" super(TextLSTM, self).__init__()\n",
"\n",
" self.lstm = nn.LSTM(input_size=n_class, hidden_size=n_hidden)\n",
" self.W = nn.Linear(n_hidden, n_class, bias=False)\n",
" self.b = nn.Parameter(torch.ones([n_class]))\n",
"\n",
" def forward(self, X):\n",
" input = X.transpose(0, 1) # X : [n_step, batch_size, n_class]\n",
"\n",
" hidden_state = torch.zeros(1, len(X), n_hidden) # [num_layers(=1) * num_directions(=1), batch_size, n_hidden]\n",
" cell_state = torch.zeros(1, len(X), n_hidden) # [num_layers(=1) * num_directions(=1), batch_size, n_hidden]\n",
"\n",
" outputs, (_, _) = self.lstm(input, (hidden_state, cell_state))\n",
" outputs = outputs[-1] # [batch_size, n_hidden]\n",
" model = self.W(outputs) + self.b # model : [batch_size, n_class]\n",
" return model\n",
"\n",
"if __name__ == '__main__':\n",
" n_step = 3 # number of cells(= number of Step)\n",
" n_hidden = 128 # number of hidden units in one cell\n",
"\n",
" char_arr = [c for c in 'abcdefghijklmnopqrstuvwxyz']\n",
" word_dict = {n: i for i, n in enumerate(char_arr)}\n",
" number_dict = {i: w for i, w in enumerate(char_arr)}\n",
" n_class = len(word_dict) # number of class(=number of vocab)\n",
"\n",
" seq_data = ['make', 'need', 'coal', 'word', 'love', 'hate', 'live', 'home', 'hash', 'star']\n",
"\n",
" model = TextLSTM()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" input_batch, target_batch = make_batch()\n",
" input_batch = torch.FloatTensor(input_batch)\n",
" target_batch = torch.LongTensor(target_batch)\n",
"\n",
" # Training\n",
" for epoch in range(1000):\n",
" optimizer.zero_grad()\n",
"\n",
" output = model(input_batch)\n",
" loss = criterion(output, target_batch)\n",
" if (epoch + 1) % 100 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" inputs = [sen[:3] for sen in seq_data]\n",
"\n",
" predict = model(input_batch).data.max(1, keepdim=True)[1]\n",
" print(inputs, '->', [number_dict[n.item()] for n in predict.squeeze()])"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+73
View File
@@ -0,0 +1,73 @@
# %%
# code by Tae Hwan Jung @graykode
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
def make_batch():
input_batch, target_batch = [], []
for seq in seq_data:
input = [word_dict[n] for n in seq[:-1]] # 'm', 'a' , 'k' is input
target = word_dict[seq[-1]] # 'e' is target
input_batch.append(np.eye(n_class)[input])
target_batch.append(target)
return input_batch, target_batch
class TextLSTM(nn.Module):
def __init__(self):
super(TextLSTM, self).__init__()
self.lstm = nn.LSTM(input_size=n_class, hidden_size=n_hidden)
self.W = nn.Linear(n_hidden, n_class, bias=False)
self.b = nn.Parameter(torch.ones([n_class]))
def forward(self, X):
input = X.transpose(0, 1) # X : [n_step, batch_size, n_class]
hidden_state = torch.zeros(1, len(X), n_hidden) # [num_layers(=1) * num_directions(=1), batch_size, n_hidden]
cell_state = torch.zeros(1, len(X), n_hidden) # [num_layers(=1) * num_directions(=1), batch_size, n_hidden]
outputs, (_, _) = self.lstm(input, (hidden_state, cell_state))
outputs = outputs[-1] # [batch_size, n_hidden]
model = self.W(outputs) + self.b # model : [batch_size, n_class]
return model
if __name__ == '__main__':
n_step = 3 # number of cells(= number of Step)
n_hidden = 128 # number of hidden units in one cell
char_arr = [c for c in 'abcdefghijklmnopqrstuvwxyz']
word_dict = {n: i for i, n in enumerate(char_arr)}
number_dict = {i: w for i, w in enumerate(char_arr)}
n_class = len(word_dict) # number of class(=number of vocab)
seq_data = ['make', 'need', 'coal', 'word', 'love', 'hate', 'live', 'home', 'hash', 'star']
model = TextLSTM()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
input_batch, target_batch = make_batch()
input_batch = torch.FloatTensor(input_batch)
target_batch = torch.LongTensor(target_batch)
# Training
for epoch in range(1000):
optimizer.zero_grad()
output = model(input_batch)
loss = criterion(output, target_batch)
if (epoch + 1) % 100 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
inputs = [sen[:3] for sen in seq_data]
predict = model(input_batch).data.max(1, keepdim=True)[1]
print(inputs, '->', [number_dict[n.item()] for n in predict.squeeze()])
+110
View File
@@ -0,0 +1,110 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung @graykode\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"\n",
"def make_batch():\n",
" input_batch = []\n",
" target_batch = []\n",
"\n",
" words = sentence.split()\n",
" for i, word in enumerate(words[:-1]):\n",
" input = [word_dict[n] for n in words[:(i + 1)]]\n",
" input = input + [0] * (max_len - len(input))\n",
" target = word_dict[words[i + 1]]\n",
" input_batch.append(np.eye(n_class)[input])\n",
" target_batch.append(target)\n",
"\n",
" return input_batch, target_batch\n",
"\n",
"class BiLSTM(nn.Module):\n",
" def __init__(self):\n",
" super(BiLSTM, self).__init__()\n",
"\n",
" self.lstm = nn.LSTM(input_size=n_class, hidden_size=n_hidden, bidirectional=True)\n",
" self.W = nn.Linear(n_hidden * 2, n_class, bias=False)\n",
" self.b = nn.Parameter(torch.ones([n_class]))\n",
"\n",
" def forward(self, X):\n",
" input = X.transpose(0, 1) # input : [n_step, batch_size, n_class]\n",
"\n",
" hidden_state = torch.zeros(1*2, len(X), n_hidden) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]\n",
" cell_state = torch.zeros(1*2, len(X), n_hidden) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]\n",
"\n",
" outputs, (_, _) = self.lstm(input, (hidden_state, cell_state))\n",
" outputs = outputs[-1] # [batch_size, n_hidden]\n",
" model = self.W(outputs) + self.b # model : [batch_size, n_class]\n",
" return model\n",
"\n",
"if __name__ == '__main__':\n",
" n_hidden = 5 # number of hidden units in one cell\n",
"\n",
" sentence = (\n",
" 'Lorem ipsum dolor sit amet consectetur adipisicing elit '\n",
" 'sed do eiusmod tempor incididunt ut labore et dolore magna '\n",
" 'aliqua Ut enim ad minim veniam quis nostrud exercitation'\n",
" )\n",
"\n",
" word_dict = {w: i for i, w in enumerate(list(set(sentence.split())))}\n",
" number_dict = {i: w for i, w in enumerate(list(set(sentence.split())))}\n",
" n_class = len(word_dict)\n",
" max_len = len(sentence.split())\n",
"\n",
" model = BiLSTM()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" input_batch, target_batch = make_batch()\n",
" input_batch = torch.FloatTensor(input_batch)\n",
" target_batch = torch.LongTensor(target_batch)\n",
"\n",
" # Training\n",
" for epoch in range(10000):\n",
" optimizer.zero_grad()\n",
" output = model(input_batch)\n",
" loss = criterion(output, target_batch)\n",
" if (epoch + 1) % 1000 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" predict = model(input_batch).data.max(1, keepdim=True)[1]\n",
" print(sentence)\n",
" print([number_dict[n.item()] for n in predict.squeeze()])\n"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+77
View File
@@ -0,0 +1,77 @@
# %%
# code by Tae Hwan Jung @graykode
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
def make_batch():
input_batch = []
target_batch = []
words = sentence.split()
for i, word in enumerate(words[:-1]):
input = [word_dict[n] for n in words[:(i + 1)]]
input = input + [0] * (max_len - len(input))
target = word_dict[words[i + 1]]
input_batch.append(np.eye(n_class)[input])
target_batch.append(target)
return input_batch, target_batch
class BiLSTM(nn.Module):
def __init__(self):
super(BiLSTM, self).__init__()
self.lstm = nn.LSTM(input_size=n_class, hidden_size=n_hidden, bidirectional=True)
self.W = nn.Linear(n_hidden * 2, n_class, bias=False)
self.b = nn.Parameter(torch.ones([n_class]))
def forward(self, X):
input = X.transpose(0, 1) # input : [n_step, batch_size, n_class]
hidden_state = torch.zeros(1*2, len(X), n_hidden) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]
cell_state = torch.zeros(1*2, len(X), n_hidden) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]
outputs, (_, _) = self.lstm(input, (hidden_state, cell_state))
outputs = outputs[-1] # [batch_size, n_hidden]
model = self.W(outputs) + self.b # model : [batch_size, n_class]
return model
if __name__ == '__main__':
n_hidden = 5 # number of hidden units in one cell
sentence = (
'Lorem ipsum dolor sit amet consectetur adipisicing elit '
'sed do eiusmod tempor incididunt ut labore et dolore magna '
'aliqua Ut enim ad minim veniam quis nostrud exercitation'
)
word_dict = {w: i for i, w in enumerate(list(set(sentence.split())))}
number_dict = {i: w for i, w in enumerate(list(set(sentence.split())))}
n_class = len(word_dict)
max_len = len(sentence.split())
model = BiLSTM()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
input_batch, target_batch = make_batch()
input_batch = torch.FloatTensor(input_batch)
target_batch = torch.LongTensor(target_batch)
# Training
for epoch in range(10000):
optimizer.zero_grad()
output = model(input_batch)
loss = criterion(output, target_batch)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
predict = model(input_batch).data.max(1, keepdim=True)[1]
print(sentence)
print([number_dict[n.item()] for n in predict.squeeze()])
+155
View File
@@ -0,0 +1,155 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung @graykode\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"\n",
"# S: Symbol that shows starting of decoding input\n",
"# E: Symbol that shows starting of decoding output\n",
"# P: Symbol that will fill in blank sequence if current batch data size is short than time steps\n",
"\n",
"def make_batch():\n",
" input_batch, output_batch, target_batch = [], [], []\n",
"\n",
" for seq in seq_data:\n",
" for i in range(2):\n",
" seq[i] = seq[i] + 'P' * (n_step - len(seq[i]))\n",
"\n",
" input = [num_dic[n] for n in seq[0]]\n",
" output = [num_dic[n] for n in ('S' + seq[1])]\n",
" target = [num_dic[n] for n in (seq[1] + 'E')]\n",
"\n",
" input_batch.append(np.eye(n_class)[input])\n",
" output_batch.append(np.eye(n_class)[output])\n",
" target_batch.append(target) # not one-hot\n",
"\n",
" # make tensor\n",
" return torch.FloatTensor(input_batch), torch.FloatTensor(output_batch), torch.LongTensor(target_batch)\n",
"\n",
"# make test batch\n",
"def make_testbatch(input_word):\n",
" input_batch, output_batch = [], []\n",
"\n",
" input_w = input_word + 'P' * (n_step - len(input_word))\n",
" input = [num_dic[n] for n in input_w]\n",
" output = [num_dic[n] for n in 'S' + 'P' * n_step]\n",
"\n",
" input_batch = np.eye(n_class)[input]\n",
" output_batch = np.eye(n_class)[output]\n",
"\n",
" return torch.FloatTensor(input_batch).unsqueeze(0), torch.FloatTensor(output_batch).unsqueeze(0)\n",
"\n",
"# Model\n",
"class Seq2Seq(nn.Module):\n",
" def __init__(self):\n",
" super(Seq2Seq, self).__init__()\n",
"\n",
" self.enc_cell = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)\n",
" self.dec_cell = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)\n",
" self.fc = nn.Linear(n_hidden, n_class)\n",
"\n",
" def forward(self, enc_input, enc_hidden, dec_input):\n",
" enc_input = enc_input.transpose(0, 1) # enc_input: [max_len(=n_step, time step), batch_size, n_class]\n",
" dec_input = dec_input.transpose(0, 1) # dec_input: [max_len(=n_step, time step), batch_size, n_class]\n",
"\n",
" # enc_states : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]\n",
" _, enc_states = self.enc_cell(enc_input, enc_hidden)\n",
" # outputs : [max_len+1(=6), batch_size, num_directions(=1) * n_hidden(=128)]\n",
" outputs, _ = self.dec_cell(dec_input, enc_states)\n",
"\n",
" model = self.fc(outputs) # model : [max_len+1(=6), batch_size, n_class]\n",
" return model\n",
"\n",
"if __name__ == '__main__':\n",
" n_step = 5\n",
" n_hidden = 128\n",
"\n",
" char_arr = [c for c in 'SEPabcdefghijklmnopqrstuvwxyz']\n",
" num_dic = {n: i for i, n in enumerate(char_arr)}\n",
" seq_data = [['man', 'women'], ['black', 'white'], ['king', 'queen'], ['girl', 'boy'], ['up', 'down'], ['high', 'low']]\n",
"\n",
" n_class = len(num_dic)\n",
" batch_size = len(seq_data)\n",
"\n",
" model = Seq2Seq()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" input_batch, output_batch, target_batch = make_batch()\n",
"\n",
" for epoch in range(5000):\n",
" # make hidden shape [num_layers * num_directions, batch_size, n_hidden]\n",
" hidden = torch.zeros(1, batch_size, n_hidden)\n",
"\n",
" optimizer.zero_grad()\n",
" # input_batch : [batch_size, max_len(=n_step, time step), n_class]\n",
" # output_batch : [batch_size, max_len+1(=n_step, time step) (becase of 'S' or 'E'), n_class]\n",
" # target_batch : [batch_size, max_len+1(=n_step, time step)], not one-hot\n",
" output = model(input_batch, hidden, output_batch)\n",
" # output : [max_len+1, batch_size, n_class]\n",
" output = output.transpose(0, 1) # [batch_size, max_len+1(=6), n_class]\n",
" loss = 0\n",
" for i in range(0, len(target_batch)):\n",
" # output[i] : [max_len+1, n_class, target_batch[i] : max_len+1]\n",
" loss += criterion(output[i], target_batch[i])\n",
" if (epoch + 1) % 1000 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Test\n",
" def translate(word):\n",
" input_batch, output_batch = make_testbatch(word)\n",
"\n",
" # make hidden shape [num_layers * num_directions, batch_size, n_hidden]\n",
" hidden = torch.zeros(1, 1, n_hidden)\n",
" output = model(input_batch, hidden, output_batch)\n",
" # output : [max_len+1(=6), batch_size(=1), n_class]\n",
"\n",
" predict = output.data.max(2, keepdim=True)[1] # select n_class dimension\n",
" decoded = [char_arr[i] for i in predict]\n",
" end = decoded.index('E')\n",
" translated = ''.join(decoded[:end])\n",
"\n",
" return translated.replace('P', '')\n",
"\n",
" print('test')\n",
" print('man ->', translate('man'))\n",
" print('mans ->', translate('mans'))\n",
" print('king ->', translate('king'))\n",
" print('black ->', translate('black'))\n",
" print('upp ->', translate('upp'))"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+122
View File
@@ -0,0 +1,122 @@
# %%
# code by Tae Hwan Jung @graykode
import numpy as np
import torch
import torch.nn as nn
# S: Symbol that shows starting of decoding input
# E: Symbol that shows starting of decoding output
# P: Symbol that will fill in blank sequence if current batch data size is short than time steps
def make_batch():
input_batch, output_batch, target_batch = [], [], []
for seq in seq_data:
for i in range(2):
seq[i] = seq[i] + 'P' * (n_step - len(seq[i]))
input = [num_dic[n] for n in seq[0]]
output = [num_dic[n] for n in ('S' + seq[1])]
target = [num_dic[n] for n in (seq[1] + 'E')]
input_batch.append(np.eye(n_class)[input])
output_batch.append(np.eye(n_class)[output])
target_batch.append(target) # not one-hot
# make tensor
return torch.FloatTensor(input_batch), torch.FloatTensor(output_batch), torch.LongTensor(target_batch)
# make test batch
def make_testbatch(input_word):
input_batch, output_batch = [], []
input_w = input_word + 'P' * (n_step - len(input_word))
input = [num_dic[n] for n in input_w]
output = [num_dic[n] for n in 'S' + 'P' * n_step]
input_batch = np.eye(n_class)[input]
output_batch = np.eye(n_class)[output]
return torch.FloatTensor(input_batch).unsqueeze(0), torch.FloatTensor(output_batch).unsqueeze(0)
# Model
class Seq2Seq(nn.Module):
def __init__(self):
super(Seq2Seq, self).__init__()
self.enc_cell = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)
self.dec_cell = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)
self.fc = nn.Linear(n_hidden, n_class)
def forward(self, enc_input, enc_hidden, dec_input):
enc_input = enc_input.transpose(0, 1) # enc_input: [max_len(=n_step, time step), batch_size, n_class]
dec_input = dec_input.transpose(0, 1) # dec_input: [max_len(=n_step, time step), batch_size, n_class]
# enc_states : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]
_, enc_states = self.enc_cell(enc_input, enc_hidden)
# outputs : [max_len+1(=6), batch_size, num_directions(=1) * n_hidden(=128)]
outputs, _ = self.dec_cell(dec_input, enc_states)
model = self.fc(outputs) # model : [max_len+1(=6), batch_size, n_class]
return model
if __name__ == '__main__':
n_step = 5
n_hidden = 128
char_arr = [c for c in 'SEPabcdefghijklmnopqrstuvwxyz']
num_dic = {n: i for i, n in enumerate(char_arr)}
seq_data = [['man', 'women'], ['black', 'white'], ['king', 'queen'], ['girl', 'boy'], ['up', 'down'], ['high', 'low']]
n_class = len(num_dic)
batch_size = len(seq_data)
model = Seq2Seq()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
input_batch, output_batch, target_batch = make_batch()
for epoch in range(5000):
# make hidden shape [num_layers * num_directions, batch_size, n_hidden]
hidden = torch.zeros(1, batch_size, n_hidden)
optimizer.zero_grad()
# input_batch : [batch_size, max_len(=n_step, time step), n_class]
# output_batch : [batch_size, max_len+1(=n_step, time step) (becase of 'S' or 'E'), n_class]
# target_batch : [batch_size, max_len+1(=n_step, time step)], not one-hot
output = model(input_batch, hidden, output_batch)
# output : [max_len+1, batch_size, n_class]
output = output.transpose(0, 1) # [batch_size, max_len+1(=6), n_class]
loss = 0
for i in range(0, len(target_batch)):
# output[i] : [max_len+1, n_class, target_batch[i] : max_len+1]
loss += criterion(output[i], target_batch[i])
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Test
def translate(word):
input_batch, output_batch = make_testbatch(word)
# make hidden shape [num_layers * num_directions, batch_size, n_hidden]
hidden = torch.zeros(1, 1, n_hidden)
output = model(input_batch, hidden, output_batch)
# output : [max_len+1(=6), batch_size(=1), n_class]
predict = output.data.max(2, keepdim=True)[1] # select n_class dimension
decoded = [char_arr[i] for i in predict]
end = decoded.index('E')
translated = ''.join(decoded[:end])
return translated.replace('P', '')
print('test')
print('man ->', translate('man'))
print('mans ->', translate('mans'))
print('king ->', translate('king'))
print('black ->', translate('black'))
print('upp ->', translate('upp'))
@@ -0,0 +1,154 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung @graykode\n",
"# Reference : https://github.com/hunkim/PyTorchZeroToAll/blob/master/14_2_seq2seq_att.py\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.nn.functional as F\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# S: Symbol that shows starting of decoding input\n",
"# E: Symbol that shows starting of decoding output\n",
"# P: Symbol that will fill in blank sequence if current batch data size is short than time steps\n",
"\n",
"def make_batch():\n",
" input_batch = [np.eye(n_class)[[word_dict[n] for n in sentences[0].split()]]]\n",
" output_batch = [np.eye(n_class)[[word_dict[n] for n in sentences[1].split()]]]\n",
" target_batch = [[word_dict[n] for n in sentences[2].split()]]\n",
"\n",
" # make tensor\n",
" return torch.FloatTensor(input_batch), torch.FloatTensor(output_batch), torch.LongTensor(target_batch)\n",
"\n",
"class Attention(nn.Module):\n",
" def __init__(self):\n",
" super(Attention, self).__init__()\n",
" self.enc_cell = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)\n",
" self.dec_cell = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)\n",
"\n",
" # Linear for attention\n",
" self.attn = nn.Linear(n_hidden, n_hidden)\n",
" self.out = nn.Linear(n_hidden * 2, n_class)\n",
"\n",
" def forward(self, enc_inputs, hidden, dec_inputs):\n",
" enc_inputs = enc_inputs.transpose(0, 1) # enc_inputs: [n_step(=n_step, time step), batch_size, n_class]\n",
" dec_inputs = dec_inputs.transpose(0, 1) # dec_inputs: [n_step(=n_step, time step), batch_size, n_class]\n",
"\n",
" # enc_outputs : [n_step, batch_size, num_directions(=1) * n_hidden], matrix F\n",
" # enc_hidden : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]\n",
" enc_outputs, enc_hidden = self.enc_cell(enc_inputs, hidden)\n",
"\n",
" trained_attn = []\n",
" hidden = enc_hidden\n",
" n_step = len(dec_inputs)\n",
" model = torch.empty([n_step, 1, n_class])\n",
"\n",
" for i in range(n_step): # each time step\n",
" # dec_output : [n_step(=1), batch_size(=1), num_directions(=1) * n_hidden]\n",
" # hidden : [num_layers(=1) * num_directions(=1), batch_size(=1), n_hidden]\n",
" dec_output, hidden = self.dec_cell(dec_inputs[i].unsqueeze(0), hidden)\n",
" attn_weights = self.get_att_weight(dec_output, enc_outputs) # attn_weights : [1, 1, n_step]\n",
" trained_attn.append(attn_weights.squeeze().data.numpy())\n",
"\n",
" # matrix-matrix product of matrices [1,1,n_step] x [1,n_step,n_hidden] = [1,1,n_hidden]\n",
" context = attn_weights.bmm(enc_outputs.transpose(0, 1))\n",
" dec_output = dec_output.squeeze(0) # dec_output : [batch_size(=1), num_directions(=1) * n_hidden]\n",
" context = context.squeeze(1) # [1, num_directions(=1) * n_hidden]\n",
" model[i] = self.out(torch.cat((dec_output, context), 1))\n",
"\n",
" # make model shape [n_step, n_class]\n",
" return model.transpose(0, 1).squeeze(0), trained_attn\n",
"\n",
" def get_att_weight(self, dec_output, enc_outputs): # get attention weight one 'dec_output' with 'enc_outputs'\n",
" n_step = len(enc_outputs)\n",
" attn_scores = torch.zeros(n_step) # attn_scores : [n_step]\n",
"\n",
" for i in range(n_step):\n",
" attn_scores[i] = self.get_att_score(dec_output, enc_outputs[i])\n",
"\n",
" # Normalize scores to weights in range 0 to 1\n",
" return F.softmax(attn_scores).view(1, 1, -1)\n",
"\n",
" def get_att_score(self, dec_output, enc_output): # enc_outputs [batch_size, num_directions(=1) * n_hidden]\n",
" score = self.attn(enc_output) # score : [batch_size, n_hidden]\n",
" return torch.dot(dec_output.view(-1), score.view(-1)) # inner product make scalar value\n",
"\n",
"if __name__ == '__main__':\n",
" n_step = 5 # number of cells(= number of Step)\n",
" n_hidden = 128 # number of hidden units in one cell\n",
"\n",
" sentences = ['ich mochte ein bier P', 'S i want a beer', 'i want a beer E']\n",
"\n",
" word_list = \" \".join(sentences).split()\n",
" word_list = list(set(word_list))\n",
" word_dict = {w: i for i, w in enumerate(word_list)}\n",
" number_dict = {i: w for i, w in enumerate(word_list)}\n",
" n_class = len(word_dict) # vocab list\n",
"\n",
" # hidden : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]\n",
" hidden = torch.zeros(1, 1, n_hidden)\n",
"\n",
" model = Attention()\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" input_batch, output_batch, target_batch = make_batch()\n",
"\n",
" # Train\n",
" for epoch in range(2000):\n",
" optimizer.zero_grad()\n",
" output, _ = model(input_batch, hidden, output_batch)\n",
"\n",
" loss = criterion(output, target_batch.squeeze(0))\n",
" if (epoch + 1) % 400 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Test\n",
" test_batch = [np.eye(n_class)[[word_dict[n] for n in 'SPPPP']]]\n",
" test_batch = torch.FloatTensor(test_batch)\n",
" predict, trained_attn = model(input_batch, hidden, test_batch)\n",
" predict = predict.data.max(1, keepdim=True)[1]\n",
" print(sentences[0], '->', [number_dict[n.item()] for n in predict.squeeze()])\n",
"\n",
" # Show Attention\n",
" fig = plt.figure(figsize=(5, 5))\n",
" ax = fig.add_subplot(1, 1, 1)\n",
" ax.matshow(trained_attn, cmap='viridis')\n",
" ax.set_xticklabels([''] + sentences[0].split(), fontdict={'fontsize': 14})\n",
" ax.set_yticklabels([''] + sentences[2].split(), fontdict={'fontsize': 14})\n",
" plt.show()"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
@@ -0,0 +1,121 @@
# %%
# code by Tae Hwan Jung @graykode
# Reference : https://github.com/hunkim/PyTorchZeroToAll/blob/master/14_2_seq2seq_att.py
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt
# S: Symbol that shows starting of decoding input
# E: Symbol that shows starting of decoding output
# P: Symbol that will fill in blank sequence if current batch data size is short than time steps
def make_batch():
input_batch = [np.eye(n_class)[[word_dict[n] for n in sentences[0].split()]]]
output_batch = [np.eye(n_class)[[word_dict[n] for n in sentences[1].split()]]]
target_batch = [[word_dict[n] for n in sentences[2].split()]]
# make tensor
return torch.FloatTensor(input_batch), torch.FloatTensor(output_batch), torch.LongTensor(target_batch)
class Attention(nn.Module):
def __init__(self):
super(Attention, self).__init__()
self.enc_cell = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)
self.dec_cell = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)
# Linear for attention
self.attn = nn.Linear(n_hidden, n_hidden)
self.out = nn.Linear(n_hidden * 2, n_class)
def forward(self, enc_inputs, hidden, dec_inputs):
enc_inputs = enc_inputs.transpose(0, 1) # enc_inputs: [n_step(=n_step, time step), batch_size, n_class]
dec_inputs = dec_inputs.transpose(0, 1) # dec_inputs: [n_step(=n_step, time step), batch_size, n_class]
# enc_outputs : [n_step, batch_size, num_directions(=1) * n_hidden], matrix F
# enc_hidden : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]
enc_outputs, enc_hidden = self.enc_cell(enc_inputs, hidden)
trained_attn = []
hidden = enc_hidden
n_step = len(dec_inputs)
model = torch.empty([n_step, 1, n_class])
for i in range(n_step): # each time step
# dec_output : [n_step(=1), batch_size(=1), num_directions(=1) * n_hidden]
# hidden : [num_layers(=1) * num_directions(=1), batch_size(=1), n_hidden]
dec_output, hidden = self.dec_cell(dec_inputs[i].unsqueeze(0), hidden)
attn_weights = self.get_att_weight(dec_output, enc_outputs) # attn_weights : [1, 1, n_step]
trained_attn.append(attn_weights.squeeze().data.numpy())
# matrix-matrix product of matrices [1,1,n_step] x [1,n_step,n_hidden] = [1,1,n_hidden]
context = attn_weights.bmm(enc_outputs.transpose(0, 1))
dec_output = dec_output.squeeze(0) # dec_output : [batch_size(=1), num_directions(=1) * n_hidden]
context = context.squeeze(1) # [1, num_directions(=1) * n_hidden]
model[i] = self.out(torch.cat((dec_output, context), 1))
# make model shape [n_step, n_class]
return model.transpose(0, 1).squeeze(0), trained_attn
def get_att_weight(self, dec_output, enc_outputs): # get attention weight one 'dec_output' with 'enc_outputs'
n_step = len(enc_outputs)
attn_scores = torch.zeros(n_step) # attn_scores : [n_step]
for i in range(n_step):
attn_scores[i] = self.get_att_score(dec_output, enc_outputs[i])
# Normalize scores to weights in range 0 to 1
return F.softmax(attn_scores).view(1, 1, -1)
def get_att_score(self, dec_output, enc_output): # enc_outputs [batch_size, num_directions(=1) * n_hidden]
score = self.attn(enc_output) # score : [batch_size, n_hidden]
return torch.dot(dec_output.view(-1), score.view(-1)) # inner product make scalar value
if __name__ == '__main__':
n_step = 5 # number of cells(= number of Step)
n_hidden = 128 # number of hidden units in one cell
sentences = ['ich mochte ein bier P', 'S i want a beer', 'i want a beer E']
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict) # vocab list
# hidden : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]
hidden = torch.zeros(1, 1, n_hidden)
model = Attention()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
input_batch, output_batch, target_batch = make_batch()
# Train
for epoch in range(2000):
optimizer.zero_grad()
output, _ = model(input_batch, hidden, output_batch)
loss = criterion(output, target_batch.squeeze(0))
if (epoch + 1) % 400 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Test
test_batch = [np.eye(n_class)[[word_dict[n] for n in 'SPPPP']]]
test_batch = torch.FloatTensor(test_batch)
predict, trained_attn = model(input_batch, hidden, test_batch)
predict = predict.data.max(1, keepdim=True)[1]
print(sentences[0], '->', [number_dict[n.item()] for n in predict.squeeze()])
# Show Attention
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(1, 1, 1)
ax.matshow(trained_attn, cmap='viridis')
ax.set_xticklabels([''] + sentences[0].split(), fontdict={'fontsize': 14})
ax.set_yticklabels([''] + sentences[2].split(), fontdict={'fontsize': 14})
plt.show()
@@ -0,0 +1,125 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung(Jeff Jung) @graykode\n",
"# Reference : https://github.com/prakashpandey9/Text-Classification-Pytorch/blob/master/models/LSTM_Attn.py\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"import torch.nn.functional as F\n",
"import matplotlib.pyplot as plt\n",
"\n",
"class BiLSTM_Attention(nn.Module):\n",
" def __init__(self):\n",
" super(BiLSTM_Attention, self).__init__()\n",
"\n",
" self.embedding = nn.Embedding(vocab_size, embedding_dim)\n",
" self.lstm = nn.LSTM(embedding_dim, n_hidden, bidirectional=True)\n",
" self.out = nn.Linear(n_hidden * 2, num_classes)\n",
"\n",
" # lstm_output : [batch_size, n_step, n_hidden * num_directions(=2)], F matrix\n",
" def attention_net(self, lstm_output, final_state):\n",
" hidden = final_state.view(-1, n_hidden * 2, 1) # hidden : [batch_size, n_hidden * num_directions(=2), 1(=n_layer)]\n",
" attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # attn_weights : [batch_size, n_step]\n",
" soft_attn_weights = F.softmax(attn_weights, 1)\n",
" # [batch_size, n_hidden * num_directions(=2), n_step] * [batch_size, n_step, 1] = [batch_size, n_hidden * num_directions(=2), 1]\n",
" context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2)\n",
" return context, soft_attn_weights.data.numpy() # context : [batch_size, n_hidden * num_directions(=2)]\n",
"\n",
" def forward(self, X):\n",
" input = self.embedding(X) # input : [batch_size, len_seq, embedding_dim]\n",
" input = input.permute(1, 0, 2) # input : [len_seq, batch_size, embedding_dim]\n",
"\n",
" hidden_state = torch.zeros(1*2, len(X), n_hidden) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]\n",
" cell_state = torch.zeros(1*2, len(X), n_hidden) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]\n",
"\n",
" # final_hidden_state, final_cell_state : [num_layers(=1) * num_directions(=2), batch_size, n_hidden]\n",
" output, (final_hidden_state, final_cell_state) = self.lstm(input, (hidden_state, cell_state))\n",
" output = output.permute(1, 0, 2) # output : [batch_size, len_seq, n_hidden]\n",
" attn_output, attention = self.attention_net(output, final_hidden_state)\n",
" return self.out(attn_output), attention # model : [batch_size, num_classes], attention : [batch_size, n_step]\n",
"\n",
"if __name__ == '__main__':\n",
" embedding_dim = 2 # embedding size\n",
" n_hidden = 5 # number of hidden units in one cell\n",
" num_classes = 2 # 0 or 1\n",
"\n",
" # 3 words sentences (=sequence_length is 3)\n",
" sentences = [\"i love you\", \"he loves me\", \"she likes baseball\", \"i hate you\", \"sorry for that\", \"this is awful\"]\n",
" labels = [1, 1, 1, 0, 0, 0] # 1 is good, 0 is not good.\n",
"\n",
" word_list = \" \".join(sentences).split()\n",
" word_list = list(set(word_list))\n",
" word_dict = {w: i for i, w in enumerate(word_list)}\n",
" vocab_size = len(word_dict)\n",
"\n",
" model = BiLSTM_Attention()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" inputs = torch.LongTensor([np.asarray([word_dict[n] for n in sen.split()]) for sen in sentences])\n",
" targets = torch.LongTensor([out for out in labels]) # To using Torch Softmax Loss function\n",
"\n",
" # Training\n",
" for epoch in range(5000):\n",
" optimizer.zero_grad()\n",
" output, attention = model(inputs)\n",
" loss = criterion(output, targets)\n",
" if (epoch + 1) % 1000 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
"\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Test\n",
" test_text = 'sorry hate you'\n",
" tests = [np.asarray([word_dict[n] for n in test_text.split()])]\n",
" test_batch = torch.LongTensor(tests)\n",
"\n",
" # Predict\n",
" predict, _ = model(test_batch)\n",
" predict = predict.data.max(1, keepdim=True)[1]\n",
" if predict[0][0] == 0:\n",
" print(test_text,\"is Bad Mean...\")\n",
" else:\n",
" print(test_text,\"is Good Mean!!\")\n",
"\n",
" fig = plt.figure(figsize=(6, 3)) # [batch_size, n_step]\n",
" ax = fig.add_subplot(1, 1, 1)\n",
" ax.matshow(attention, cmap='viridis')\n",
" ax.set_xticklabels(['']+['first_word', 'second_word', 'third_word'], fontdict={'fontsize': 14}, rotation=90)\n",
" ax.set_yticklabels(['']+['batch_1', 'batch_2', 'batch_3', 'batch_4', 'batch_5', 'batch_6'], fontdict={'fontsize': 14})\n",
" plt.show()"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
@@ -0,0 +1,92 @@
# %%
# code by Tae Hwan Jung(Jeff Jung) @graykode
# Reference : https://github.com/prakashpandey9/Text-Classification-Pytorch/blob/master/models/LSTM_Attn.py
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import matplotlib.pyplot as plt
class BiLSTM_Attention(nn.Module):
def __init__(self):
super(BiLSTM_Attention, self).__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.lstm = nn.LSTM(embedding_dim, n_hidden, bidirectional=True)
self.out = nn.Linear(n_hidden * 2, num_classes)
# lstm_output : [batch_size, n_step, n_hidden * num_directions(=2)], F matrix
def attention_net(self, lstm_output, final_state):
hidden = final_state.view(-1, n_hidden * 2, 1) # hidden : [batch_size, n_hidden * num_directions(=2), 1(=n_layer)]
attn_weights = torch.bmm(lstm_output, hidden).squeeze(2) # attn_weights : [batch_size, n_step]
soft_attn_weights = F.softmax(attn_weights, 1)
# [batch_size, n_hidden * num_directions(=2), n_step] * [batch_size, n_step, 1] = [batch_size, n_hidden * num_directions(=2), 1]
context = torch.bmm(lstm_output.transpose(1, 2), soft_attn_weights.unsqueeze(2)).squeeze(2)
return context, soft_attn_weights.data.numpy() # context : [batch_size, n_hidden * num_directions(=2)]
def forward(self, X):
input = self.embedding(X) # input : [batch_size, len_seq, embedding_dim]
input = input.permute(1, 0, 2) # input : [len_seq, batch_size, embedding_dim]
hidden_state = torch.zeros(1*2, len(X), n_hidden) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]
cell_state = torch.zeros(1*2, len(X), n_hidden) # [num_layers(=1) * num_directions(=2), batch_size, n_hidden]
# final_hidden_state, final_cell_state : [num_layers(=1) * num_directions(=2), batch_size, n_hidden]
output, (final_hidden_state, final_cell_state) = self.lstm(input, (hidden_state, cell_state))
output = output.permute(1, 0, 2) # output : [batch_size, len_seq, n_hidden]
attn_output, attention = self.attention_net(output, final_hidden_state)
return self.out(attn_output), attention # model : [batch_size, num_classes], attention : [batch_size, n_step]
if __name__ == '__main__':
embedding_dim = 2 # embedding size
n_hidden = 5 # number of hidden units in one cell
num_classes = 2 # 0 or 1
# 3 words sentences (=sequence_length is 3)
sentences = ["i love you", "he loves me", "she likes baseball", "i hate you", "sorry for that", "this is awful"]
labels = [1, 1, 1, 0, 0, 0] # 1 is good, 0 is not good.
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
vocab_size = len(word_dict)
model = BiLSTM_Attention()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
inputs = torch.LongTensor([np.asarray([word_dict[n] for n in sen.split()]) for sen in sentences])
targets = torch.LongTensor([out for out in labels]) # To using Torch Softmax Loss function
# Training
for epoch in range(5000):
optimizer.zero_grad()
output, attention = model(inputs)
loss = criterion(output, targets)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Test
test_text = 'sorry hate you'
tests = [np.asarray([word_dict[n] for n in test_text.split()])]
test_batch = torch.LongTensor(tests)
# Predict
predict, _ = model(test_batch)
predict = predict.data.max(1, keepdim=True)[1]
if predict[0][0] == 0:
print(test_text,"is Bad Mean...")
else:
print(test_text,"is Good Mean!!")
fig = plt.figure(figsize=(6, 3)) # [batch_size, n_step]
ax = fig.add_subplot(1, 1, 1)
ax.matshow(attention, cmap='viridis')
ax.set_xticklabels(['']+['first_word', 'second_word', 'third_word'], fontdict={'fontsize': 14}, rotation=90)
ax.set_yticklabels(['']+['batch_1', 'batch_2', 'batch_3', 'batch_4', 'batch_5', 'batch_6'], fontdict={'fontsize': 14})
plt.show()
@@ -0,0 +1,282 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung(Jeff Jung) @graykode, Derek Miller @dmmiller612\n",
"# Reference : https://github.com/jadore801120/attention-is-all-you-need-pytorch\n",
"# https://github.com/JayParks/transformer\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# S: Symbol that shows starting of decoding input\n",
"# E: Symbol that shows starting of decoding output\n",
"# P: Symbol that will fill in blank sequence if current batch data size is short than time steps\n",
"\n",
"def make_batch():\n",
" input_batch = [[src_vocab[n] for n in sentences[0].split()]]\n",
" output_batch = [[tgt_vocab[n] for n in sentences[1].split()]]\n",
" target_batch = [[tgt_vocab[n] for n in sentences[2].split()]]\n",
" return torch.LongTensor(input_batch), torch.LongTensor(output_batch), torch.LongTensor(target_batch)\n",
"\n",
"def get_sinusoid_encoding_table(n_position, d_model):\n",
" def cal_angle(position, hid_idx):\n",
" return position / np.power(10000, 2 * (hid_idx // 2) / d_model)\n",
" def get_posi_angle_vec(position):\n",
" return [cal_angle(position, hid_j) for hid_j in range(d_model)]\n",
"\n",
" sinusoid_table = np.array([get_posi_angle_vec(pos_i) for pos_i in range(n_position)])\n",
" sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2]) # dim 2i\n",
" sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2]) # dim 2i+1\n",
" return torch.FloatTensor(sinusoid_table)\n",
"\n",
"def get_attn_pad_mask(seq_q, seq_k):\n",
" # print(seq_q)\n",
" batch_size, len_q = seq_q.size()\n",
" batch_size, len_k = seq_k.size()\n",
" # eq(zero) is PAD token\n",
" pad_attn_mask = seq_k.data.eq(0).unsqueeze(1) # batch_size x 1 x len_k(=len_q), one is masking\n",
" return pad_attn_mask.expand(batch_size, len_q, len_k) # batch_size x len_q x len_k\n",
"\n",
"def get_attn_subsequent_mask(seq):\n",
" attn_shape = [seq.size(0), seq.size(1), seq.size(1)]\n",
" subsequent_mask = np.triu(np.ones(attn_shape), k=1)\n",
" subsequent_mask = torch.from_numpy(subsequent_mask).byte()\n",
" return subsequent_mask\n",
"\n",
"class ScaledDotProductAttention(nn.Module):\n",
" def __init__(self):\n",
" super(ScaledDotProductAttention, self).__init__()\n",
"\n",
" def forward(self, Q, K, V, attn_mask):\n",
" scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) # scores : [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]\n",
" scores.masked_fill_(attn_mask, -1e9) # Fills elements of self tensor with value where mask is one.\n",
" attn = nn.Softmax(dim=-1)(scores)\n",
" context = torch.matmul(attn, V)\n",
" return context, attn\n",
"\n",
"class MultiHeadAttention(nn.Module):\n",
" def __init__(self):\n",
" super(MultiHeadAttention, self).__init__()\n",
" self.W_Q = nn.Linear(d_model, d_k * n_heads)\n",
" self.W_K = nn.Linear(d_model, d_k * n_heads)\n",
" self.W_V = nn.Linear(d_model, d_v * n_heads)\n",
" self.linear = nn.Linear(n_heads * d_v, d_model)\n",
" self.layer_norm = nn.LayerNorm(d_model)\n",
"\n",
" def forward(self, Q, K, V, attn_mask):\n",
" # q: [batch_size x len_q x d_model], k: [batch_size x len_k x d_model], v: [batch_size x len_k x d_model]\n",
" residual, batch_size = Q, Q.size(0)\n",
" # (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)\n",
" q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2) # q_s: [batch_size x n_heads x len_q x d_k]\n",
" k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2) # k_s: [batch_size x n_heads x len_k x d_k]\n",
" v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2) # v_s: [batch_size x n_heads x len_k x d_v]\n",
"\n",
" attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1) # attn_mask : [batch_size x n_heads x len_q x len_k]\n",
"\n",
" # context: [batch_size x n_heads x len_q x d_v], attn: [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]\n",
" context, attn = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)\n",
" context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) # context: [batch_size x len_q x n_heads * d_v]\n",
" output = self.linear(context)\n",
" return self.layer_norm(output + residual), attn # output: [batch_size x len_q x d_model]\n",
"\n",
"class PoswiseFeedForwardNet(nn.Module):\n",
" def __init__(self):\n",
" super(PoswiseFeedForwardNet, self).__init__()\n",
" self.conv1 = nn.Conv1d(in_channels=d_model, out_channels=d_ff, kernel_size=1)\n",
" self.conv2 = nn.Conv1d(in_channels=d_ff, out_channels=d_model, kernel_size=1)\n",
" self.layer_norm = nn.LayerNorm(d_model)\n",
"\n",
" def forward(self, inputs):\n",
" residual = inputs # inputs : [batch_size, len_q, d_model]\n",
" output = nn.ReLU()(self.conv1(inputs.transpose(1, 2)))\n",
" output = self.conv2(output).transpose(1, 2)\n",
" return self.layer_norm(output + residual)\n",
"\n",
"class EncoderLayer(nn.Module):\n",
" def __init__(self):\n",
" super(EncoderLayer, self).__init__()\n",
" self.enc_self_attn = MultiHeadAttention()\n",
" self.pos_ffn = PoswiseFeedForwardNet()\n",
"\n",
" def forward(self, enc_inputs, enc_self_attn_mask):\n",
" enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask) # enc_inputs to same Q,K,V\n",
" enc_outputs = self.pos_ffn(enc_outputs) # enc_outputs: [batch_size x len_q x d_model]\n",
" return enc_outputs, attn\n",
"\n",
"class DecoderLayer(nn.Module):\n",
" def __init__(self):\n",
" super(DecoderLayer, self).__init__()\n",
" self.dec_self_attn = MultiHeadAttention()\n",
" self.dec_enc_attn = MultiHeadAttention()\n",
" self.pos_ffn = PoswiseFeedForwardNet()\n",
"\n",
" def forward(self, dec_inputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask):\n",
" dec_outputs, dec_self_attn = self.dec_self_attn(dec_inputs, dec_inputs, dec_inputs, dec_self_attn_mask)\n",
" dec_outputs, dec_enc_attn = self.dec_enc_attn(dec_outputs, enc_outputs, enc_outputs, dec_enc_attn_mask)\n",
" dec_outputs = self.pos_ffn(dec_outputs)\n",
" return dec_outputs, dec_self_attn, dec_enc_attn\n",
"\n",
"class Encoder(nn.Module):\n",
" def __init__(self):\n",
" super(Encoder, self).__init__()\n",
" self.src_emb = nn.Embedding(src_vocab_size, d_model)\n",
" self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(src_len+1, d_model),freeze=True)\n",
" self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])\n",
"\n",
" def forward(self, enc_inputs): # enc_inputs : [batch_size x source_len]\n",
" enc_outputs = self.src_emb(enc_inputs) + self.pos_emb(torch.LongTensor([[1,2,3,4,0]]))\n",
" enc_self_attn_mask = get_attn_pad_mask(enc_inputs, enc_inputs)\n",
" enc_self_attns = []\n",
" for layer in self.layers:\n",
" enc_outputs, enc_self_attn = layer(enc_outputs, enc_self_attn_mask)\n",
" enc_self_attns.append(enc_self_attn)\n",
" return enc_outputs, enc_self_attns\n",
"\n",
"class Decoder(nn.Module):\n",
" def __init__(self):\n",
" super(Decoder, self).__init__()\n",
" self.tgt_emb = nn.Embedding(tgt_vocab_size, d_model)\n",
" self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(tgt_len+1, d_model),freeze=True)\n",
" self.layers = nn.ModuleList([DecoderLayer() for _ in range(n_layers)])\n",
"\n",
" def forward(self, dec_inputs, enc_inputs, enc_outputs): # dec_inputs : [batch_size x target_len]\n",
" dec_outputs = self.tgt_emb(dec_inputs) + self.pos_emb(torch.LongTensor([[5,1,2,3,4]]))\n",
" dec_self_attn_pad_mask = get_attn_pad_mask(dec_inputs, dec_inputs)\n",
" dec_self_attn_subsequent_mask = get_attn_subsequent_mask(dec_inputs)\n",
" dec_self_attn_mask = torch.gt((dec_self_attn_pad_mask + dec_self_attn_subsequent_mask), 0)\n",
"\n",
" dec_enc_attn_mask = get_attn_pad_mask(dec_inputs, enc_inputs)\n",
"\n",
" dec_self_attns, dec_enc_attns = [], []\n",
" for layer in self.layers:\n",
" dec_outputs, dec_self_attn, dec_enc_attn = layer(dec_outputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask)\n",
" dec_self_attns.append(dec_self_attn)\n",
" dec_enc_attns.append(dec_enc_attn)\n",
" return dec_outputs, dec_self_attns, dec_enc_attns\n",
"\n",
"class Transformer(nn.Module):\n",
" def __init__(self):\n",
" super(Transformer, self).__init__()\n",
" self.encoder = Encoder()\n",
" self.decoder = Decoder()\n",
" self.projection = nn.Linear(d_model, tgt_vocab_size, bias=False)\n",
" def forward(self, enc_inputs, dec_inputs):\n",
" enc_outputs, enc_self_attns = self.encoder(enc_inputs)\n",
" dec_outputs, dec_self_attns, dec_enc_attns = self.decoder(dec_inputs, enc_inputs, enc_outputs)\n",
" dec_logits = self.projection(dec_outputs) # dec_logits : [batch_size x src_vocab_size x tgt_vocab_size]\n",
" return dec_logits.view(-1, dec_logits.size(-1)), enc_self_attns, dec_self_attns, dec_enc_attns\n",
"\n",
"def greedy_decoder(model, enc_input, start_symbol):\n",
" \"\"\"\n",
" For simplicity, a Greedy Decoder is Beam search when K=1. This is necessary for inference as we don't know the\n",
" target sequence input. Therefore we try to generate the target input word by word, then feed it into the transformer.\n",
" Starting Reference: http://nlp.seas.harvard.edu/2018/04/03/attention.html#greedy-decoding\n",
" :param model: Transformer Model\n",
" :param enc_input: The encoder input\n",
" :param start_symbol: The start symbol. In this example it is 'S' which corresponds to index 4\n",
" :return: The target input\n",
" \"\"\"\n",
" enc_outputs, enc_self_attns = model.encoder(enc_input)\n",
" dec_input = torch.zeros(1, 5).type_as(enc_input.data)\n",
" next_symbol = start_symbol\n",
" for i in range(0, 5):\n",
" dec_input[0][i] = next_symbol\n",
" dec_outputs, _, _ = model.decoder(dec_input, enc_input, enc_outputs)\n",
" projected = model.projection(dec_outputs)\n",
" prob = projected.squeeze(0).max(dim=-1, keepdim=False)[1]\n",
" next_word = prob.data[i]\n",
" next_symbol = next_word.item()\n",
" return dec_input\n",
"\n",
"def showgraph(attn):\n",
" attn = attn[-1].squeeze(0)[0]\n",
" attn = attn.squeeze(0).data.numpy()\n",
" fig = plt.figure(figsize=(n_heads, n_heads)) # [n_heads, n_heads]\n",
" ax = fig.add_subplot(1, 1, 1)\n",
" ax.matshow(attn, cmap='viridis')\n",
" ax.set_xticklabels(['']+sentences[0].split(), fontdict={'fontsize': 14}, rotation=90)\n",
" ax.set_yticklabels(['']+sentences[2].split(), fontdict={'fontsize': 14})\n",
" plt.show()\n",
"\n",
"if __name__ == '__main__':\n",
" sentences = ['ich mochte ein bier P', 'S i want a beer', 'i want a beer E']\n",
" # Transformer Parameters\n",
" # Padding Should be Zero index\n",
" src_vocab = {'P': 0, 'ich': 1, 'mochte': 2, 'ein': 3, 'bier': 4}\n",
" src_vocab_size = len(src_vocab)\n",
"\n",
" tgt_vocab = {'P': 0, 'i': 1, 'want': 2, 'a': 3, 'beer': 4, 'S': 5, 'E': 6}\n",
" number_dict = {i: w for i, w in enumerate(tgt_vocab)}\n",
" tgt_vocab_size = len(tgt_vocab)\n",
"\n",
" src_len = 5 # length of source\n",
" tgt_len = 5 # length of target\n",
"\n",
" d_model = 512 # Embedding Size\n",
" d_ff = 2048 # FeedForward dimension\n",
" d_k = d_v = 64 # dimension of K(=Q), V\n",
" n_layers = 6 # number of Encoder of Decoder Layer\n",
" n_heads = 8 # number of heads in Multi-Head Attention\n",
"\n",
" model = Transformer()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" enc_inputs, dec_inputs, target_batch = make_batch()\n",
"\n",
" for epoch in range(20):\n",
" optimizer.zero_grad()\n",
" outputs, enc_self_attns, dec_self_attns, dec_enc_attns = model(enc_inputs, dec_inputs)\n",
" loss = criterion(outputs, target_batch.contiguous().view(-1))\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Test\n",
" greedy_dec_input = greedy_decoder(model, enc_inputs, start_symbol=tgt_vocab[\"S\"])\n",
" predict, _, _, _ = model(enc_inputs, greedy_dec_input)\n",
" predict = predict.data.max(1, keepdim=True)[1]\n",
" print(sentences[0], '->', [number_dict[n.item()] for n in predict.squeeze()])\n",
"\n",
" print('first head of last state enc_self_attns')\n",
" showgraph(enc_self_attns)\n",
"\n",
" print('first head of last state dec_self_attns')\n",
" showgraph(dec_self_attns)\n",
"\n",
" print('first head of last state dec_enc_attns')\n",
" showgraph(dec_enc_attns)"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
@@ -0,0 +1,249 @@
# %%
# code by Tae Hwan Jung(Jeff Jung) @graykode, Derek Miller @dmmiller612
# Reference : https://github.com/jadore801120/attention-is-all-you-need-pytorch
# https://github.com/JayParks/transformer
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
# S: Symbol that shows starting of decoding input
# E: Symbol that shows starting of decoding output
# P: Symbol that will fill in blank sequence if current batch data size is short than time steps
def make_batch():
input_batch = [[src_vocab[n] for n in sentences[0].split()]]
output_batch = [[tgt_vocab[n] for n in sentences[1].split()]]
target_batch = [[tgt_vocab[n] for n in sentences[2].split()]]
return torch.LongTensor(input_batch), torch.LongTensor(output_batch), torch.LongTensor(target_batch)
def get_sinusoid_encoding_table(n_position, d_model):
def cal_angle(position, hid_idx):
return position / np.power(10000, 2 * (hid_idx // 2) / d_model)
def get_posi_angle_vec(position):
return [cal_angle(position, hid_j) for hid_j in range(d_model)]
sinusoid_table = np.array([get_posi_angle_vec(pos_i) for pos_i in range(n_position)])
sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2]) # dim 2i
sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2]) # dim 2i+1
return torch.FloatTensor(sinusoid_table)
def get_attn_pad_mask(seq_q, seq_k):
# print(seq_q)
batch_size, len_q = seq_q.size()
batch_size, len_k = seq_k.size()
# eq(zero) is PAD token
pad_attn_mask = seq_k.data.eq(0).unsqueeze(1) # batch_size x 1 x len_k(=len_q), one is masking
return pad_attn_mask.expand(batch_size, len_q, len_k) # batch_size x len_q x len_k
def get_attn_subsequent_mask(seq):
attn_shape = [seq.size(0), seq.size(1), seq.size(1)]
subsequent_mask = np.triu(np.ones(attn_shape), k=1)
subsequent_mask = torch.from_numpy(subsequent_mask).byte()
return subsequent_mask
class ScaledDotProductAttention(nn.Module):
def __init__(self):
super(ScaledDotProductAttention, self).__init__()
def forward(self, Q, K, V, attn_mask):
scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) # scores : [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]
scores.masked_fill_(attn_mask, -1e9) # Fills elements of self tensor with value where mask is one.
attn = nn.Softmax(dim=-1)(scores)
context = torch.matmul(attn, V)
return context, attn
class MultiHeadAttention(nn.Module):
def __init__(self):
super(MultiHeadAttention, self).__init__()
self.W_Q = nn.Linear(d_model, d_k * n_heads)
self.W_K = nn.Linear(d_model, d_k * n_heads)
self.W_V = nn.Linear(d_model, d_v * n_heads)
self.linear = nn.Linear(n_heads * d_v, d_model)
self.layer_norm = nn.LayerNorm(d_model)
def forward(self, Q, K, V, attn_mask):
# q: [batch_size x len_q x d_model], k: [batch_size x len_k x d_model], v: [batch_size x len_k x d_model]
residual, batch_size = Q, Q.size(0)
# (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)
q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2) # q_s: [batch_size x n_heads x len_q x d_k]
k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2) # k_s: [batch_size x n_heads x len_k x d_k]
v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2) # v_s: [batch_size x n_heads x len_k x d_v]
attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1) # attn_mask : [batch_size x n_heads x len_q x len_k]
# context: [batch_size x n_heads x len_q x d_v], attn: [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]
context, attn = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)
context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) # context: [batch_size x len_q x n_heads * d_v]
output = self.linear(context)
return self.layer_norm(output + residual), attn # output: [batch_size x len_q x d_model]
class PoswiseFeedForwardNet(nn.Module):
def __init__(self):
super(PoswiseFeedForwardNet, self).__init__()
self.conv1 = nn.Conv1d(in_channels=d_model, out_channels=d_ff, kernel_size=1)
self.conv2 = nn.Conv1d(in_channels=d_ff, out_channels=d_model, kernel_size=1)
self.layer_norm = nn.LayerNorm(d_model)
def forward(self, inputs):
residual = inputs # inputs : [batch_size, len_q, d_model]
output = nn.ReLU()(self.conv1(inputs.transpose(1, 2)))
output = self.conv2(output).transpose(1, 2)
return self.layer_norm(output + residual)
class EncoderLayer(nn.Module):
def __init__(self):
super(EncoderLayer, self).__init__()
self.enc_self_attn = MultiHeadAttention()
self.pos_ffn = PoswiseFeedForwardNet()
def forward(self, enc_inputs, enc_self_attn_mask):
enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask) # enc_inputs to same Q,K,V
enc_outputs = self.pos_ffn(enc_outputs) # enc_outputs: [batch_size x len_q x d_model]
return enc_outputs, attn
class DecoderLayer(nn.Module):
def __init__(self):
super(DecoderLayer, self).__init__()
self.dec_self_attn = MultiHeadAttention()
self.dec_enc_attn = MultiHeadAttention()
self.pos_ffn = PoswiseFeedForwardNet()
def forward(self, dec_inputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask):
dec_outputs, dec_self_attn = self.dec_self_attn(dec_inputs, dec_inputs, dec_inputs, dec_self_attn_mask)
dec_outputs, dec_enc_attn = self.dec_enc_attn(dec_outputs, enc_outputs, enc_outputs, dec_enc_attn_mask)
dec_outputs = self.pos_ffn(dec_outputs)
return dec_outputs, dec_self_attn, dec_enc_attn
class Encoder(nn.Module):
def __init__(self):
super(Encoder, self).__init__()
self.src_emb = nn.Embedding(src_vocab_size, d_model)
self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(src_len+1, d_model),freeze=True)
self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])
def forward(self, enc_inputs): # enc_inputs : [batch_size x source_len]
enc_outputs = self.src_emb(enc_inputs) + self.pos_emb(torch.LongTensor([[1,2,3,4,0]]))
enc_self_attn_mask = get_attn_pad_mask(enc_inputs, enc_inputs)
enc_self_attns = []
for layer in self.layers:
enc_outputs, enc_self_attn = layer(enc_outputs, enc_self_attn_mask)
enc_self_attns.append(enc_self_attn)
return enc_outputs, enc_self_attns
class Decoder(nn.Module):
def __init__(self):
super(Decoder, self).__init__()
self.tgt_emb = nn.Embedding(tgt_vocab_size, d_model)
self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(tgt_len+1, d_model),freeze=True)
self.layers = nn.ModuleList([DecoderLayer() for _ in range(n_layers)])
def forward(self, dec_inputs, enc_inputs, enc_outputs): # dec_inputs : [batch_size x target_len]
dec_outputs = self.tgt_emb(dec_inputs) + self.pos_emb(torch.LongTensor([[5,1,2,3,4]]))
dec_self_attn_pad_mask = get_attn_pad_mask(dec_inputs, dec_inputs)
dec_self_attn_subsequent_mask = get_attn_subsequent_mask(dec_inputs)
dec_self_attn_mask = torch.gt((dec_self_attn_pad_mask + dec_self_attn_subsequent_mask), 0)
dec_enc_attn_mask = get_attn_pad_mask(dec_inputs, enc_inputs)
dec_self_attns, dec_enc_attns = [], []
for layer in self.layers:
dec_outputs, dec_self_attn, dec_enc_attn = layer(dec_outputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask)
dec_self_attns.append(dec_self_attn)
dec_enc_attns.append(dec_enc_attn)
return dec_outputs, dec_self_attns, dec_enc_attns
class Transformer(nn.Module):
def __init__(self):
super(Transformer, self).__init__()
self.encoder = Encoder()
self.decoder = Decoder()
self.projection = nn.Linear(d_model, tgt_vocab_size, bias=False)
def forward(self, enc_inputs, dec_inputs):
enc_outputs, enc_self_attns = self.encoder(enc_inputs)
dec_outputs, dec_self_attns, dec_enc_attns = self.decoder(dec_inputs, enc_inputs, enc_outputs)
dec_logits = self.projection(dec_outputs) # dec_logits : [batch_size x src_vocab_size x tgt_vocab_size]
return dec_logits.view(-1, dec_logits.size(-1)), enc_self_attns, dec_self_attns, dec_enc_attns
def greedy_decoder(model, enc_input, start_symbol):
"""
For simplicity, a Greedy Decoder is Beam search when K=1. This is necessary for inference as we don't know the
target sequence input. Therefore we try to generate the target input word by word, then feed it into the transformer.
Starting Reference: http://nlp.seas.harvard.edu/2018/04/03/attention.html#greedy-decoding
:param model: Transformer Model
:param enc_input: The encoder input
:param start_symbol: The start symbol. In this example it is 'S' which corresponds to index 4
:return: The target input
"""
enc_outputs, enc_self_attns = model.encoder(enc_input)
dec_input = torch.zeros(1, 5).type_as(enc_input.data)
next_symbol = start_symbol
for i in range(0, 5):
dec_input[0][i] = next_symbol
dec_outputs, _, _ = model.decoder(dec_input, enc_input, enc_outputs)
projected = model.projection(dec_outputs)
prob = projected.squeeze(0).max(dim=-1, keepdim=False)[1]
next_word = prob.data[i]
next_symbol = next_word.item()
return dec_input
def showgraph(attn):
attn = attn[-1].squeeze(0)[0]
attn = attn.squeeze(0).data.numpy()
fig = plt.figure(figsize=(n_heads, n_heads)) # [n_heads, n_heads]
ax = fig.add_subplot(1, 1, 1)
ax.matshow(attn, cmap='viridis')
ax.set_xticklabels(['']+sentences[0].split(), fontdict={'fontsize': 14}, rotation=90)
ax.set_yticklabels(['']+sentences[2].split(), fontdict={'fontsize': 14})
plt.show()
if __name__ == '__main__':
sentences = ['ich mochte ein bier P', 'S i want a beer', 'i want a beer E']
# Transformer Parameters
# Padding Should be Zero index
src_vocab = {'P': 0, 'ich': 1, 'mochte': 2, 'ein': 3, 'bier': 4}
src_vocab_size = len(src_vocab)
tgt_vocab = {'P': 0, 'i': 1, 'want': 2, 'a': 3, 'beer': 4, 'S': 5, 'E': 6}
number_dict = {i: w for i, w in enumerate(tgt_vocab)}
tgt_vocab_size = len(tgt_vocab)
src_len = 5 # length of source
tgt_len = 5 # length of target
d_model = 512 # Embedding Size
d_ff = 2048 # FeedForward dimension
d_k = d_v = 64 # dimension of K(=Q), V
n_layers = 6 # number of Encoder of Decoder Layer
n_heads = 8 # number of heads in Multi-Head Attention
model = Transformer()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
enc_inputs, dec_inputs, target_batch = make_batch()
for epoch in range(20):
optimizer.zero_grad()
outputs, enc_self_attns, dec_self_attns, dec_enc_attns = model(enc_inputs, dec_inputs)
loss = criterion(outputs, target_batch.contiguous().view(-1))
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Test
greedy_dec_input = greedy_decoder(model, enc_inputs, start_symbol=tgt_vocab["S"])
predict, _, _, _ = model(enc_inputs, greedy_dec_input)
predict = predict.data.max(1, keepdim=True)[1]
print(sentences[0], '->', [number_dict[n.item()] for n in predict.squeeze()])
print('first head of last state enc_self_attns')
showgraph(enc_self_attns)
print('first head of last state dec_self_attns')
showgraph(dec_self_attns)
print('first head of last state dec_enc_attns')
showgraph(dec_enc_attns)
+259
View File
@@ -0,0 +1,259 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung(Jeff Jung) @graykode, Derek Miller @dmmiller612\n",
"# Reference : https://github.com/jadore801120/attention-is-all-you-need-pytorch\n",
"# https://github.com/JayParks/transformer\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# S: Symbol that shows starting of decoding input\n",
"# E: Symbol that shows starting of decoding output\n",
"# P: Symbol that will fill in blank sequence if current batch data size is short than time steps\n",
"\n",
"def make_batch(sentences):\n",
" input_batch = [[src_vocab[n] for n in sentences[0].split()]]\n",
" output_batch = [[tgt_vocab[n] for n in sentences[1].split()]]\n",
" target_batch = [[tgt_vocab[n] for n in sentences[2].split()]]\n",
" return torch.LongTensor(input_batch), torch.LongTensor(output_batch), torch.LongTensor(target_batch)\n",
"\n",
"def get_sinusoid_encoding_table(n_position, d_model):\n",
" def cal_angle(position, hid_idx):\n",
" return position / np.power(10000, 2 * (hid_idx // 2) / d_model)\n",
" def get_posi_angle_vec(position):\n",
" return [cal_angle(position, hid_j) for hid_j in range(d_model)]\n",
"\n",
" sinusoid_table = np.array([get_posi_angle_vec(pos_i) for pos_i in range(n_position)])\n",
" sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2]) # dim 2i\n",
" sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2]) # dim 2i+1\n",
" return torch.FloatTensor(sinusoid_table)\n",
"\n",
"def get_attn_pad_mask(seq_q, seq_k):\n",
" batch_size, len_q = seq_q.size()\n",
" batch_size, len_k = seq_k.size()\n",
" # eq(zero) is PAD token\n",
" pad_attn_mask = seq_k.data.eq(0).unsqueeze(1) # batch_size x 1 x len_k(=len_q), one is masking\n",
" return pad_attn_mask.expand(batch_size, len_q, len_k) # batch_size x len_q x len_k\n",
"\n",
"def get_attn_subsequent_mask(seq):\n",
" attn_shape = [seq.size(0), seq.size(1), seq.size(1)]\n",
" subsequent_mask = np.triu(np.ones(attn_shape), k=1)\n",
" subsequent_mask = torch.from_numpy(subsequent_mask).byte()\n",
" return subsequent_mask\n",
"\n",
"class ScaledDotProductAttention(nn.Module):\n",
" def __init__(self):\n",
" super(ScaledDotProductAttention, self).__init__()\n",
"\n",
" def forward(self, Q, K, V, attn_mask):\n",
" scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) # scores : [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]\n",
" scores.masked_fill_(attn_mask, -1e9) # Fills elements of self tensor with value where mask is one.\n",
" attn = nn.Softmax(dim=-1)(scores)\n",
" context = torch.matmul(attn, V)\n",
" return context, attn\n",
"\n",
"class MultiHeadAttention(nn.Module):\n",
" def __init__(self):\n",
" super(MultiHeadAttention, self).__init__()\n",
" self.W_Q = nn.Linear(d_model, d_k * n_heads)\n",
" self.W_K = nn.Linear(d_model, d_k * n_heads)\n",
" self.W_V = nn.Linear(d_model, d_v * n_heads)\n",
" self.linear = nn.Linear(n_heads * d_v, d_model)\n",
" self.layer_norm = nn.LayerNorm(d_model)\n",
"\n",
" def forward(self, Q, K, V, attn_mask):\n",
" # q: [batch_size x len_q x d_model], k: [batch_size x len_k x d_model], v: [batch_size x len_k x d_model]\n",
" residual, batch_size = Q, Q.size(0)\n",
" # (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)\n",
" q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2) # q_s: [batch_size x n_heads x len_q x d_k]\n",
" k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2) # k_s: [batch_size x n_heads x len_k x d_k]\n",
" v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2) # v_s: [batch_size x n_heads x len_k x d_v]\n",
"\n",
" attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1) # attn_mask : [batch_size x n_heads x len_q x len_k]\n",
"\n",
" # context: [batch_size x n_heads x len_q x d_v], attn: [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]\n",
" context, attn = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)\n",
" context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) # context: [batch_size x len_q x n_heads * d_v]\n",
" output = self.linear(context)\n",
" return self.layer_norm(output + residual), attn # output: [batch_size x len_q x d_model]\n",
"\n",
"class PoswiseFeedForwardNet(nn.Module):\n",
" def __init__(self):\n",
" super(PoswiseFeedForwardNet, self).__init__()\n",
" self.conv1 = nn.Conv1d(in_channels=d_model, out_channels=d_ff, kernel_size=1)\n",
" self.conv2 = nn.Conv1d(in_channels=d_ff, out_channels=d_model, kernel_size=1)\n",
" self.layer_norm = nn.LayerNorm(d_model)\n",
"\n",
" def forward(self, inputs):\n",
" residual = inputs # inputs : [batch_size, len_q, d_model]\n",
" output = nn.ReLU()(self.conv1(inputs.transpose(1, 2)))\n",
" output = self.conv2(output).transpose(1, 2)\n",
" return self.layer_norm(output + residual)\n",
"\n",
"class EncoderLayer(nn.Module):\n",
" def __init__(self):\n",
" super(EncoderLayer, self).__init__()\n",
" self.enc_self_attn = MultiHeadAttention()\n",
" self.pos_ffn = PoswiseFeedForwardNet()\n",
"\n",
" def forward(self, enc_inputs, enc_self_attn_mask):\n",
" enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask) # enc_inputs to same Q,K,V\n",
" enc_outputs = self.pos_ffn(enc_outputs) # enc_outputs: [batch_size x len_q x d_model]\n",
" return enc_outputs, attn\n",
"\n",
"class DecoderLayer(nn.Module):\n",
" def __init__(self):\n",
" super(DecoderLayer, self).__init__()\n",
" self.dec_self_attn = MultiHeadAttention()\n",
" self.dec_enc_attn = MultiHeadAttention()\n",
" self.pos_ffn = PoswiseFeedForwardNet()\n",
"\n",
" def forward(self, dec_inputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask):\n",
" dec_outputs, dec_self_attn = self.dec_self_attn(dec_inputs, dec_inputs, dec_inputs, dec_self_attn_mask)\n",
" dec_outputs, dec_enc_attn = self.dec_enc_attn(dec_outputs, enc_outputs, enc_outputs, dec_enc_attn_mask)\n",
" dec_outputs = self.pos_ffn(dec_outputs)\n",
" return dec_outputs, dec_self_attn, dec_enc_attn\n",
"\n",
"class Encoder(nn.Module):\n",
" def __init__(self):\n",
" super(Encoder, self).__init__()\n",
" self.src_emb = nn.Embedding(src_vocab_size, d_model)\n",
" self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(src_len+1, d_model),freeze=True)\n",
" self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])\n",
"\n",
" def forward(self, enc_inputs): # enc_inputs : [batch_size x source_len]\n",
" enc_outputs = self.src_emb(enc_inputs) + self.pos_emb(torch.LongTensor([[1,2,3,4,0]]))\n",
" enc_self_attn_mask = get_attn_pad_mask(enc_inputs, enc_inputs)\n",
" enc_self_attns = []\n",
" for layer in self.layers:\n",
" enc_outputs, enc_self_attn = layer(enc_outputs, enc_self_attn_mask)\n",
" enc_self_attns.append(enc_self_attn)\n",
" return enc_outputs, enc_self_attns\n",
"\n",
"class Decoder(nn.Module):\n",
" def __init__(self):\n",
" super(Decoder, self).__init__()\n",
" self.tgt_emb = nn.Embedding(tgt_vocab_size, d_model)\n",
" self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(tgt_len+1, d_model),freeze=True)\n",
" self.layers = nn.ModuleList([DecoderLayer() for _ in range(n_layers)])\n",
"\n",
" def forward(self, dec_inputs, enc_inputs, enc_outputs): # dec_inputs : [batch_size x target_len]\n",
" dec_outputs = self.tgt_emb(dec_inputs) + self.pos_emb(torch.LongTensor([[5,1,2,3,4]]))\n",
" dec_self_attn_pad_mask = get_attn_pad_mask(dec_inputs, dec_inputs)\n",
" dec_self_attn_subsequent_mask = get_attn_subsequent_mask(dec_inputs)\n",
" dec_self_attn_mask = torch.gt((dec_self_attn_pad_mask + dec_self_attn_subsequent_mask), 0)\n",
"\n",
" dec_enc_attn_mask = get_attn_pad_mask(dec_inputs, enc_inputs)\n",
"\n",
" dec_self_attns, dec_enc_attns = [], []\n",
" for layer in self.layers:\n",
" dec_outputs, dec_self_attn, dec_enc_attn = layer(dec_outputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask)\n",
" dec_self_attns.append(dec_self_attn)\n",
" dec_enc_attns.append(dec_enc_attn)\n",
" return dec_outputs, dec_self_attns, dec_enc_attns\n",
"\n",
"class Transformer(nn.Module):\n",
" def __init__(self):\n",
" super(Transformer, self).__init__()\n",
" self.encoder = Encoder()\n",
" self.decoder = Decoder()\n",
" self.projection = nn.Linear(d_model, tgt_vocab_size, bias=False)\n",
" def forward(self, enc_inputs, dec_inputs):\n",
" enc_outputs, enc_self_attns = self.encoder(enc_inputs)\n",
" dec_outputs, dec_self_attns, dec_enc_attns = self.decoder(dec_inputs, enc_inputs, enc_outputs)\n",
" dec_logits = self.projection(dec_outputs) # dec_logits : [batch_size x src_vocab_size x tgt_vocab_size]\n",
" return dec_logits.view(-1, dec_logits.size(-1)), enc_self_attns, dec_self_attns, dec_enc_attns\n",
"\n",
"def showgraph(attn):\n",
" attn = attn[-1].squeeze(0)[0]\n",
" attn = attn.squeeze(0).data.numpy()\n",
" fig = plt.figure(figsize=(n_heads, n_heads)) # [n_heads, n_heads]\n",
" ax = fig.add_subplot(1, 1, 1)\n",
" ax.matshow(attn, cmap='viridis')\n",
" ax.set_xticklabels(['']+sentences[0].split(), fontdict={'fontsize': 14}, rotation=90)\n",
" ax.set_yticklabels(['']+sentences[2].split(), fontdict={'fontsize': 14})\n",
" plt.show()\n",
"\n",
"if __name__ == '__main__':\n",
" sentences = ['ich mochte ein bier P', 'S i want a beer', 'i want a beer E']\n",
"\n",
" # Transformer Parameters\n",
" # Padding Should be Zero\n",
" src_vocab = {'P': 0, 'ich': 1, 'mochte': 2, 'ein': 3, 'bier': 4}\n",
" src_vocab_size = len(src_vocab)\n",
"\n",
" tgt_vocab = {'P': 0, 'i': 1, 'want': 2, 'a': 3, 'beer': 4, 'S': 5, 'E': 6}\n",
" number_dict = {i: w for i, w in enumerate(tgt_vocab)}\n",
" tgt_vocab_size = len(tgt_vocab)\n",
"\n",
" src_len = 5 # length of source\n",
" tgt_len = 5 # length of target\n",
"\n",
" d_model = 512 # Embedding Size\n",
" d_ff = 2048 # FeedForward dimension\n",
" d_k = d_v = 64 # dimension of K(=Q), V\n",
" n_layers = 6 # number of Encoder of Decoder Layer\n",
" n_heads = 8 # number of heads in Multi-Head Attention\n",
"\n",
" model = Transformer()\n",
"\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" enc_inputs, dec_inputs, target_batch = make_batch(sentences)\n",
"\n",
" for epoch in range(20):\n",
" optimizer.zero_grad()\n",
" outputs, enc_self_attns, dec_self_attns, dec_enc_attns = model(enc_inputs, dec_inputs)\n",
" loss = criterion(outputs, target_batch.contiguous().view(-1))\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Test\n",
" predict, _, _, _ = model(enc_inputs, dec_inputs)\n",
" predict = predict.data.max(1, keepdim=True)[1]\n",
" print(sentences[0], '->', [number_dict[n.item()] for n in predict.squeeze()])\n",
"\n",
" print('first head of last state enc_self_attns')\n",
" showgraph(enc_self_attns)\n",
"\n",
" print('first head of last state dec_self_attns')\n",
" showgraph(dec_self_attns)\n",
"\n",
" print('first head of last state dec_enc_attns')\n",
" showgraph(dec_enc_attns)"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+226
View File
@@ -0,0 +1,226 @@
# %%
# code by Tae Hwan Jung(Jeff Jung) @graykode, Derek Miller @dmmiller612
# Reference : https://github.com/jadore801120/attention-is-all-you-need-pytorch
# https://github.com/JayParks/transformer
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
# S: Symbol that shows starting of decoding input
# E: Symbol that shows starting of decoding output
# P: Symbol that will fill in blank sequence if current batch data size is short than time steps
def make_batch(sentences):
input_batch = [[src_vocab[n] for n in sentences[0].split()]]
output_batch = [[tgt_vocab[n] for n in sentences[1].split()]]
target_batch = [[tgt_vocab[n] for n in sentences[2].split()]]
return torch.LongTensor(input_batch), torch.LongTensor(output_batch), torch.LongTensor(target_batch)
def get_sinusoid_encoding_table(n_position, d_model):
def cal_angle(position, hid_idx):
return position / np.power(10000, 2 * (hid_idx // 2) / d_model)
def get_posi_angle_vec(position):
return [cal_angle(position, hid_j) for hid_j in range(d_model)]
sinusoid_table = np.array([get_posi_angle_vec(pos_i) for pos_i in range(n_position)])
sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2]) # dim 2i
sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2]) # dim 2i+1
return torch.FloatTensor(sinusoid_table)
def get_attn_pad_mask(seq_q, seq_k):
batch_size, len_q = seq_q.size()
batch_size, len_k = seq_k.size()
# eq(zero) is PAD token
pad_attn_mask = seq_k.data.eq(0).unsqueeze(1) # batch_size x 1 x len_k(=len_q), one is masking
return pad_attn_mask.expand(batch_size, len_q, len_k) # batch_size x len_q x len_k
def get_attn_subsequent_mask(seq):
attn_shape = [seq.size(0), seq.size(1), seq.size(1)]
subsequent_mask = np.triu(np.ones(attn_shape), k=1)
subsequent_mask = torch.from_numpy(subsequent_mask).byte()
return subsequent_mask
class ScaledDotProductAttention(nn.Module):
def __init__(self):
super(ScaledDotProductAttention, self).__init__()
def forward(self, Q, K, V, attn_mask):
scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) # scores : [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]
scores.masked_fill_(attn_mask, -1e9) # Fills elements of self tensor with value where mask is one.
attn = nn.Softmax(dim=-1)(scores)
context = torch.matmul(attn, V)
return context, attn
class MultiHeadAttention(nn.Module):
def __init__(self):
super(MultiHeadAttention, self).__init__()
self.W_Q = nn.Linear(d_model, d_k * n_heads)
self.W_K = nn.Linear(d_model, d_k * n_heads)
self.W_V = nn.Linear(d_model, d_v * n_heads)
self.linear = nn.Linear(n_heads * d_v, d_model)
self.layer_norm = nn.LayerNorm(d_model)
def forward(self, Q, K, V, attn_mask):
# q: [batch_size x len_q x d_model], k: [batch_size x len_k x d_model], v: [batch_size x len_k x d_model]
residual, batch_size = Q, Q.size(0)
# (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)
q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2) # q_s: [batch_size x n_heads x len_q x d_k]
k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2) # k_s: [batch_size x n_heads x len_k x d_k]
v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2) # v_s: [batch_size x n_heads x len_k x d_v]
attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1) # attn_mask : [batch_size x n_heads x len_q x len_k]
# context: [batch_size x n_heads x len_q x d_v], attn: [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]
context, attn = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)
context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) # context: [batch_size x len_q x n_heads * d_v]
output = self.linear(context)
return self.layer_norm(output + residual), attn # output: [batch_size x len_q x d_model]
class PoswiseFeedForwardNet(nn.Module):
def __init__(self):
super(PoswiseFeedForwardNet, self).__init__()
self.conv1 = nn.Conv1d(in_channels=d_model, out_channels=d_ff, kernel_size=1)
self.conv2 = nn.Conv1d(in_channels=d_ff, out_channels=d_model, kernel_size=1)
self.layer_norm = nn.LayerNorm(d_model)
def forward(self, inputs):
residual = inputs # inputs : [batch_size, len_q, d_model]
output = nn.ReLU()(self.conv1(inputs.transpose(1, 2)))
output = self.conv2(output).transpose(1, 2)
return self.layer_norm(output + residual)
class EncoderLayer(nn.Module):
def __init__(self):
super(EncoderLayer, self).__init__()
self.enc_self_attn = MultiHeadAttention()
self.pos_ffn = PoswiseFeedForwardNet()
def forward(self, enc_inputs, enc_self_attn_mask):
enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask) # enc_inputs to same Q,K,V
enc_outputs = self.pos_ffn(enc_outputs) # enc_outputs: [batch_size x len_q x d_model]
return enc_outputs, attn
class DecoderLayer(nn.Module):
def __init__(self):
super(DecoderLayer, self).__init__()
self.dec_self_attn = MultiHeadAttention()
self.dec_enc_attn = MultiHeadAttention()
self.pos_ffn = PoswiseFeedForwardNet()
def forward(self, dec_inputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask):
dec_outputs, dec_self_attn = self.dec_self_attn(dec_inputs, dec_inputs, dec_inputs, dec_self_attn_mask)
dec_outputs, dec_enc_attn = self.dec_enc_attn(dec_outputs, enc_outputs, enc_outputs, dec_enc_attn_mask)
dec_outputs = self.pos_ffn(dec_outputs)
return dec_outputs, dec_self_attn, dec_enc_attn
class Encoder(nn.Module):
def __init__(self):
super(Encoder, self).__init__()
self.src_emb = nn.Embedding(src_vocab_size, d_model)
self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(src_len+1, d_model),freeze=True)
self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])
def forward(self, enc_inputs): # enc_inputs : [batch_size x source_len]
enc_outputs = self.src_emb(enc_inputs) + self.pos_emb(torch.LongTensor([[1,2,3,4,0]]))
enc_self_attn_mask = get_attn_pad_mask(enc_inputs, enc_inputs)
enc_self_attns = []
for layer in self.layers:
enc_outputs, enc_self_attn = layer(enc_outputs, enc_self_attn_mask)
enc_self_attns.append(enc_self_attn)
return enc_outputs, enc_self_attns
class Decoder(nn.Module):
def __init__(self):
super(Decoder, self).__init__()
self.tgt_emb = nn.Embedding(tgt_vocab_size, d_model)
self.pos_emb = nn.Embedding.from_pretrained(get_sinusoid_encoding_table(tgt_len+1, d_model),freeze=True)
self.layers = nn.ModuleList([DecoderLayer() for _ in range(n_layers)])
def forward(self, dec_inputs, enc_inputs, enc_outputs): # dec_inputs : [batch_size x target_len]
dec_outputs = self.tgt_emb(dec_inputs) + self.pos_emb(torch.LongTensor([[5,1,2,3,4]]))
dec_self_attn_pad_mask = get_attn_pad_mask(dec_inputs, dec_inputs)
dec_self_attn_subsequent_mask = get_attn_subsequent_mask(dec_inputs)
dec_self_attn_mask = torch.gt((dec_self_attn_pad_mask + dec_self_attn_subsequent_mask), 0)
dec_enc_attn_mask = get_attn_pad_mask(dec_inputs, enc_inputs)
dec_self_attns, dec_enc_attns = [], []
for layer in self.layers:
dec_outputs, dec_self_attn, dec_enc_attn = layer(dec_outputs, enc_outputs, dec_self_attn_mask, dec_enc_attn_mask)
dec_self_attns.append(dec_self_attn)
dec_enc_attns.append(dec_enc_attn)
return dec_outputs, dec_self_attns, dec_enc_attns
class Transformer(nn.Module):
def __init__(self):
super(Transformer, self).__init__()
self.encoder = Encoder()
self.decoder = Decoder()
self.projection = nn.Linear(d_model, tgt_vocab_size, bias=False)
def forward(self, enc_inputs, dec_inputs):
enc_outputs, enc_self_attns = self.encoder(enc_inputs)
dec_outputs, dec_self_attns, dec_enc_attns = self.decoder(dec_inputs, enc_inputs, enc_outputs)
dec_logits = self.projection(dec_outputs) # dec_logits : [batch_size x src_vocab_size x tgt_vocab_size]
return dec_logits.view(-1, dec_logits.size(-1)), enc_self_attns, dec_self_attns, dec_enc_attns
def showgraph(attn):
attn = attn[-1].squeeze(0)[0]
attn = attn.squeeze(0).data.numpy()
fig = plt.figure(figsize=(n_heads, n_heads)) # [n_heads, n_heads]
ax = fig.add_subplot(1, 1, 1)
ax.matshow(attn, cmap='viridis')
ax.set_xticklabels(['']+sentences[0].split(), fontdict={'fontsize': 14}, rotation=90)
ax.set_yticklabels(['']+sentences[2].split(), fontdict={'fontsize': 14})
plt.show()
if __name__ == '__main__':
sentences = ['ich mochte ein bier P', 'S i want a beer', 'i want a beer E']
# Transformer Parameters
# Padding Should be Zero
src_vocab = {'P': 0, 'ich': 1, 'mochte': 2, 'ein': 3, 'bier': 4}
src_vocab_size = len(src_vocab)
tgt_vocab = {'P': 0, 'i': 1, 'want': 2, 'a': 3, 'beer': 4, 'S': 5, 'E': 6}
number_dict = {i: w for i, w in enumerate(tgt_vocab)}
tgt_vocab_size = len(tgt_vocab)
src_len = 5 # length of source
tgt_len = 5 # length of target
d_model = 512 # Embedding Size
d_ff = 2048 # FeedForward dimension
d_k = d_v = 64 # dimension of K(=Q), V
n_layers = 6 # number of Encoder of Decoder Layer
n_heads = 8 # number of heads in Multi-Head Attention
model = Transformer()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
enc_inputs, dec_inputs, target_batch = make_batch(sentences)
for epoch in range(20):
optimizer.zero_grad()
outputs, enc_self_attns, dec_self_attns, dec_enc_attns = model(enc_inputs, dec_inputs)
loss = criterion(outputs, target_batch.contiguous().view(-1))
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Test
predict, _, _, _ = model(enc_inputs, dec_inputs)
predict = predict.data.max(1, keepdim=True)[1]
print(sentences[0], '->', [number_dict[n.item()] for n in predict.squeeze()])
print('first head of last state enc_self_attns')
showgraph(enc_self_attns)
print('first head of last state dec_self_attns')
showgraph(dec_self_attns)
print('first head of last state dec_enc_attns')
showgraph(dec_enc_attns)
+271
View File
@@ -0,0 +1,271 @@
{
"cells": [
{
"cell_type": "code",
"metadata": {},
"source": [
"# code by Tae Hwan Jung(Jeff Jung) @graykode\n",
"# Reference : https://github.com/jadore801120/attention-is-all-you-need-pytorch\n",
"# https://github.com/JayParks/transformer, https://github.com/dhlee347/pytorchic-bert\n",
"import math\n",
"import re\n",
"from random import *\n",
"import numpy as np\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.optim as optim\n",
"\n",
"# sample IsNext and NotNext to be same in small batch size\n",
"def make_batch():\n",
" batch = []\n",
" positive = negative = 0\n",
" while positive != batch_size/2 or negative != batch_size/2:\n",
" tokens_a_index, tokens_b_index= randrange(len(sentences)), randrange(len(sentences)) # sample random index in sentences\n",
" tokens_a, tokens_b= token_list[tokens_a_index], token_list[tokens_b_index]\n",
" input_ids = [word_dict['[CLS]']] + tokens_a + [word_dict['[SEP]']] + tokens_b + [word_dict['[SEP]']]\n",
" segment_ids = [0] * (1 + len(tokens_a) + 1) + [1] * (len(tokens_b) + 1)\n",
"\n",
" # MASK LM\n",
" n_pred = min(max_pred, max(1, int(round(len(input_ids) * 0.15)))) # 15 % of tokens in one sentence\n",
" cand_maked_pos = [i for i, token in enumerate(input_ids)\n",
" if token != word_dict['[CLS]'] and token != word_dict['[SEP]']]\n",
" shuffle(cand_maked_pos)\n",
" masked_tokens, masked_pos = [], []\n",
" for pos in cand_maked_pos[:n_pred]:\n",
" masked_pos.append(pos)\n",
" masked_tokens.append(input_ids[pos])\n",
" if random() < 0.8: # 80%\n",
" input_ids[pos] = word_dict['[MASK]'] # make mask\n",
" elif random() < 0.5: # 10%\n",
" index = randint(0, vocab_size - 1) # random index in vocabulary\n",
" input_ids[pos] = word_dict[number_dict[index]] # replace\n",
"\n",
" # Zero Paddings\n",
" n_pad = maxlen - len(input_ids)\n",
" input_ids.extend([0] * n_pad)\n",
" segment_ids.extend([0] * n_pad)\n",
"\n",
" # Zero Padding (100% - 15%) tokens\n",
" if max_pred > n_pred:\n",
" n_pad = max_pred - n_pred\n",
" masked_tokens.extend([0] * n_pad)\n",
" masked_pos.extend([0] * n_pad)\n",
"\n",
" if tokens_a_index + 1 == tokens_b_index and positive < batch_size/2:\n",
" batch.append([input_ids, segment_ids, masked_tokens, masked_pos, True]) # IsNext\n",
" positive += 1\n",
" elif tokens_a_index + 1 != tokens_b_index and negative < batch_size/2:\n",
" batch.append([input_ids, segment_ids, masked_tokens, masked_pos, False]) # NotNext\n",
" negative += 1\n",
" return batch\n",
"# Proprecessing Finished\n",
"\n",
"def get_attn_pad_mask(seq_q, seq_k):\n",
" batch_size, len_q = seq_q.size()\n",
" batch_size, len_k = seq_k.size()\n",
" # eq(zero) is PAD token\n",
" pad_attn_mask = seq_k.data.eq(0).unsqueeze(1) # batch_size x 1 x len_k(=len_q), one is masking\n",
" return pad_attn_mask.expand(batch_size, len_q, len_k) # batch_size x len_q x len_k\n",
"\n",
"def gelu(x):\n",
" \"Implementation of the gelu activation function by Hugging Face\"\n",
" return x * 0.5 * (1.0 + torch.erf(x / math.sqrt(2.0)))\n",
"\n",
"class Embedding(nn.Module):\n",
" def __init__(self):\n",
" super(Embedding, self).__init__()\n",
" self.tok_embed = nn.Embedding(vocab_size, d_model) # token embedding\n",
" self.pos_embed = nn.Embedding(maxlen, d_model) # position embedding\n",
" self.seg_embed = nn.Embedding(n_segments, d_model) # segment(token type) embedding\n",
" self.norm = nn.LayerNorm(d_model)\n",
"\n",
" def forward(self, x, seg):\n",
" seq_len = x.size(1)\n",
" pos = torch.arange(seq_len, dtype=torch.long)\n",
" pos = pos.unsqueeze(0).expand_as(x) # (seq_len,) -> (batch_size, seq_len)\n",
" embedding = self.tok_embed(x) + self.pos_embed(pos) + self.seg_embed(seg)\n",
" return self.norm(embedding)\n",
"\n",
"class ScaledDotProductAttention(nn.Module):\n",
" def __init__(self):\n",
" super(ScaledDotProductAttention, self).__init__()\n",
"\n",
" def forward(self, Q, K, V, attn_mask):\n",
" scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) # scores : [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]\n",
" scores.masked_fill_(attn_mask, -1e9) # Fills elements of self tensor with value where mask is one.\n",
" attn = nn.Softmax(dim=-1)(scores)\n",
" context = torch.matmul(attn, V)\n",
" return context, attn\n",
"\n",
"class MultiHeadAttention(nn.Module):\n",
" def __init__(self):\n",
" super(MultiHeadAttention, self).__init__()\n",
" self.W_Q = nn.Linear(d_model, d_k * n_heads)\n",
" self.W_K = nn.Linear(d_model, d_k * n_heads)\n",
" self.W_V = nn.Linear(d_model, d_v * n_heads)\n",
" def forward(self, Q, K, V, attn_mask):\n",
" # q: [batch_size x len_q x d_model], k: [batch_size x len_k x d_model], v: [batch_size x len_k x d_model]\n",
" residual, batch_size = Q, Q.size(0)\n",
" # (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)\n",
" q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2) # q_s: [batch_size x n_heads x len_q x d_k]\n",
" k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2) # k_s: [batch_size x n_heads x len_k x d_k]\n",
" v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2) # v_s: [batch_size x n_heads x len_k x d_v]\n",
"\n",
" attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1) # attn_mask : [batch_size x n_heads x len_q x len_k]\n",
"\n",
" # context: [batch_size x n_heads x len_q x d_v], attn: [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]\n",
" context, attn = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)\n",
" context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) # context: [batch_size x len_q x n_heads * d_v]\n",
" output = nn.Linear(n_heads * d_v, d_model)(context)\n",
" return nn.LayerNorm(d_model)(output + residual), attn # output: [batch_size x len_q x d_model]\n",
"\n",
"class PoswiseFeedForwardNet(nn.Module):\n",
" def __init__(self):\n",
" super(PoswiseFeedForwardNet, self).__init__()\n",
" self.fc1 = nn.Linear(d_model, d_ff)\n",
" self.fc2 = nn.Linear(d_ff, d_model)\n",
"\n",
" def forward(self, x):\n",
" # (batch_size, len_seq, d_model) -> (batch_size, len_seq, d_ff) -> (batch_size, len_seq, d_model)\n",
" return self.fc2(gelu(self.fc1(x)))\n",
"\n",
"class EncoderLayer(nn.Module):\n",
" def __init__(self):\n",
" super(EncoderLayer, self).__init__()\n",
" self.enc_self_attn = MultiHeadAttention()\n",
" self.pos_ffn = PoswiseFeedForwardNet()\n",
"\n",
" def forward(self, enc_inputs, enc_self_attn_mask):\n",
" enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask) # enc_inputs to same Q,K,V\n",
" enc_outputs = self.pos_ffn(enc_outputs) # enc_outputs: [batch_size x len_q x d_model]\n",
" return enc_outputs, attn\n",
"\n",
"class BERT(nn.Module):\n",
" def __init__(self):\n",
" super(BERT, self).__init__()\n",
" self.embedding = Embedding()\n",
" self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])\n",
" self.fc = nn.Linear(d_model, d_model)\n",
" self.activ1 = nn.Tanh()\n",
" self.linear = nn.Linear(d_model, d_model)\n",
" self.activ2 = gelu\n",
" self.norm = nn.LayerNorm(d_model)\n",
" self.classifier = nn.Linear(d_model, 2)\n",
" # decoder is shared with embedding layer\n",
" embed_weight = self.embedding.tok_embed.weight\n",
" n_vocab, n_dim = embed_weight.size()\n",
" self.decoder = nn.Linear(n_dim, n_vocab, bias=False)\n",
" self.decoder.weight = embed_weight\n",
" self.decoder_bias = nn.Parameter(torch.zeros(n_vocab))\n",
"\n",
" def forward(self, input_ids, segment_ids, masked_pos):\n",
" output = self.embedding(input_ids, segment_ids)\n",
" enc_self_attn_mask = get_attn_pad_mask(input_ids, input_ids)\n",
" for layer in self.layers:\n",
" output, enc_self_attn = layer(output, enc_self_attn_mask)\n",
" # output : [batch_size, len, d_model], attn : [batch_size, n_heads, d_mode, d_model]\n",
" # it will be decided by first token(CLS)\n",
" h_pooled = self.activ1(self.fc(output[:, 0])) # [batch_size, d_model]\n",
" logits_clsf = self.classifier(h_pooled) # [batch_size, 2]\n",
"\n",
" masked_pos = masked_pos[:, :, None].expand(-1, -1, output.size(-1)) # [batch_size, max_pred, d_model]\n",
" # get masked position from final output of transformer.\n",
" h_masked = torch.gather(output, 1, masked_pos) # masking position [batch_size, max_pred, d_model]\n",
" h_masked = self.norm(self.activ2(self.linear(h_masked)))\n",
" logits_lm = self.decoder(h_masked) + self.decoder_bias # [batch_size, max_pred, n_vocab]\n",
"\n",
" return logits_lm, logits_clsf\n",
"\n",
"if __name__ == '__main__':\n",
" # BERT Parameters\n",
" maxlen = 30 # maximum of length\n",
" batch_size = 6\n",
" max_pred = 5 # max tokens of prediction\n",
" n_layers = 6 # number of Encoder of Encoder Layer\n",
" n_heads = 12 # number of heads in Multi-Head Attention\n",
" d_model = 768 # Embedding Size\n",
" d_ff = 768 * 4 # 4*d_model, FeedForward dimension\n",
" d_k = d_v = 64 # dimension of K(=Q), V\n",
" n_segments = 2\n",
"\n",
" text = (\n",
" 'Hello, how are you? I am Romeo.\\n'\n",
" 'Hello, Romeo My name is Juliet. Nice to meet you.\\n'\n",
" 'Nice meet you too. How are you today?\\n'\n",
" 'Great. My baseball team won the competition.\\n'\n",
" 'Oh Congratulations, Juliet\\n'\n",
" 'Thanks you Romeo'\n",
" )\n",
" sentences = re.sub(\"[.,!?\\\\-]\", '', text.lower()).split('\\n') # filter '.', ',', '?', '!'\n",
" word_list = list(set(\" \".join(sentences).split()))\n",
" word_dict = {'[PAD]': 0, '[CLS]': 1, '[SEP]': 2, '[MASK]': 3}\n",
" for i, w in enumerate(word_list):\n",
" word_dict[w] = i + 4\n",
" number_dict = {i: w for i, w in enumerate(word_dict)}\n",
" vocab_size = len(word_dict)\n",
"\n",
" token_list = list()\n",
" for sentence in sentences:\n",
" arr = [word_dict[s] for s in sentence.split()]\n",
" token_list.append(arr)\n",
"\n",
" model = BERT()\n",
" criterion = nn.CrossEntropyLoss()\n",
" optimizer = optim.Adam(model.parameters(), lr=0.001)\n",
"\n",
" batch = make_batch()\n",
" input_ids, segment_ids, masked_tokens, masked_pos, isNext = map(torch.LongTensor, zip(*batch))\n",
"\n",
" for epoch in range(100):\n",
" optimizer.zero_grad()\n",
" logits_lm, logits_clsf = model(input_ids, segment_ids, masked_pos)\n",
" loss_lm = criterion(logits_lm.transpose(1, 2), masked_tokens) # for masked LM\n",
" loss_lm = (loss_lm.float()).mean()\n",
" loss_clsf = criterion(logits_clsf, isNext) # for sentence classification\n",
" loss = loss_lm + loss_clsf\n",
" if (epoch + 1) % 10 == 0:\n",
" print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))\n",
" loss.backward()\n",
" optimizer.step()\n",
"\n",
" # Predict mask tokens ans isNext\n",
" input_ids, segment_ids, masked_tokens, masked_pos, isNext = map(torch.LongTensor, zip(batch[0]))\n",
" print(text)\n",
" print([number_dict[w.item()] for w in input_ids[0] if number_dict[w.item()] != '[PAD]'])\n",
"\n",
" logits_lm, logits_clsf = model(input_ids, segment_ids, masked_pos)\n",
" logits_lm = logits_lm.data.max(2)[1][0].data.numpy()\n",
" print('masked tokens list : ',[pos.item() for pos in masked_tokens[0] if pos.item() != 0])\n",
" print('predict masked tokens list : ',[pos for pos in logits_lm if pos != 0])\n",
"\n",
" logits_clsf = logits_clsf.data.max(1)[1].data.numpy()[0]\n",
" print('isNext : ', True if isNext else False)\n",
" print('predict isNext : ',True if logits_clsf else False)\n"
],
"outputs": [],
"execution_count": null
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"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.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
+238
View File
@@ -0,0 +1,238 @@
# %%
# code by Tae Hwan Jung(Jeff Jung) @graykode
# Reference : https://github.com/jadore801120/attention-is-all-you-need-pytorch
# https://github.com/JayParks/transformer, https://github.com/dhlee347/pytorchic-bert
import math
import re
from random import *
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
# sample IsNext and NotNext to be same in small batch size
def make_batch():
batch = []
positive = negative = 0
while positive != batch_size/2 or negative != batch_size/2:
tokens_a_index, tokens_b_index= randrange(len(sentences)), randrange(len(sentences)) # sample random index in sentences
tokens_a, tokens_b= token_list[tokens_a_index], token_list[tokens_b_index]
input_ids = [word_dict['[CLS]']] + tokens_a + [word_dict['[SEP]']] + tokens_b + [word_dict['[SEP]']]
segment_ids = [0] * (1 + len(tokens_a) + 1) + [1] * (len(tokens_b) + 1)
# MASK LM
n_pred = min(max_pred, max(1, int(round(len(input_ids) * 0.15)))) # 15 % of tokens in one sentence
cand_maked_pos = [i for i, token in enumerate(input_ids)
if token != word_dict['[CLS]'] and token != word_dict['[SEP]']]
shuffle(cand_maked_pos)
masked_tokens, masked_pos = [], []
for pos in cand_maked_pos[:n_pred]:
masked_pos.append(pos)
masked_tokens.append(input_ids[pos])
if random() < 0.8: # 80%
input_ids[pos] = word_dict['[MASK]'] # make mask
elif random() < 0.5: # 10%
index = randint(0, vocab_size - 1) # random index in vocabulary
input_ids[pos] = word_dict[number_dict[index]] # replace
# Zero Paddings
n_pad = maxlen - len(input_ids)
input_ids.extend([0] * n_pad)
segment_ids.extend([0] * n_pad)
# Zero Padding (100% - 15%) tokens
if max_pred > n_pred:
n_pad = max_pred - n_pred
masked_tokens.extend([0] * n_pad)
masked_pos.extend([0] * n_pad)
if tokens_a_index + 1 == tokens_b_index and positive < batch_size/2:
batch.append([input_ids, segment_ids, masked_tokens, masked_pos, True]) # IsNext
positive += 1
elif tokens_a_index + 1 != tokens_b_index and negative < batch_size/2:
batch.append([input_ids, segment_ids, masked_tokens, masked_pos, False]) # NotNext
negative += 1
return batch
# Proprecessing Finished
def get_attn_pad_mask(seq_q, seq_k):
batch_size, len_q = seq_q.size()
batch_size, len_k = seq_k.size()
# eq(zero) is PAD token
pad_attn_mask = seq_k.data.eq(0).unsqueeze(1) # batch_size x 1 x len_k(=len_q), one is masking
return pad_attn_mask.expand(batch_size, len_q, len_k) # batch_size x len_q x len_k
def gelu(x):
"Implementation of the gelu activation function by Hugging Face"
return x * 0.5 * (1.0 + torch.erf(x / math.sqrt(2.0)))
class Embedding(nn.Module):
def __init__(self):
super(Embedding, self).__init__()
self.tok_embed = nn.Embedding(vocab_size, d_model) # token embedding
self.pos_embed = nn.Embedding(maxlen, d_model) # position embedding
self.seg_embed = nn.Embedding(n_segments, d_model) # segment(token type) embedding
self.norm = nn.LayerNorm(d_model)
def forward(self, x, seg):
seq_len = x.size(1)
pos = torch.arange(seq_len, dtype=torch.long)
pos = pos.unsqueeze(0).expand_as(x) # (seq_len,) -> (batch_size, seq_len)
embedding = self.tok_embed(x) + self.pos_embed(pos) + self.seg_embed(seg)
return self.norm(embedding)
class ScaledDotProductAttention(nn.Module):
def __init__(self):
super(ScaledDotProductAttention, self).__init__()
def forward(self, Q, K, V, attn_mask):
scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) # scores : [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]
scores.masked_fill_(attn_mask, -1e9) # Fills elements of self tensor with value where mask is one.
attn = nn.Softmax(dim=-1)(scores)
context = torch.matmul(attn, V)
return context, attn
class MultiHeadAttention(nn.Module):
def __init__(self):
super(MultiHeadAttention, self).__init__()
self.W_Q = nn.Linear(d_model, d_k * n_heads)
self.W_K = nn.Linear(d_model, d_k * n_heads)
self.W_V = nn.Linear(d_model, d_v * n_heads)
def forward(self, Q, K, V, attn_mask):
# q: [batch_size x len_q x d_model], k: [batch_size x len_k x d_model], v: [batch_size x len_k x d_model]
residual, batch_size = Q, Q.size(0)
# (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)
q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2) # q_s: [batch_size x n_heads x len_q x d_k]
k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2) # k_s: [batch_size x n_heads x len_k x d_k]
v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2) # v_s: [batch_size x n_heads x len_k x d_v]
attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1) # attn_mask : [batch_size x n_heads x len_q x len_k]
# context: [batch_size x n_heads x len_q x d_v], attn: [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]
context, attn = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)
context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) # context: [batch_size x len_q x n_heads * d_v]
output = nn.Linear(n_heads * d_v, d_model)(context)
return nn.LayerNorm(d_model)(output + residual), attn # output: [batch_size x len_q x d_model]
class PoswiseFeedForwardNet(nn.Module):
def __init__(self):
super(PoswiseFeedForwardNet, self).__init__()
self.fc1 = nn.Linear(d_model, d_ff)
self.fc2 = nn.Linear(d_ff, d_model)
def forward(self, x):
# (batch_size, len_seq, d_model) -> (batch_size, len_seq, d_ff) -> (batch_size, len_seq, d_model)
return self.fc2(gelu(self.fc1(x)))
class EncoderLayer(nn.Module):
def __init__(self):
super(EncoderLayer, self).__init__()
self.enc_self_attn = MultiHeadAttention()
self.pos_ffn = PoswiseFeedForwardNet()
def forward(self, enc_inputs, enc_self_attn_mask):
enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask) # enc_inputs to same Q,K,V
enc_outputs = self.pos_ffn(enc_outputs) # enc_outputs: [batch_size x len_q x d_model]
return enc_outputs, attn
class BERT(nn.Module):
def __init__(self):
super(BERT, self).__init__()
self.embedding = Embedding()
self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])
self.fc = nn.Linear(d_model, d_model)
self.activ1 = nn.Tanh()
self.linear = nn.Linear(d_model, d_model)
self.activ2 = gelu
self.norm = nn.LayerNorm(d_model)
self.classifier = nn.Linear(d_model, 2)
# decoder is shared with embedding layer
embed_weight = self.embedding.tok_embed.weight
n_vocab, n_dim = embed_weight.size()
self.decoder = nn.Linear(n_dim, n_vocab, bias=False)
self.decoder.weight = embed_weight
self.decoder_bias = nn.Parameter(torch.zeros(n_vocab))
def forward(self, input_ids, segment_ids, masked_pos):
output = self.embedding(input_ids, segment_ids)
enc_self_attn_mask = get_attn_pad_mask(input_ids, input_ids)
for layer in self.layers:
output, enc_self_attn = layer(output, enc_self_attn_mask)
# output : [batch_size, len, d_model], attn : [batch_size, n_heads, d_mode, d_model]
# it will be decided by first token(CLS)
h_pooled = self.activ1(self.fc(output[:, 0])) # [batch_size, d_model]
logits_clsf = self.classifier(h_pooled) # [batch_size, 2]
masked_pos = masked_pos[:, :, None].expand(-1, -1, output.size(-1)) # [batch_size, max_pred, d_model]
# get masked position from final output of transformer.
h_masked = torch.gather(output, 1, masked_pos) # masking position [batch_size, max_pred, d_model]
h_masked = self.norm(self.activ2(self.linear(h_masked)))
logits_lm = self.decoder(h_masked) + self.decoder_bias # [batch_size, max_pred, n_vocab]
return logits_lm, logits_clsf
if __name__ == '__main__':
# BERT Parameters
maxlen = 30 # maximum of length
batch_size = 6
max_pred = 5 # max tokens of prediction
n_layers = 6 # number of Encoder of Encoder Layer
n_heads = 12 # number of heads in Multi-Head Attention
d_model = 768 # Embedding Size
d_ff = 768 * 4 # 4*d_model, FeedForward dimension
d_k = d_v = 64 # dimension of K(=Q), V
n_segments = 2
text = (
'Hello, how are you? I am Romeo.\n'
'Hello, Romeo My name is Juliet. Nice to meet you.\n'
'Nice meet you too. How are you today?\n'
'Great. My baseball team won the competition.\n'
'Oh Congratulations, Juliet\n'
'Thanks you Romeo'
)
sentences = re.sub("[.,!?\\-]", '', text.lower()).split('\n') # filter '.', ',', '?', '!'
word_list = list(set(" ".join(sentences).split()))
word_dict = {'[PAD]': 0, '[CLS]': 1, '[SEP]': 2, '[MASK]': 3}
for i, w in enumerate(word_list):
word_dict[w] = i + 4
number_dict = {i: w for i, w in enumerate(word_dict)}
vocab_size = len(word_dict)
token_list = list()
for sentence in sentences:
arr = [word_dict[s] for s in sentence.split()]
token_list.append(arr)
model = BERT()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
batch = make_batch()
input_ids, segment_ids, masked_tokens, masked_pos, isNext = map(torch.LongTensor, zip(*batch))
for epoch in range(100):
optimizer.zero_grad()
logits_lm, logits_clsf = model(input_ids, segment_ids, masked_pos)
loss_lm = criterion(logits_lm.transpose(1, 2), masked_tokens) # for masked LM
loss_lm = (loss_lm.float()).mean()
loss_clsf = criterion(logits_clsf, isNext) # for sentence classification
loss = loss_lm + loss_clsf
if (epoch + 1) % 10 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
# Predict mask tokens ans isNext
input_ids, segment_ids, masked_tokens, masked_pos, isNext = map(torch.LongTensor, zip(batch[0]))
print(text)
print([number_dict[w.item()] for w in input_ids[0] if number_dict[w.item()] != '[PAD]'])
logits_lm, logits_clsf = model(input_ids, segment_ids, masked_pos)
logits_lm = logits_lm.data.max(2)[1][0].data.numpy()
print('masked tokens list : ',[pos.item() for pos in masked_tokens[0] if pos.item() != 0])
print('predict masked tokens list : ',[pos for pos in logits_lm if pos != 0])
logits_clsf = logits_clsf.data.max(1)[1].data.numpy()[0]
print('isNext : ', True if isNext else False)
print('predict isNext : ',True if logits_clsf else False)
+6
View File
@@ -0,0 +1,6 @@
## Contribution Guidelines
Thank you to everyone who contributes. Here are some rules to follow before contributing.
1. Contributions are open to the smallest details such as typos, comments and code refactors.
2. Do not commit the jupyter notebook file(*.ipynb). When the modified python code is merged into the master branch, the github action automatically generates an ipynb.
3. Please attach a commit message appropriate to the modified code.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 TaeHwan Jung
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+84
View File
@@ -0,0 +1,84 @@
## nlp-tutorial
<p align="center"><img width="100" src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/TensorFlowLogo.svg/225px-TensorFlowLogo.svg.png" /> <img width="100" src="https://media-thumbs.golden.com/OLqzmrmwAzY1P7Sl29k2T9WjJdM=/200x200/smart/golden-storage-production.s3.amazonaws.com/topic_images/e08914afa10a4179893eeb07cb5e4713.png" /></p>
`nlp-tutorial` is a tutorial for who is studying NLP(Natural Language Processing) using **Pytorch**. Most of the models in NLP were implemented with less than **100 lines** of code.(except comments or blank lines)
- [08-14-2020] Old TensorFlow v1 code is archived in [the archive folder](archive). For beginner readability, only pytorch version 1.0 or higher is supported.
## Curriculum - (Example Purpose)
#### 1. Basic Embedding Model
- 1-1. [NNLM(Neural Network Language Model)](1-1.NNLM) - **Predict Next Word**
- Paper - [A Neural Probabilistic Language Model(2003)](http://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf)
- Colab - [NNLM.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/1-1.NNLM/NNLM.ipynb)
- 1-2. [Word2Vec(Skip-gram)](1-2.Word2Vec) - **Embedding Words and Show Graph**
- Paper - [Distributed Representations of Words and Phrases
and their Compositionality(2013)](https://papers.nips.cc/paper/5021-distributed-representations-of-words-and-phrases-and-their-compositionality.pdf)
- Colab - [Word2Vec.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/1-2.Word2Vec/Word2Vec_Skipgram(Softmax).ipynb)
- 1-3. [FastText(Application Level)](1-3.FastText) - **Sentence Classification**
- Paper - [Bag of Tricks for Efficient Text Classification(2016)](https://arxiv.org/pdf/1607.01759.pdf)
- Colab - [FastText.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/1-3.FastText/FastText.ipynb)
#### 2. CNN(Convolutional Neural Network)
- 2-1. [TextCNN](2-1.TextCNN) - **Binary Sentiment Classification**
- Paper - [Convolutional Neural Networks for Sentence Classification(2014)](http://www.aclweb.org/anthology/D14-1181)
- [TextCNN.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/2-1.TextCNN/TextCNN.ipynb)
#### 3. RNN(Recurrent Neural Network)
- 3-1. [TextRNN](3-1.TextRNN) - **Predict Next Step**
- Paper - [Finding Structure in Time(1990)](http://psych.colorado.edu/~kimlab/Elman1990.pdf)
- Colab - [TextRNN.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/3-1.TextRNN/TextRNN.ipynb)
- 3-2. [TextLSTM](https://github.com/graykode/nlp-tutorial/tree/master/3-2.TextLSTM) - **Autocomplete**
- Paper - [LONG SHORT-TERM MEMORY(1997)](https://www.bioinf.jku.at/publications/older/2604.pdf)
- Colab - [TextLSTM.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/3-2.TextLSTM/TextLSTM.ipynb)
- 3-3. [Bi-LSTM](3-3.Bi-LSTM) - **Predict Next Word in Long Sentence**
- Colab - [Bi_LSTM.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/3-3.Bi-LSTM/Bi_LSTM.ipynb)
#### 4. Attention Mechanism
- 4-1. [Seq2Seq](4-1.Seq2Seq) - **Change Word**
- Paper - [Learning Phrase Representations using RNN EncoderDecoder
for Statistical Machine Translation(2014)](https://arxiv.org/pdf/1406.1078.pdf)
- Colab - [Seq2Seq.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/4-1.Seq2Seq/Seq2Seq.ipynb)
- 4-2. [Seq2Seq with Attention](4-2.Seq2Seq(Attention)) - **Translate**
- Paper - [Neural Machine Translation by Jointly Learning to Align and Translate(2014)](https://arxiv.org/abs/1409.0473)
- Colab - [Seq2Seq(Attention).ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/4-2.Seq2Seq(Attention)/Seq2Seq(Attention).ipynb)
- 4-3. [Bi-LSTM with Attention](4-3.Bi-LSTM(Attention)) - **Binary Sentiment Classification**
- Colab - [Bi_LSTM(Attention).ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/4-3.Bi-LSTM(Attention)/Bi_LSTM(Attention).ipynb)
#### 5. Model based on Transformer
- 5-1. [The Transformer](5-1.Transformer) - **Translate**
- Paper - [Attention Is All You Need(2017)](https://arxiv.org/abs/1706.03762)
- Colab - [Transformer.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/5-1.Transformer/Transformer.ipynb), [Transformer(Greedy_decoder).ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/5-1.Transformer/Transformer(Greedy_decoder).ipynb)
- 5-2. [BERT](5-2.BERT) - **Classification Next Sentence & Predict Masked Tokens**
- Paper - [BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding(2018)](https://arxiv.org/abs/1810.04805)
- Colab - [BERT.ipynb](https://colab.research.google.com/github/graykode/nlp-tutorial/blob/master/5-2.BERT/BERT.ipynb)
## Dependencies
- Python 3.5+
- Pytorch 1.0.0+
## Author
- Tae Hwan Jung(Jeff Jung) @graykode
- Author Email : nlkey2022@gmail.com
- Acknowledgements to [mojitok](http://mojitok.com/) as NLP Research Internship.
+7
View File
@@ -0,0 +1,7 @@
# WeHub 来源说明
- 原始项目:`graykode/nlp-tutorial`
- 原始仓库:https://github.com/graykode/nlp-tutorial
- 导入方式:上游默认分支的最新快照
- 原作者、版权和许可证信息以原始仓库及本仓库 LICENSE 为准
- 本文件仅用于记录来源,不代表 WeHub 是原项目作者
+67
View File
@@ -0,0 +1,67 @@
# code by Tae Hwan Jung @graykode
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
sentences = [ "i like dog", "i love coffee", "i hate milk"]
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict) # number of Vocabulary
# NNLM Parameter
n_step = 2 # number of steps ['i like', 'i love', 'i hate']
n_hidden = 2 # number of hidden units
def make_batch(sentences):
input_batch = []
target_batch = []
for sen in sentences:
word = sen.split()
input = [word_dict[n] for n in word[:-1]]
target = word_dict[word[-1]]
input_batch.append(np.eye(n_class)[input])
target_batch.append(np.eye(n_class)[target])
return input_batch, target_batch
# Model
X = tf.placeholder(tf.float32, [None, n_step, n_class]) # [batch_size, number of steps, number of Vocabulary]
Y = tf.placeholder(tf.float32, [None, n_class])
input = tf.reshape(X, shape=[-1, n_step * n_class]) # [batch_size, n_step * n_class]
H = tf.Variable(tf.random_normal([n_step * n_class, n_hidden]))
d = tf.Variable(tf.random_normal([n_hidden]))
U = tf.Variable(tf.random_normal([n_hidden, n_class]))
b = tf.Variable(tf.random_normal([n_class]))
tanh = tf.nn.tanh(d + tf.matmul(input, H)) # [batch_size, n_hidden]
model = tf.matmul(tanh, U) + b # [batch_size, n_class]
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
prediction =tf.argmax(model, 1)
# Training
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
input_batch, target_batch = make_batch(sentences)
for epoch in range(5000):
_, loss = sess.run([optimizer, cost], feed_dict={X: input_batch, Y: target_batch})
if (epoch + 1)%1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
# Predict
predict = sess.run([prediction], feed_dict={X: input_batch})
# Test
input = [sen.split()[:2] for sen in sentences]
print([sen.split()[:2] for sen in sentences], '->', [number_dict[n] for n in predict[0]])
@@ -0,0 +1,80 @@
'''
code by Tae Hwan Jung(Jeff Jung) @graykode
reference : https://github.com/golbin/TensorFlow-Tutorials/blob/master/04%20-%20Neural%20Network%20Basic/03%20-%20Word2Vec.py
'''
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
tf.reset_default_graph()
# 3 Words Sentence
sentences = [ "i like dog", "i like cat", "i like animal",
"dog cat animal", "apple cat dog like", "dog fish milk like",
"dog cat eyes like", "i like apple", "apple i hate",
"apple i movie book music like", "cat dog hate", "cat dog like"]
word_sequence = " ".join(sentences).split()
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
# Word2Vec Parameter
batch_size = 20
embedding_size = 2 # To show 2 dim embedding graph
num_sampled = 10 # for negative sampling, less than batch_size
voc_size = len(word_list)
def random_batch(data, size):
random_inputs = []
random_labels = []
random_index = np.random.choice(range(len(data)), size, replace=False)
for i in random_index:
random_inputs.append(data[i][0]) # target
random_labels.append([data[i][1]]) # context word
return random_inputs, random_labels
# Make skip gram of one size window
skip_grams = []
for i in range(1, len(word_sequence) - 1):
target = word_dict[word_sequence[i]]
context = [word_dict[word_sequence[i - 1]], word_dict[word_sequence[i + 1]]]
for w in context:
skip_grams.append([target, w])
# Model
inputs = tf.placeholder(tf.int32, shape=[batch_size])
labels = tf.placeholder(tf.int32, shape=[batch_size, 1]) # To use tf.nn.nce_loss, [batch_size, 1]
embeddings = tf.Variable(tf.random_uniform([voc_size, embedding_size], -1.0, 1.0))
selected_embed = tf.nn.embedding_lookup(embeddings, inputs)
nce_weights = tf.Variable(tf.random_uniform([voc_size, embedding_size], -1.0, 1.0))
nce_biases = tf.Variable(tf.zeros([voc_size]))
# Loss and optimizer
cost = tf.reduce_mean(tf.nn.nce_loss(nce_weights, nce_biases, labels, selected_embed, num_sampled, voc_size))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
# Training
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
for epoch in range(5000):
batch_inputs, batch_labels = random_batch(skip_grams, batch_size)
_, loss = sess.run([optimizer, cost], feed_dict={inputs: batch_inputs, labels: batch_labels})
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
trained_embeddings = embeddings.eval()
for i, label in enumerate(word_list):
x, y = trained_embeddings[i]
plt.scatter(x, y)
plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
plt.show()
@@ -0,0 +1,77 @@
'''
code by Tae Hwan Jung(Jeff Jung) @graykode
'''
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
tf.reset_default_graph()
# 3 Words Sentence
sentences = [ "i like dog", "i like cat", "i like animal",
"dog cat animal", "apple cat dog like", "dog fish milk like",
"dog cat eyes like", "i like apple", "apple i hate",
"apple i movie book music like", "cat dog hate", "cat dog like"]
word_sequence = " ".join(sentences).split()
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
# Word2Vec Parameter
batch_size = 20
embedding_size = 2 # To show 2 dim embedding graph
voc_size = len(word_list)
def random_batch(data, size):
random_inputs = []
random_labels = []
random_index = np.random.choice(range(len(data)), size, replace=False)
for i in random_index:
random_inputs.append(np.eye(voc_size)[data[i][0]]) # target
random_labels.append(np.eye(voc_size)[data[i][1]]) # context word
return random_inputs, random_labels
# Make skip gram of one size window
skip_grams = []
for i in range(1, len(word_sequence) - 1):
target = word_dict[word_sequence[i]]
context = [word_dict[word_sequence[i - 1]], word_dict[word_sequence[i + 1]]]
for w in context:
skip_grams.append([target, w])
# Model
inputs = tf.placeholder(tf.float32, shape=[None, voc_size])
labels = tf.placeholder(tf.float32, shape=[None, voc_size])
# W and WT is not Traspose relationship
W = tf.Variable(tf.random_uniform([voc_size, embedding_size], -1.0, 1.0))
WT = tf.Variable(tf.random_uniform([embedding_size, voc_size], -1.0, 1.0))
hidden_layer = tf.matmul(inputs, W) # [batch_size, embedding_size]
output_layer = tf.matmul(hidden_layer, WT) # [batch_size, voc_size]
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=output_layer, labels=labels))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
for epoch in range(5000):
batch_inputs, batch_labels = random_batch(skip_grams, batch_size)
_, loss = sess.run([optimizer, cost], feed_dict={inputs: batch_inputs, labels: batch_labels})
if (epoch + 1)%1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
trained_embeddings = W.eval()
for i, label in enumerate(word_list):
x, y = trained_embeddings[i]
plt.scatter(x, y)
plt.annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points', ha='right', va='bottom')
plt.show()
@@ -0,0 +1,94 @@
'''
code by Tae Hwan Jung(Jeff Jung) @graykode
Reference : https://github.com/ioatr/textcnn
'''
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
# Text-CNN Parameter
embedding_size = 2 # n-gram
sequence_length = 3
num_classes = 2 # 0 or 1
filter_sizes = [2,2,2] # n-gram window
num_filters = 3
# 3 words sentences (=sequence_length is 3)
sentences = ["i love you","he loves me", "she likes baseball", "i hate you","sorry for that", "this is awful"]
labels = [1,1,1,0,0,0] # 1 is good, 0 is not good.
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
vocab_size = len(word_dict)
inputs = []
for sen in sentences:
inputs.append(np.asarray([word_dict[n] for n in sen.split()]))
outputs = []
for out in labels:
outputs.append(np.eye(num_classes)[out]) # ONE-HOT : To using Tensor Softmax Loss function
# Model
X = tf.placeholder(tf.int32, [None, sequence_length])
Y = tf.placeholder(tf.int32, [None, num_classes])
W = tf.Variable(tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0))
embedded_chars = tf.nn.embedding_lookup(W, X) # [batch_size, sequence_length, embedding_size]
embedded_chars = tf.expand_dims(embedded_chars, -1) # add channel(=1) [batch_size, sequence_length, embedding_size, 1]
pooled_outputs = []
for i, filter_size in enumerate(filter_sizes):
filter_shape = [filter_size, embedding_size, 1, num_filters]
W = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1))
b = tf.Variable(tf.constant(0.1, shape=[num_filters]))
conv = tf.nn.conv2d(embedded_chars, # [batch_size, sequence_length, embedding_size, 1]
W, # [filter_size(n-gram window), embedding_size, 1, num_filters(=3)]
strides=[1, 1, 1, 1],
padding='VALID')
h = tf.nn.relu(tf.nn.bias_add(conv, b))
pooled = tf.nn.max_pool(h,
ksize=[1, sequence_length - filter_size + 1, 1, 1], # [batch_size, filter_height, filter_width, channel]
strides=[1, 1, 1, 1],
padding='VALID')
pooled_outputs.append(pooled) # dim of pooled : [batch_size(=6), output_height(=1), output_width(=1), channel(=1)]
num_filters_total = num_filters * len(filter_sizes)
h_pool = tf.concat(pooled_outputs, num_filters) # h_pool : [batch_size(=6), output_height(=1), output_width(=1), channel(=1) * 3]
h_pool_flat = tf.reshape(h_pool, [-1, num_filters_total]) # [batch_size, ]
# Model-Training
Weight = tf.get_variable('W', shape=[num_filters_total, num_classes],
initializer=tf.contrib.layers.xavier_initializer())
Bias = tf.Variable(tf.constant(0.1, shape=[num_classes]))
model = tf.nn.xw_plus_b(h_pool_flat, Weight, Bias)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
# Model-Predict
hypothesis = tf.nn.softmax(model)
predictions = tf.argmax(hypothesis, 1)
# Training
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for epoch in range(5000):
_, loss = sess.run([optimizer, cost], feed_dict={X: inputs, Y: outputs})
if (epoch + 1)%1000 == 0:
print('Epoch:', '%06d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
# Test
test_text = 'sorry hate you'
tests = []
tests.append(np.asarray([word_dict[n] for n in test_text.split()]))
predict = sess.run([predictions], feed_dict={X: tests})
result = predict[0][0]
if result == 0:
print(test_text,"is Bad Mean...")
else:
print(test_text,"is Good Mean!!")
@@ -0,0 +1,70 @@
'''
code by Tae Hwan Jung(Jeff Jung) @graykode
'''
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
sentences = [ "i like dog", "i love coffee", "i hate milk"]
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict)
# TextRNN Parameter
n_step = 2 # number of cells(= number of Step)
n_hidden = 5 # number of hidden units in one cell
def make_batch(sentences):
input_batch = []
target_batch = []
for sen in sentences:
word = sen.split()
input = [word_dict[n] for n in word[:-1]]
target = word_dict[word[-1]]
input_batch.append(np.eye(n_class)[input])
target_batch.append(np.eye(n_class)[target])
return input_batch, target_batch
# Model
X = tf.placeholder(tf.float32, [None, n_step, n_class]) # [batch_size, n_step, n_class]
Y = tf.placeholder(tf.float32, [None, n_class]) # [batch_size, n_class]
W = tf.Variable(tf.random_normal([n_hidden, n_class]))
b = tf.Variable(tf.random_normal([n_class]))
cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
outputs, states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
# outputs : [batch_size, n_step, n_hidden]
outputs = tf.transpose(outputs, [1, 0, 2]) # [n_step, batch_size, n_hidden]
outputs = outputs[-1] # [batch_size, n_hidden]
model = tf.matmul(outputs, W) + b # model : [batch_size, n_class]
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
prediction = tf.cast(tf.argmax(model, 1), tf.int32)
# Training
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
input_batch, target_batch = make_batch(sentences)
for epoch in range(5000):
_, loss = sess.run([optimizer, cost], feed_dict={X: input_batch, Y: target_batch})
if (epoch + 1)%1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
input = [sen.split()[:2] for sen in sentences]
predict = sess.run([prediction], feed_dict={X: input_batch})
print([sen.split()[:2] for sen in sentences], '->', [number_dict[n] for n in predict[0]])
@@ -0,0 +1,66 @@
'''
code by Tae Hwan Jung(Jeff Jung) @graykode
'''
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
char_arr = [c for c in 'abcdefghijklmnopqrstuvwxyz']
word_dict = {n: i for i, n in enumerate(char_arr)}
number_dict = {i: w for i, w in enumerate(char_arr)}
n_class = len(word_dict) # number of class(=number of vocab)
seq_data = ['make', 'need', 'coal', 'word', 'love', 'hate', 'live', 'home', 'hash', 'star']
# TextLSTM Parameters
n_step = 3
n_hidden = 128
def make_batch(seq_data):
input_batch, target_batch = [], []
for seq in seq_data:
input = [word_dict[n] for n in seq[:-1]] # 'm', 'a' , 'k' is input
target = word_dict[seq[-1]] # 'e' is target
input_batch.append(np.eye(n_class)[input])
target_batch.append(np.eye(n_class)[target])
return input_batch, target_batch
# Model
X = tf.placeholder(tf.float32, [None, n_step, n_class]) # [batch_size, n_step, n_class]
Y = tf.placeholder(tf.float32, [None, n_class]) # [batch_size, n_class]
W = tf.Variable(tf.random_normal([n_hidden, n_class]))
b = tf.Variable(tf.random_normal([n_class]))
cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden)
outputs, states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
# outputs : [batch_size, n_step, n_hidden]
outputs = tf.transpose(outputs, [1, 0, 2]) # [n_step, batch_size, n_hidden]
outputs = outputs[-1] # [batch_size, n_hidden]
model = tf.matmul(outputs, W) + b # model : [batch_size, n_class]
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
prediction = tf.cast(tf.argmax(model, 1), tf.int32)
# Training
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
input_batch, target_batch = make_batch(seq_data)
for epoch in range(1000):
_, loss = sess.run([optimizer, cost], feed_dict={X: input_batch, Y: target_batch})
if (epoch + 1)%100 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
inputs = [sen[:3] for sen in seq_data]
predict = sess.run([prediction], feed_dict={X: input_batch})
print(inputs, '->', [number_dict[n] for n in predict[0]])
@@ -0,0 +1,73 @@
'''
code by Tae Hwan Jung(Jeff Jung) @graykode
'''
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
sentence = (
'Lorem ipsum dolor sit amet consectetur adipisicing elit '
'sed do eiusmod tempor incididunt ut labore et dolore magna '
'aliqua Ut enim ad minim veniam quis nostrud exercitation'
)
word_dict = {w: i for i, w in enumerate(list(set(sentence.split())))}
number_dict = {i: w for i, w in enumerate(list(set(sentence.split())))}
n_class = len(word_dict)
n_step = len(sentence.split())
n_hidden = 5
def make_batch(sentence):
input_batch = []
target_batch = []
words = sentence.split()
for i, word in enumerate(words[:-1]):
input = [word_dict[n] for n in words[:(i + 1)]]
input = input + [0] * (n_step - len(input))
target = word_dict[words[i + 1]]
input_batch.append(np.eye(n_class)[input])
target_batch.append(np.eye(n_class)[target])
return input_batch, target_batch
# Bi-LSTM Model
X = tf.placeholder(tf.float32, [None, n_step, n_class])
Y = tf.placeholder(tf.float32, [None, n_class])
W = tf.Variable(tf.random_normal([n_hidden * 2, n_class]))
b = tf.Variable(tf.random_normal([n_class]))
lstm_fw_cell = tf.nn.rnn_cell.LSTMCell(n_hidden)
lstm_bw_cell = tf.nn.rnn_cell.LSTMCell(n_hidden)
# outputs : [batch_size, len_seq, n_hidden], states : [batch_size, n_hidden]
outputs, _ = tf.nn.bidirectional_dynamic_rnn(lstm_fw_cell,lstm_bw_cell, X, dtype=tf.float32)
outputs = tf.concat([outputs[0], outputs[1]], 2) # output[0] : lstm_fw, output[1] : lstm_bw
outputs = tf.transpose(outputs, [1, 0, 2]) # [n_step, batch_size, n_hidden]
outputs = outputs[-1] # [batch_size, n_hidden]
model = tf.matmul(outputs, W) + b
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
prediction = tf.cast(tf.argmax(model, 1), tf.int32)
# Training
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
input_batch, target_batch = make_batch(sentence)
for epoch in range(10000):
_, loss = sess.run([optimizer, cost], feed_dict={X: input_batch, Y: target_batch})
if (epoch + 1)%1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
predict = sess.run([prediction], feed_dict={X: input_batch})
print(sentence)
print([number_dict[n] for n in [pre for pre in predict[0]]])
@@ -0,0 +1,93 @@
'''
code by Tae Hwan Jung(Jeff Jung) @graykode
reference : https://github.com/golbin/TensorFlow-Tutorials/blob/master/10%20-%20RNN/03%20-%20Seq2Seq.py
'''
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
# S: Symbol that shows starting of decoding input
# E: Symbol that shows starting of decoding output
# P: Symbol that will fill in blank sequence if current batch data size is short than time steps
char_arr = [c for c in 'SEPabcdefghijklmnopqrstuvwxyz']
num_dic = {n: i for i, n in enumerate(char_arr)}
seq_data = [['man', 'women'], ['black', 'white'], ['king', 'queen'], ['girl', 'boy'], ['up', 'down'], ['high', 'low']]
# Seq2Seq Parameter
n_step = 5
n_hidden = 128
n_class = len(num_dic) # number of class(=number of vocab)
def make_batch(seq_data):
input_batch, output_batch, target_batch = [], [], []
for seq in seq_data:
for i in range(2):
seq[i] = seq[i] + 'P' * (n_step - len(seq[i]))
input = [num_dic[n] for n in seq[0]]
output = [num_dic[n] for n in ('S' + seq[1])]
target = [num_dic[n] for n in (seq[1] + 'E')]
input_batch.append(np.eye(n_class)[input])
output_batch.append(np.eye(n_class)[output])
target_batch.append(target)
return input_batch, output_batch, target_batch
# Model
enc_input = tf.placeholder(tf.float32, [None, None, n_class]) # [batch_size, max_len(=encoder_step), n_class]
dec_input = tf.placeholder(tf.float32, [None, None, n_class]) # [batch_size, max_len+1(=decoder_step) (becase of 'S' or 'E'), n_class]
targets = tf.placeholder(tf.int64, [None, None]) # [batch_size, max_len+1], not one-hot
with tf.variable_scope('encode'):
enc_cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
enc_cell = tf.nn.rnn_cell.DropoutWrapper(enc_cell, output_keep_prob=0.5)
_, enc_states = tf.nn.dynamic_rnn(enc_cell, enc_input, dtype=tf.float32)
# encoder state will go to decoder initial_state, enc_states : [batch_size, n_hidden(=128)]
with tf.variable_scope('decode'):
dec_cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
dec_cell = tf.nn.rnn_cell.DropoutWrapper(dec_cell, output_keep_prob=0.5)
outputs, _ = tf.nn.dynamic_rnn(dec_cell, dec_input, initial_state=enc_states, dtype=tf.float32)
# outputs : [batch_size, max_len+1, n_hidden(=128)]
model = tf.layers.dense(outputs, n_class, activation=None) # model : [batch_size, max_len+1, n_class]
cost = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=model, labels=targets))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
# Training
sess = tf.Session()
sess.run(tf.global_variables_initializer())
input_batch, output_batch, target_batch = make_batch(seq_data)
for epoch in range(5000):
_, loss = sess.run([optimizer, cost], feed_dict={enc_input: input_batch, dec_input: output_batch, targets: target_batch})
if (epoch + 1)%1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
# Test
def translate(word):
seq_data = [word, 'P' * len(word)]
input_batch, output_batch, _ = make_batch([seq_data])
prediction = tf.argmax(model, 2)
result = sess.run(prediction, feed_dict={enc_input: input_batch, dec_input: output_batch})
decoded = [char_arr[i] for i in result[0]]
end = decoded.index('E')
translated = ''.join(decoded[:end])
return translated.replace('P','')
print('test')
print('man ->', translate('man'))
print('mans ->', translate('mans'))
print('king ->', translate('king'))
print('black ->', translate('black'))
print('upp ->', translate('upp'))
@@ -0,0 +1,108 @@
# code by Tae Hwan Jung(Jeff Jung) @graykode
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
tf.reset_default_graph()
# S: Symbol that shows starting of decoding input
# E: Symbol that shows starting of decoding output
# P: Symbol that will fill in blank sequence if current batch data size is short than time steps
sentences = ['ich mochte ein bier P', 'S i want a beer', 'i want a beer E']
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
number_dict = {i: w for i, w in enumerate(word_list)}
n_class = len(word_dict) # vocab list
# Parameter
n_step = 5 # maxium number of words in one sentence(=number of time steps)
n_hidden = 128
def make_batch(sentences):
input_batch = [np.eye(n_class)[[word_dict[n] for n in sentences[0].split()]]]
output_batch = [np.eye(n_class)[[word_dict[n] for n in sentences[1].split()]]]
target_batch = [[word_dict[n] for n in sentences[2].split()]]
return input_batch, output_batch, target_batch
# Model
enc_inputs = tf.placeholder(tf.float32, [None, None, n_class]) # [batch_size, n_step, n_class]
dec_inputs = tf.placeholder(tf.float32, [None, None, n_class]) # [batch_size, n_step, n_class]
targets = tf.placeholder(tf.int64, [1, n_step]) # [batch_size, n_step], not one-hot
# Linear for attention
attn = tf.Variable(tf.random_normal([n_hidden, n_hidden]))
out = tf.Variable(tf.random_normal([n_hidden * 2, n_class]))
def get_att_score(dec_output, enc_output): # enc_output [n_step, n_hidden]
score = tf.squeeze(tf.matmul(enc_output, attn), 0) # score : [n_hidden]
dec_output = tf.squeeze(dec_output, [0, 1]) # dec_output : [n_hidden]
return tf.tensordot(dec_output, score, 1) # inner product make scalar value
def get_att_weight(dec_output, enc_outputs):
attn_scores = [] # list of attention scalar : [n_step]
enc_outputs = tf.transpose(enc_outputs, [1, 0, 2]) # enc_outputs : [n_step, batch_size, n_hidden]
for i in range(n_step):
attn_scores.append(get_att_score(dec_output, enc_outputs[i]))
# Normalize scores to weights in range 0 to 1
return tf.reshape(tf.nn.softmax(attn_scores), [1, 1, -1]) # [1, 1, n_step]
model = []
Attention = []
with tf.variable_scope('encode'):
enc_cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
enc_cell = tf.nn.rnn_cell.DropoutWrapper(enc_cell, output_keep_prob=0.5)
# enc_outputs : [batch_size(=1), n_step(=decoder_step), n_hidden(=128)]
# enc_hidden : [batch_size(=1), n_hidden(=128)]
enc_outputs, enc_hidden = tf.nn.dynamic_rnn(enc_cell, enc_inputs, dtype=tf.float32)
with tf.variable_scope('decode'):
dec_cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
dec_cell = tf.nn.rnn_cell.DropoutWrapper(dec_cell, output_keep_prob=0.5)
inputs = tf.transpose(dec_inputs, [1, 0, 2])
hidden = enc_hidden
for i in range(n_step):
# time_major True mean inputs shape: [max_time, batch_size, ...]
dec_output, hidden = tf.nn.dynamic_rnn(dec_cell, tf.expand_dims(inputs[i], 1),
initial_state=hidden, dtype=tf.float32, time_major=True)
attn_weights = get_att_weight(dec_output, enc_outputs) # attn_weights : [1, 1, n_step]
Attention.append(tf.squeeze(attn_weights))
# matrix-matrix product of matrices [1, 1, n_step] x [1, n_step, n_hidden] = [1, 1, n_hidden]
context = tf.matmul(attn_weights, enc_outputs)
dec_output = tf.squeeze(dec_output, 0) # [1, n_step]
context = tf.squeeze(context, 1) # [1, n_hidden]
model.append(tf.matmul(tf.concat((dec_output, context), 1), out)) # [n_step, batch_size(=1), n_class]
trained_attn = tf.stack([Attention[0], Attention[1], Attention[2], Attention[3], Attention[4]], 0) # to show attention matrix
model = tf.transpose(model, [1, 0, 2]) # model : [n_step, n_class]
prediction = tf.argmax(model, 2)
cost = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=model, labels=targets))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
# Training and Test
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
for epoch in range(2000):
input_batch, output_batch, target_batch = make_batch(sentences)
_, loss, attention = sess.run([optimizer, cost, trained_attn],
feed_dict={enc_inputs: input_batch, dec_inputs: output_batch, targets: target_batch})
if (epoch + 1) % 400 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
predict_batch = [np.eye(n_class)[[word_dict[n] for n in 'P P P P P'.split()]]]
result = sess.run(prediction, feed_dict={enc_inputs: input_batch, dec_inputs: predict_batch})
print(sentences[0].split(), '->', [number_dict[n] for n in result[0]])
# Show Attention
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(1, 1, 1)
ax.matshow(attention, cmap='viridis')
ax.set_xticklabels([''] + sentences[0].split(), fontdict={'fontsize': 14})
ax.set_yticklabels([''] + sentences[2].split(), fontdict={'fontsize': 14})
plt.show()
@@ -0,0 +1,92 @@
'''
code by Tae Hwan Jung(Jeff Jung) @graykode
Reference : https://github.com/prakashpandey9/Text-Classification-Pytorch/blob/master/models/LSTM_Attn.py
'''
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
tf.reset_default_graph()
# Bi-LSTM(Attention) Parameters
embedding_dim = 2
n_hidden = 5 # number of hidden units in one cell
n_step = 3 # all sentence is consist of 3 words
n_class = 2 # 0 or 1
# 3 words sentences (=sequence_length is 3)
sentences = ["i love you", "he loves me", "she likes baseball", "i hate you", "sorry for that", "this is awful"]
labels = [1, 1, 1, 0, 0, 0] # 1 is good, 0 is not good.
word_list = " ".join(sentences).split()
word_list = list(set(word_list))
word_dict = {w: i for i, w in enumerate(word_list)}
vocab_size = len(word_dict)
input_batch = []
for sen in sentences:
input_batch.append(np.asarray([word_dict[n] for n in sen.split()]))
target_batch = []
for out in labels:
target_batch.append(np.eye(n_class)[out]) # ONE-HOT : To using Tensor Softmax Loss function
# LSTM Model
X = tf.placeholder(tf.int32, [None, n_step])
Y = tf.placeholder(tf.int32, [None, n_class])
out = tf.Variable(tf.random_normal([n_hidden * 2, n_class]))
embedding = tf.Variable(tf.random_uniform([vocab_size, embedding_dim]))
input = tf.nn.embedding_lookup(embedding, X) # [batch_size, len_seq, embedding_dim]
lstm_fw_cell = tf.nn.rnn_cell.LSTMCell(n_hidden)
lstm_bw_cell = tf.nn.rnn_cell.LSTMCell(n_hidden)
# output : [batch_size, len_seq, n_hidden], states : [batch_size, n_hidden]
output, final_state = tf.nn.bidirectional_dynamic_rnn(lstm_fw_cell,lstm_bw_cell, input, dtype=tf.float32)
# Attention
output = tf.concat([output[0], output[1]], 2) # output[0] : lstm_fw, output[1] : lstm_bw
final_hidden_state = tf.concat([final_state[1][0], final_state[1][1]], 1) # final_hidden_state : [batch_size, n_hidden * num_directions(=2)]
final_hidden_state = tf.expand_dims(final_hidden_state, 2) # final_hidden_state : [batch_size, n_hidden * num_directions(=2), 1]
attn_weights = tf.squeeze(tf.matmul(output, final_hidden_state), 2) # attn_weights : [batch_size, n_step]
soft_attn_weights = tf.nn.softmax(attn_weights, 1)
context = tf.matmul(tf.transpose(output, [0, 2, 1]), tf.expand_dims(soft_attn_weights, 2)) # context : [batch_size, n_hidden * num_directions(=2), 1]
context = tf.squeeze(context, 2) # [batch_size, n_hidden * num_directions(=2)]
model = tf.matmul(context, out)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
# Model-Predict
hypothesis = tf.nn.softmax(model)
predictions = tf.argmax(hypothesis, 1)
# Training
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
for epoch in range(5000):
_, loss, attention = sess.run([optimizer, cost, soft_attn_weights], feed_dict={X: input_batch, Y: target_batch})
if (epoch + 1)%1000 == 0:
print('Epoch:', '%06d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
# Test
test_text = 'sorry hate you'
tests = [np.asarray([word_dict[n] for n in test_text.split()])]
predict = sess.run([predictions], feed_dict={X: tests})
result = predict[0][0]
if result == 0:
print(test_text,"is Bad Mean...")
else:
print(test_text,"is Good Mean!!")
fig = plt.figure(figsize=(6, 3)) # [batch_size, n_step]
ax = fig.add_subplot(1, 1, 1)
ax.matshow(attention, cmap='viridis')
ax.set_xticklabels([''] + ['first_word', 'second_word', 'third_word'], fontdict={'fontsize': 14}, rotation=90)
ax.set_yticklabels([''] + ['batch_1', 'batch_2', 'batch_3', 'batch_4', 'batch_5', 'batch_6'], fontdict={'fontsize': 14})
plt.show()