Kaggle competition: COVID19 Global Forecasting (Week 4)
<SOS> metric: MCRMSLE Kaggle data source: covid19-global-forecasting-(week-4)<import_modules>
week = 4
import math
import re
import numpy as np
import pandas as pd
from gensim.models import KeyedVectors
from keras.models import Sequential, Model
from keras.layers import Dense, CuDNNGRU, Dropout, Embedding, SpatialDropout1D, GlobalAveragePooling1D, Bidirectional
from keras.layers import GlobalMaxPooling1D, CuDNNLSTM, Input, concatenate, Lambda, CuDNNLSTM
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.callbacks import Callback
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score, precision_score, recall_score<define_variables>
import numpy as np
import pandas as pd
import datetime
import os
import matplotlib.pyplot as plt
num_features = 300
num_steps = 120
num_steps_lstm = num_steps // 2
batch_size = 512
val_size = 0<load_from_csv>
train = pd.read_csv(f"/kaggle/input/covid19-global-forecasting-week-{week}/train.csv")
 train.loc[:, "geo"] = np.where(train.loc[:, "Province_State"].isna() , train.loc[:, "Country_Region"], train.loc[:, "Country_Region"] + "_" + train.loc[:, "Province_State"])
 train.loc[:, 'Date'] = pd.to_datetime(train.loc[:, 'Date'])
 train = train.loc[train.loc[:, 'Date'] > '2020-02-20', :]
train_last_date = train.Date.unique() [-1]
print(f"Dataset has training data untill : {str(train_last_date)[:10]}")
 print(f"Training dates: {len(train.Date.unique())}" )
def load_csv() :
train_df = pd.read_csv(".. /input/train.csv")
 train_df, val_df = train_test_split(train_df, test_size=val_size)
 test_df = pd.read_csv(".. /input/test.csv")
 print("Train size: %d, Validation size: %d, Test size: %d" %(len(train_df), len(val_df), len(test_df)))
 return train_df, val_df, test_df<define_variables>
all_countries = train.groupby(['Date'] ).agg({'ConfirmedCases': np.sum} ).reset_index()
all_countries['sh'] = train.groupby(['Date'] ).agg({'ConfirmedCases': np.sum} ).reset_index().shift(1)['ConfirmedCases']
all_countries['sh'] =(all_countries['ConfirmedCases'] / all_countries['sh'])- 1
all_countries = all_countries.set_index("Date")
 all_countries['sh'].plot()
def pre_process_data(data_set_name, sentences):
replaced_sentences = []
if len(sentences)> 0:
non_word_re = re.compile('([^a-zA-Z])')
 replaced_sentences = [non_word_re.sub(r' \1 ', s)for s in sentences]
print("%s processed(%d lines)" %(data_set_name, len(sentences)))
 return replaced_sentences<load_from_csv>
train_old = train.loc[train.loc[:, 'Date'] > '2020-04-01', :]
def load_data() :
train_df, val_df, test_df = load_csv()
X_train = pre_process_data("train question_text", train_df.question_text)
 X_val = pre_process_data("validation question_text", val_df.question_text)
 X_test = pre_process_data("test question_text", test_df.question_text)
 tokenizer = Tokenizer(filters='', lower=False)
 tokenizer.fit_on_texts(X_train)
 tokenizer.fit_on_texts(X_val)
 tokenizer.fit_on_texts(X_test)
 X_train = tokenizer.texts_to_sequences(X_train)
 X_val = tokenizer.texts_to_sequences(X_val)
 X_test = tokenizer.texts_to_sequences(X_test)
 X_train = pad_sequences(X_train, maxlen=num_steps, padding='post')
 X_val = pad_sequences(X_val, maxlen=num_steps, padding='post')
 X_test = pad_sequences(X_test, maxlen=num_steps, padding='post')
 print("words to sequences mapped")
 return X_train, train_df.target.values, X_val, val_df.target.values, test_df.qid.values, X_test, tokenizer.word_index<split>
