We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Extend NaiveForecaster
Extend `NaiveForecaster` to include all common naive forecasting strategies. For an overview, see this [chapter](https://otexts.com/fpp2/simple-methods.html#simple-methods).

- [x] introduce `seasonal` as boolean kwarg, refactor "seasonal_last" and implement "seasonal_mean", so that we can set `seasonal=True` and `strategy="mean"` for example
- [x] add "drift" strategy, the forecasts should be similar to the forecasts from `ReducedRegressionForecaster(regressor=LinearRegression(), ...)`
- [ ] implement more efficient `update_predict` routine

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sktime/forecasting/naive.py`
Content:
```
1 #!/usr/bin/env python3 -u
2 # coding: utf-8
3 # copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
4 
5 __all__ = ["NaiveForecaster"]
6 __author__ = ["Markus Löning", "Piyush Gade"]
7 
8 from warnings import warn
9 
10 import numpy as np
11 from sktime.forecasting.base._base import DEFAULT_ALPHA
12 from sktime.forecasting.base._sktime import BaseLastWindowForecaster
13 from sktime.forecasting.base._sktime import OptionalForecastingHorizonMixin
14 from sktime.utils.validation.forecasting import check_sp
15 from sktime.utils.validation.forecasting import check_window_length
16 
17 
18 class NaiveForecaster(OptionalForecastingHorizonMixin,
19                       BaseLastWindowForecaster):
20     """
21     NaiveForecaster is a forecaster that makes forecasts using simple
22     strategies.
23 
24     Parameters
25     ----------
26     strategy : str{"last", "mean"}, optional (default="last")
27         Strategy used to make forecasts:
28 
29         * "last" : forecast the last value in the
30                     training series when sp is 1.
31                     When sp is not 1,
32                     last value of each season
33                     in the last window will be
34                     forecasted for each season.
35         * "mean" : forecast the mean of last window
36                      of training series when sp is 1.
37                      When sp is not 1, mean of all values
38                      in a season from last window will be
39                      forecasted for each season.
40 
41     sp : int, optional (default=1)
42         Seasonal periodicity to use in the seasonal forecasting.
43 
44     window_length : int or None, optional (default=None)
45         Window length to use in the `mean` strategy. If None, entire training
46             series will be used.
47     """
48 
49     def __init__(self, strategy="last", window_length=None, sp=1):
50         super(NaiveForecaster, self).__init__()
51         self.strategy = strategy
52         self.sp = sp
53         self.window_length = window_length
54 
55     def fit(self, y_train, fh=None, X_train=None):
56         """Fit to training data.
57 
58         Parameters
59         ----------
60         y_train : pd.Series
61             Target time series to which to fit the forecaster.
62         fh : int, list or np.array, optional (default=None)
63             The forecasters horizon with the steps ahead to to predict.
64         X_train : pd.DataFrame, optional (default=None)
65             Exogenous variables are ignored
66         Returns
67         -------
68         self : returns an instance of self.
69         """  # X_train is ignored
70         self._set_oh(y_train)
71         self._set_fh(fh)
72 
73         if self.strategy == "last":
74             if self.sp == 1:
75                 if self.window_length is not None:
76                     warn("For the `last` strategy, "
77                          "the `window_length` value will be ignored if `sp` "
78                          "== 1.")
79                 self.window_length_ = 1
80 
81             else:
82                 self.sp_ = check_sp(self.sp)
83 
84                 # window length we need for forecasts is just the
85                 # length of seasonal periodicity
86                 self.window_length_ = self.sp_
87 
88         elif self.strategy == "mean":
89             # check window length is greater than sp for seasonal mean
90             if self.window_length is not None and self.sp != 1:
91                 if self.window_length < self.sp:
92                     raise ValueError(f"The `window_length`: "
93                                      f"{self.window_length} is smaller than "
94                                      f"`sp`: {self.sp}.")
95             self.window_length_ = check_window_length(self.window_length)
96             self.sp_ = check_sp(self.sp)
97 
98             #  if not given, set default window length for the mean strategy
99             if self.window_length is None:
100                 self.window_length_ = len(y_train)
101 
102         else:
103             allowed_strategies = ("last", "mean")
104             raise ValueError(f"Unknown strategy: {self.strategy}. Expected "
105                              f"one of: {allowed_strategies}.")
106 
107         # check window length
108         if self.window_length_ > len(self.oh):
109             param = "sp" if self.strategy == "last" and self.sp != 1 \
110                 else "window_length_"
111             raise ValueError(
112                 f"The {param}: {self.window_length_} is larger than "
113                 f"the training series.")
114 
115         self._is_fitted = True
116         return self
117 
118     def _predict_last_window(self, fh, X=None, return_pred_int=False,
119                              alpha=DEFAULT_ALPHA):
120         """Internal predict"""
121         last_window = self._get_last_window()
122 
123         # if last window only contains missing values, return nan
124         if np.all(np.isnan(last_window)) or len(last_window) == 0:
125             return self._predict_nan(fh)
126 
127         elif self.strategy == "last":
128             if self.sp == 1:
129                 return np.repeat(last_window[-1], len(fh))
130 
131             else:
132                 # we need to replicate the last window if max(fh) is larger
133                 # than sp,so that we still make forecasts by repeating the
134                 # last value for that season, assume fh is sorted, i.e. max(
135                 # fh) == fh[-1]
136                 if fh[-1] > self.sp_:
137                     reps = np.int(np.ceil(fh[-1] / self.sp_))
138                     last_window = np.tile(last_window, reps=reps)
139 
140                 # get zero-based index by subtracting the minimum
141                 fh_idx = fh.index_like(self.cutoff)
142                 return last_window[fh_idx]
143 
144         elif self.strategy == "mean":
145             if self.sp == 1:
146                 return np.repeat(np.nanmean(last_window), len(fh))
147 
148             else:
149                 # if the window length is not a multiple of sp, we pad the
150                 # window with nan values for easy computation of the mean
151                 remainder = self.window_length_ % self.sp_
152                 if remainder > 0:
153                     pad_width = self.sp_ - remainder
154                 else:
155                     pad_width = 0
156                 last_window = np.hstack([last_window,
157                                          np.full(pad_width, np.nan)])
158 
159                 # reshape last window, one column per season
160                 last_window = last_window.reshape(np.int(np.ceil(
161                     self.window_length_ / self.sp_)), self.sp_)
162 
163                 # compute seasonal mean, averaging over rows
164                 y_pred = np.nanmean(last_window, axis=0)
165 
166                 # we need to replicate the last window if max(fh) is
167                 # larger than sp,
168                 # so that we still make forecasts by repeating the
169                 # last value for that season,
170                 # assume fh is sorted, i.e. max(fh) == fh[-1]
171                 # only slicing all the last seasons into last_window
172                 if fh[-1] > self.sp_:
173                     reps = np.int(np.ceil(fh[-1] / self.sp_))
174                     y_pred = np.tile(y_pred, reps=reps)
175 
176                 # get zero-based index by subtracting the minimum
177                 fh_idx = fh.index_like(self.cutoff)
178                 return y_pred[fh_idx]
179
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sktime/forecasting/naive.py b/sktime/forecasting/naive.py
--- a/sktime/forecasting/naive.py
+++ b/sktime/forecasting/naive.py
@@ -23,7 +23,7 @@
 
     Parameters
     ----------
-    strategy : str{"last", "mean"}, optional (default="last")
+    strategy : str{"last", "mean", "drift"}, optional (default="last")
         Strategy used to make forecasts:
 
         * "last" : forecast the last value in the
@@ -37,6 +37,9 @@
                      When sp is not 1, mean of all values
                      in a season from last window will be
                      forecasted for each season.
+        * "drift": forecast by fitting a line between the
+                    first and last point of the window and
+                     extrapolating it into the future
 
     sp : int, optional (default=1)
         Seasonal periodicity to use in the seasonal forecasting.
@@ -99,8 +102,22 @@
             if self.window_length is None:
                 self.window_length_ = len(y_train)
 
+        elif self.strategy == "drift":
+            if self.sp != 1:
+                warn("For the `drift` strategy, "
+                     "the `sp` value will be ignored.")
+            # window length we need for forecasts is just the
+            # length of seasonal periodicity
+            self.window_length_ = check_window_length(self.window_length)
+            if self.window_length is None:
+                self.window_length_ = len(y_train)
+            if self.window_length == 1:
+                raise ValueError(f"For the `drift` strategy, "
+                                 f"the `window_length`: {self.window_length} "
+                                 f"value must be greater than one.")
+
         else:
-            allowed_strategies = ("last", "mean")
+            allowed_strategies = ("last", "mean", "drift")
             raise ValueError(f"Unknown strategy: {self.strategy}. Expected "
                              f"one of: {allowed_strategies}.")
 
@@ -176,3 +193,22 @@
                 # get zero-based index by subtracting the minimum
                 fh_idx = fh.index_like(self.cutoff)
                 return y_pred[fh_idx]
+
+        # if self.strategy == "drift":
+        else:
+            if self.window_length_ != 1:
+                if np.any(np.isnan(last_window[[0, -1]])):
+                    raise ValueError(f"For {self.strategy},"
+                                     f"first and last elements in the last "
+                                     f"window must not be a missing value.")
+                else:
+                    # formula for slope
+                    slope = (last_window[-1] -
+                             last_window[0]) / (self.window_length_ - 1)
+
+                    # get zero-based index by subtracting the minimum
+                    fh_idx = fh.index_like(self.cutoff)
+
+                    # linear extrapolation
+                    y_pred = last_window[-1] + (fh_idx + 1) * slope
+                    return y_pred

{"golden_diff": "diff --git a/sktime/forecasting/naive.py b/sktime/forecasting/naive.py\n--- a/sktime/forecasting/naive.py\n+++ b/sktime/forecasting/naive.py\n@@ -23,7 +23,7 @@\n \n     Parameters\n     ----------\n-    strategy : str{\"last\", \"mean\"}, optional (default=\"last\")\n+    strategy : str{\"last\", \"mean\", \"drift\"}, optional (default=\"last\")\n         Strategy used to make forecasts:\n \n         * \"last\" : forecast the last value in the\n@@ -37,6 +37,9 @@\n                      When sp is not 1, mean of all values\n                      in a season from last window will be\n                      forecasted for each season.\n+        * \"drift\": forecast by fitting a line between the\n+                    first and last point of the window and\n+                     extrapolating it into the future\n \n     sp : int, optional (default=1)\n         Seasonal periodicity to use in the seasonal forecasting.\n@@ -99,8 +102,22 @@\n             if self.window_length is None:\n                 self.window_length_ = len(y_train)\n \n+        elif self.strategy == \"drift\":\n+            if self.sp != 1:\n+                warn(\"For the `drift` strategy, \"\n+                     \"the `sp` value will be ignored.\")\n+            # window length we need for forecasts is just the\n+            # length of seasonal periodicity\n+            self.window_length_ = check_window_length(self.window_length)\n+            if self.window_length is None:\n+                self.window_length_ = len(y_train)\n+            if self.window_length == 1:\n+                raise ValueError(f\"For the `drift` strategy, \"\n+                                 f\"the `window_length`: {self.window_length} \"\n+                                 f\"value must be greater than one.\")\n+\n         else:\n-            allowed_strategies = (\"last\", \"mean\")\n+            allowed_strategies = (\"last\", \"mean\", \"drift\")\n             raise ValueError(f\"Unknown strategy: {self.strategy}. Expected \"\n                              f\"one of: {allowed_strategies}.\")\n \n@@ -176,3 +193,22 @@\n                 # get zero-based index by subtracting the minimum\n                 fh_idx = fh.index_like(self.cutoff)\n                 return y_pred[fh_idx]\n+\n+        # if self.strategy == \"drift\":\n+        else:\n+            if self.window_length_ != 1:\n+                if np.any(np.isnan(last_window[[0, -1]])):\n+                    raise ValueError(f\"For {self.strategy},\"\n+                                     f\"first and last elements in the last \"\n+                                     f\"window must not be a missing value.\")\n+                else:\n+                    # formula for slope\n+                    slope = (last_window[-1] -\n+                             last_window[0]) / (self.window_length_ - 1)\n+\n+                    # get zero-based index by subtracting the minimum\n+                    fh_idx = fh.index_like(self.cutoff)\n+\n+                    # linear extrapolation\n+                    y_pred = last_window[-1] + (fh_idx + 1) * slope\n+                    return y_pred\n", "issue": "Extend NaiveForecaster\nExtend `NaiveForecaster` to include all common naive forecasting strategies. For an overview, see this [chapter](https://otexts.com/fpp2/simple-methods.html#simple-methods).\r\n\r\n- [x] introduce `seasonal` as boolean kwarg, refactor \"seasonal_last\" and implement \"seasonal_mean\", so that we can set `seasonal=True` and `strategy=\"mean\"` for example\r\n- [x] add \"drift\" strategy, the forecasts should be similar to the forecasts from `ReducedRegressionForecaster(regressor=LinearRegression(), ...)`\r\n- [ ] implement more efficient `update_predict` routine\n", "before_files": [{"content": "#!/usr/bin/env python3 -u\n# coding: utf-8\n# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)\n\n__all__ = [\"NaiveForecaster\"]\n__author__ = [\"Markus L\u00f6ning\", \"Piyush Gade\"]\n\nfrom warnings import warn\n\nimport numpy as np\nfrom sktime.forecasting.base._base import DEFAULT_ALPHA\nfrom sktime.forecasting.base._sktime import BaseLastWindowForecaster\nfrom sktime.forecasting.base._sktime import OptionalForecastingHorizonMixin\nfrom sktime.utils.validation.forecasting import check_sp\nfrom sktime.utils.validation.forecasting import check_window_length\n\n\nclass NaiveForecaster(OptionalForecastingHorizonMixin,\n                      BaseLastWindowForecaster):\n    \"\"\"\n    NaiveForecaster is a forecaster that makes forecasts using simple\n    strategies.\n\n    Parameters\n    ----------\n    strategy : str{\"last\", \"mean\"}, optional (default=\"last\")\n        Strategy used to make forecasts:\n\n        * \"last\" : forecast the last value in the\n                    training series when sp is 1.\n                    When sp is not 1,\n                    last value of each season\n                    in the last window will be\n                    forecasted for each season.\n        * \"mean\" : forecast the mean of last window\n                     of training series when sp is 1.\n                     When sp is not 1, mean of all values\n                     in a season from last window will be\n                     forecasted for each season.\n\n    sp : int, optional (default=1)\n        Seasonal periodicity to use in the seasonal forecasting.\n\n    window_length : int or None, optional (default=None)\n        Window length to use in the `mean` strategy. If None, entire training\n            series will be used.\n    \"\"\"\n\n    def __init__(self, strategy=\"last\", window_length=None, sp=1):\n        super(NaiveForecaster, self).__init__()\n        self.strategy = strategy\n        self.sp = sp\n        self.window_length = window_length\n\n    def fit(self, y_train, fh=None, X_train=None):\n        \"\"\"Fit to training data.\n\n        Parameters\n        ----------\n        y_train : pd.Series\n            Target time series to which to fit the forecaster.\n        fh : int, list or np.array, optional (default=None)\n            The forecasters horizon with the steps ahead to to predict.\n        X_train : pd.DataFrame, optional (default=None)\n            Exogenous variables are ignored\n        Returns\n        -------\n        self : returns an instance of self.\n        \"\"\"  # X_train is ignored\n        self._set_oh(y_train)\n        self._set_fh(fh)\n\n        if self.strategy == \"last\":\n            if self.sp == 1:\n                if self.window_length is not None:\n                    warn(\"For the `last` strategy, \"\n                         \"the `window_length` value will be ignored if `sp` \"\n                         \"== 1.\")\n                self.window_length_ = 1\n\n            else:\n                self.sp_ = check_sp(self.sp)\n\n                # window length we need for forecasts is just the\n                # length of seasonal periodicity\n                self.window_length_ = self.sp_\n\n        elif self.strategy == \"mean\":\n            # check window length is greater than sp for seasonal mean\n            if self.window_length is not None and self.sp != 1:\n                if self.window_length < self.sp:\n                    raise ValueError(f\"The `window_length`: \"\n                                     f\"{self.window_length} is smaller than \"\n                                     f\"`sp`: {self.sp}.\")\n            self.window_length_ = check_window_length(self.window_length)\n            self.sp_ = check_sp(self.sp)\n\n            #  if not given, set default window length for the mean strategy\n            if self.window_length is None:\n                self.window_length_ = len(y_train)\n\n        else:\n            allowed_strategies = (\"last\", \"mean\")\n            raise ValueError(f\"Unknown strategy: {self.strategy}. Expected \"\n                             f\"one of: {allowed_strategies}.\")\n\n        # check window length\n        if self.window_length_ > len(self.oh):\n            param = \"sp\" if self.strategy == \"last\" and self.sp != 1 \\\n                else \"window_length_\"\n            raise ValueError(\n                f\"The {param}: {self.window_length_} is larger than \"\n                f\"the training series.\")\n\n        self._is_fitted = True\n        return self\n\n    def _predict_last_window(self, fh, X=None, return_pred_int=False,\n                             alpha=DEFAULT_ALPHA):\n        \"\"\"Internal predict\"\"\"\n        last_window = self._get_last_window()\n\n        # if last window only contains missing values, return nan\n        if np.all(np.isnan(last_window)) or len(last_window) == 0:\n            return self._predict_nan(fh)\n\n        elif self.strategy == \"last\":\n            if self.sp == 1:\n                return np.repeat(last_window[-1], len(fh))\n\n            else:\n                # we need to replicate the last window if max(fh) is larger\n                # than sp,so that we still make forecasts by repeating the\n                # last value for that season, assume fh is sorted, i.e. max(\n                # fh) == fh[-1]\n                if fh[-1] > self.sp_:\n                    reps = np.int(np.ceil(fh[-1] / self.sp_))\n                    last_window = np.tile(last_window, reps=reps)\n\n                # get zero-based index by subtracting the minimum\n                fh_idx = fh.index_like(self.cutoff)\n                return last_window[fh_idx]\n\n        elif self.strategy == \"mean\":\n            if self.sp == 1:\n                return np.repeat(np.nanmean(last_window), len(fh))\n\n            else:\n                # if the window length is not a multiple of sp, we pad the\n                # window with nan values for easy computation of the mean\n                remainder = self.window_length_ % self.sp_\n                if remainder > 0:\n                    pad_width = self.sp_ - remainder\n                else:\n                    pad_width = 0\n                last_window = np.hstack([last_window,\n                                         np.full(pad_width, np.nan)])\n\n                # reshape last window, one column per season\n                last_window = last_window.reshape(np.int(np.ceil(\n                    self.window_length_ / self.sp_)), self.sp_)\n\n                # compute seasonal mean, averaging over rows\n                y_pred = np.nanmean(last_window, axis=0)\n\n                # we need to replicate the last window if max(fh) is\n                # larger than sp,\n                # so that we still make forecasts by repeating the\n                # last value for that season,\n                # assume fh is sorted, i.e. max(fh) == fh[-1]\n                # only slicing all the last seasons into last_window\n                if fh[-1] > self.sp_:\n                    reps = np.int(np.ceil(fh[-1] / self.sp_))\n                    y_pred = np.tile(y_pred, reps=reps)\n\n                # get zero-based index by subtracting the minimum\n                fh_idx = fh.index_like(self.cutoff)\n                return y_pred[fh_idx]\n", "path": "sktime/forecasting/naive.py"}], "after_files": [{"content": "#!/usr/bin/env python3 -u\n# coding: utf-8\n# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)\n\n__all__ = [\"NaiveForecaster\"]\n__author__ = [\"Markus L\u00f6ning\", \"Piyush Gade\"]\n\nfrom warnings import warn\n\nimport numpy as np\nfrom sktime.forecasting.base._base import DEFAULT_ALPHA\nfrom sktime.forecasting.base._sktime import BaseLastWindowForecaster\nfrom sktime.forecasting.base._sktime import OptionalForecastingHorizonMixin\nfrom sktime.utils.validation.forecasting import check_sp\nfrom sktime.utils.validation.forecasting import check_window_length\n\n\nclass NaiveForecaster(OptionalForecastingHorizonMixin,\n                      BaseLastWindowForecaster):\n    \"\"\"\n    NaiveForecaster is a forecaster that makes forecasts using simple\n    strategies.\n\n    Parameters\n    ----------\n    strategy : str{\"last\", \"mean\", \"drift\"}, optional (default=\"last\")\n        Strategy used to make forecasts:\n\n        * \"last\" : forecast the last value in the\n                    training series when sp is 1.\n                    When sp is not 1,\n                    last value of each season\n                    in the last window will be\n                    forecasted for each season.\n        * \"mean\" : forecast the mean of last window\n                     of training series when sp is 1.\n                     When sp is not 1, mean of all values\n                     in a season from last window will be\n                     forecasted for each season.\n        * \"drift\": forecast by fitting a line between the\n                    first and last point of the window and\n                     extrapolating it into the future\n\n    sp : int, optional (default=1)\n        Seasonal periodicity to use in the seasonal forecasting.\n\n    window_length : int or None, optional (default=None)\n        Window length to use in the `mean` strategy. If None, entire training\n            series will be used.\n    \"\"\"\n\n    def __init__(self, strategy=\"last\", window_length=None, sp=1):\n        super(NaiveForecaster, self).__init__()\n        self.strategy = strategy\n        self.sp = sp\n        self.window_length = window_length\n\n    def fit(self, y_train, fh=None, X_train=None):\n        \"\"\"Fit to training data.\n\n        Parameters\n        ----------\n        y_train : pd.Series\n            Target time series to which to fit the forecaster.\n        fh : int, list or np.array, optional (default=None)\n            The forecasters horizon with the steps ahead to to predict.\n        X_train : pd.DataFrame, optional (default=None)\n            Exogenous variables are ignored\n        Returns\n        -------\n        self : returns an instance of self.\n        \"\"\"  # X_train is ignored\n        self._set_oh(y_train)\n        self._set_fh(fh)\n\n        if self.strategy == \"last\":\n            if self.sp == 1:\n                if self.window_length is not None:\n                    warn(\"For the `last` strategy, \"\n                         \"the `window_length` value will be ignored if `sp` \"\n                         \"== 1.\")\n                self.window_length_ = 1\n\n            else:\n                self.sp_ = check_sp(self.sp)\n\n                # window length we need for forecasts is just the\n                # length of seasonal periodicity\n                self.window_length_ = self.sp_\n\n        elif self.strategy == \"mean\":\n            # check window length is greater than sp for seasonal mean\n            if self.window_length is not None and self.sp != 1:\n                if self.window_length < self.sp:\n                    raise ValueError(f\"The `window_length`: \"\n                                     f\"{self.window_length} is smaller than \"\n                                     f\"`sp`: {self.sp}.\")\n            self.window_length_ = check_window_length(self.window_length)\n            self.sp_ = check_sp(self.sp)\n\n            #  if not given, set default window length for the mean strategy\n            if self.window_length is None:\n                self.window_length_ = len(y_train)\n\n        elif self.strategy == \"drift\":\n            if self.sp != 1:\n                warn(\"For the `drift` strategy, \"\n                     \"the `sp` value will be ignored.\")\n            # window length we need for forecasts is just the\n            # length of seasonal periodicity\n            self.window_length_ = check_window_length(self.window_length)\n            if self.window_length is None:\n                self.window_length_ = len(y_train)\n            if self.window_length == 1:\n                raise ValueError(f\"For the `drift` strategy, \"\n                                 f\"the `window_length`: {self.window_length} \"\n                                 f\"value must be greater than one.\")\n\n        else:\n            allowed_strategies = (\"last\", \"mean\", \"drift\")\n            raise ValueError(f\"Unknown strategy: {self.strategy}. Expected \"\n                             f\"one of: {allowed_strategies}.\")\n\n        # check window length\n        if self.window_length_ > len(self.oh):\n            param = \"sp\" if self.strategy == \"last\" and self.sp != 1 \\\n                else \"window_length_\"\n            raise ValueError(\n                f\"The {param}: {self.window_length_} is larger than \"\n                f\"the training series.\")\n\n        self._is_fitted = True\n        return self\n\n    def _predict_last_window(self, fh, X=None, return_pred_int=False,\n                             alpha=DEFAULT_ALPHA):\n        \"\"\"Internal predict\"\"\"\n        last_window = self._get_last_window()\n\n        # if last window only contains missing values, return nan\n        if np.all(np.isnan(last_window)) or len(last_window) == 0:\n            return self._predict_nan(fh)\n\n        elif self.strategy == \"last\":\n            if self.sp == 1:\n                return np.repeat(last_window[-1], len(fh))\n\n            else:\n                # we need to replicate the last window if max(fh) is larger\n                # than sp,so that we still make forecasts by repeating the\n                # last value for that season, assume fh is sorted, i.e. max(\n                # fh) == fh[-1]\n                if fh[-1] > self.sp_:\n                    reps = np.int(np.ceil(fh[-1] / self.sp_))\n                    last_window = np.tile(last_window, reps=reps)\n\n                # get zero-based index by subtracting the minimum\n                fh_idx = fh.index_like(self.cutoff)\n                return last_window[fh_idx]\n\n        elif self.strategy == \"mean\":\n            if self.sp == 1:\n                return np.repeat(np.nanmean(last_window), len(fh))\n\n            else:\n                # if the window length is not a multiple of sp, we pad the\n                # window with nan values for easy computation of the mean\n                remainder = self.window_length_ % self.sp_\n                if remainder > 0:\n                    pad_width = self.sp_ - remainder\n                else:\n                    pad_width = 0\n                last_window = np.hstack([last_window,\n                                         np.full(pad_width, np.nan)])\n\n                # reshape last window, one column per season\n                last_window = last_window.reshape(np.int(np.ceil(\n                    self.window_length_ / self.sp_)), self.sp_)\n\n                # compute seasonal mean, averaging over rows\n                y_pred = np.nanmean(last_window, axis=0)\n\n                # we need to replicate the last window if max(fh) is\n                # larger than sp,\n                # so that we still make forecasts by repeating the\n                # last value for that season,\n                # assume fh is sorted, i.e. max(fh) == fh[-1]\n                # only slicing all the last seasons into last_window\n                if fh[-1] > self.sp_:\n                    reps = np.int(np.ceil(fh[-1] / self.sp_))\n                    y_pred = np.tile(y_pred, reps=reps)\n\n                # get zero-based index by subtracting the minimum\n                fh_idx = fh.index_like(self.cutoff)\n                return y_pred[fh_idx]\n\n        # if self.strategy == \"drift\":\n        else:\n            if self.window_length_ != 1:\n                if np.any(np.isnan(last_window[[0, -1]])):\n                    raise ValueError(f\"For {self.strategy},\"\n                                     f\"first and last elements in the last \"\n                                     f\"window must not be a missing value.\")\n                else:\n                    # formula for slope\n                    slope = (last_window[-1] -\n                             last_window[0]) / (self.window_length_ - 1)\n\n                    # get zero-based index by subtracting the minimum\n                    fh_idx = fh.index_like(self.cutoff)\n\n                    # linear extrapolation\n                    y_pred = last_window[-1] + (fh_idx + 1) * slope\n                    return y_pred\n", "path": "sktime/forecasting/naive.py"}]}