Kaggle competition: COVID19 Global Forecasting (Week 1)
<SOS> metric: MCRMSLE Kaggle data source: covid19-global-forecasting-(week-1)<find_best_score>
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.core.display import display, HTML
import plotly.graph_objects as go
import warnings
import datetime
import math
from scipy.optimize import minimize
print(svc_gs.best_score_ )<train_on_grid>
pd.set_option('display.max_columns', None)
 pd.set_option('display.max_rows', 500)
 pd.set_option('display.expand_frame_repr', False)
 display(HTML("<style>div.output_scroll { height: 35em; }</style>"))
%matplotlib inline
%config InlineBackend.figure_format ='retina'
warnings.filterwarnings('ignore' )
lgb_model = LGBMClassifier()
test_parameters = {
"n_estimators": [int(x)for x in np.linspace(5, 30, 6)],
"reg_alpha": [0, 0.75, 1, 1.25],
"learning_rate": [0.5, 0.4, 0.35, 0.3, 0.25, 0.2],
"subsample": [0.5, 0.75, 1]
}
lgb_gs = GridSearchCV(lgb_model, test_parameters, scoring="accuracy", cv=8, n_jobs=4)
 lgb_gs.fit(train, y_train )<find_best_score>
days_forecast = 40
print(lgb_gs.best_score_ )<choose_model_class>
conf_df = pd.read_csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv')
 deaths_df = pd.read_csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Deaths.csv')
 recv_df = pd.read_csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Recovered.csv' )
ensemble_model = VotingClassifier(estimators=[ 
("logit", logit_gs.best_estimator_), 
("rf", rf_gs.best_estimator_), 
("svc", svc_gs.best_estimator_), 
("lgb", lgb_gs.best_estimator_),
], voting = "hard" )<train_model>
full_table = full_table[full_table['Province/State'].str.contains(',')!=True]
ensemble_model.fit(train, y_train )<compute_test_metric>
cases = ['Confirmed', 'Deaths', 'Recovered', 'Active']
full_table['Active'] = full_table['Confirmed'] - full_table['Deaths'] - full_table['Recovered']
full_table['Country/Region'] = full_table['Country/Region'].replace('Mainland China', 'China')
 full_table[['Province/State']] = full_table[['Province/State']].fillna('' )
ensemble_model.score(train, y_train )<choose_model_class>
df = full_table.groupby(['Country/Region', 'Province/State'])['Confirmed', 'Deaths', 'Recovered', 'Active'].max()
df = full_table.groupby('Date')['Confirmed', 'Deaths', 'Recovered', 'Active'].sum().reset_index()
df = df[df['Date']==max(df['Date'])].reset_index(drop=True)
 df
classifier = Sequential()
classifier.add(Dense(activation="relu", input_dim=6, units=11, kernel_initializer="uniform"))
classifier.add(Dense(activation="relu", units=11, kernel_initializer="uniform"))
classifier.add(Dropout(0.5))
classifier.add(Dense(activation="relu", units=11, kernel_initializer="uniform"))
classifier.add(Dropout(0.5))
classifier.add(Dense(activation="relu", units=5, kernel_initializer="uniform"))
classifier.add(Dense(activation="sigmoid", units=1, kernel_initializer="uniform"))
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
 classifier.summary()<define_variables>
df_model_select = full_table.groupby(['Country/Region','Province/State'] ).last().reset_index()
df_model_select = df_model_select[['Country/Region','Province/State','Confirmed']]
df_model_select['Offset error'] = 100
df_model_select['No Offset error'] = 100
features = train[['Pclass', 'Sex', 'Age', 'Fare', 'Embarked', 'FamSize']].values 
<train_model>
countries = list(set(full_table['Country/Region']))
countries.sort()
for country in countries:
clusters = list(set(full_table['Province/State'][(full_table['Country/Region'] == country)]))
clusters.sort()
for cluster in clusters:
print(' ')
 print('-----------------')
 print(country + ' - ' + cluster)
 df = full_table[(full_table['Country/Region'] == country)&(full_table['Province/State'] == cluster)]
df = df.groupby(['Date','Country/Region'] ).sum().reset_index()
df['Date'] = pd.to_datetime(df['Date'])
 df = df.sort_values(by=['Date'])
 df = df.set_index('Date')[['Confirmed']]
df.drop(df.tail(3 ).index,inplace=True)
 df_result = df.copy()
