<jupyter_start><jupyter_text>Baseline ModelsLet's look at some simple ways we could model this problem to get a baseline to build from. One way to get pretty far with seasonal data like this is to look at past values and either pick the most recent value from that date or average all the data from past matching dates.<jupyter_code>week_by_dept_df = get_week_by_dept_df()
week_by_dept_df.head()<jupyter_output><empty_output><jupyter_text>The dates don't line up perfectly year-by-year, so let's see if just shifting by 52 rows works.<jupyter_code>index = week_by_dept_df.index[:52]
for i in range(3):
    l, = plt.plot(index, week_by_dept_df.iloc[:52, i])
    plt.plot(index, week_by_dept_df.iloc[52:104, i], '--', color=l.get_color())
plt.gcf().autofmt_xdate()
plt.show()<jupyter_output><empty_output><jupyter_text>The solid lines below are for the year starting in Feb. 2010, and the dashed lines are for the corresponding dates from the next 52 rows. Christmas and Halloween line up well, and Easter doesn't but that's because it was the 4th in 2010 and the 24th in 2011. So this looks good. Before making a baseline, let's set up our evaluation function as described [here](https://www.kaggle.com/c/walmart-recruiting-store-sales-forecastingevaluation).<jupyter_code>def wmae(y_pred, y_actual, is_holiday=None, holiday_weight=5):
    if is_holiday is None:
        test_df = load_test_df()
        is_holiday = test_df['IsHoliday']
    n = len(y_pred)
    assert(n == len(y_actual))
    assert(n == len(is_holiday))
    weights = np.ones(n)
    weights[is_holiday] = holiday_weight
    return 1.0 / np.sum(weights) * np.sum(weights * np.abs(y_actual - y_pred))
class PrevYearBaseline():
    def __init__(self, fillna_method='interpolate'):
        self.fillna_method = fillna_method
    
    def fit(self, X):
        """Given X with columns 'Store', 'Dept', 'Date', and 'Weekly_Sales',
        save data to be accessed by predict
        """
        self.week_by_dept = get_week_by_dept_df(X, fillna_method=self.fillna_method)
    
    def predict(self, X, return_pivoted=False):
        """Given X with columns 'Store', 'Dept', and 'Date', predict 'Weekly_Sales'
        """
        X = make_id_column(X)
        pred_week_by_dept = get_week_by_dept_df(X, fillna_method=None, values=None)
        for c in pred_week_by_dept.columns:
            if c not in self.week_by_dept.columns:
                self.week_by_dept[c] = self.week_by_dept.mean(axis=1)
        
        copy_week_by_dept = self.week_by_dept[pred_week_by_dept.columns.tolist()].copy()
        copy_week_by_dept.index += timedelta(weeks=52)
        pred_week_by_dept = copy_week_by_dept.loc[pred_week_by_dept.index]
        if return_pivoted:
            return pred_week_by_dept
        else:
            unpivoted = unpivot_week_by_dept_df(pred_week_by_dept)
            unpivoted = make_id_column(unpivoted)
            unpivoted = unpivoted.set_index('Id', drop=True)
            unpivoted = unpivoted.reindex(X['Id'])
            return unpivoted['Weekly_Sales']
full_train_df = load_train_df()
split_date = full_train_df['Date'].min() + timedelta(weeks=104)
train_df = full_train_df[full_train_df['Date']<split_date]
test_df = full_train_df[full_train_df['Date']>=split_date]
test_df = make_id_column(test_df).set_index('Id', drop=True)
test_df, y_actual = test_df[['Store', 'Dept', 'Date', 'IsHoliday']], test_df['Weekly_Sales']
bl = PrevYearBaseline()
bl.fit(train_df)
y_pred = bl.predict(test_df)<jupyter_output><empty_output><jupyter_text>Error on holdout set on last 39 weeks of data trained on 2 years of data:<jupyter_code>wmae(y_pred, y_actual, test_df['IsHoliday'])<jupyter_output><empty_output><jupyter_text>Check score on Kaggle<jupyter_code>bl = PrevYearBaseline()
test_df = load_test_df()
bl.fit(full_train_df)
y_pred = bl.predict(test_df)
file_path = join(project_dir, 'data/processed/baseline_kaggle_sub.csv')
makedirs(dirname(file_path), exist_ok=True)
if not exists(file_path):
    y_pred.to_csv(file_path, index=True, header=True)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10894749815134336, 'fraction_numerical': 0.0101059896475228, 'mean_word_length': 4.4837837837837835, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 22, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '563752', 'license': 'MIT', 'n_tokens_mistral': 1514, 'n_tokens_neox': 1452, 'n_words': 324, 'path': 'notebooks/01_Baseline-Models.ipynb', 'repo_name': 'benlindsay/walmart-forecasting', 'size': '4057'}