-
Notifications
You must be signed in to change notification settings - Fork 1
/
classifier.py
87 lines (71 loc) · 2.83 KB
/
classifier.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from transformer import TransformerEncoder, PositionalEncodings
class ResidualBlock(nn.Module):
"""Represents 1D version of the residual block: https://arxiv.org/abs/1512.03385"""
def __init__(self, input_dim):
"""Initializes the module."""
super(ResidualBlock, self).__init__()
self.block = nn.Sequential(
nn.Linear(input_dim, input_dim),
nn.LeakyReLU(),
nn.Linear(input_dim, input_dim),
)
def forward(self, x):
"""Performs forward pass of the module."""
skip_connection = x
x = self.block(x)
x = skip_connection + x
return x
class NERClassifier(nn.Module):
"""Represents model which classifies named entities in the given body of text."""
def __init__(self, config):
"""Initializes the module."""
super(NERClassifier, self).__init__()
num_classes = len(config["class_mapping"])
embedding_dim = config["embeddings"]["size"]
num_of_transformer_layers = config["num_of_transformer_layers"]
transformer_embedding_dim = config["transformer_embedding_dim"]
attention_heads = config["attention_heads"]
ff_dim = config["transformer_ff_dim"]
dropout = config["dropout"]
# Load pretrained word embeddings
word_embeddings = torch.Tensor(np.loadtxt(config["embeddings"]["path"]))
self.embedding_layer = nn.Embedding.from_pretrained(
word_embeddings,
freeze=True,
padding_idx=config["PAD_idx"]
)
self.entry_mapping = nn.Linear(embedding_dim, transformer_embedding_dim)
self.res_block = ResidualBlock(transformer_embedding_dim)
self.positional_encodings = PositionalEncodings(
config["max_len"],
transformer_embedding_dim,
dropout
)
self.transformer_encoder = TransformerEncoder(
num_of_transformer_layers,
attention_heads,
transformer_embedding_dim,
ff_dim,
dropout
)
self.classifier = nn.Linear(transformer_embedding_dim, num_classes)
def forward(self, x, padding_mask):
"""Performs forward pass of the module."""
# Get token embeddings for each word in a sequence
x = self.embedding_layer(x)
# Map input tokens to the transformer embedding dim
x = self.entry_mapping(x)
x = F.leaky_relu(x)
x = self.res_block(x)
x = F.leaky_relu(x)
# Leverage the self-attention mechanism on the input sequence
x = self.positional_encodings(x)
x = x.permute(1, 0, 2)
x, _ = self.transformer_encoder(x, padding_mask)
x = x.permute(1, 0, 2)
y_pred = self.classifier(x)
return y_pred