def model(N, a, alpha, t0, t):
return N *(1 - math.e **(-a *(t-t0)))** alpha
def model_loss(params):
N, a, alpha, t0 = params
global df
r = 0
for t in range(len(df)) :
r +=(model(N, a, alpha, t0, t)- df.iloc[t, 0])** 2
return r
try:
N = df['Confirmed'][-1]
T = -df['Confirmed'][0]
except:
N = 10000
T = 0
opt = minimize(model_loss, x0=np.array([N, 0.1, 5, T]), method='Nelder-Mead', tol=1e-7 ).x
print('Offset' + str(opt))
x_actual = pd.to_datetime(df.reset_index().iloc[:,0])
 x_actual =list(x_actual)
 y_actual = list(df.reset_index().iloc[:,1])
 start_date = pd.to_datetime(df.index[0])
 x_model = []
y_model = []
for t in range(len(df)+ days_forecast):
x_model.append(start_date + datetime.timedelta(days=t))
y_model.append(round(model(*opt,t)))
 df2 = pd.DataFrame(y_model,index=x_model,columns=['Offset'])
 df2.index.name = 'Date'
df_result = pd.merge(df_result,
df2,
how='outer',
left_on=['Date'],
right_on=['Date'])
 def model(N, a, alpha, t):
return N *(1 - math.e **(-a *(t)))** alpha
def model_loss(params):
N, a, alpha = params
global df
r = 0
for t in range(len(df)) :
r +=(model(N, a, alpha, t)- df.iloc[t, 0])** 2
return r
try:
N = df['Confirmed'][-1]
except:
N = 10000
opt = minimize(model_loss, x0=np.array([N, 0.1, 5]), method='Nelder-Mead', tol=1e-7 ).x
print('No offset' + str(opt))
try:
start_date = pd.to_datetime(df.index[0])
 x_model = []
y_model = []
for t in range(len(df)+ days_forecast):
x_model.append(start_date + datetime.timedelta(days=t))
y_model.append(round(model(*opt,t)))
 df2 = pd.DataFrame(y_model,index=x_model,columns=['No Offset'])
 df2.index.name = 'Date'
df_result = pd.merge(df_result,
df2,
how='outer',
left_on=['Date'],
right_on=['Date'])
 df_result = df_result[df_result['Confirmed'].notnull() ]
err_offset = 0
err_no_offset = 0
for t in range(len(df_result)) :
err_offset +=(math.log(df_result['Offset'].iloc[t]+1)-math.log(df_result['Confirmed'].iloc[t]+1)) **2
err_no_offset +=(math.log(df_result['No Offset'].iloc[t]+1)-math.log(df_result['Confirmed'].iloc[t]+1)) **2
err_offset = math.sqrt(err_offset/len(df_result))
err_no_offset = math.sqrt(err_no_offset/len(df_result))
df_model_select['Offset error'][(df_model_select['Country/Region']==country)&(df_model_select['Province/State']==cluster)] = err_offset
df_model_select['No Offset error'][(df_model_select['Country/Region']==country)&(df_model_select['Province/State']==cluster)] = err_no_offset
except:
pass
history = classifier.fit(features, target, batch_size = 32, epochs=200, validation_split=0.1,verbose = 1,shuffle=True )<predict_on_test>
df_model_select = full_table.groupby(['Country/Region','Province/State'] ).last().reset_index()
df_model_select = df_model_select[['Country/Region','Province/State','Deaths']]
df_model_select['Offset error'] = 100
df_model_select['No Offset error'] = 100
predictions = ensemble_model.predict(test)
 predictions<save_to_csv>
countries = list(set(full_table['Country/Region']))
countries.sort()
for country in countries:
clusters = list(set(full_table['Province/State'][(full_table['Country/Region'] == country)]))
clusters.sort()
for cluster in clusters:
print(' ')
 print('-----------------')
 print(country + ' - ' + cluster)
 df = full_table[(full_table['Country/Region'] == country)&(full_table['Province/State'] == cluster)]
df = df.groupby(['Date','Country/Region'] ).sum().reset_index()
df['Date'] = pd.to_datetime(df['Date'])
 df = df.sort_values(by=['Date'])
 df = df.set_index('Date')[['Deaths']]
df.drop(df.tail(3 ).index,inplace=True)
 df_result = df.copy()
