Repository: sktime/sktime

Issue:
ThetaForecaster does not work with "initial_level" different from None
**Describe the bug**
When calling
`forecaster = ThetaForecaster(initial_level=0.5, deseasonalize=True, sp=1)` then fitting via `forecaster.fit(y_train)` leads to the following error:

```python
`Traceback (most recent call last):

  File "<ipython-input-362-6ef348c52370>", line 1, in <module>
    forecaster.fit(y_train)

  File "/Users/muhlbach/opt/anaconda3/envs/experimental/lib/python3.8/site-packages/sktime/forecasting/theta.py", line 131, in fit
    super(ThetaForecaster, self).fit(y, fh=fh)

  File "/Users/muhlbach/opt/anaconda3/envs/experimental/lib/python3.8/site-packages/sktime/forecasting/base/adapters/_statsmodels.py", line 47, in fit
    self._fit_forecaster(y, X)

  File "/Users/muhlbach/opt/anaconda3/envs/experimental/lib/python3.8/site-packages/sktime/forecasting/exp_smoothing.py", line 79, in _fit_forecaster
    self._forecaster = _ExponentialSmoothing(

  File "/Users/muhlbach/opt/anaconda3/envs/experimental/lib/python3.8/site-packages/pandas/util/_decorators.py", line 199, in wrapper
    return func(*args, **kwargs)

  File "/Users/muhlbach/opt/anaconda3/envs/experimental/lib/python3.8/site-packages/statsmodels/tsa/holtwinters/model.py", line 291, in __init__
    self._initialize()

  File "/Users/muhlbach/opt/anaconda3/envs/experimental/lib/python3.8/site-packages/statsmodels/tsa/holtwinters/model.py", line 439, in _initialize
    raise ValueError(msg.format("level"))

ValueError: initialization method is estimated but initial_level has been set.`
```

**To Reproduce**

```python
from sktime.forecasting.theta import ThetaForecaster
from sktime.datasets import load_airline
y = load_airline()
forecaster = ThetaForecaster(initial_level=0.5).fit(y)
```

**Expected behavior**
It should estimate Theta with initial smoothing level.

**Additional context**
I think the problem relates to the class ExponentialSmoothing and the fact that users cannot provide the `initialization_method` argument. See https://github.com/alan-turing-institute/sktime/blob/060af89907d135e41491d61f0966e285289a805b/sktime/forecasting/exp_smoothing.py#L10 



Discussion:
Thanks @muhlbach for raising the issue! Would appreciate a PR to make this more flexible. 
@mloning: Sure thing! I'm not very experienced in this domain, so can you provide a hint to where to start? If I understand it correctly, I need write permissions to create a branch, which I don't have. Thus, do you want me to create a pull request from a fork?
Yes that's right, fork it and create a PR, more details [here](https://github.com/alan-turing-institute/sktime/blob/79ac80ab65adb30fdf233e98433646c1989da2fc/CONTRIBUTING.md#git-and-github-workflow). 
Hi, can I work on this? I did some research around this and seems are like when we are inheriting ExponentialSmoothing, it misses on quite a few important parameters as per the docs here. https://www.statsmodels.org/stable/_modules/statsmodels/tsa/holtwinters/model.html

I think we just need to add all the initialization parameters to the theta forecaster and that'll fix it.

@yashlamba yes, please open a PR, a good first step would be to create a unit test for it and then fix it. 
So I looked around whether we need to pass other parameters such as `initial_trend`, `initial_seasonal` with `initial_level`, and `initialization_method`. This was mentioned as a requirement [here](https://www.statsmodels.org/stable/_modules/statsmodels/tsa/holtwinters/model.html) for Exponential Smoothing.

So I referred to the `ThetaModel` implementation of statsmodels [here](https://github.com/statsmodels/statsmodels/blob/d42dc3f3c63edf0e2eb08f9297705ed9333c4357/statsmodels/tsa/forecasting/theta.py#L259), where they aren't receiving the `initialization_method` from the user, but implicitly using the required value when `initial_value` is passed. Should we do something similar or receive it from the user?
@yashlamba sounds like a good idea, comparing our implementation to the one in statsmodels may also be a good idea (see #421) 

Resolving patch:
diff --git a/sktime/forecasting/theta.py b/sktime/forecasting/theta.py
--- a/sktime/forecasting/theta.py
+++ b/sktime/forecasting/theta.py
@@ -94,7 +94,6 @@ def __init__(self, initial_level=None, deseasonalize=True, sp=1):
 
         self.sp = sp
         self.deseasonalize = deseasonalize
-
         self.deseasonalizer_ = None
         self.trend_ = None
         self.initial_level_ = None
@@ -126,6 +125,7 @@ def fit(self, y, X=None, fh=None):
             self.deseasonalizer_ = Deseasonalizer(sp=self.sp, model="multiplicative")
             y = self.deseasonalizer_.fit_transform(y)
 
+        self.initialization_method = "known" if self.initial_level else "estimated"
         # fit exponential smoothing forecaster
         # find theta lines: Theta lines are just SES + drift
         super(ThetaForecaster, self).fit(y, fh=fh)


Test patch:
diff --git a/sktime/forecasting/tests/test_theta.py b/sktime/forecasting/tests/test_theta.py
--- a/sktime/forecasting/tests/test_theta.py
+++ b/sktime/forecasting/tests/test_theta.py
@@ -43,3 +43,15 @@ def test_pred_errors_against_y_test(fh):
     for ints in intervals:
         assert np.all(y_test > ints["lower"])
         assert np.all(y_test < ints["upper"])
+
+
+def test_forecaster_with_initial_level():
+    y = np.log1p(load_airline())
+    y_train, y_test = temporal_train_test_split(y)
+    fh = np.arange(len(y_test)) + 1
+
+    f = ThetaForecaster(initial_level=0.1, sp=12)
+    f.fit(y_train)
+    y_pred = f.predict(fh=fh)
+
+    np.testing.assert_allclose(y_pred, y_test, rtol=0.05)