lisphilar / covid19-sir

CovsirPhy: Python library for COVID-19 analysis with phase-dependent SIR-derived ODE models.
https://lisphilar.github.io/covid19-sir/
Apache License 2.0
110 stars 44 forks source link

[Fix] fit_predict() raises TypeError when zeros are used as parameter values #954

Closed baluballa closed 2 years ago

baluballa commented 2 years ago

Summary

cs.Scenario fit_predict returns TypeError: @kappa value must be an instance of <class 'float'>, but <class 'int'> was applied. snl_summary().head():

Scenario    Phase   Type    Start   End Population  ODE Rt  theta   kappa   rho sigma   tau RMSLE   Trials  Runtime
Main    4th Past    04Mar2021   01Jun2021   76974   SIR-F   0.03    0.1100239299822033  0.0 0.0008796448444716329   0.02678424034499663 1440    0.2872550993072971  187.0   0 min  6 sec
Main    5th Past    02Jun2021   29Jun2021   76974   SIR-F   2.82    8.268306793035177e-05   0.0 0.04913668950005093 0.01740660792406505 1440    0.27892669831750116 503.0   0 min 14 sec
Main    6th Past    30Jun2021   22Jul2021   76974   SIR-F   1.75    0.0005104042982707577   0.0 0.04213192094495948 0.02410096122873117 1440    0.16655624199326435 191.0   0 min  6 sec
Main    7th Past    23Jul2021   27Aug2021   76974   SIR-F   1.58    0.0008633703790732846   0.0 0.06978901301376986 0.04426403811170927 1440    0.06933157865606702 123.0   0 min  4 sec
Main    8th Past    28Aug2021   06Sep2021   77095   SIR-F   3.85    0.0004043347725488704   0.0 0.10754997078162233 0.027901537823681242    1440    0.07598065126660718 357.0   0 min 10 sec

As you can see Kappa is zero so I assume type will be int but function requires float.

Codes

snl.fit_predict(name="Forecast").summary(name="Forecast")

import covsirphy as cs
# Dataset preparation
data_loader = cs.DataLoader("datasets",update_interval=24)
data_loader.read_dataframe(LoadDataFramesFromMySQL(place))
# Scenario analysis
is based on local data. 

Outputs

cs.Scenario fit_predict returns TypeError: @kappa value must be an instance of <class 'float'>, but <class 'int'> was applied.

Environment

lisphilar commented 2 years ago

@baluballa , Thank you for your feedback and I have just tried to fix this issue with pull request #955. Integers will be converted to floating values before checking value types. Could you check this change is valid with the latest development version 2.22.1-alpha before 2.22.2 release?

pip install --upgrade "git+https://github.com/lisphilar/covid19-sir.git#egg=covsirphy"
baluballa commented 2 years ago

Seems like I still get the error: Running snl.fit_predict(name="Forecast").summary(name="Forecast") on version '2.22.1-alpha' I get: TypeError: @kappa value must be an instance of <class 'float'>, but <class 'int'> was applied.

snl.summary().info() yelds:

<class 'pandas.core.frame.DataFrame'>
MultiIndex: 31 entries, ('Main', '2nd') to ('Forecast', '10th')
Data columns (total 14 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   Type        31 non-null     object 
 1   Start       31 non-null     object 
 2   End         31 non-null     object 
 3   Population  31 non-null     int64  
 4   ODE         31 non-null     object 
 5   Rt          31 non-null     float64
 6   theta       31 non-null     float64
 7   kappa       31 non-null     float64
 8   rho         31 non-null     float64
 9   sigma       31 non-null     float64
 10  tau         31 non-null     int64  
 11  RMSLE       31 non-null     object 
 12  Trials      31 non-null     object 
 13  Runtime     31 non-null     object 
dtypes: float64(5), int64(2), object(7)
memory usage: 4.1+ KB

So it seems at least in snl.summary() pandas df kappa is float. Complete tracelog shows:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_14448/3287474095.py in <module>
----> 1 snl.fit_predict(name="Forecast").summary(name="Forecast")

~\AppData\Local\Programs\Python\Python39\lib\site-packages\covsirphy\analysis\scenario.py in fit_predict(self, oxcgrt_data, name, **kwargs)
   1436         """
   1437         self.fit(oxcgrt_data=oxcgrt_data, name=name, **find_args(Scenario.fit, **kwargs))
-> 1438         self.predict(name=name, **find_args(Scenario.predict, **kwargs))
   1439         return self
   1440 

~\AppData\Local\Programs\Python\Python39\lib\site-packages\covsirphy\analysis\scenario.py in predict(self, days, name)
   1411         # Set new future phases
   1412         for phase_dict in phase_df.to_dict(orient="records"):
-> 1413             self.add(name=name, **phase_dict)
   1414         return self
   1415 

~\AppData\Local\Programs\Python\Python39\lib\site-packages\covsirphy\analysis\scenario.py in add(self, name, end_date, days, model, tau, **kwargs)
    455             param_dict = {k: v for (k, v) in pre_param_dict.items() if k in self._model.PARAMETERS}
    456             if param_dict:
--> 457                 param_dict = self._ensure_kwargs(self._model.PARAMETERS, float, **param_dict)
    458                 param_df = pd.DataFrame(param_dict, index=pd.date_range(start, end))
    459                 tracker.set_ode(self._model, param_df, self._tau)

~\AppData\Local\Programs\Python\Python39\lib\site-packages\covsirphy\util\term.py in _ensure_kwargs(self, arg_list, value_type, **kwargs)
    544             if param not in kwargs:
    545                 raise KeyError(f"Value of {param} was not specified with keyword arguments.")
--> 546             self._ensure_instance(kwargs[param], value_type, name=f"{param} value")
    547         return {param: kwargs[param] for param in arg_list}
    548 

~\AppData\Local\Programs\Python\Python39\lib\site-packages\covsirphy\util\term.py in _ensure_instance(target, class_obj, name)
    370         s = f"@{name} must be an instance of {class_obj}, but {type(target)} was applied."
    371         if not isinstance(target, class_obj):
--> 372             raise TypeError(s)
    373         return target
    374 

TypeError: @kappa value must be an instance of <class 'float'>, but <class 'int'> was applied.

Data is from a data_loader.read_dataframe(). However I can export data as csv and provide, but I believe data set is big.

Regards.

lisphilar commented 2 years ago

Thank you for the details. One additional line between 456 and 457 in covsirphy\analysis\scenario.py to covert int to float may solve the issue. I will check that ASAP but actually this weekend.

lisphilar commented 2 years ago

959 was merged. Could you try the script with version 2.22.1-beta?

baluballa commented 2 years ago

Seems fixed now! tested version = 2.22.1-beta Thanks

lisphilar commented 2 years ago

Thank you for your confirmation! I will close this issue.