def model(N, a, alpha, t0, t):
return N *(1 - math.e **(-a *(t-t0)))** alpha
def model_loss(params):
N, a, alpha, t0 = params
global df
r = 0
for t in range(len(df)) :
r +=(model(N, a, alpha, t0, t)- df.iloc[t, 0])** 2
return r
try:
N = df['Deaths'][-1]
T = -df['Deaths'][0]
except:
N = 10000
T = 0
opt = minimize(model_loss, x0=np.array([N, 0.1, 5, T]), method='Nelder-Mead', tol=1e-7 ).x
print('Offset' + str(opt))
x_actual = pd.to_datetime(df.reset_index().iloc[:,0])
 x_actual =list(x_actual)
 y_actual = list(df.reset_index().iloc[:,1])
 start_date = pd.to_datetime(df.index[0])
 x_model = []
y_model = []
for t in range(len(df)+ days_forecast):
x_model.append(start_date + datetime.timedelta(days=t))
y_model.append(round(model(*opt,t)))
 df2 = pd.DataFrame(y_model,index=x_model,columns=['Offset'])
 df2.index.name = 'Date'
df_result = pd.merge(df_result,
df2,
how='outer',
left_on=['Date'],
right_on=['Date'])
 def model(N, a, alpha, t):
return N *(1 - math.e **(-a *(t)))** alpha
def model_loss(params):
N, a, alpha = params
global df
r = 0
for t in range(len(df)) :
r +=(model(N, a, alpha, t)- df.iloc[t, 0])** 2
return r
try:
N = df['Deaths'][-1]
except:
N = 10000
opt = minimize(model_loss, x0=np.array([N, 0.1, 5]), method='Nelder-Mead', tol=1e-7 ).x
print('No offset' + str(opt))
try:
start_date = pd.to_datetime(df.index[0])
 x_model = []
y_model = []
for t in range(len(df)+ days_forecast):
x_model.append(start_date + datetime.timedelta(days=t))
y_model.append(round(model(*opt,t)))
 df2 = pd.DataFrame(y_model,index=x_model,columns=['No Offset'])
 df2.index.name = 'Date'
df_result = pd.merge(df_result,
df2,
how='outer',
left_on=['Date'],
right_on=['Date'])
 df_result = df_result[df_result['Deaths'].notnull() ]
err_offset = 0
err_no_offset = 0
for t in range(len(df_result)) :
err_offset +=(math.log(df_result['Offset'].iloc[t]+1)-math.log(df_result['Deaths'].iloc[t]+1)) **2
err_no_offset +=(math.log(df_result['No Offset'].iloc[t]+1)-math.log(df_result['Deaths'].iloc[t]+1)) **2
err_offset = math.sqrt(err_offset/len(df_result))
err_no_offset = math.sqrt(err_no_offset/len(df_result))
df_model_select['Offset error'][(df_model_select['Country/Region']==country)&(df_model_select['Province/State']==cluster)] = err_offset
df_model_select['No Offset error'][(df_model_select['Country/Region']==country)&(df_model_select['Province/State']==cluster)] = err_no_offset
except:
pass
submission = pd.DataFrame({'PassengerId': original_test.PassengerId,'Survived': predictions})
 submission.to_csv('my_submission.csv', index=False )<import_modules>
df_ca_train = pd.read_csv('.. /input/covid19-global-forecasting-week-1/train.csv')
 df_ca_test = pd.read_csv('.. /input/covid19-global-forecasting-week-1/test.csv')
 df_ca_submission = pd.read_csv('.. /input/covid19-global-forecasting-week-1/submission.csv' )
import os
import sys
from operator import itemgetter
import numpy as np
import pandas as pd
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt<set_options>
full_table = df_ca_train
full_table[['Province/State']] = full_table[['Province/State']].fillna('')
 df_comp = df_ca_test
df_comp[['Province/State']] = df_comp[['Province/State']].fillna('')
 df_comp['Date'] = pd.to_datetime(df_comp['Date'])
 df_comp['ConfirmedCases']=0
df_comp['Fatalities']=0
pd.set_option('display.max_columns', 200)
 pd.set_option('display.max_rows', 200)
 pd.plotting.register_matplotlib_converters()
n_jobs = -1
colors = {
'very_light_gray': '
'light_gray': '
'medium_gray': '
'very_dark_gray': '
'orange': '
'light_blue': '
'light_purple': '
'light_green': '
'light_yellow': '
'light_red': '
'light_cyan': '
}<load_from_csv>
countries = list(set(full_table['Country/Region']))
countries.sort()
for country in countries:
clusters = list(set(full_table['Province/State'][(full_table['Country/Region'] == country)]))
clusters.sort()
for cluster in clusters:
print(' ')
 print('-----------------')
 print(str(country)+ ' - ' + str(cluster))