test = pd.read_csv(f"/kaggle/input/covid19-global-forecasting-week-{week}/test.csv")
 test.loc[:, 'Date'] = pd.to_datetime(test.loc[:, 'Date'])
 test_first_date = test.loc[:, 'Date'].values[0]
test_last_date = test.loc[:, 'Date'].values[-1]
print(f'Test period from {str(test_first_date)[:10]} to {str(test_last_date)[:10]}' )
X_train, y_train, X_val, y_val, test_qids, X_test, word_index = load_data()<compute_test_metric>
period =(np.array(test_last_date, dtype='datetime64[D]' ).astype(np.int64)- np.array(train_last_date, dtype='datetime64[D]' ).astype(np.int64))
def get_coefs(word, *arr):
return word, np.asarray(arr, dtype='float32' )<load_pretrained>
print(f"Prediction days: {(np.array(test_last_date, dtype='datetime64[D]' ).astype(np.int64)- np.array(train_last_date, dtype='datetime64[D]' ).astype(np.int64)) +1}")
 print(f"Public set: {(np.array(train_last_date, dtype='datetime64[D]' ).astype(np.int64)- np.array(test_first_date, dtype='datetime64[D]' ).astype(np.int64)) +1}")
 print(f"Full prediction set: {(np.array(test_last_date, dtype='datetime64[D]' ).astype(np.int64)- np.array(test_first_date, dtype='datetime64[D]' ).astype(np.int64)) +1}" )
def load_glove() :
path = '.. /input/embeddings/glove.840B.300d/glove.840B.300d.txt'
glove = dict(get_coefs(*o.split(" ")) for o in open(path)if len(o)> 100)
 print("glove loaded")
 return glove<feature_engineering>
win = 32
hor = 2
def get_word_vec(word, vocab):
if word in vocab:
return vocab[word]
wl = word.lower()
if wl in vocab:
return vocab[wl]
wu = word.upper()
if wu in vocab:
return vocab[wu]
vec = np.zeros(num_features)
 i = word_index[word]
j = 0
while i > 0:
vec[j] =(i % 1000)/ 1000
j = j + 1
i = i // 1000
return vec<feature_engineering>
train.loc[:, 'ConfirmedCases'] = train.loc[:, 'ConfirmedCases'] - train.groupby('geo')['ConfirmedCases'].shift(periods=1)
 train.loc[:, 'Fatalities'] = train.loc[:, 'Fatalities'] - train.groupby('geo')['Fatalities'].shift(periods=1)
 train = train.groupby('geo' ).tail(train.groupby('geo' ).size().values[0]-1)
 train.loc[train.loc[:, 'ConfirmedCases'] < 0, 'ConfirmedCases'] = 0.0
train.loc[train.loc[:, 'Fatalities'] < 0, 'Fatalities'] = 0.0
train
def build_embedding_matrix(load_vocab_func):
vocab = load_vocab_func()
unk_dict = dict()
embedding_matrix = np.zeros(( len(word_index)+ 1, num_features))
for word, i in word_index.items() :
embedding_matrix[i] = get_word_vec(word, vocab)
 print("embedding weight matrix built")
 return embedding_matrix<choose_model_class>
train.Country_Region.value_counts()
embedding_matrix = build_embedding_matrix(load_glove )<compute_test_metric>
%%bash
pip install pytorch_lightning
def calculate_f1(y_true, y_pred, threshold):
y_pred_int =(y_pred > threshold ).astype(int)
 s = np.sum(y_pred_int)
 rate = s / len(y_pred_int)
 if(s == 0 or s == len(y_pred_int)) :
return 0.0, y_pred_int, rate
f1 = f1_score(y_true, y_pred_int)
 return f1, y_pred_int, rate<compute_test_metric>
import torch.nn as nn
import torch
import torch.nn.functional as F
import pytorch_lightning as ptl
from torch import optim
from torch.utils.data import DataLoader
from collections import OrderedDict
def f1_matrics(y_true, y_pred):
t_max, rate_max, f1_max, p, r = 0.0, 0.0, 0.0, 0.0, 0.0
for i in range(200, 500, 5):
t = i * 0.001
f1, y_pred_int, rate = calculate_f1(y_true, y_pred, t)
 if(f1 > f1_max):
