-
Notifications
You must be signed in to change notification settings - Fork 27
/
model.py
145 lines (121 loc) · 5.31 KB
/
model.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""
Author: Ivan Bongiorni, https://github.com/IvanBongiorni
2020-03-19
Models implementation.
"""
import tensorflow as tf
def build_vanilla_seq2seq(params):
"""
Implements a seq2seq RNN with Convolutional self attention. It keeps a canonical
Encoder-Decoder structure: an Embedding layers receives the sequence of chars and
learns a representation. This series is received by two different layers at the same time.
First, an LSTM Encoder layer, whose output is repeated and sent to the Decoder. Second, a
block of 1D Conv layers. Their kernel filters work as multi-head self attention layers.
All their scores are pushed through a TanH gate that scales each score in the [-1,1] range.
Both LSTM and Conv outputs are concatenated and sent to an LSTM Decoder, that processes
the signal and sents it to Dense layers, performing the prediction for each step of the
output series.
Args: params dict
"""
from tensorflow.keras.models import Model
from tensorflow.keras.layers import (
Input, LSTM, RepeatVector, Conv1D, BatchNormalization,
Concatenate, TimeDistributed, Dense
)
## ENCODER
encoder_input = Input((params['len_input'], 17))
# LSTM block
encoder_lstm = LSTM(units = params['encoder_lstm_units'])(encoder_input)
output_lstm = RepeatVector(params['len_input'])(encoder_lstm)
# Conv block
conv_1 = Conv1D(
filters = params['conv_filters'],
kernel_size = params['kernel_size'],
activation = params['conv_activation'],
kernel_initializer = params['conv_initializer'],
padding = 'same')(encoder_input)
if params['use_batchnorm']:
conv_1 = BatchNormalization()(conv_1)
conv_2 = Conv1D(
filters = params['conv_filters'],
kernel_size = params['kernel_size'],
activation = params['conv_activation'],
kernel_initializer = params['conv_initializer'],
padding = 'same')(conv_1)
if params['use_batchnorm']:
conv_2 = BatchNormalization()(conv_2)
conv_3 = Conv1D(
filters = params['conv_filters'],
kernel_size = params['kernel_size'],
activation = params['conv_activation'],
kernel_initializer = params['conv_initializer'],
padding = 'same')(conv_2)
if params['use_batchnorm']:
conv_3 = BatchNormalization()(conv_3)
conv_4 = Conv1D(
filters = params['conv_filters'],
kernel_size = params['kernel_size'],
activation = params['conv_activation'],
kernel_initializer = params['conv_initializer'],
padding = 'same')(conv_3)
if params['use_batchnorm']:
conv_4 = BatchNormalization()(conv_4)
# Concatenate LSTM and Conv Encoder outputs for Decoder LSTM layer
encoder_output = Concatenate(axis = -1)([output_lstm, conv_2])
decoder_lstm = LSTM(params['decoder_dense_units'], return_sequences = True)(encoder_output)
decoder_output = TimeDistributed(
Dense(units = 1,
activation = params['decoder_output_activation'],
kernel_initializer = params['decoder_dense_initializer']))(decoder_lstm)
seq2seq = Model(inputs = [encoder_input], outputs = [decoder_output])
return seq2seq
def build_discriminator(params):
'''
Discriminator is based on the Vanilla seq2seq Encoder. The Decoder is removed
and a Dense layer is left instead to perform binary classification.
'''
from tensorflow.keras.models import Model
from tensorflow.keras.layers import (
Input, LSTM, RepeatVector, Conv1D, BatchNormalization,
Concatenate, Flatten, TimeDistributed, Dense
)
## ENCODER
encoder_input = Input((None, 17))
# LSTM block
encoder_lstm = LSTM(units = params['encoder_lstm_units'])(encoder_input)
output_lstm = RepeatVector(params['len_input'])(encoder_lstm)
# Conv block
conv_1 = Conv1D(
filters = params['conv_filters'],
kernel_size = params['kernel_size'],
activation = params['conv_activation'],
kernel_initializer = params['conv_initializer'],
padding = 'same')(encoder_input)
if params['use_batchnorm']:
conv_1 = BatchNormalization()(conv_1)
conv_2 = Conv1D(
filters = params['conv_filters'],
kernel_size = params['kernel_size'],
activation = params['conv_activation'],
kernel_initializer = params['conv_initializer'],
padding = 'same')(conv_1)
if params['use_batchnorm']:
conv_2 = BatchNormalization()(conv_2)
# Concatenate LSTM and Conv Encoder outputs and Flatten for Decoder LSTM layer
encoder_output = Concatenate(axis = -1)([output_lstm, conv_2])
encoder_output = Flatten()(encoder_output)
# Final layer for binary classification (real/fake)
discriminator_output = Dense(
units = 1,
activation = 'sigmoid',
kernel_initializer = params['decoder_dense_initializer'])(encoder_output)
Discriminator = Model(inputs = [encoder_input], outputs = [discriminator_output])
return Discriminator
def build_GAN(params):
'''
This is just a wrapper in case the model is trained as a GAN. It calls the vanilla
seq2seq Generator, and build_discriminator() for the Discriminator model.
'''
generator = build_vanilla_seq2seq(params)
discriminator = build_discriminator(params)
return generator, discriminator