df = full_table[(full_table['Country/Region'] == country)&(full_table['Province/State'] == cluster)]
df = df.groupby(['Date','Country/Region'] ).sum().reset_index()
df['Date'] = pd.to_datetime(df['Date'])
 df = df.sort_values(by=['Date'])
 df = df.set_index('Date')[['ConfirmedCases']]
df_result = df.copy()
def model(N, a, alpha, t):
return N *(1 - math.e **(-a *(t)))** alpha
def model_loss(params):
N, a, alpha = params
global df
r = 0
for t in range(len(df)) :
r +=(model(N, a, alpha, t)- df.iloc[t, 0])** 2
return r
try:
N = df['ConfirmedCases'][-1]
except:
N = 10000
opt = minimize(model_loss, x0=np.array([N, 0.1, 5]), method='Nelder-Mead', tol=1e-7 ).x
print(opt)
 x_actual = pd.to_datetime(df.reset_index().iloc[:,0])
 x_actual = list(x_actual)
 y_actual = list(df.reset_index().iloc[:,1])
 start_date = pd.to_datetime(df.index[0])
 days_forecast = len(df)+len(df_ca_test)-7
x_model = []
y_model = []
for t in range(days_forecast):
x_model.append(start_date + datetime.timedelta(days=t))
y_model.append(round(model(*opt,t)))
 df2 = pd.DataFrame(y_model,index=x_model,columns=['ConfirmedCases'])
 df2.index.name = 'Date'
df2['Country/Region']=country
df2['Province/State']=cluster
df_comp = pd.merge(df_comp,
df2,
how='left',
on=['Date','Country/Region','Province/State'] 
)
 df_comp = df_comp.rename(columns={'ConfirmedCases_y': 'ConfirmedCases'})
 df_comp['ConfirmedCases'] = df_comp['ConfirmedCases'].fillna(df_comp['ConfirmedCases_x'])
 df_comp = df_comp[['ForecastId','Province/State','Country/Region','Date','ConfirmedCases','Fatalities']]
train = pd.read_csv('/kaggle/input/covid19-global-forecasting-week-1/train.csv', parse_dates=['Date'])
 test = pd.read_csv('/kaggle/input/covid19-global-forecasting-week-1/test.csv', parse_dates=['Date'])
 print('Original training data')
 train.head()
start_date, cutoff_date, max_date = train['Date'].to_numpy() [0], np.datetime64('2020-03-24'), test['Date'].to_numpy() [-1]
data = train[train['Date'] <= cutoff_date].copy()
validation_data = train[train['Date'] >= cutoff_date].copy()
validation_data['ConfirmedCasesActual'] = validation_data['ConfirmedCases']
validation_data['ConfirmedCases'] = np.NaN
validation_data['FatalitiesActual'] = validation_data['Fatalities']
validation_data['Fatalities'] = np.NaN
dates, validation_dates, test_dates = data['Date'].unique() , validation_data['Date'].unique() , test['Date'].unique()
all_dates = np.unique(np.concatenate(( dates, test_dates)))
 data['ForecastId'] = -1
validation_data['ForecastId'] = -1
test_data = test.copy()
test_data['ConfirmedCases'] = np.NaN
test_data['Fatalities'] = np.NaN<feature_engineering>
countries = list(set(full_table['Country/Region']))
countries.sort()
for country in countries:
clusters = list(set(full_table['Province/State'][(full_table['Country/Region'] == country)]))
clusters.sort()
for cluster in clusters:
print(' ')
 print('-----------------')
 print(str(country)+ ' - ' + str(cluster))
df = full_table[(full_table['Country/Region'] == country)&(full_table['Province/State'] == cluster)]
df = df.groupby(['Date','Country/Region'] ).sum().reset_index()
df['Date'] = pd.to_datetime(df['Date'])
 df = df.sort_values(by=['Date'])
 df = df.set_index('Date')[['Fatalities']]