f1_max, y_int_max, rate_max, t_max = f1, y_pred_int, rate, t
if f1_max > 0.0:
p = precision_score(y_true, y_int_max)
 r = recall_score(y_true, y_int_max)
 print("[Threshold: %.6f, Rate: %.6f, F1_Score: %.6f, Precision: %.6f, Recall: %.6f]
" %(t_max, rate_max, f1_max, p, r))<predict_on_test>
def rmsle(predict, target):
return torch.sqrt(((torch.log(predict + 1)- torch.log(target + 1)) **2 ).mean() )
class F1Evaluation(Callback):
def __init__(self, X, y_true):
super(Callback, self ).__init__()
self.X = X
self.y_true = y_true
def on_epoch_end(self, epoch, logs={}):
if(len(self.X)> 0):
y_preds = self.model.predict(self.X)
 for y in y_preds:
f1_matrics(self.y_true, y )<define_search_model>
class MTSFDataset(torch.utils.data.Dataset):
def __init__(self, window, horizon, set_type, tra, validation):
assert type(set_type)== type('str')
 self.window = window
self.horizon = horizon
self.tra = tra
self.validation = validation
self.set_type = set_type
if set_type == 'train':
rawdata = tra
elif set_type == 'validation':
rawdata = validation
_, self.len, self.var_num = rawdata.shape
self.sample_num = max(self.len - self.window - self.horizon + 1, 0)
 self.samples, self.labels = self.__getsamples(rawdata)
 def __getsamples(self, data):
x, y = [], []
for j in range(len(data)) :
X = torch.zeros(( self.sample_num, self.window, self.var_num))
Y = torch.zeros(( self.sample_num, 1, self.var_num))
for i in range(self.sample_num):
start = i
end = i + self.window
X[i, :, :] = torch.from_numpy(data[j, start:end, :])
 Y[i, :, :] = torch.from_numpy(data[j, end+self.horizon-1, :])
 x.append(X)
 y.append(Y)
 return(torch.cat(x), torch.cat(y))
def __len__(self):
return self.sample_num
def __getitem__(self, idx):
sample = [self.samples[idx, :, :], self.labels[idx, :, :]]
return sample
def build_model_branch(x, gru=True):
if gru:
rnn = Bidirectional(CuDNNGRU(200, return_sequences=True))(x)
 else:
rnn = Bidirectional(CuDNNLSTM(200, return_sequences=True))(x)
 part = 2
cells = []
for i in range(part):
rnn_p = Lambda(lambda x: x[:,i::part,:] )(rnn)
 avg = GlobalAveragePooling1D()(rnn_p)
 drp = Dropout(0.3 )(avg)
 den = Dense(16, activation='relu' )(drp)
 cells.append(den)
 x = concatenate(cells)
 x = Dropout(0.3 )(x)
 return Dense(1, activation='sigmoid' )(x )<choose_model_class>
class ScaledDotProductAttention(nn.Module):
def __init__(self, temperature, attn_dropout=0.1):
super().__init__()
self.temperature = temperature
self.dropout = nn.Dropout(attn_dropout)
 self.softmax = nn.Softmax(dim=2)
 def forward(self, q, k, v):
attn = torch.bmm(q, k.transpose(1, 2))
attn = attn / self.temperature
attn = self.softmax(attn)
 attn = self.dropout(attn)
 output = torch.bmm(attn, v)
 return output, attn
class MultiHeadAttention(nn.Module):
def __init__(self, n_head, d_model, d_k, d_v, dropout=0.1):
super().__init__()
self.n_head = n_head
self.d_k = d_k
self.d_v = d_v
self.w_qs = nn.Linear(d_model, n_head * d_k)
 self.w_ks = nn.Linear(d_model, n_head * d_k)
 self.w_vs = nn.Linear(d_model, n_head * d_v)
 nn.init.normal_(self.w_qs.weight, mean=0, std=np.sqrt(2.0 /(d_model + d_k)))
 nn.init.normal_(self.w_ks.weight, mean=0, std=np.sqrt(2.0 /(d_model + d_k)))
 nn.init.normal_(self.w_vs.weight, mean=0, std=np.sqrt(2.0 /(d_model + d_v)))
 self.attention = ScaledDotProductAttention(temperature=np.power(d_k, 0.5))
self.layer_norm = nn.LayerNorm(d_model)
 self.fc = nn.Linear(n_head * d_v, d_model)
 nn.init.xavier_normal_(self.fc.weight)
 self.dropout = nn.Dropout(dropout)
 def forward(self, q, k, v):
d_k, d_v, n_head = self.d_k, self.d_v, self.n_head
sz_b, len_q, _ = q.size()
sz_b, len_k, _ = k.size()
sz_b, len_v, _ = v.size()
residual = q
q = self.w_qs(q ).view(sz_b, len_q, n_head, d_k)
 k = self.w_ks(k ).view(sz_b, len_k, n_head, d_k)
 v = self.w_vs(v ).view(sz_b, len_v, n_head, d_v)
 q = q.permute(2, 0, 1, 3 ).contiguous().view(-1, len_q, d_k)
 k = k.permute(2, 0, 1, 3 ).contiguous().view(-1, len_k, d_k)
 v = v.permute(2, 0, 1, 3 ).contiguous().view(-1, len_v, d_v)
 output, attn = self.attention(q, k, v)
 output = output.view(n_head, sz_b, len_q, d_v)
 output = output.permute(1, 2, 0, 3 ).contiguous().view(sz_b, len_q, -1)
 output = self.dropout(self.fc(output))
output = self.layer_norm(output + residual)
 return output, attn
class PositionwiseFeedForward(nn.Module):
def __init__(self, d_in, d_hid, dropout=0.1):
super().__init__()
self.w_1 = nn.Conv1d(d_in, d_hid, 1)
 self.w_2 = nn.Conv1d(d_hid, d_in, 1)
 self.layer_norm = nn.LayerNorm(d_in)
 self.dropout = nn.Dropout(dropout)
 def forward(self, x):
residual = x
output = x.transpose(1, 2)
 output = self.w_2(F.relu(self.w_1(output)))
 output = output.transpose(1, 2)
 output = self.dropout(output)
 output = self.layer_norm(output + residual)
 return output
class EncoderLayer(nn.Module):
def __init__(self, d_model, d_inner, n_head, d_k, d_v, dropout=0.1):
super(EncoderLayer, self ).__init__()
self.slf_attn = MultiHeadAttention(
 n_head, d_model, d_k, d_v, dropout=dropout)
 self.pos_ffn = PositionwiseFeedForward(d_model, d_inner, dropout=dropout)
 def forward(self, enc_input):
enc_output, enc_slf_attn = self.slf_attn(
 enc_input, enc_input, enc_input)
 enc_output = self.pos_ffn(enc_output)
 return enc_output, enc_slf_attn
class DecoderLayer(nn.Module):
def __init__(self, d_model, d_inner, n_head, d_k, d_v, dropout=0.1):
super(DecoderLayer, self ).__init__()
self.slf_attn = MultiHeadAttention(n_head, d_model, d_k, d_v, dropout=dropout)
 self.enc_attn = MultiHeadAttention(n_head, d_model, d_k, d_v, dropout=dropout)
 self.pos_ffn = PositionwiseFeedForward(d_model, d_inner, dropout=dropout)
 def forward(self, dec_input, enc_output, non_pad_mask=None, slf_attn_mask=None, dec_enc_attn_mask=None):
dec_output, dec_slf_attn = self.slf_attn(
 dec_input, dec_input, dec_input, mask=slf_attn_mask)
 dec_output, dec_enc_attn = self.enc_attn(
 dec_output, enc_output, enc_output, mask=dec_enc_attn_mask)
 dec_output = self.pos_ffn(dec_output)
 return dec_output, dec_slf_attn, dec_enc_attn
class Single_Global_SelfAttn_Module(nn.Module):
def __init__(
 self,
window, n_multiv, n_kernels, w_kernel,
d_k, d_v, d_model, d_inner,
n_layers, n_head, drop_prob=0.1):

 super(Single_Global_SelfAttn_Module, self ).__init__()
self.window = window
self.w_kernel = w_kernel
self.n_multiv = n_multiv
self.d_model = d_model
self.drop_prob = drop_prob
self.conv2 = nn.Conv2d(1, n_kernels,(window, w_kernel))
self.in_linear = nn.Linear(n_kernels, d_model)
 self.out_linear = nn.Linear(d_model, n_kernels)
 self.layer_stack = nn.ModuleList([
EncoderLayer(d_model, d_inner, n_head, d_k, d_v, dropout=drop_prob)
 for _ in range(n_layers)])
 def forward(self, x, return_attns=False):
x = x.view(-1, self.w_kernel, self.window, self.n_multiv)
 x2 = F.relu(self.conv2(x))
x2 = nn.Dropout(p=self.drop_prob )(x2)
 x = torch.squeeze(x2, 2)
 x = torch.transpose(x, 1, 2)
 src_seq = self.in_linear(x)
 enc_slf_attn_list = []
enc_output = src_seq
for enc_layer in self.layer_stack:
enc_output, enc_slf_attn = enc_layer(enc_output)
 if return_attns:
enc_slf_attn_list += [enc_slf_attn]
if return_attns:
return enc_output, enc_slf_attn_list
enc_output = self.out_linear(enc_output)
 return enc_output,
class Single_Local_SelfAttn_Module(nn.Module):
def __init__(
 self,
window, local, n_multiv, n_kernels, w_kernel,
d_k, d_v, d_model, d_inner,
n_layers, n_head, drop_prob=0.1):

 super(Single_Local_SelfAttn_Module, self ).__init__()
self.window = window
self.w_kernel = w_kernel
self.n_multiv = n_multiv
self.d_model = d_model
self.drop_prob = drop_prob
self.conv1 = nn.Conv2d(1, n_kernels,(local, w_kernel))
self.pooling1 = nn.AdaptiveMaxPool2d(( 1, n_multiv))
self.in_linear = nn.Linear(n_kernels, d_model)
 self.out_linear = nn.Linear(d_model, n_kernels)
 self.layer_stack = nn.ModuleList([
EncoderLayer(d_model, d_inner, n_head, d_k, d_v, dropout=drop_prob)
 for _ in range(n_layers)])
 def forward(self, x, return_attns=False):
x = x.view(-1, self.w_kernel, self.window, self.n_multiv)
 x1 = F.relu(self.conv1(x))
x1 = self.pooling1(x1)
 x1 = nn.Dropout(p=self.drop_prob )(x1)
 x = torch.squeeze(x1, 2)
 x = torch.transpose(x, 1, 2)
 src_seq = self.in_linear(x)
 enc_slf_attn_list = []
enc_output = src_seq
for enc_layer in self.layer_stack:
enc_output, enc_slf_attn = enc_layer(enc_output)
 if return_attns:
enc_slf_attn_list += [enc_slf_attn]
if return_attns:
return enc_output, enc_slf_attn_list
enc_output = self.out_linear(enc_output)
 return enc_output,
class AR(nn.Module):
def __init__(self, window):
super(AR, self ).__init__()
self.linear = nn.Linear(window, 1)
 def forward(self, x):
x = torch.transpose(x, 1, 2)
 x = self.linear(x)
 x = torch.transpose(x, 1, 2)
 return x
class DSANet(ptl.LightningModule):
def __init__(self, tra, validation, n_multiv, batch_size=16, window=64, local=3, n_kernels=32,
drop_prob=0.1, criterion='rmsle_loss', learning_rate=0.005, horizon=14):
super(DSANet, self ).__init__()
self.batch_size = batch_size
self.window = window
self.local = local
self.n_multiv = n_multiv
self.n_kernels = n_kernels
self.w_kernel = 1
self.d_model = 512
self.d_inner = 2048
self.n_layers = 6
self.n_head = 8
self.d_k = 64
self.d_v = 64
self.drop_prob = drop_prob
self.criterion = criterion
self.learning_rate = learning_rate
self.horizon = horizon
self.tra = tra
self.validation = validation
self.__build_model()
def __build_model(self):
self.sgsf = Single_Global_SelfAttn_Module(
 window=self.window, n_multiv=self.n_multiv, n_kernels=self.n_kernels,
w_kernel=self.w_kernel, d_k=self.d_k, d_v=self.d_v, d_model=self.d_model,
d_inner=self.d_inner, n_layers=self.n_layers, n_head=self.n_head, drop_prob=self.drop_prob)
 self.slsf = Single_Local_SelfAttn_Module(
 window=self.window, local=self.local, n_multiv=self.n_multiv, n_kernels=self.n_kernels,
w_kernel=self.w_kernel, d_k=self.d_k, d_v=self.d_v, d_model=self.d_model,
d_inner=self.d_inner, n_layers=self.n_layers, n_head=self.n_head, drop_prob=self.drop_prob)
 self.ar = AR(window=self.window)
 self.W_output1 = nn.Linear(2 * self.n_kernels, 1)
 self.dropout = nn.Dropout(p=self.drop_prob)
 self.active_func = nn.Tanh()
def forward(self, x):
sgsf_output, *_ = self.sgsf(x)
 slsf_output, *_ = self.slsf(x)
 sf_output = torch.cat(( sgsf_output, slsf_output), 2)
 sf_output = self.dropout(sf_output)
 sf_output = self.W_output1(sf_output)
 sf_output = torch.transpose(sf_output, 1, 2)
 ar_output = self.ar(x)
 output = sf_output + ar_output
output[output < 0] = 0.0
return output
def loss(self, labels, predictions):
if self.criterion == 'l1_loss':
loss = F.l1_loss(predictions, labels)
 elif self.criterion == 'mse_loss':
loss = F.mse_loss(predictions, labels)
 elif self.criterion == 'rmsle_loss':
loss = rmsle(predictions, labels)
 return loss
def training_step(self, data_batch, batch_i):
x, y = data_batch
y_hat = self.forward(x)
 loss_val = self.loss(y, y_hat)
 if self.trainer.use_dp:
loss_val = loss_val.unsqueeze(0)
 output = OrderedDict({
'loss': loss_val
})
 return output
def validation_step(self, data_batch, batch_i):
x, y = data_batch
y_hat = self.forward(x)
 loss_val = self.loss(y, y_hat)
 if self.trainer.use_dp:
loss_val = loss_val.unsqueeze(0)
 output = OrderedDict({
'val_loss': loss_val,
'y': y,
'y_hat': y_hat,
})
 return output
def validation_epoch_end(self, outputs):
loss_sum = 0
for x in outputs:
loss_sum += x['val_loss'].item()
val_loss_mean = loss_sum / len(outputs)
 y = torch.cat(( [x['y'] for x in outputs]), 0)
 y_hat = torch.cat(( [x['y_hat'] for x in outputs]), 0)
 num_var = y.size(-1)
 y = y.view(-1, num_var)
 y_hat = y_hat.view(-1, num_var)
 sample_num = y.size(0)
 y_diff = y_hat - y
y_mean = torch.mean(y)
 y_translation = y - y_mean
val_rrse = torch.sqrt(torch.sum(torch.pow(y_diff, 2)))/ torch.sqrt(torch.sum(torch.pow(y_translation, 2)))
 y_m = torch.mean(y, 0, True)
 y_hat_m = torch.mean(y_hat, 0, True)
 y_d = y - y_m
y_hat_d = y_hat - y_hat_m
corr_top = torch.sum(y_d * y_hat_d, 0)
 corr_bottom = torch.sqrt(( torch.sum(torch.pow(y_d, 2), 0)* torch.sum(torch.pow(y_hat_d, 2), 0)))
 corr_inter = corr_top / corr_bottom
val_corr =(1./ num_var)* torch.sum(corr_inter)
 val_mae =(1./(sample_num * num_var)) * torch.sum(torch.abs(y_diff))
tqdm_dic = {
'val_loss': val_loss_mean,
'RRSE': val_rrse.item() ,
'CORR': val_corr.item() ,
'MAE': val_mae.item()
}
return tqdm_dic
def configure_optimizers(self):
optimizer = optim.Adam(self.parameters() , lr=self.learning_rate)
 scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10)
 return [optimizer], [scheduler]