df_result = df.copy()
def model(N, a, alpha, t):
return N *(1 - math.e **(-a *(t)))** alpha
def model_loss(params):
N, a, alpha = params
global df
r = 0
for t in range(len(df)) :
r +=(model(N, a, alpha, t)- df.iloc[t, 0])** 2
return r
try:
N = df['Fatalities'][-1]
except:
N = 10000
opt = minimize(model_loss, x0=np.array([N, 0.1, 5]), method='Nelder-Mead', tol=1e-7 ).x
print(opt)
 x_actual = pd.to_datetime(df.reset_index().iloc[:,0])
 x_actual = list(x_actual)
 y_actual = list(df.reset_index().iloc[:,1])
 start_date = pd.to_datetime(df.index[0])
 days_forecast = len(df)+len(df_ca_test)-7
x_model = []
y_model = []
for t in range(days_forecast):
x_model.append(start_date + datetime.timedelta(days=t))
y_model.append(round(model(*opt,t)))
 df2 = pd.DataFrame(y_model,index=x_model,columns=['Fatalities'])
 df2.index.name = 'Date'
df2['Country/Region']=country
df2['Province/State']=cluster
df_comp = pd.merge(df_comp,
df2,
how='left',
on=['Date','Country/Region','Province/State'] 
)
 df_comp = df_comp.rename(columns={'Fatalities_y': 'Fatalities'})
 df_comp['Fatalities'] = df_comp['Fatalities'].fillna(df_comp['Fatalities_x'])
 df_comp = df_comp[['ForecastId','Province/State','Country/Region','Date','ConfirmedCases','Fatalities']]
def unique_area_key(row):
if pd.isnull(row['Province/State']): return row['Country/Region']
return f'{row["Country/Region"]} {row["Province/State"]}'
data['unique_area_key'] = data.apply(unique_area_key, axis=1)
 validation_data['unique_area_key'] = validation_data.apply(unique_area_key, axis=1)
 test_data['unique_area_key'] = test_data.apply(unique_area_key, axis=1 )<train_on_grid>
df_comp[df_comp['Fatalities']>0]
def get_counts_for_key(df, key):
return df[df['unique_area_key'] == key][['Date', 'ConfirmedCases', 'Fatalities']]
def rmsle(y, y0):
return np.sqrt(np.mean(np.square(np.log1p(y[-15:])- np.log1p(y0[-15:]))))
def sigmoid(x, A, slope, offset):
return A /(1 + np.exp(( x -(offset + 17.75)) / slope))
def fit_to_sigmoid(dates, actual_counts, all_dates):
max_counts = actual_counts.max() + 1
x =(dates - start_date)/ np.timedelta64(1, 'D')
 p, _ = curve_fit(
 sigmoid,
x,
actual_counts,
p0=[max_counts / 2.0, -5, 10],
bounds=(
 [0, -np.inf, 0],
[max_counts * 10.0, -2.0, 100] 
),
maxfev=5000, 
)
 return(
 sigmoid(( all_dates - start_date)/ np.timedelta64(1, 'D'), *p),
p,
rmsle(sigmoid(( dates - start_date)/ np.timedelta64(1, 'D'), *p), actual_counts)
)
 def exponential(x, A, B, cutoff):
y_1 = A * x[x < cutoff]
y_2 = B *(x[x >= cutoff] - cutoff)+ A * x[x >= cutoff][0]
return np.concatenate(( y_1, y_2))
def fit_to_exponential(dates, actual_counts, all_dates):
x =(dates - start_date)/ np.timedelta64(1, 'D')
 p, _ = curve_fit(
 exponential,
x,
actual_counts,
p0=[0.01, 1, x[1]],
bounds=(
 [0, 0, x[0]],
[np.inf, np.inf, x[-1]] 
),
maxfev=10000, 
)
 return(
 exponential(( all_dates - start_date)/ np.timedelta64(1, 'D'), *p),
p,
rmsle(exponential(( dates - start_date)/ np.timedelta64(1, 'D'), *p), actual_counts)
 )<train_model>
df_ca_test['Date'] = pd.to_datetime(df_ca_test['Date'] )
keys = data['unique_area_key'].unique()
params = {}
for index, key in enumerate(keys):
print(f'Running key {index + 1} of {len(keys)}: {key}')
 counts = get_counts_for_key(data, key)
 try:
confirmed_cases_sigmoid, confirmed_cases_sigmoid_p, confirmed_cases_sigmoid_score = fit_to_sigmoid(counts['Date'], counts['ConfirmedCases'], all_dates)
 except:
print(f'Failed to fit sigmoid on confirmed cases: {sys.exc_info() }')
 confirmed_cases_sigmoid, confirmed_cases_sigmoid_p, confirmed_cases_sigmoid_score = None, None, None
try:
fatalities_sigmoid, fatalities_sigmoid_p, fatalities_sigmoid_score = fit_to_sigmoid(counts['Date'], counts['Fatalities'], all_dates)
 except:
print(f'Failed to fit sigmoid on fatalities: {sys.exc_info() }')
 fatalities_sigmoid, fatalities_sigmoid_p, fatalities_sigmoid_score = None, None, None
try:
confirmed_cases_exp, confirmed_cases_exp_p, confirmed_cases_exp_score = fit_to_exponential(counts['Date'].to_numpy() , counts['ConfirmedCases'], all_dates)
 except:
print(f'Failed to fit exp on confirmed cases: {sys.exc_info() }')
 confirmed_cases_exp, confirmed_cases_exp_p, confirmed_cases_exp_score = None, None, None
try:
fatalities_exp, fatalities_exp_p, fatalities_exp_score = fit_to_exponential(counts['Date'].to_numpy() , counts['Fatalities'], all_dates)
 except:
print(f'Failed to fit exp on fatalities: {sys.exc_info() }')
 fatalities_exp, fatalities_exp_p, fatalities_exp_score = None, None, None
params[key] = {
'confirmed_cases_sigmoid_p': confirmed_cases_sigmoid_p,
'confirmed_cases_sigmoid_score': confirmed_cases_sigmoid_score,
'fatalities_sigmoid_p': fatalities_sigmoid_p,
'fatalities_sigmoid_score': fatalities_sigmoid_score,
'confirmed_cases_exp_p': confirmed_cases_exp_p,
'confirmed_cases_exp_score': confirmed_cases_exp_score,
'fatalities_exp_p': fatalities_exp_p,
'fatalities_exp_score': fatalities_exp_score,
}
validation_counts = get_counts_for_key(validation_data, key)
 fig = plt.figure(figsize=(12, 6))
ax = fig.add_subplot(121)
 if confirmed_cases_sigmoid_score != None:
ax.plot(
 all_dates,
confirmed_cases_sigmoid,
color=colors['light_blue'] if confirmed_cases_exp_score == None or confirmed_cases_exp_score > confirmed_cases_sigmoid_score else colors['light_gray'],
linestyle=':',
label=f'sigmoid {(confirmed_cases_sigmoid_score):.4f}' 
)
 if confirmed_cases_exp_score != None:
ax.plot(
 all_dates,
confirmed_cases_exp,
color=colors['light_blue'] if confirmed_cases_sigmoid_score == None or confirmed_cases_sigmoid_score > confirmed_cases_exp_score else colors['light_gray'],
label=f'exp {(confirmed_cases_exp_score):.4f}' 
)
 ax.plot(
 counts['Date'],
counts['ConfirmedCases'],
color=colors['very_dark_gray'],
marker='.',
linestyle='None' 
)
 ticks = all_dates[::13]
label_from_tick = lambda tick: pd.to_datetime(tick ).strftime('%b %d')
 tick_labels = list(map(label_from_tick, ticks))
plt.xticks(ticks, tick_labels, rotation=20, horizontalalignment='right')
 plt.legend(loc='upper left')
 ax = fig.add_subplot(122)
 if fatalities_sigmoid_score != None:
ax.plot(
 all_dates,
fatalities_sigmoid,
color=colors['light_blue'] if fatalities_exp_score == None or fatalities_exp_score > fatalities_sigmoid_score else colors['light_gray'],
linestyle=':',
label=f'sigmoid {(fatalities_sigmoid_score):.4f}' 
)
 if fatalities_exp_score != None:
ax.plot(
 all_dates,
fatalities_exp,
color=colors['light_blue'] if fatalities_sigmoid_score == None or fatalities_sigmoid_score > fatalities_exp_score else colors['light_gray'],
label=f'exp {(fatalities_exp_score):.4f}' 
)
 ax.plot(
 counts['Date'],
counts['Fatalities'],
color=colors['very_dark_gray'],
marker='.',
linestyle='None' 
)
 ticks = all_dates[::13]
label_from_tick = lambda tick: pd.to_datetime(tick ).strftime('%b %d')
 tick_labels = list(map(label_from_tick, ticks))
plt.xticks(ticks, tick_labels, rotation=20, horizontalalignment='right')
 plt.legend(loc='upper left')
 plt.title(f'{key} results')
 plt.show()<feature_engineering>
df_sub = df_comp[['ForecastId','ConfirmedCases','Fatalities']]
<import_modules><EOS> 
df_sub.to_csv('submission.csv',index=False )