def __dataloader(self, train):
set_type = train
dataset = MTSFDataset(window=self.window, horizon=self.horizon,
set_type=set_type,
tra=self.tra, validation=self.validation)
 train_sampler = None
batch_size = self.batch_size
should_shuffle = train_sampler is None
loader = DataLoader(
 dataset=dataset,
batch_size=batch_size,
shuffle=should_shuffle,
sampler=train_sampler,
num_workers=4 
)
 return loader
@ptl.data_loader
def train_dataloader(self):
return self.__dataloader(train='train')
 @ptl.data_loader
def val_dataloader(self):
return self.__dataloader(train='validation' )
def build_model() :
inp = Input(shape=(num_steps,))
emb = Embedding(len(embedding_matrix), num_features, weights=[embedding_matrix], trainable=False )(inp)
 emb = SpatialDropout1D(0.3 )(emb)
 y = build_model_branch(emb)
 x = Lambda(lambda x: x[:, :num_steps_lstm, :] )(emb)
 z = build_model_branch(x, gru=False)
 x = concatenate([y, z])
 x = Dense(8, activation='relu' )(x)
 x = Dense(1, activation='sigmoid' )(x)
 mdl = Model(inputs=inp, outputs=[x, y, z])
 mdl.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
 mdl.summary()
return mdl<choose_model_class>
model_cases = DSANet(np.array([train_fatal, train_cases]), np.array([valid_fatal, valid_cases]), train_cases.shape[1], window=win,
learning_rate=0.01, horizon=hor, drop_prob=0.5, batch_size=128)
 trainer = ptl.Trainer(val_check_interval=1, max_steps=5000, gpus=1, show_progress_bar=False)
 trainer.fit(model_cases )
model = build_model()<train_model>
pred_size =(np.array(test_last_date, dtype='datetime64[D]' ).astype(np.int64)- np.array(test_first_date, dtype='datetime64[D]' ).astype(np.int64)) +1
f1_evl = F1Evaluation(X_val, y_val)
 model.fit(X_train, [y_train] * 3, batch_size=batch_size, epochs=6, callbacks=[f1_evl] )<predict_on_test>
sub = pd.read_csv("/kaggle/input/covid-sberbank/sample_submission.csv")
 sub
def get_pred_int(y_pred):
y = y_pred.reshape(-1)
 n_pos = math.floor(len(y)* 0.07)
 ind_pred = np.argsort(y)[-n_pos:]
y_int = np.zeros(y_pred.shape, dtype=int)
 y_int.flat[ind_pred] = 1
return y_int, y[ind_pred[0]]<predict_on_test>
sub.country.value_counts().sort_values()
y_preds = model.predict(X_test, batch_size=1024, verbose=0 )<save_to_csv>
sub = pd.read_csv(f"/kaggle/input/covid19-global-forecasting-week-{week}/submission.csv")
 sub = test.merge(res, how='left', on=['Date', 'Province_State', 'Country_Region'] ).loc[:, ["ForecastId", "ConfirmedCases", "Fatalities"]]
sub['Fatalities'] = np.array(sub['Fatalities'], dtype=np.int)
 sub["ConfirmedCases"] = np.array(sub["ConfirmedCases"], dtype=np.int)
 sub
<load_pretrained><EOS> 
sub.to_csv("submission.csv", index=False )