| @@ -1,8 +0,0 @@ | |||
| model: | |||
| class_name: Model | |||
| kwargs: {} | |||
| stat_specifications: | |||
| - module_path: learnware.specification | |||
| class_name: RKMETableSpecification | |||
| file_name: rkme.json | |||
| kwargs: {} | |||
| @@ -1,21 +0,0 @@ | |||
| import os | |||
| import joblib | |||
| import numpy as np | |||
| import lightgbm as lgb | |||
| from learnware.model import BaseModel | |||
| class Model(BaseModel): | |||
| def __init__(self): | |||
| super(Model, self).__init__(input_shape=(82,), output_shape=(1,)) | |||
| dir_path = os.path.dirname(os.path.abspath(__file__)) | |||
| self.model = lgb.Booster(model_file=os.path.join(dir_path, "model.out")) | |||
| def fit(self, X: np.ndarray, y: np.ndarray): | |||
| pass | |||
| def predict(self, X: np.ndarray) -> np.ndarray: | |||
| return self.model.predict(X) | |||
| def finetune(self, X: np.ndarray, y: np.ndarray): | |||
| pass | |||
| @@ -1,3 +0,0 @@ | |||
| # M5 Dataset | |||
| Walmart store, involves the unit sales of various products sold in the USA, organized in the form of grouped time series. More specifically, the dataset involves the unit sales of 3049 products, classified in 3 product categories (Hobbies, Foods, and Household). | |||
| @@ -1,65 +0,0 @@ | |||
| from cgi import test | |||
| import os | |||
| import joblib | |||
| import lightgbm as lgb | |||
| from .config import store_list, model_dir | |||
| from .utils import acquire_data, get_weights, model_predict, score, measure_aux_algo | |||
| from .generate_data import regenerate_data | |||
| from .train import retrain_models, grid_training_sample, train_adaptation_grid | |||
| class DataLoader: | |||
| def __init__(self): | |||
| self.algo = "ridge" | |||
| def set_algo(self, algo): | |||
| self.algo = algo | |||
| def get_algo_list(self): | |||
| return ["lgb", "ridge"] | |||
| def get_idx_list(self): | |||
| return list(range(len(store_list))) | |||
| def get_idx_data(self, idx): | |||
| store = store_list[idx] | |||
| # fill_flag = self.algo == "ridge" | |||
| fill_flag = True | |||
| return acquire_data(store, fill_flag) | |||
| def get_weights(self): | |||
| return get_weights(self.algo) | |||
| def get_model_path(self, idx): | |||
| return os.path.join(model_dir, "{}_{}.out".format(self.algo, store_list[idx])) | |||
| def predict(self, idx, test_x): | |||
| store = store_list[idx] | |||
| if os.path.exists(os.path.join(model_dir, f"{self.algo}_{store}.out")): | |||
| return model_predict(self.algo, idx, test_x) | |||
| else: | |||
| self.retrain_models() | |||
| return model_predict(self.algo, idx, test_x) | |||
| def score(self, real_y, pred_y, sample_weight=None, multioutput="raw_values"): | |||
| return score(real_y, pred_y, sample_weight, multioutput) | |||
| def regenerate_data(self): | |||
| regenerate_data() | |||
| def retrain_models(self): | |||
| retrain_models(self.algo) | |||
| def grid_training_sample(self, user_list=list(range(10))): | |||
| grid_training_sample(self.algo, user_list) | |||
| def train_adaptation_grid( | |||
| self, max_sample, test_sample, user_list=list(range(10)), adaptation_model=[], residual=False | |||
| ): | |||
| train_adaptation_grid(self.algo, max_sample, test_sample, user_list, adaptation_model, residual) | |||
| def measure_aux_algo(self, idx, test_sample, model): | |||
| return measure_aux_algo(idx, test_sample, model) | |||
| @@ -1,139 +0,0 @@ | |||
| import os | |||
| ROOT_PATH = os.path.abspath(os.path.join(__file__, "..", "data")) | |||
| raw_data_dir = os.path.join(ROOT_PATH, "raw") | |||
| processed_data_dir = os.path.join(ROOT_PATH, "processed") | |||
| model_dir = os.path.join(ROOT_PATH, "models") | |||
| grid_dir = os.path.join(ROOT_PATH, "grid_sample") | |||
| TARGET = "sales" | |||
| START_TRAIN = 1 | |||
| END_TRAIN = 1941 - 28 | |||
| category_list = ["item_id", "dept_id", "cat_id", "event_name_1", "event_name_2", "event_type_1", "event_type_2"] | |||
| features_columns = [ | |||
| "item_id", | |||
| "dept_id", | |||
| "cat_id", | |||
| "release", | |||
| "sell_price", | |||
| "price_max", | |||
| "price_min", | |||
| "price_std", | |||
| "price_mean", | |||
| "price_norm", | |||
| "price_nunique", | |||
| "item_nunique", | |||
| "price_momentum", | |||
| "price_momentum_m", | |||
| "price_momentum_y", | |||
| "event_name_1", | |||
| "event_type_1", | |||
| "event_name_2", | |||
| "event_type_2", | |||
| "snap", | |||
| "tm_d", | |||
| "tm_w", | |||
| "tm_m", | |||
| "tm_y", | |||
| "tm_wm", | |||
| "tm_dw", | |||
| "tm_w_end", | |||
| "sales_lag_28", | |||
| "sales_lag_29", | |||
| "sales_lag_30", | |||
| "sales_lag_31", | |||
| "sales_lag_32", | |||
| "sales_lag_33", | |||
| "sales_lag_34", | |||
| "sales_lag_35", | |||
| "sales_lag_36", | |||
| "sales_lag_37", | |||
| "sales_lag_38", | |||
| "sales_lag_39", | |||
| "sales_lag_40", | |||
| "sales_lag_41", | |||
| "sales_lag_42", | |||
| "rolling_mean_7", | |||
| "rolling_std_7", | |||
| "rolling_mean_14", | |||
| "rolling_std_14", | |||
| "rolling_mean_30", | |||
| "rolling_std_30", | |||
| "rolling_mean_60", | |||
| "rolling_std_60", | |||
| "rolling_mean_180", | |||
| "rolling_std_180", | |||
| "rolling_mean_tmp_1_7", | |||
| "rolling_mean_tmp_1_14", | |||
| "rolling_mean_tmp_1_30", | |||
| "rolling_mean_tmp_1_60", | |||
| "rolling_mean_tmp_7_7", | |||
| "rolling_mean_tmp_7_14", | |||
| "rolling_mean_tmp_7_30", | |||
| "rolling_mean_tmp_7_60", | |||
| "rolling_mean_tmp_14_7", | |||
| "rolling_mean_tmp_14_14", | |||
| "rolling_mean_tmp_14_30", | |||
| "rolling_mean_tmp_14_60", | |||
| # "enc_state_id_mean", | |||
| # "enc_state_id_std", | |||
| # "enc_store_id_mean", | |||
| # "enc_store_id_std", | |||
| "enc_cat_id_mean", | |||
| "enc_cat_id_std", | |||
| "enc_dept_id_mean", | |||
| "enc_dept_id_std", | |||
| "enc_state_id_cat_id_mean", | |||
| "enc_state_id_cat_id_std", | |||
| "enc_state_id_dept_id_mean", | |||
| "enc_state_id_dept_id_std", | |||
| "enc_store_id_cat_id_mean", | |||
| "enc_store_id_cat_id_std", | |||
| "enc_store_id_dept_id_mean", | |||
| "enc_store_id_dept_id_std", | |||
| "enc_item_id_mean", | |||
| "enc_item_id_std", | |||
| "enc_item_id_state_id_mean", | |||
| "enc_item_id_state_id_std", | |||
| "enc_item_id_store_id_mean", | |||
| "enc_item_id_store_id_std", | |||
| ] | |||
| label_column = ["sales"] | |||
| lgb_params_list = [ | |||
| [0.015, 224, 66], | |||
| [0.01, 224, 50], | |||
| [0.01, 300, 80], | |||
| [0.015, 128, 50], | |||
| [0.015, 300, 50], | |||
| [0.01, 300, 66], | |||
| [0.015, 300, 80], | |||
| [0.15, 224, 80], | |||
| [0.005, 300, 50], | |||
| [0.015, 224, 50], | |||
| ] | |||
| store_list = ["CA_1", "CA_2", "CA_3", "CA_4", "TX_1", "TX_2", "TX_3", "WI_1", "WI_2", "WI_3"] | |||
| dataset_info = { | |||
| "name": "M5", | |||
| "range of date": "2011.01.29-2016.06.19", | |||
| "description": "Walmart store, involves the unit sales of various products sold in the USA, organized in the form of grouped time series. More specifically, the dataset involves the unit sales of 3049 products, classified in 3 product categories (Hobbies, Foods, and Household).", | |||
| "location": [ | |||
| "California, United States", | |||
| "California, United States", | |||
| "California, United States", | |||
| "California, United States", | |||
| "Texas, United States", | |||
| "Texas, United States", | |||
| "Texas, United States", | |||
| "Wisconsin, United States", | |||
| "Wisconsin, United States", | |||
| "Wisconsin, United States", | |||
| ], | |||
| } | |||
| @@ -1,338 +0,0 @@ | |||
| import numpy as np | |||
| import pandas as pd | |||
| from math import ceil | |||
| from tqdm import tqdm | |||
| from copy import deepcopy as dco | |||
| import os, sys, gc, time, warnings, pickle, psutil, random | |||
| from sklearn.preprocessing import LabelEncoder | |||
| from sklearn.preprocessing import MinMaxScaler | |||
| from .utils import * | |||
| from .config import raw_data_dir, processed_data_dir, TARGET | |||
| warnings.filterwarnings("ignore") | |||
| # ==================== preprocessing ==================== | |||
| def melt_raw_data(train_df): | |||
| if os.path.exists(os.path.join(processed_data_dir, "melt_raw_data.pkl")): | |||
| return pd.read_pickle(os.path.join(processed_data_dir, "melt_raw_data.pkl")) | |||
| index_columns = ["id", "item_id", "dept_id", "cat_id", "store_id", "state_id"] | |||
| grid_df = pd.melt(train_df, id_vars=index_columns, var_name="d", value_name=TARGET) | |||
| for col in index_columns: | |||
| grid_df[col] = grid_df[col].astype("category") | |||
| grid_df.to_pickle(os.path.join(processed_data_dir, "melt_raw_data.pkl")) | |||
| return grid_df | |||
| def add_release_week(grid_df, prices_df, calendar_df): | |||
| if os.path.exists(os.path.join(processed_data_dir, "add_release_week.pkl")): | |||
| return pd.read_pickle(os.path.join(processed_data_dir, "add_release_week.pkl")) | |||
| release_df = prices_df.groupby(["store_id", "item_id"])["wm_yr_wk"].agg(["min"]).reset_index() | |||
| release_df.columns = ["store_id", "item_id", "release"] | |||
| grid_df = merge_by_concat(grid_df, release_df, ["store_id", "item_id"]) | |||
| grid_df = merge_by_concat(grid_df, calendar_df[["wm_yr_wk", "d"]], ["d"]) | |||
| # cutoff meaningless rows | |||
| grid_df = grid_df[grid_df["wm_yr_wk"] >= grid_df["release"]] | |||
| grid_df = grid_df.reset_index(drop=True) | |||
| # scale the release | |||
| grid_df["release"] = grid_df["release"] - grid_df["release"].min() | |||
| grid_df["release"] = grid_df["release"].astype(np.int16) | |||
| grid_df.to_pickle(os.path.join(processed_data_dir, "add_release_week.pkl")) | |||
| return grid_df | |||
| def add_prices(grid_df, prices_df, calendar_df): | |||
| if os.path.exists(os.path.join(processed_data_dir, "add_prices.pkl")): | |||
| return pd.read_pickle(os.path.join(processed_data_dir, "add_prices.pkl")) | |||
| prices_df["price_max"] = prices_df.groupby(["store_id", "item_id"])["sell_price"].transform("max") | |||
| prices_df["price_min"] = prices_df.groupby(["store_id", "item_id"])["sell_price"].transform("min") | |||
| prices_df["price_std"] = prices_df.groupby(["store_id", "item_id"])["sell_price"].transform("std") | |||
| prices_df["price_mean"] = prices_df.groupby(["store_id", "item_id"])["sell_price"].transform("mean") | |||
| prices_df["price_norm"] = prices_df["sell_price"] / prices_df["price_max"] | |||
| prices_df["price_nunique"] = prices_df.groupby(["store_id", "item_id"])["sell_price"].transform("nunique") | |||
| prices_df["item_nunique"] = prices_df.groupby(["store_id", "sell_price"])["item_id"].transform("nunique") | |||
| calendar_prices = calendar_df[["wm_yr_wk", "month", "year"]] | |||
| calendar_prices = calendar_prices.drop_duplicates(subset=["wm_yr_wk"]) | |||
| prices_df = prices_df.merge(calendar_prices[["wm_yr_wk", "month", "year"]], on=["wm_yr_wk"], how="left") | |||
| prices_df["price_momentum"] = prices_df["sell_price"] / prices_df.groupby(["store_id", "item_id"])[ | |||
| "sell_price" | |||
| ].transform(lambda x: x.shift(1)) | |||
| prices_df["price_momentum_m"] = prices_df["sell_price"] / prices_df.groupby(["store_id", "item_id", "month"])[ | |||
| "sell_price" | |||
| ].transform("mean") | |||
| prices_df["price_momentum_y"] = prices_df["sell_price"] / prices_df.groupby(["store_id", "item_id", "year"])[ | |||
| "sell_price" | |||
| ].transform("mean") | |||
| grid_df = reduce_mem_usage(grid_df) | |||
| prices_df = reduce_mem_usage(prices_df) | |||
| original_columns = list(grid_df) | |||
| grid_df = grid_df.merge(prices_df, on=["store_id", "item_id", "wm_yr_wk"], how="left") | |||
| grid_df = reduce_mem_usage(grid_df) | |||
| grid_df.to_pickle(os.path.join(processed_data_dir, "add_prices.pkl")) | |||
| return grid_df | |||
| def add_date(grid_df, calendar_df): | |||
| if os.path.exists(os.path.join(processed_data_dir, "add_date.pkl")): | |||
| return pd.read_pickle(os.path.join(processed_data_dir, "add_date.pkl")) | |||
| # merge calendar partly | |||
| icols = [ | |||
| "date", | |||
| "d", | |||
| "event_name_1", | |||
| "event_type_1", | |||
| "event_name_2", | |||
| "event_type_2", | |||
| "snap_CA", | |||
| "snap_TX", | |||
| "snap_WI", | |||
| ] | |||
| grid_df = grid_df.merge(calendar_df[icols], on=["d"], how="left") | |||
| # convert to category | |||
| icols = [ | |||
| "event_name_1", | |||
| "event_type_1", | |||
| "event_name_2", | |||
| "event_type_2", | |||
| "snap_CA", | |||
| "snap_TX", | |||
| "snap_WI", | |||
| ] | |||
| for col in icols: | |||
| grid_df[col] = grid_df[col].astype("category") | |||
| # make some features from date | |||
| grid_df["date"] = pd.to_datetime(grid_df["date"]) | |||
| grid_df["tm_d"] = grid_df["date"].dt.day.astype(np.int8) | |||
| grid_df["tm_w"] = grid_df["date"].dt.week.astype(np.int8) | |||
| grid_df["tm_m"] = grid_df["date"].dt.month.astype(np.int8) | |||
| grid_df["tm_y"] = grid_df["date"].dt.year | |||
| grid_df["tm_y"] = (grid_df["tm_y"] - grid_df["tm_y"].min()).astype(np.int8) | |||
| grid_df["tm_wm"] = grid_df["tm_d"].apply(lambda x: ceil(x / 7)).astype(np.int8) | |||
| grid_df["tm_dw"] = grid_df["date"].dt.dayofweek.astype(np.int8) | |||
| grid_df["tm_w_end"] = (grid_df["tm_dw"] >= 5).astype(np.int8) | |||
| # clear columns | |||
| grid_df["d"] = grid_df["d"].apply(lambda x: x[2:]).astype(np.int16) | |||
| grid_df = grid_df.drop("wm_yr_wk", 1) | |||
| grid_df.to_pickle(os.path.join(processed_data_dir, "add_date.pkl")) | |||
| return grid_df | |||
| def add_lags_rollings(grid_df): | |||
| if os.path.exists(os.path.join(processed_data_dir, "add_lags_rollings.pkl")): | |||
| return pd.read_pickle(os.path.join(processed_data_dir, "add_lags_rollings.pkl")) | |||
| # add lags | |||
| SHIFT_DAY = 28 | |||
| LAG_DAYS = [col for col in range(SHIFT_DAY, SHIFT_DAY + 15)] | |||
| grid_df = grid_df.assign( | |||
| **{ | |||
| "{}_lag_{}".format(col, l): grid_df.groupby(["id"])[col].transform(lambda x: x.shift(l)) | |||
| for l in LAG_DAYS | |||
| for col in [TARGET] | |||
| } | |||
| ) | |||
| for col in list(grid_df): | |||
| if "lag" in col: | |||
| grid_df[col] = grid_df[col].astype(np.float16) | |||
| # add rollings | |||
| for i in [7, 14, 30, 60, 180]: | |||
| grid_df["rolling_mean_" + str(i)] = ( | |||
| grid_df.groupby(["id"])[TARGET].transform(lambda x: x.shift(SHIFT_DAY).rolling(i).mean()).astype(np.float16) | |||
| ) | |||
| grid_df["rolling_std_" + str(i)] = ( | |||
| grid_df.groupby(["id"])[TARGET].transform(lambda x: x.shift(SHIFT_DAY).rolling(i).std()).astype(np.float16) | |||
| ) | |||
| # sliding window | |||
| for d_shift in [1, 7, 14]: | |||
| for d_window in [7, 14, 30, 60]: | |||
| col_name = "rolling_mean_tmp_" + str(d_shift) + "_" + str(d_window) | |||
| grid_df[col_name] = ( | |||
| grid_df.groupby(["id"])[TARGET] | |||
| .transform(lambda x: x.shift(SHIFT_DAY + d_shift).rolling(d_window).mean()) | |||
| .astype(np.float16) | |||
| ) | |||
| grid_df.to_pickle(os.path.join(processed_data_dir, "add_lags_rollings.pkl")) | |||
| return grid_df | |||
| def add_mean_enc(grid_df): | |||
| if os.path.exists(os.path.join(processed_data_dir, "add_mean_enc.pkl")): | |||
| return pd.read_pickle(os.path.join(processed_data_dir, "add_mean_enc.pkl")) | |||
| sales_df = dco(grid_df["sales"]) | |||
| grid_df["sales"][grid_df["d"] > (1941 - 28)] = np.nan | |||
| icols = [ | |||
| ["state_id"], | |||
| ["store_id"], | |||
| ["cat_id"], | |||
| ["dept_id"], | |||
| ["state_id", "cat_id"], | |||
| ["state_id", "dept_id"], | |||
| ["store_id", "cat_id"], | |||
| ["store_id", "dept_id"], | |||
| ["item_id"], | |||
| ["item_id", "state_id"], | |||
| ["item_id", "store_id"], | |||
| ] | |||
| for col in icols: | |||
| col_name = "_" + "_".join(col) + "_" | |||
| grid_df["enc" + col_name + "mean"] = grid_df.groupby(col)["sales"].transform("mean").astype(np.float16) | |||
| grid_df["enc" + col_name + "std"] = grid_df.groupby(col)["sales"].transform("std").astype(np.float16) | |||
| grid_df["sales"] = sales_df | |||
| grid_df.to_pickle(os.path.join(processed_data_dir, "add_mean_enc.pkl")) | |||
| return grid_df | |||
| def add_snap(grid_df): | |||
| if os.path.exists(os.path.join(processed_data_dir, "all_data_df.pkl")): | |||
| return pd.read_pickle(os.path.join(processed_data_dir, "all_data_df.pkl")) | |||
| mask_CA = grid_df["state_id"] == "CA" | |||
| mask_WI = grid_df["state_id"] == "WI" | |||
| mask_TX = grid_df["state_id"] == "TX" | |||
| grid_df["snap"] = grid_df["snap_CA"] | |||
| grid_df.loc[mask_WI, "snap"] = grid_df["snap_WI"] | |||
| grid_df.loc[mask_TX, "snap"] = grid_df["snap_TX"] | |||
| grid_df.to_pickle(os.path.join(processed_data_dir, "all_data_df.pkl")) | |||
| return grid_df | |||
| def preprocessing_m5(): | |||
| train_df = pd.read_csv(os.path.join(raw_data_dir, "sales_train_evaluation.csv")) | |||
| prices_df = pd.read_csv(os.path.join(raw_data_dir, "sell_prices.csv")) | |||
| calendar_df = pd.read_csv(os.path.join(raw_data_dir, "calendar.csv")) | |||
| grid_df = melt_raw_data(train_df) | |||
| print(f"df: ({grid_df.shape[0]}, {grid_df.shape[1]}) Melting raw data down!") | |||
| grid_df = add_release_week(grid_df, prices_df, calendar_df) | |||
| print(f"df: ({grid_df.shape[0]}, {grid_df.shape[1]}) Adding release week down!") | |||
| grid_df = add_prices(grid_df, prices_df, calendar_df) | |||
| print(f"df: ({grid_df.shape[0]}, {grid_df.shape[1]}) Adding prices down!") | |||
| grid_df = add_date(grid_df, calendar_df) | |||
| print(f"df: ({grid_df.shape[0]}, {grid_df.shape[1]}) Adding date down!") | |||
| grid_df = add_lags_rollings(grid_df) | |||
| print(f"df: ({grid_df.shape[0]}, {grid_df.shape[1]}) Adding lags and rollings down!") | |||
| grid_df = add_mean_enc(grid_df) | |||
| print(f"df: ({grid_df.shape[0]}, {grid_df.shape[1]}) Adding mean encoding down!") | |||
| grid_df = pd.read_pickle(os.path.join(processed_data_dir, "add_mean_enc.pkl")) | |||
| grid_df = add_snap(grid_df) | |||
| print("Save the data down!") | |||
| # ==================== split dataset ==================== | |||
| def label_encode(df, columns): | |||
| le = LabelEncoder() | |||
| data_list = [] | |||
| for column in columns: | |||
| data_list += df[column].drop_duplicates().values.tolist() | |||
| le.fit(data_list) | |||
| for column in columns: | |||
| df[column] = le.transform(df[column].values.tolist()) | |||
| return df | |||
| def reorganize_data(grid_df): | |||
| grid_df["snap"] = grid_df["snap"].astype("int8") | |||
| columns_list = [ | |||
| ["item_id"], | |||
| ["dept_id"], | |||
| ["cat_id"], | |||
| ["event_name_1", "event_name_2"], | |||
| ["event_type_1", "event_type_2"], | |||
| ] | |||
| for columns in columns_list: | |||
| grid_df[columns] = label_encode(grid_df[columns], columns) | |||
| return reduce_mem_usage(grid_df) | |||
| def split_data(df, store, fill_flag=False): | |||
| for cat in category_list: | |||
| df[cat] = df[cat].astype("category") | |||
| if fill_flag: | |||
| df = reduce_mem_usage(df, float16_flag=False) | |||
| cols = df.isnull().any() | |||
| idx = list(cols[cols.values].index) | |||
| df[idx] = df.groupby("item_id", sort=False)[idx].apply(lambda x: x.ffill().bfill()) | |||
| df[idx] = df[idx].fillna(df[idx].mean()) | |||
| mms = MinMaxScaler() | |||
| df[features_columns] = mms.fit_transform(df[features_columns]) | |||
| df = reduce_mem_usage(df) | |||
| train_df = df[df["d"] <= END_TRAIN] | |||
| val_df = df[df["d"] > END_TRAIN] | |||
| train_df = train_df[features_columns + label_column] | |||
| val_df = val_df[features_columns + label_column] | |||
| print(train_df.shape, val_df.shape) | |||
| suffix = f"_fill" if fill_flag else "" | |||
| train_df.to_pickle(os.path.join(processed_data_dir, f"train_{store}{suffix}.pkl")) | |||
| val_df.to_pickle(os.path.join(processed_data_dir, f"val_{store}{suffix}.pkl")) | |||
| def split_m5(): | |||
| grid_df = pd.read_pickle(os.path.join(processed_data_dir, "all_data_df.pkl")) | |||
| if os.path.exists(os.path.join(processed_data_dir, "label_encode.pkl")): | |||
| grid_df = pd.read_pickle(os.path.join(processed_data_dir, "label_encode.pkl")) | |||
| else: | |||
| grid_df = reorganize_data(grid_df) | |||
| grid_df.to_pickle(os.path.join(processed_data_dir, "label_encode.pkl")) | |||
| for store in store_list: | |||
| # split_data(grid_df[grid_df["store_id"] == store], store) | |||
| split_data(grid_df[grid_df["store_id"] == store], store, True) | |||
| def regenerate_data(): | |||
| preprocessing_m5() | |||
| split_m5() | |||
| @@ -1,452 +0,0 @@ | |||
| import gc | |||
| import joblib | |||
| import random | |||
| import numpy as np | |||
| import pandas as pd | |||
| from tqdm import tqdm | |||
| import os, warnings | |||
| import lightgbm as lgb | |||
| from sklearn.svm import SVR | |||
| from sklearn.linear_model import Ridge | |||
| from sklearn.kernel_ridge import KernelRidge | |||
| from sklearn.metrics import mean_squared_error | |||
| from sklearn.metrics.pairwise import rbf_kernel | |||
| from .utils import * | |||
| from .config import model_dir, grid_dir, store_list, lgb_params_list | |||
| warnings.filterwarnings("ignore") | |||
| def train_lgb_model(train_x, train_y, val_x, val_y, store, lr, nl, md, best, save=True, n_estimators=0, train_flag=0): | |||
| lgb_params = { | |||
| "boosting_type": "gbdt", | |||
| "objective": "rmse", | |||
| "metric": "rmse", | |||
| "learning_rate": lr, | |||
| "num_leaves": nl, | |||
| "max_depth": md, | |||
| "n_estimators": 100000, | |||
| "boost_from_average": False, | |||
| "verbose": -1, | |||
| } | |||
| if train_flag: | |||
| idx = int(len(train_y) * 0.1) | |||
| train_data = lgb.Dataset(train_x[:-idx], label=train_y[:-idx]) | |||
| val_data = lgb.Dataset(train_x[-idx:], label=train_y[-idx:]) | |||
| else: | |||
| train_data = lgb.Dataset(train_x, label=train_y) | |||
| val_data = lgb.Dataset(val_x, label=val_y) | |||
| if n_estimators: | |||
| lgb_params["n_estimators"] = n_estimators | |||
| gbm = lgb.train(lgb_params, train_data, verbose_eval=100) | |||
| else: | |||
| gbm = lgb.train(lgb_params, train_data, valid_sets=[val_data], verbose_eval=100, early_stopping_rounds=1000) | |||
| test_y = gbm.predict(val_x, num_iteration=gbm.best_iteration) | |||
| res = mean_squared_error(val_y, test_y, squared=False) | |||
| if res < best: | |||
| best = res | |||
| if save: | |||
| gbm.save_model(os.path.join(model_dir, f"lgb_{store}.out")) | |||
| return best | |||
| def train_ridge_model(train_x, train_y, val_x, val_y, store, a, best, save=True): | |||
| model = Ridge(alpha=a) | |||
| model.fit(train_x, train_y) | |||
| test_y = model.predict(val_x) | |||
| res = mean_squared_error(val_y, test_y, squared=False) | |||
| if res < best: | |||
| best = res | |||
| if save: | |||
| joblib.dump(model, os.path.join(model_dir, f"ridge_{store}.out")) | |||
| return best | |||
| def train_svm_model( | |||
| train_x, train_y, val_x, val_y, store, C, epsilon, best, save=True, gamma=0.1, adaptation_model=[], K1=None, K2=None | |||
| ): | |||
| if K1 is None: | |||
| model = SVR(C=C, epsilon=epsilon, max_iter=30000, cache_size=10240, verbose=True, gamma=gamma) | |||
| else: | |||
| model = AuxiliarySVR( | |||
| C=C, | |||
| epsilon=epsilon, | |||
| gamma=gamma, | |||
| adaptation_model=adaptation_model, | |||
| max_iter=30000, | |||
| cache_size=10240, | |||
| verbose=True, | |||
| K1=K1, | |||
| K2=K2, | |||
| ) | |||
| model.fit(train_x, train_y) | |||
| test_y = model.predict(val_x) | |||
| res = mean_squared_error(val_y, test_y, squared=False) | |||
| if res < best: | |||
| best = res | |||
| if save: | |||
| joblib.dump(model, os.path.join(model_dir, f"svm_{store}.out")) | |||
| return best | |||
| def train_krr_model(train_x, train_y, val_x, val_y, store, a, best, save=True, gamma=0.1, K1=None, K2=None): | |||
| if K1 is None: | |||
| model = KernelRidge(kernel="rbf", alpha=a, gamma=gamma) | |||
| model.fit(train_x, train_y) | |||
| test_y = model.predict(val_x) | |||
| res = mean_squared_error(val_y, test_y, squared=False) | |||
| else: | |||
| len1, len2 = len(train_y), len(val_y) | |||
| model = KernelRidge(kernel="precomputed", alpha=a) | |||
| model.fit(K1[-len1:, -len1:], train_y) | |||
| test_y = model.predict(K2[-len2:, -len1:]) | |||
| res = mean_squared_error(val_y, test_y, squared=False) | |||
| if res < best: | |||
| best = res | |||
| if save: | |||
| joblib.dump(model, os.path.join(model_dir, f"krr_{store}.out")) | |||
| return best | |||
| def grid_search(store_id, algo, search_lgb_flag=False): | |||
| store = store_list[store_id] | |||
| if algo == "lgb": | |||
| train_x, train_y, val_x, val_y = acquire_data(store, True) | |||
| learning_rate = [0.005, 0.01, 0.015] | |||
| num_leaves = [128, 224, 300] | |||
| max_depth = [50, 66, 80] | |||
| best = 10000000 | |||
| if search_lgb_flag: | |||
| for lr in learning_rate: | |||
| for nl in num_leaves: | |||
| for md in max_depth: | |||
| best = train_lgb_model(train_x, train_y, val_x, val_y, store, lr, nl, md, best) | |||
| print(f"store: {store}, lr: {lr}, nl: {nl}, md: {md}, best: {best}") | |||
| else: | |||
| lr, nl, md = lgb_params_list[store_id] | |||
| best = train_lgb_model(train_x, train_y, val_x, val_y, store, lr, nl, md, best) | |||
| print(f"store: {store}, lr: {lr}, nl: {nl}, md: {md}, best: {best}") | |||
| elif algo == "ridge": | |||
| train_x, train_y, val_x, val_y = acquire_data(store, True) | |||
| alpha = [0.01, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10, 20, 30] | |||
| best = 10000000 | |||
| for a in alpha: | |||
| best = train_ridge_model(train_x, train_y, val_x, val_y, store, a, best) | |||
| print(f"store: {store}, alpha: {a}, best: {best}") | |||
| def grid_training_sample(algo, user_list=list(range(10))): | |||
| for i in range(len(user_list)): | |||
| store_id = user_list[i] | |||
| store = store_list[store_id] | |||
| org_train_x, org_train_y, val_x, val_y = acquire_data(store, True) | |||
| res = [] | |||
| proportion_list = [ | |||
| 100, | |||
| 300, | |||
| 500, | |||
| 700, | |||
| 900, | |||
| 1000, | |||
| 3000, | |||
| 5000, | |||
| 7000, | |||
| 9000, | |||
| 10000, | |||
| 30000, | |||
| 50000, | |||
| 70000, | |||
| 90000, | |||
| 100000, | |||
| 300000, | |||
| 500000, | |||
| 700000, | |||
| 900000, | |||
| 1000000, | |||
| 3000000, | |||
| 5000000, | |||
| ] | |||
| for proportion in proportion_list: | |||
| """ | |||
| random | |||
| org_idx_list = list(range(len(org_train_y))) | |||
| idx_list = random.sample(org_idx_list, min(proportion, len(org_train_y))) | |||
| train_x = org_train_x.iloc[idx_list] | |||
| train_y = org_train_y.iloc[idx_list] | |||
| """ | |||
| train_x = org_train_x[-proportion:] | |||
| train_y = org_train_y[-proportion:] | |||
| best = 10000000 | |||
| if algo == "lgb": | |||
| lr, nl, md = lgb_params_list[store_id] | |||
| best = train_lgb_model( | |||
| train_x, train_y, val_x, val_y, store, lr, nl, md, best, save=False, n_estimators=3000, train_flag=0 | |||
| ) | |||
| print(f"store: {store}, lr: {lr}, nl: {nl}, md: {md}, best: {best}") | |||
| elif algo == "ridge": | |||
| alpha = [0.01, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10, 20, 30] | |||
| for a in alpha: | |||
| best = train_ridge_model(train_x, train_y, val_x, val_y, store, a, best, save=False) | |||
| print(f"store: {store}, alpha: {a}, best: {best}") | |||
| elif algo == "svm": | |||
| C = [1, 10, 100] | |||
| epsilon = 0.001 | |||
| for c in C: | |||
| best = train_svm_model(train_x, train_y, val_x, val_y, store, c, epsilon, best, save=False) | |||
| print(f"store: {store}, C: {c}, epsilon: {epsilon}, best: {best}") | |||
| res.append([proportion, best]) | |||
| np.savetxt(os.path.join(grid_dir, f"grid_sample_{algo}_{store}.out"), np.array(res)) | |||
| if proportion > len(org_train_y): | |||
| break | |||
| def retrain_models(algo): | |||
| for store_id in range(10): | |||
| grid_search(store_id, algo) | |||
| def train_adaptation_grid( | |||
| algo, max_sample, test_sample, user_list=list(range(10)), adaptation_model=[], residual=False | |||
| ): | |||
| """ | |||
| adaptation_model = [ | |||
| [("lgb", 1), ("ridge", 2)], | |||
| [("lgb", 1), ("ridge", 2)] | |||
| ] | |||
| """ | |||
| proportion_list = [ | |||
| 100, | |||
| 300, | |||
| 500, | |||
| 700, | |||
| 900, | |||
| 1000, | |||
| 3000, | |||
| 5000, | |||
| 7000, | |||
| 9000, | |||
| 10000, | |||
| 30000, | |||
| 50000, | |||
| 70000, | |||
| 90000, | |||
| 100000, | |||
| 300000, | |||
| 500000, | |||
| 700000, | |||
| 900000, | |||
| 1000000, | |||
| 3000000, | |||
| 5000000, | |||
| ] | |||
| sample_idx = proportion_list.index(max_sample) + 1 | |||
| for i in range(len(user_list)): | |||
| store_id = user_list[i] | |||
| store = store_list[store_id] | |||
| org_train_x, org_train_y, val_x, val_y = acquire_data(store, True) | |||
| val_x = val_x[-test_sample:] | |||
| val_y = val_y[-test_sample:] | |||
| if algo == "lgb" or algo == "ridge": | |||
| res = [] | |||
| if adaptation_model != []: | |||
| if residual: | |||
| aux_algo, model_idx = adaptation_model[i][0] | |||
| org_train_y -= model_predict(aux_algo, model_idx, org_train_x) | |||
| val_y -= model_predict(aux_algo, model_idx, val_x) | |||
| else: | |||
| train_y_list, val_y_list = [], [] | |||
| for aux_algo, model_idx in adaptation_model[i]: | |||
| train_y_list.append(model_predict(aux_algo, model_idx, org_train_x)) | |||
| val_y_list.append(model_predict(aux_algo, model_idx, val_x)) | |||
| for j in range(len(train_y_list)): | |||
| org_train_x[f"model_values_{j}"] = train_y_list[j] | |||
| val_x[f"model_values_{j}"] = val_y_list[j] | |||
| for proportion in proportion_list[:sample_idx]: | |||
| """ | |||
| random | |||
| org_idx_list = list(range(len(org_train_y))) | |||
| idx_list = random.sample(org_idx_list, min(proportion, len(org_train_y))) | |||
| train_x = org_train_x.iloc[idx_list] | |||
| train_y = org_train_y.iloc[idx_list] | |||
| """ | |||
| train_x = org_train_x[-proportion:] | |||
| train_y = org_train_y[-proportion:] | |||
| best = 10000000 | |||
| if algo == "lgb": | |||
| if max_sample < 50000: | |||
| learning_rate = [0.005, 0.01, 0.015] | |||
| num_leaves = [128, 224, 300] | |||
| max_depth = [50, 66, 80] | |||
| for lr in learning_rate: | |||
| for nl in num_leaves: | |||
| for md in max_depth: | |||
| best = train_lgb_model( | |||
| train_x, train_y, val_x, val_y, store, lr, nl, md, best, save=False | |||
| ) | |||
| print(f"store: {store}, lr: {lr}, nl: {nl}, md: {md}, best: {best}") | |||
| else: | |||
| lr, nl, md = lgb_params_list[store_id] | |||
| best = train_lgb_model( | |||
| train_x, | |||
| train_y, | |||
| val_x, | |||
| val_y, | |||
| store, | |||
| lr, | |||
| nl, | |||
| md, | |||
| best, | |||
| save=False, | |||
| n_estimators=3000, | |||
| train_flag=0, | |||
| ) | |||
| print(f"store: {store}, lr: {lr}, nl: {nl}, md: {md}, best: {best}") | |||
| elif algo == "ridge": | |||
| alpha = [0.01, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10, 20, 30] | |||
| for a in alpha: | |||
| best = train_ridge_model(train_x, train_y, val_x, val_y, store, a, best, save=False) | |||
| print(f"store: {store}, alpha: {a}, best: {best}") | |||
| res.append([proportion, best]) | |||
| text = str(adaptation_model[i]) if adaptation_model != [] else "null" | |||
| text += "_residual_" if residual else "" | |||
| np.savetxt(os.path.join(grid_dir, f"{algo}_using_{text}_{store}.out"), np.array(res)) | |||
| if proportion > len(org_train_y): | |||
| break | |||
| elif algo == "svm" or algo == "krr": | |||
| res = [[proportion, 10000] for proportion in proportion_list[:sample_idx]] | |||
| org_train_x = org_train_x.to_numpy() | |||
| org_train_y = org_train_y.to_numpy() | |||
| val_x = val_x.to_numpy() | |||
| val_y = val_y.to_numpy() | |||
| y1_list, y2_list = [], [] | |||
| gamma_list = [0.01, 0.1, 0.5, 1] | |||
| if residual: | |||
| aux_algo, model_idx = adaptation_model[i][0] | |||
| org_train_y = org_train_y.astype(np.float64) | |||
| val_y = val_y.astype(np.float64) | |||
| org_train_y -= model_predict(aux_algo, model_idx, org_train_x) | |||
| val_y -= model_predict(aux_algo, model_idx, val_x) | |||
| elif adaptation_model != []: | |||
| for aux_algo, idx in adaptation_model[i]: | |||
| y1_list.append(model_predict(aux_algo, idx, org_train_x[-max_sample:]).reshape(-1, 1)) | |||
| y2_list.append(model_predict(aux_algo, idx, val_x).reshape(-1, 1)) | |||
| for gamma in gamma_list: | |||
| K1 = np.zeros((max_sample, max_sample)) | |||
| K2 = np.zeros((len(val_x), max_sample)) | |||
| if (not residual) and adaptation_model != []: | |||
| for j in range(len(adaptation_model[i])): | |||
| aux_algo, idx = adaptation_model[i][j] | |||
| y1 = y1_list[j] | |||
| y2 = y2_list[j] | |||
| K1 += np.dot(y1, y1.T) | |||
| K2 += np.dot(y2, y1.T) | |||
| K1 += rbf_kernel(org_train_x[-max_sample:], org_train_x[-max_sample:], gamma=gamma) | |||
| K2 += rbf_kernel(val_x, org_train_x[-max_sample:], gamma=gamma) | |||
| for idx in range(len(proportion_list[:sample_idx])): | |||
| proportion = proportion_list[idx] | |||
| """ | |||
| random | |||
| org_idx_list = list(range(len(org_train_y))) | |||
| idx_list = random.sample(org_idx_list, min(proportion, len(org_train_y))) | |||
| train_x = org_train_x.iloc[idx_list] | |||
| train_y = org_train_y.iloc[idx_list] | |||
| """ | |||
| train_x = org_train_x[-proportion:] | |||
| train_y = org_train_y[-proportion:] | |||
| best = 10000000 | |||
| if algo == "svm": | |||
| C = [1, 10, 50, 100, 200] | |||
| epsilon = 0.001 | |||
| for c in C: | |||
| adapt_m = [] if adaptation_model == [] else adaptation_model[i] | |||
| best = train_svm_model( | |||
| train_x, | |||
| train_y, | |||
| val_x, | |||
| val_y, | |||
| store, | |||
| c, | |||
| epsilon, | |||
| best, | |||
| save=False, | |||
| gamma=gamma, | |||
| adaptation_model=adapt_m, | |||
| K1=K1, | |||
| K2=K2, | |||
| ) | |||
| print(f"store: {store}, gamma: {gamma}, C: {c}, epsilon: {epsilon}, best: {best}") | |||
| elif algo == "krr": | |||
| alpha = [0.01, 0.1, 0.5, 1.0, 5.0, 10] | |||
| for a in alpha: | |||
| best = train_krr_model( | |||
| train_x, train_y, val_x, val_y, store, a, best, save=False, gamma=gamma, K1=K1, K2=K2 | |||
| ) | |||
| print(f"store: {store}, a: {a}, gamma: {gamma}, best: {best}") | |||
| if best < res[idx][1]: | |||
| res[idx][1] = best | |||
| text = str(adaptation_model[i]) if adaptation_model != [] else "null" | |||
| text += "_residual" if residual else "" | |||
| np.savetxt(os.path.join(grid_dir, f"{algo}_using_{text}_{store}.out"), np.array(res)) | |||
| if proportion > len(org_train_y): | |||
| break | |||
| del train_x, train_y | |||
| gc.collect() | |||
| del K1, K2 | |||
| gc.collect() | |||
| del org_train_x, org_train_y | |||
| gc.collect() | |||
| @@ -1,177 +0,0 @@ | |||
| from math import gamma | |||
| from tkinter import Y | |||
| import joblib | |||
| from tqdm import tqdm | |||
| import numpy as np | |||
| import pandas as pd | |||
| import lightgbm as lgb | |||
| from sklearn.svm import SVR | |||
| from sklearn.metrics import mean_squared_error | |||
| from sklearn.metrics.pairwise import rbf_kernel | |||
| import os, sys, gc, time, warnings, pickle, psutil, random | |||
| import matplotlib.pyplot as plt | |||
| from mpl_toolkits.axes_grid1 import make_axes_locatable | |||
| from .config import * | |||
| class AuxiliarySVR: | |||
| def __init__( | |||
| self, C, epsilon, gamma, adaptation_model=[], max_iter=30000, cache_size=10240, verbose=False, K1=None, K2=None | |||
| ): | |||
| self.gamma = gamma | |||
| self.adaptation_model = adaptation_model | |||
| self.model = SVR( | |||
| C=C, | |||
| epsilon=epsilon, | |||
| kernel=self.auxiliary_rbf_kernel, | |||
| max_iter=max_iter, | |||
| cache_size=cache_size, | |||
| verbose=verbose, | |||
| ) | |||
| self.K1 = K1 | |||
| self.K2 = K2 | |||
| def auxiliary_rbf_kernel(self, X1, X2): | |||
| if self.K1 is not None: | |||
| if X1.shape[0] == X2.shape[0]: | |||
| return self.K1[-X1.shape[0] :, -X2.shape[0] :] | |||
| else: | |||
| return self.K2[-X1.shape[0] :, -X2.shape[0] :] | |||
| else: | |||
| K = np.zeros((len(X1), len(X2))) | |||
| for algo, idx in self.adaptation_model: | |||
| Y1 = model_predict(algo, idx, X1).reshape(-1, 1) | |||
| Y2 = model_predict(algo, idx, X2).reshape(-1, 1) | |||
| K += Y1 @ Y2.T | |||
| K += rbf_kernel(X1, X2, self.gamma) | |||
| return K | |||
| def fit(self, X, Y): | |||
| self.gamma = 1 / X.shape[1] | |||
| self.model.fit(X, Y) | |||
| def predict(self, X): | |||
| return self.model.predict(X) | |||
| def measure_aux_algo(idx, test_sample, model): | |||
| """ | |||
| model = ("lgb", 1) | |||
| """ | |||
| store = store_list[idx] | |||
| org_train_x, org_train_y, val_x, val_y = acquire_data(store, True) | |||
| pred_y = model_predict(model[0], model[1], val_x[-test_sample:]) | |||
| return score(pred_y, val_y[-test_sample:]) | |||
| # Simple "Memory profilers" to see memory usage | |||
| def get_memory_usage(): | |||
| return np.round(psutil.Process(os.getpid()).memory_info()[0] / 2.0**30, 2) | |||
| def sizeof_fmt(num, suffix="B"): | |||
| for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: | |||
| if abs(num) < 1024.0: | |||
| return "%3.1f%s%s" % (num, unit, suffix) | |||
| num /= 1024.0 | |||
| return "%.1f%s%s" % (num, "Yi", suffix) | |||
| # Memory Reducer | |||
| def reduce_mem_usage(df, float16_flag=True, verbose=True): | |||
| numerics = ["int16", "int32", "int64", "float16", "float32", "float64"] | |||
| start_mem = df.memory_usage().sum() / 1024**2 | |||
| for col in df.columns: | |||
| col_type = df[col].dtypes | |||
| if col_type in numerics: | |||
| c_min = df[col].min() | |||
| c_max = df[col].max() | |||
| if str(col_type)[:3] == "int": | |||
| if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max: | |||
| df[col] = df[col].astype(np.int8) | |||
| elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max: | |||
| df[col] = df[col].astype(np.int16) | |||
| elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max: | |||
| df[col] = df[col].astype(np.int32) | |||
| elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max: | |||
| df[col] = df[col].astype(np.int64) | |||
| else: | |||
| if float16_flag and c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max: | |||
| df[col] = df[col].astype(np.float16) | |||
| elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max: | |||
| df[col] = df[col].astype(np.float32) | |||
| else: | |||
| df[col] = df[col].astype(np.float64) | |||
| end_mem = df.memory_usage().sum() / 1024**2 | |||
| if verbose: | |||
| print( | |||
| "Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)".format( | |||
| end_mem, 100 * (start_mem - end_mem) / start_mem | |||
| ) | |||
| ) | |||
| return df | |||
| # Merging by concat to not lose dtypes | |||
| def merge_by_concat(df1, df2, merge_on): | |||
| merged_gf = df1[merge_on] | |||
| merged_gf = merged_gf.merge(df2, on=merge_on, how="left") | |||
| new_columns = [col for col in list(merged_gf) if col not in merge_on] | |||
| df1 = pd.concat([df1, merged_gf[new_columns]], axis=1) | |||
| return df1 | |||
| def model_predict(algo, idx, test_x): | |||
| store = store_list[idx] | |||
| if algo == "lgb": | |||
| model = lgb.Booster(model_file=os.path.join(model_dir, f"lgb_{store}.out")) | |||
| return model.predict(test_x, num_iteration=model.best_iteration) | |||
| elif algo == "ridge": | |||
| model = joblib.load(os.path.join(model_dir, f"ridge_{store}.out")) | |||
| return model.predict(test_x) | |||
| elif algo == "svm": | |||
| model = joblib.load(os.path.join(model_dir, f"svm_{store}.out")) | |||
| return model.predict(test_x) | |||
| def get_weights(algo): | |||
| weights = [] | |||
| if algo == "lgb": | |||
| for store in store_list: | |||
| model = lgb.Booster(model_file=os.path.join(model_dir, f"lgb_{store}.out")) | |||
| weights.append(model.feature_importance()) | |||
| else: | |||
| for store in store_list: | |||
| model = joblib.load(os.path.join(model_dir, f"ridge_{store}.out")) | |||
| weights.append(model.coef_) | |||
| return np.array(weights) | |||
| def score(real_y, pred_y, sample_weight, multioutput): | |||
| return mean_squared_error(real_y, pred_y, sample_weight=sample_weight, multioutput=multioutput, squared=False) | |||
| def acquire_data(store, fill_flag=False): | |||
| TARGET = "sales" | |||
| suffix = f"_fill" if fill_flag else "" | |||
| train = pd.read_pickle(os.path.join(processed_data_dir, f"train_{store}{suffix}.pkl")) | |||
| val = pd.read_pickle(os.path.join(processed_data_dir, f"val_{store}{suffix}.pkl")) | |||
| train_y = train[TARGET] | |||
| train_x = train.drop(columns=TARGET, axis=1) | |||
| val_y = val[TARGET] | |||
| val_x = val.drop(columns=TARGET, axis=1) | |||
| train_x = train_x.to_numpy() | |||
| train_y = train_y.to_numpy() | |||
| val_x = val_x.to_numpy() | |||
| val_y = val_y.to_numpy() | |||
| return train_x, train_y, val_x, val_y | |||
| @@ -1,211 +0,0 @@ | |||
| import os | |||
| import fire | |||
| import time | |||
| import zipfile | |||
| import numpy as np | |||
| from tqdm import tqdm | |||
| from shutil import copyfile, rmtree | |||
| import learnware | |||
| from learnware.market import instantiate_learnware_market, BaseUserInfo | |||
| from learnware.reuse import JobSelectorReuser, AveragingReuser | |||
| from learnware.specification import generate_rkme_table_spec | |||
| from m5 import DataLoader | |||
| from learnware.logger import get_module_logger | |||
| logger = get_module_logger("m5_test", level="INFO") | |||
| output_description = { | |||
| "Dimension": 1, | |||
| "Description": {}, | |||
| } | |||
| input_description = { | |||
| "Dimension": 82, | |||
| "Description": {}, | |||
| } | |||
| semantic_specs = [ | |||
| { | |||
| "Data": {"Values": ["Table"], "Type": "Class"}, | |||
| "Task": {"Values": ["Regression"], "Type": "Class"}, | |||
| "Library": {"Values": ["Scikit-learn"], "Type": "Class"}, | |||
| "Scenario": {"Values": ["Business"], "Type": "Tag"}, | |||
| "Description": {"Values": "", "Type": "String"}, | |||
| "Name": {"Values": "learnware_1", "Type": "String"}, | |||
| "Input": input_description, | |||
| "Output": output_description, | |||
| "License": {"Values": ["MIT"], "Type": "Class"}, | |||
| } | |||
| ] | |||
| user_semantic = { | |||
| "Data": {"Values": ["Table"], "Type": "Class"}, | |||
| "Task": {"Values": ["Regression"], "Type": "Class"}, | |||
| "Library": {"Values": ["Scikit-learn"], "Type": "Class"}, | |||
| "Scenario": {"Values": ["Business"], "Type": "Tag"}, | |||
| "Description": {"Values": "", "Type": "String"}, | |||
| "Name": {"Values": "", "Type": "String"}, | |||
| "Input": input_description, | |||
| "Output": output_description, | |||
| "License": {"Values": ["MIT"], "Type": "Class"}, | |||
| } | |||
| class M5DatasetWorkflow: | |||
| def _init_m5_dataset(self): | |||
| m5 = DataLoader() | |||
| m5.regenerate_data() | |||
| algo_list = ["ridge", "lgb"] | |||
| for algo in algo_list: | |||
| m5.set_algo(algo) | |||
| m5.retrain_models() | |||
| def _init_learnware_market(self): | |||
| """initialize learnware market""" | |||
| # database_ops.clear_learnware_table() | |||
| learnware.init() | |||
| easy_market = instantiate_learnware_market(name="easy", rebuild=True) | |||
| print("Total Item:", len(easy_market)) | |||
| zip_path_list = [] | |||
| curr_root = os.path.dirname(os.path.abspath(__file__)) | |||
| curr_root = os.path.join(curr_root, "learnware_pool") | |||
| for zip_path in os.listdir(curr_root): | |||
| zip_path_list.append(os.path.join(curr_root, zip_path)) | |||
| for idx, zip_path in enumerate(zip_path_list): | |||
| semantic_spec = semantic_specs[0] | |||
| semantic_spec["Name"]["Values"] = "learnware_%d" % (idx) | |||
| semantic_spec["Description"]["Values"] = "test_learnware_number_%d" % (idx) | |||
| easy_market.add_learnware(zip_path, semantic_spec) | |||
| print("Total Item:", len(easy_market)) | |||
| def prepare_learnware(self, regenerate_flag=False): | |||
| if regenerate_flag: | |||
| self._init_m5_dataset() | |||
| m5 = DataLoader() | |||
| idx_list = m5.get_idx_list() | |||
| algo_list = ["lgb"] # algo_list = ["ridge", "lgb"] | |||
| curr_root = os.path.dirname(os.path.abspath(__file__)) | |||
| curr_root = os.path.join(curr_root, "learnware_pool") | |||
| os.makedirs(curr_root, exist_ok=True) | |||
| for idx in tqdm(idx_list): | |||
| train_x, train_y, test_x, test_y = m5.get_idx_data(idx) | |||
| st = time.time() | |||
| spec = generate_rkme_table_spec(X=train_x, gamma=0.1, cuda_idx=0) | |||
| ed = time.time() | |||
| logger.info("Stat spec generated in %.3f s" % (ed - st)) | |||
| for algo in algo_list: | |||
| m5.set_algo(algo) | |||
| dir_path = os.path.join(curr_root, f"{algo}_{idx}") | |||
| os.makedirs(dir_path, exist_ok=True) | |||
| spec_path = os.path.join(dir_path, "rkme.json") | |||
| spec.save(spec_path) | |||
| model_path = m5.get_model_path(idx) | |||
| model_file = os.path.join(dir_path, "model.out") | |||
| copyfile(model_path, model_file) | |||
| init_file = os.path.join(dir_path, "__init__.py") | |||
| copyfile("example_init.py", init_file) | |||
| yaml_file = os.path.join(dir_path, "learnware.yaml") | |||
| copyfile("example.yaml", yaml_file) | |||
| zip_file = dir_path + ".zip" | |||
| with zipfile.ZipFile(zip_file, "w") as zip_obj: | |||
| for foldername, subfolders, filenames in os.walk(dir_path): | |||
| for filename in filenames: | |||
| file_path = os.path.join(foldername, filename) | |||
| zip_info = zipfile.ZipInfo(filename) | |||
| zip_info.compress_type = zipfile.ZIP_STORED | |||
| with open(file_path, "rb") as file: | |||
| zip_obj.writestr(zip_info, file.read()) | |||
| rmtree(dir_path) | |||
| def test(self, regenerate_flag=False): | |||
| self.prepare_learnware(regenerate_flag) | |||
| self._init_learnware_market() | |||
| easy_market = instantiate_learnware_market(name="easy") | |||
| print("Total Item:", len(easy_market)) | |||
| m5 = DataLoader() | |||
| idx_list = m5.get_idx_list() | |||
| os.makedirs("./user_spec", exist_ok=True) | |||
| single_score_list = [] | |||
| random_score_list = [] | |||
| job_selector_score_list = [] | |||
| ensemble_score_list = [] | |||
| improve_list = [] | |||
| for idx in idx_list: | |||
| train_x, train_y, test_x, test_y = m5.get_idx_data(idx) | |||
| user_spec = generate_rkme_table_spec(X=test_x, gamma=0.1, cuda_idx=0) | |||
| user_spec_path = f"./user_spec/user_{idx}.json" | |||
| user_spec.save(user_spec_path) | |||
| user_info = BaseUserInfo(semantic_spec=user_semantic, stat_info={"RKMETableSpecification": user_spec}) | |||
| search_result = easy_market.search_learnware(user_info) | |||
| single_result = search_result.get_single_results() | |||
| multiple_result = search_result.get_multiple_results() | |||
| print(f"search result of user{idx}:") | |||
| print( | |||
| f"single model num: {len(single_result)}, max_score: {single_result[0].score}, min_score: {single_result[-1].score}" | |||
| ) | |||
| loss_list = [] | |||
| for single_item in single_result: | |||
| pred_y = single_item.learnware.predict(test_x) | |||
| loss_list.append(m5.score(test_y, pred_y)) | |||
| print( | |||
| f"Top1-score: {single_result[0].score}, learnware_id: {single_result[0].learnware.id}, loss: {loss_list[0]}" | |||
| ) | |||
| if len(multiple_result) > 0: | |||
| mixture_id = " ".join([learnware.id for learnware in multiple_result[0].learnwares]) | |||
| print(f"mixture_score: {multiple_result[0].score}, mixture_learnware: {mixture_id}") | |||
| mixture_learnware_list = multiple_result[0].learnwares | |||
| else: | |||
| mixture_learnware_list = [single_result[0].learnware] | |||
| reuse_job_selector = JobSelectorReuser(learnware_list=mixture_learnware_list, use_herding=False) | |||
| job_selector_predict_y = reuse_job_selector.predict(user_data=test_x) | |||
| job_selector_score = m5.score(test_y, job_selector_predict_y) | |||
| print(f"mixture reuse loss (job selector): {job_selector_score}") | |||
| reuse_ensemble = AveragingReuser(learnware_list=mixture_learnware_list, mode="vote_by_prob") | |||
| ensemble_predict_y = reuse_ensemble.predict(user_data=test_x) | |||
| ensemble_score = m5.score(test_y, ensemble_predict_y) | |||
| print(f"mixture reuse loss (ensemble): {ensemble_score}\n") | |||
| single_score_list.append(loss_list[0]) | |||
| random_score_list.append(np.mean(loss_list)) | |||
| job_selector_score_list.append(job_selector_score) | |||
| ensemble_score_list.append(ensemble_score) | |||
| improve_list.append((np.mean(loss_list) - loss_list[0]) / np.mean(loss_list)) | |||
| logger.info("Single search score %.3f +/- %.3f" % (np.mean(single_score_list), np.std(single_score_list))) | |||
| logger.info("Random search score: %.3f +/- %.3f" % (np.mean(random_score_list), np.std(random_score_list))) | |||
| logger.info("Average score improvement: %.3f" % (np.mean(improve_list))) | |||
| logger.info( | |||
| "Job selector score: %.3f +/- %.3f" % (np.mean(job_selector_score_list), np.std(job_selector_score_list)) | |||
| ) | |||
| logger.info( | |||
| "Average ensemble score: %.3f +/- %.3f" % (np.mean(ensemble_score_list), np.std(ensemble_score_list)) | |||
| ) | |||
| if __name__ == "__main__": | |||
| fire.Fire(M5DatasetWorkflow) | |||
| @@ -1,87 +0,0 @@ | |||
| import hashlib | |||
| import requests | |||
| import os | |||
| import random | |||
| import json | |||
| import time | |||
| from tqdm import tqdm | |||
| email = "tanzh@lamda.nju.edu.cn" | |||
| password = hashlib.md5(b"Qwerty123").hexdigest() | |||
| login_url = "http://210.28.134.201:8089/auth/login" | |||
| submit_url = "http://210.28.134.201:8089/user/add_learnware" | |||
| all_data_type = ["Table", "Image", "Video", "Text", "Audio"] | |||
| all_task_type = [ | |||
| "Classification", | |||
| "Regression", | |||
| "Clustering", | |||
| "Feature Extraction", | |||
| "Generation", | |||
| "Segmentation", | |||
| "Object Detection", | |||
| ] | |||
| all_device_type = ["CPU", "GPU"] | |||
| all_scenario = [ | |||
| "Business", | |||
| "Financial", | |||
| "Health", | |||
| "Politics", | |||
| "Computer", | |||
| "Internet", | |||
| "Traffic", | |||
| "Nature", | |||
| "Fashion", | |||
| "Industry", | |||
| "Agriculture", | |||
| "Education", | |||
| "Entertainment", | |||
| "Architecture", | |||
| ] | |||
| # ############### | |||
| # 以上部分无需修改 # | |||
| # ############### | |||
| def main(): | |||
| session = requests.Session() | |||
| res = session.post(login_url, json={"email": email, "password": password}) | |||
| # /path/to/learnware/folder 修改为学件文件夹地址 | |||
| learnware_pool = os.listdir(os.path.join(os.path.abspath("."), "learnware_pool")) | |||
| for learnware in learnware_pool: | |||
| # 修改相应的语义规约 | |||
| name = "M5_Shop" + "%02d" % int(learnware.split(".")[0].split("_")[1]) | |||
| name = name + "_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) | |||
| description = f"This is a description of learnware {name}" | |||
| data = random.choice(all_data_type) | |||
| task = random.choice(all_task_type) | |||
| device = list(set(random.choices(all_device_type, k=2))) | |||
| scenario = list(set(random.choices(all_scenario, k=5))) | |||
| semantic_specification = { | |||
| "Data": {"Values": ["Table"], "Type": "Class"}, | |||
| "Task": {"Values": ["Regression"], "Type": "Class"}, | |||
| "Device": {"Values": ["CPU"], "Type": "Tag"}, | |||
| "Scenario": {"Values": ["Business"], "Type": "Tag"}, | |||
| "Description": {"Values": "A sales-forecasting model from Walmart store", "Type": "String"}, | |||
| "Name": {"Values": name, "Type": "String"}, | |||
| "License": {"Values": ["MIT"], "Type": "Class"}, | |||
| } | |||
| res = session.post( | |||
| submit_url, | |||
| data={ | |||
| "semantic_specification": json.dumps(semantic_specification), | |||
| }, | |||
| files={ | |||
| "learnware_file": open( | |||
| os.path.join(os.path.abspath("."), "learnware_pool", learnware), | |||
| "rb", | |||
| ) | |||
| }, | |||
| ) | |||
| assert json.loads(res.text)["code"] == 0, "Upload error" | |||
| if __name__ == "__main__": | |||
| main() | |||
| @@ -1,8 +0,0 @@ | |||
| model: | |||
| class_name: Model | |||
| kwargs: {} | |||
| stat_specifications: | |||
| - module_path: learnware.specification | |||
| class_name: RKMETableSpecification | |||
| file_name: rkme.json | |||
| kwargs: {} | |||
| @@ -1,20 +0,0 @@ | |||
| import os | |||
| import joblib | |||
| import numpy as np | |||
| from learnware.model import BaseModel | |||
| class Model(BaseModel): | |||
| def __init__(self): | |||
| super(Model, self).__init__(input_shape=(31,), output_shape=(1,)) | |||
| dir_path = os.path.dirname(os.path.abspath(__file__)) | |||
| self.model = joblib.load(os.path.join(dir_path, "model.out")) | |||
| def fit(self, X: np.ndarray, y: np.ndarray): | |||
| pass | |||
| def predict(self, X: np.ndarray) -> np.ndarray: | |||
| return self.model.predict(X) | |||
| def finetune(self, X: np.ndarray, y: np.ndarray): | |||
| pass | |||
| @@ -1,208 +0,0 @@ | |||
| import os | |||
| import fire | |||
| import zipfile | |||
| import time | |||
| import numpy as np | |||
| from tqdm import tqdm | |||
| from shutil import copyfile, rmtree | |||
| import learnware | |||
| from learnware.market import instantiate_learnware_market, BaseUserInfo | |||
| from learnware.reuse import JobSelectorReuser, AveragingReuser | |||
| from learnware.specification import generate_rkme_table_spec | |||
| from pfs import Dataloader | |||
| from learnware.logger import get_module_logger | |||
| logger = get_module_logger("pfs_test", level="INFO") | |||
| output_description = { | |||
| "Dimension": 1, | |||
| "Description": {}, | |||
| } | |||
| input_description = { | |||
| "Dimension": 31, | |||
| "Description": {}, | |||
| } | |||
| semantic_specs = [ | |||
| { | |||
| "Data": {"Values": ["Table"], "Type": "Class"}, | |||
| "Task": {"Values": ["Regression"], "Type": "Class"}, | |||
| "Library": {"Values": ["Scikit-learn"], "Type": "Class"}, | |||
| "Scenario": {"Values": ["Business"], "Type": "Tag"}, | |||
| "Description": {"Values": "", "Type": "String"}, | |||
| "Name": {"Values": "learnware_1", "Type": "String"}, | |||
| "Input": input_description, | |||
| "Output": output_description, | |||
| "License": {"Values": ["MIT"], "Type": "Class"}, | |||
| } | |||
| ] | |||
| user_semantic = { | |||
| "Data": {"Values": ["Table"], "Type": "Class"}, | |||
| "Task": {"Values": ["Regression"], "Type": "Class"}, | |||
| "Library": {"Values": ["Scikit-learn"], "Type": "Class"}, | |||
| "Scenario": {"Values": ["Business"], "Type": "Tag"}, | |||
| "Description": {"Values": "", "Type": "String"}, | |||
| "Name": {"Values": "", "Type": "String"}, | |||
| "Input": input_description, | |||
| "Output": output_description, | |||
| "License": {"Values": ["MIT"], "Type": "Class"}, | |||
| } | |||
| class PFSDatasetWorkflow: | |||
| def _init_pfs_dataset(self): | |||
| pfs = Dataloader() | |||
| pfs.regenerate_data() | |||
| algo_list = ["ridge"] # "ridge", "lgb" | |||
| for algo in algo_list: | |||
| pfs.set_algo(algo) | |||
| pfs.retrain_models() | |||
| def _init_learnware_market(self): | |||
| """initialize learnware market""" | |||
| learnware.init() | |||
| easy_market = instantiate_learnware_market(market_id="pfs", name="easy", rebuild=True) | |||
| print("Total Item:", len(easy_market)) | |||
| zip_path_list = [] | |||
| curr_root = os.path.dirname(os.path.abspath(__file__)) | |||
| curr_root = os.path.join(curr_root, "learnware_pool") | |||
| for zip_path in os.listdir(curr_root): | |||
| zip_path_list.append(os.path.join(curr_root, zip_path)) | |||
| for idx, zip_path in enumerate(zip_path_list): | |||
| semantic_spec = semantic_specs[0] | |||
| semantic_spec["Name"]["Values"] = "learnware_%d" % (idx) | |||
| semantic_spec["Description"]["Values"] = "test_learnware_number_%d" % (idx) | |||
| easy_market.add_learnware(zip_path, semantic_spec) | |||
| print("Total Item:", len(easy_market)) | |||
| def prepare_learnware(self, regenerate_flag=False): | |||
| if regenerate_flag: | |||
| self._init_pfs_dataset() | |||
| pfs = Dataloader() | |||
| idx_list = pfs.get_idx_list() | |||
| algo_list = ["ridge"] # ["ridge", "lgb"] | |||
| curr_root = os.path.dirname(os.path.abspath(__file__)) | |||
| curr_root = os.path.join(curr_root, "learnware_pool") | |||
| os.makedirs(curr_root, exist_ok=True) | |||
| for idx in tqdm(idx_list): | |||
| train_x, train_y, test_x, test_y = pfs.get_idx_data(idx) | |||
| st = time.time() | |||
| spec = generate_rkme_table_spec(X=train_x, gamma=0.1, cuda_idx=0) | |||
| ed = time.time() | |||
| logger.info("Stat spec generated in %.3f s" % (ed - st)) | |||
| for algo in algo_list: | |||
| pfs.set_algo(algo) | |||
| dir_path = os.path.join(curr_root, f"{algo}_{idx}") | |||
| os.makedirs(dir_path, exist_ok=True) | |||
| spec_path = os.path.join(dir_path, "rkme.json") | |||
| spec.save(spec_path) | |||
| model_path = pfs.get_model_path(idx) | |||
| model_file = os.path.join(dir_path, "model.out") | |||
| copyfile(model_path, model_file) | |||
| init_file = os.path.join(dir_path, "__init__.py") | |||
| copyfile("example_init.py", init_file) | |||
| yaml_file = os.path.join(dir_path, "learnware.yaml") | |||
| copyfile("example.yaml", yaml_file) | |||
| zip_file = dir_path + ".zip" | |||
| with zipfile.ZipFile(zip_file, "w") as zip_obj: | |||
| for foldername, subfolders, filenames in os.walk(dir_path): | |||
| for filename in filenames: | |||
| file_path = os.path.join(foldername, filename) | |||
| zip_info = zipfile.ZipInfo(filename) | |||
| zip_info.compress_type = zipfile.ZIP_STORED | |||
| with open(file_path, "rb") as file: | |||
| zip_obj.writestr(zip_info, file.read()) | |||
| rmtree(dir_path) | |||
| def test(self, regenerate_flag=False): | |||
| self.prepare_learnware(regenerate_flag) | |||
| self._init_learnware_market() | |||
| easy_market = instantiate_learnware_market(market_id="pfs", name="easy") | |||
| print("Total Item:", len(easy_market)) | |||
| pfs = Dataloader() | |||
| idx_list = pfs.get_idx_list() | |||
| os.makedirs("./user_spec", exist_ok=True) | |||
| single_score_list = [] | |||
| random_score_list = [] | |||
| job_selector_score_list = [] | |||
| ensemble_score_list = [] | |||
| improve_list = [] | |||
| for idx in idx_list: | |||
| train_x, train_y, test_x, test_y = pfs.get_idx_data(idx) | |||
| user_spec = generate_rkme_table_spec(X=test_x, gamma=0.1, cuda_idx=0) | |||
| user_spec_path = f"./user_spec/user_{idx}.json" | |||
| user_spec.save(user_spec_path) | |||
| user_info = BaseUserInfo(semantic_spec=user_semantic, stat_info={"RKMETableSpecification": user_spec}) | |||
| search_result = easy_market.search_learnware(user_info) | |||
| single_result = search_result.get_single_results() | |||
| multiple_result = search_result.get_multiple_results() | |||
| print(f"search result of user{idx}:") | |||
| print( | |||
| f"single model num: {len(single_result)}, max_score: {single_result[0].score}, min_score: {single_result[-1].score}" | |||
| ) | |||
| loss_list = [] | |||
| for single_item in single_result: | |||
| pred_y = single_item.learnware.predict(test_x) | |||
| loss_list.append(pfs.score(test_y, pred_y)) | |||
| print( | |||
| f"Top1-score: {single_result[0].score}, learnware_id: {single_result[0].learnware.id}, loss: {loss_list[0]}, random: {np.mean(loss_list)}" | |||
| ) | |||
| if len(multiple_result) > 0: | |||
| mixture_id = " ".join([learnware.id for learnware in multiple_result[0].learnwares]) | |||
| print(f"mixture_score: {multiple_result[0].score}, mixture_learnware: {mixture_id}") | |||
| mixture_learnware_list = multiple_result[0].learnwares | |||
| else: | |||
| mixture_learnware_list = [single_result[0].learnware] | |||
| reuse_job_selector = JobSelectorReuser(learnware_list=mixture_learnware_list, use_herding=False) | |||
| job_selector_predict_y = reuse_job_selector.predict(user_data=test_x) | |||
| job_selector_score = pfs.score(test_y, job_selector_predict_y) | |||
| print(f"mixture reuse loss (job selector): {job_selector_score}") | |||
| reuse_ensemble = AveragingReuser(learnware_list=mixture_learnware_list) | |||
| ensemble_predict_y = reuse_ensemble.predict(user_data=test_x) | |||
| ensemble_score = pfs.score(test_y, ensemble_predict_y) | |||
| print(f"mixture reuse loss (ensemble): {ensemble_score}\n") | |||
| single_score_list.append(loss_list[0]) | |||
| random_score_list.append(np.mean(loss_list)) | |||
| job_selector_score_list.append(job_selector_score) | |||
| ensemble_score_list.append(ensemble_score) | |||
| improve_list.append((np.mean(loss_list) - loss_list[0]) / np.mean(loss_list)) | |||
| logger.info("Single search score %.3f +/- %.3f" % (np.mean(single_score_list), np.std(single_score_list))) | |||
| logger.info("Random search score: %.3f +/- %.3f" % (np.mean(random_score_list), np.std(random_score_list))) | |||
| logger.info("Average score improvement: %.3f" % (np.mean(improve_list))) | |||
| logger.info( | |||
| "Job selector score: %.3f +/- %.3f" % (np.mean(job_selector_score_list), np.std(job_selector_score_list)) | |||
| ) | |||
| logger.info( | |||
| "Average ensemble score: %.3f +/- %.3f" % (np.mean(ensemble_score_list), np.std(ensemble_score_list)) | |||
| ) | |||
| if __name__ == "__main__": | |||
| fire.Fire(PFSDatasetWorkflow) | |||
| @@ -1,48 +0,0 @@ | |||
| # Learnware based on Prediction Future Sales (PFS) data downloaded from Kaggle | |||
| --> Data Page Link: https://www.kaggle.com/c/competitive-data-science-predict-future-sales/data | |||
| --> Code Page Link: https://www.kaggle.com/uladzimirkapeika/feature-engineering-lightgbm-top-1 | |||
| # PFS任务描述 | |||
| --> 目标:预测每个商店每个商品在下一个月的销量(注意:粒度为月,而不是每天) | |||
| --> 特征信息:商店所在城市信息、商品类别信息、商品价格信息、商品历史价格信息(特征工程中只使用了前三个月的历史信息然后拼接在一起)等 | |||
| --> 使用的模型:XgBoost, LightGBM, LinearRegression | |||
| --> 评价指标:RMSE | |||
| * split_pfs_data.py | |||
| --> 根据Kaggle上公开的数据预处理方案处理下载的数据 | |||
| --> 直接运行即可将数据根据Shop ID划分为每个商店的信息,包括: | |||
| ----> 每个商品在每个月下的特征和目标值,存储为pandas.DataFrame格式 | |||
| ----> 字段包括: | |||
| -- 标识信息: 'shop_id', 'item_id', 'date_block_num' (标识月份), | |||
| -- 目标值(本月销量): 'item_cnt_month', | |||
| -- 城市信息: 'city_code', 'city_coord_1', 'city_coord_2', 'country_part', | |||
| -- 商品种类信息: 'item_category_common', 'item_category_code', | |||
| -- 该月的时间信息: 'weeknd_count', 'days_in_month', | |||
| -- 商品是否第一次销售: 'item_first_interaction', 'shop_item_sold_before', | |||
| -- 商品前三个月的销售量和价格信息: | |||
| 'item_cnt_month_lag_1', 'item_cnt_month_lag_2', 'item_cnt_month_lag_3', | |||
| 'item_shop_price_avg_lag_1', 'item_shop_price_avg_lag_2', 'item_shop_price_avg_lag_3', | |||
| 'item_target_enc_lag_1', 'item_target_enc_lag_2', 'item_target_enc_lag_3', | |||
| 'item_loc_target_enc_lag_1', 'item_loc_target_enc_lag_2', 'item_loc_target_enc_lag_3', 'item_shop_target_enc_lag_1', 'item_shop_target_enc_lag_2', 'item_shop_target_enc_lag_3', | |||
| 'new_item_cat_avg_lag_1', 'new_item_cat_avg_lag_2', 'new_item_cat_avg_lag_3', | |||
| 'new_item_shop_cat_avg_lag_1', 'new_item_shop_cat_avg_lag_2', 'new_item_shop_cat_avg_lag_3', | |||
| 'item_cnt_month_lag_1_adv', 'item_cnt_month_lag_2_adv', 'item_cnt_month_lag_3_adv' | |||
| ----> 特征: 除了'item_cnt_month'之外的列都当做特征列 | |||
| ----> 目标值: 'item_cnt_month' | |||
| ----> 时间标识: 'data_block_num'将2013.01到2015.10月的数据标识为0-33,要预测的2015.11月数据为34 | |||
| --> 存储结果分为两部分: 按照时间划分的train & val,是pandas.DataFrame格式 | |||
| * pfs_cross_transfer.py | |||
| --> 在各自商店训练集上训练一个模型,然后在所有商店的测试集上测试,保存两两预测的RMSE结果,并进行分析 | |||
| --> 分析包括两部分:(1) 对于一个目标商店,其余源域模型的性能均值,方差,最小值(最好的模型),最大值,超过均值的源域数目,选择最好模型能够提升的比例等等;(2) HeatMap | |||
| --> 需要扩展的方向:(1) LightGBM, Ridge, Xgboost,以及超参数调参;(2) 特征工程去除标识信息,例如shop_id, item_id等等 | |||
| * data_api.py | |||
| --> 后续封装的代码,需继续完善 | |||
| * packages | |||
| --> pip install lightgbm | |||
| @@ -1,77 +0,0 @@ | |||
| import joblib | |||
| import os | |||
| from sklearn.metrics import mean_squared_error | |||
| from .pfs_cross_transfer import * | |||
| from .split_data import feature_engineering | |||
| class Dataloader: | |||
| def __init__(self): | |||
| self.algo = "ridge" | |||
| def regenerate_data(self): | |||
| feature_engineering() | |||
| def set_algo(self, algo): | |||
| self.algo = algo | |||
| def get_algo_list(self): | |||
| return ["lgb", "ridge"] | |||
| def get_idx_list(self): | |||
| return [i for i in range(53)] | |||
| def get_idx_data(self, idx): | |||
| shop_ids = [i for i in range(60) if i not in [0, 1, 40]] | |||
| shop_ids = [i for i in shop_ids if i not in [8, 11, 23, 36]] | |||
| fpath = os.path.join(pfs_split_dir, "Shop{:0>2d}-train.csv".format(shop_ids[idx])) | |||
| train_xs, train_ys, _, _ = load_pfs_data(fpath) | |||
| fpath = os.path.join(pfs_split_dir, "Shop{:0>2d}-val.csv".format(shop_ids[idx])) | |||
| test_xs, test_ys, _, _ = load_pfs_data(fpath) | |||
| return train_xs, train_ys, test_xs, test_ys | |||
| def get_model_path(self, idx): | |||
| shop_ids = [i for i in range(60) if i not in [0, 1, 40]] | |||
| shop_ids = [i for i in shop_ids if i not in [8, 11, 23, 36]] | |||
| return os.path.join(model_dir, "{}_Shop{:0>2d}.out".format(self.algo, shop_ids[idx])) | |||
| def retrain_models(self): | |||
| algo = self.algo | |||
| errs = get_errors(algo=algo) | |||
| fpath = os.path.join(pfs_res_dir, "PFS_{}_errs.txt".format(algo)) | |||
| np.savetxt(fpath, errs.T) | |||
| plot_heatmap(errs.T, algo) | |||
| weights = np.loadtxt(os.path.join(pfs_res_dir, "PFS_{}_weights.txt".format(algo))) | |||
| plot_performance(errs.T, weights, algo) | |||
| def retrain_split_models(self): | |||
| fpath = os.path.join(pfs_res_dir, "PFS_{}_split_errs_user.txt".format(self.algo)) | |||
| if os.path.exists(fpath): | |||
| return np.loadtxt(fpath) | |||
| algo = self.algo | |||
| errs = get_split_errs(algo=algo) | |||
| fpath = os.path.join(pfs_res_dir, "PFS_{}_split_errs_user.txt".format(algo)) | |||
| np.savetxt(fpath, errs) | |||
| return errs | |||
| def get_errs(self): | |||
| return np.loadtxt(os.path.join(pfs_res_dir, "PFS_{}_errs.txt".format(self.algo))) | |||
| def get_weights(self): | |||
| return np.loadtxt(os.path.join(pfs_res_dir, "PFS_{}_weights.txt".format(self.algo))) | |||
| def predict(self, idx, test_x): | |||
| shop_ids = [i for i in range(60) if i not in [0, 1, 40]] | |||
| shop_ids = [i for i in shop_ids if i not in [8, 11, 23, 36]] | |||
| model = joblib.load(os.path.join(model_dir, "{}_Shop{:0>2d}.out".format(self.algo, shop_ids[idx]))) | |||
| # test_x = (test_x - test_x.min(0)) / (test_x.max(0) - test_x.min(0) + 0.0001) | |||
| return model.predict(test_x) | |||
| def score(self, real_y, pred_y, sample_weight=None): | |||
| return mean_squared_error(real_y, pred_y, sample_weight=sample_weight, squared=False) | |||
| @@ -1,272 +0,0 @@ | |||
| market_store_list = [ | |||
| 0, | |||
| 2, | |||
| 3, | |||
| 4, | |||
| 5, | |||
| 6, | |||
| 7, | |||
| 8, | |||
| 9, | |||
| 10, | |||
| 12, | |||
| 13, | |||
| 14, | |||
| 15, | |||
| 16, | |||
| 17, | |||
| 18, | |||
| 20, | |||
| 22, | |||
| 23, | |||
| 24, | |||
| 25, | |||
| 26, | |||
| 27, | |||
| 28, | |||
| 30, | |||
| 31, | |||
| 32, | |||
| 33, | |||
| 34, | |||
| 35, | |||
| 37, | |||
| 38, | |||
| 39, | |||
| 40, | |||
| 42, | |||
| 44, | |||
| 45, | |||
| 46, | |||
| 47, | |||
| 48, | |||
| 50, | |||
| 52, | |||
| ] | |||
| user_store_list = [1, 11, 19, 21, 29, 36, 43, 49] | |||
| dataset_info = { | |||
| "name": "PFS", | |||
| "range of date": "2014.01-2015.10", | |||
| "description": "You are provided with daily historical sales data. The task is to forecast the total amount of products sold in every shop for the test set. Note that the list of shops and products slightly changes every month. More specifically, the dataset involves 53 shops in Russia", | |||
| "location_original": [ | |||
| "Адыгея, Россия", | |||
| "Балашиха, Россия", | |||
| "Волжский, Россия", | |||
| "Вологда, Россия", | |||
| "Воронеж, Россия", | |||
| "Воронеж, Россия", | |||
| "Воронеж, Россия", | |||
| "выезд, Россия", | |||
| "Жуковский, Россия", | |||
| "интернет-магазин, Россия", | |||
| "Казань, Россия", | |||
| "Калуга, Россия", | |||
| "колонна, Россия", | |||
| "Красноярск, Россия", | |||
| "Красноярск, Россия", | |||
| "курск, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Москва, Россия", | |||
| "Мытищи, Россия", | |||
| "Н.Новгород, Россия", | |||
| "Н.Новгород, Россия", | |||
| "Новосибирск, Россия", | |||
| "Новосибирск, Россия", | |||
| "Ростовнадон, Россия", | |||
| "Ростовнадон, Россия", | |||
| "спб, Россия", | |||
| "спб, Россия", | |||
| "самара, Россия", | |||
| "самара, Россия", | |||
| "Сергий, Россия", | |||
| "Сургут, Россия", | |||
| "томск, Россия", | |||
| "тюмень, Россия", | |||
| "тюмень, Россия", | |||
| "тюмень, Россия", | |||
| "Уфа, Россия", | |||
| "Уфа, Россия", | |||
| "Химки, Россия", | |||
| "цифровой, Россия", | |||
| "Чехи, Россия", | |||
| "Якутск, Россия", | |||
| "Якутск, Россия", | |||
| "Ярославль, Россия", | |||
| ], | |||
| "location_english": [ | |||
| "adygea, Russia", | |||
| "Balashikha, Russia", | |||
| "Volzhsky, Russia", | |||
| "Vologda, Russia", | |||
| "Voronezh, Russia", | |||
| "Voronezh, Russia", | |||
| "Voronezh, Russia", | |||
| "outbound, Russia", | |||
| "zhukovsky, Russia", | |||
| "online stor, Russia", | |||
| "Kazan, Russia", | |||
| "Kaluga, Russia", | |||
| "column, Russia", | |||
| "Krasnoyarsk, Russia", | |||
| "Krasnoyarsk, Russia", | |||
| "kursk, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "Moscow, Russia", | |||
| "mytishchi, Russia", | |||
| "N.Novgorod, Russia", | |||
| "N.Novgorod, Russia", | |||
| "Novosibirsk, Russia", | |||
| "Novosibirsk, Russia", | |||
| "rostovnadon, Russia", | |||
| "rostovnadon, Russia", | |||
| "spb, Russia", | |||
| "spb, Russia", | |||
| "samara, Russia", | |||
| "samara, Russia", | |||
| "Sergius, Russia", | |||
| "surgut, Russia", | |||
| "tomsk, Russia", | |||
| "tyumen, Russia", | |||
| "tyumen, Russia", | |||
| "tyumen, Russia", | |||
| "Ufa, Russia", | |||
| "Ufa, Russia", | |||
| "Khimki, Russia", | |||
| "numeric, Russia", | |||
| "Czechs, Russia", | |||
| "Yakutsk, Russia", | |||
| "Yakutsk, Russia", | |||
| "Yaroslavl, Russia", | |||
| ], | |||
| "location_chinese": [ | |||
| "阿迪格亚, 俄罗斯", | |||
| "巴拉希哈, 俄罗斯", | |||
| "沃尔日斯基, 俄罗斯", | |||
| "沃洛格达, 俄罗斯", | |||
| "沃罗涅日, 俄罗斯", | |||
| "沃罗涅日, 俄罗斯", | |||
| "沃罗涅日, 俄罗斯", | |||
| "对外贸易, 俄罗斯", | |||
| "茹科夫斯基, 俄罗斯", | |||
| "在线商店, 俄罗斯", | |||
| "喀山, 俄罗斯", | |||
| "卡卢加, 俄罗斯", | |||
| "科洛姆纳, 俄罗斯", | |||
| "克拉斯诺亚尔斯克, 俄罗斯", | |||
| "克拉斯诺亚尔斯克, 俄罗斯", | |||
| "库尔斯克, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "莫斯科, 俄罗斯", | |||
| "梅季希, 俄罗斯", | |||
| "北诺夫哥罗德, 俄罗斯", | |||
| "北诺夫哥罗德, 俄罗斯", | |||
| "新西伯利亚, 俄罗斯", | |||
| "新西伯利亚, 俄罗斯", | |||
| "罗斯托夫纳东, 俄罗斯", | |||
| "罗斯托夫纳东, 俄罗斯", | |||
| "圣彼得堡, 俄罗斯", | |||
| "圣彼得堡, 俄罗斯", | |||
| "萨马拉, 俄罗斯", | |||
| "萨马拉, 俄罗斯", | |||
| "谢尔盖, 俄罗斯", | |||
| "苏尔古特, 俄罗斯", | |||
| "托木斯克, 俄罗斯", | |||
| "秋明, 俄罗斯", | |||
| "秋明, 俄罗斯", | |||
| "秋明, 俄罗斯", | |||
| "乌法, 俄罗斯", | |||
| "乌法, 俄罗斯", | |||
| "希姆基, 俄罗斯", | |||
| "在线商店, 俄罗斯", | |||
| "契诃夫, 俄罗斯", | |||
| "雅库茨克, 俄罗斯", | |||
| "雅库茨克, 俄罗斯", | |||
| "雅罗斯拉夫尔, 俄罗斯", | |||
| ], | |||
| "memory(KB)": [ | |||
| 246, | |||
| 302, | |||
| 3631, | |||
| 379, | |||
| 862, | |||
| 1020, | |||
| 471, | |||
| 867, | |||
| 588, | |||
| 233, | |||
| 657, | |||
| 1272, | |||
| 801, | |||
| 469, | |||
| 146, | |||
| 1309, | |||
| 98, | |||
| 1003, | |||
| 932, | |||
| 257, | |||
| 1959, | |||
| 1361, | |||
| 35, | |||
| 3265, | |||
| 217, | |||
| 283, | |||
| 4311, | |||
| 1155, | |||
| 43, | |||
| 1388, | |||
| 1971, | |||
| 971, | |||
| 7272, | |||
| 2782, | |||
| 304, | |||
| 6801, | |||
| 4942, | |||
| 181, | |||
| 190, | |||
| 3664, | |||
| 2061, | |||
| 170, | |||
| 807, | |||
| 593, | |||
| 1584, | |||
| 257, | |||
| 1819, | |||
| 50, | |||
| 1063, | |||
| 692, | |||
| 336, | |||
| 277, | |||
| 743, | |||
| ], | |||
| } | |||
| @@ -1,21 +0,0 @@ | |||
| import os | |||
| ROOT_PATH = os.path.abspath(os.path.join(__file__, "..", "data")) | |||
| raw_data_dir = os.path.join(ROOT_PATH, "raw_data") | |||
| split_data_dir = os.path.join(ROOT_PATH, "split_data") | |||
| res_dir = os.path.join(ROOT_PATH, "results") | |||
| model_dir = os.path.join(ROOT_PATH, "models") | |||
| model_dir2 = os.path.join(ROOT_PATH, "models2") | |||
| for dir_name in [ROOT_PATH, raw_data_dir, split_data_dir, res_dir, model_dir, model_dir2]: | |||
| if not os.path.exists(dir_name): | |||
| os.mkdir(dir_name) | |||
| pfs_data_dir = os.path.join(raw_data_dir, "PFS") | |||
| pfs_split_dir = os.path.join(split_data_dir, "PFS") | |||
| pfs_res_dir = os.path.join(res_dir, "PFS") | |||
| for dir_name in [pfs_data_dir, pfs_split_dir, pfs_res_dir]: | |||
| if not os.path.exists(dir_name): | |||
| os.mkdir(dir_name) | |||
| @@ -1,382 +0,0 @@ | |||
| import os | |||
| import pickle | |||
| import joblib | |||
| import numpy as np | |||
| import pandas as pd | |||
| import lightgbm as lgb | |||
| from sklearn.linear_model import Ridge | |||
| from sklearn.model_selection import GridSearchCV | |||
| from matplotlib import pyplot as plt | |||
| import matplotlib.ticker as ticker | |||
| from mpl_toolkits.axes_grid1 import make_axes_locatable | |||
| np.seterr(divide="ignore", invalid="ignore") | |||
| from .paths import pfs_split_dir, pfs_res_dir, model_dir | |||
| np.random.seed(0) | |||
| def load_pfs_data(fpath): | |||
| df = pd.read_csv(fpath) | |||
| features = list(df.columns) | |||
| features.remove("item_cnt_month") | |||
| features.remove("date_block_num") | |||
| # remove id info | |||
| # features.remove('shop_id') | |||
| # features.remove('item_id') | |||
| # remove discrete info | |||
| # features.remove('city_code') | |||
| # features.remove('item_category_code') | |||
| # features.remove('item_category_common') | |||
| xs = df[features].values | |||
| ys = df["item_cnt_month"].values | |||
| categorical_feature_names = ["country_part", "item_category_common", "item_category_code", "city_code"] | |||
| types = None | |||
| return xs, ys, features, types | |||
| def get_split_errs(algo): | |||
| """ | |||
| according to proportion_list, generate errs whose shape is [shop, split_data] | |||
| """ | |||
| shop_ids = [i for i in range(60) if i not in [0, 1, 40]] | |||
| shop_ids = [i for i in shop_ids if i not in [8, 11, 23, 36]] | |||
| user_list = [i for i in range(53)] | |||
| proportion_list = [100, 300, 500, 700, 900, 1000, 3000, 5000, 7000, 9000, 10000, 30000, 50000, 70000] | |||
| # train | |||
| errs = np.zeros((len(user_list), len(proportion_list))) | |||
| for s, sid in enumerate(user_list): | |||
| # load train data | |||
| fpath = os.path.join(pfs_split_dir, "Shop{:0>2d}-train.csv".format(shop_ids[sid])) | |||
| fpath_val = os.path.join(pfs_split_dir, "Shop{:0>2d}-val.csv".format(shop_ids[sid])) | |||
| train_xs, train_ys, _, _ = load_pfs_data(fpath) | |||
| val_xs, val_ys, _, _ = load_pfs_data(fpath_val) | |||
| print(shop_ids[sid], train_xs.shape, train_ys.shape) | |||
| # data regu | |||
| # train_xs = (train_xs - train_xs.min(0)) / (train_xs.max(0) - train_xs.min(0) + 0.0001) | |||
| # val_xs = (val_xs - val_xs.min(0)) / (val_xs.max(0) - val_xs.min(0) + 0.0001) | |||
| if algo == "lgb": | |||
| for tmp in range(len(proportion_list)): | |||
| model = lgb.LGBMModel( | |||
| boosting_type="gbdt", | |||
| num_leaves=2**7 - 1, | |||
| learning_rate=0.01, | |||
| objective="rmse", | |||
| metric="rmse", | |||
| feature_fraction=0.75, | |||
| bagging_fraction=0.75, | |||
| bagging_freq=5, | |||
| seed=1, | |||
| verbose=1, | |||
| n_estimators=100000, | |||
| ) | |||
| model_ori = joblib.load(os.path.join(model_dir, "{}_Shop{:0>2d}.out".format("lgb", shop_ids[sid]))) | |||
| para = model_ori.get_params() | |||
| para["n_estimators"] = 1000 | |||
| model.set_params(**para) | |||
| split = train_xs.shape[0] - proportion_list[tmp] | |||
| model.fit( | |||
| train_xs[split:,], | |||
| train_ys[split:], | |||
| eval_set=[(val_xs, val_ys)], | |||
| early_stopping_rounds=50, | |||
| verbose=100, | |||
| ) | |||
| pred_ys = model.predict(val_xs) | |||
| rmse = np.sqrt(((val_ys - pred_ys) ** 2).mean()) | |||
| errs[s][tmp] = rmse | |||
| return errs | |||
| def get_errors(algo): | |||
| shop_ids = [i for i in range(60) if i not in [0, 1, 40]] | |||
| shop_ids = [i for i in shop_ids if i not in [8, 11, 23, 36]] | |||
| # train | |||
| K = len(shop_ids) | |||
| feature_weight = np.zeros(()) | |||
| errs = np.zeros((K, K)) | |||
| for s, sid in enumerate(shop_ids): | |||
| # load train data | |||
| fpath = os.path.join(pfs_split_dir, "Shop{:0>2d}-train.csv".format(sid)) | |||
| fpath_val = os.path.join(pfs_split_dir, "Shop{:0>2d}-val.csv".format(sid)) | |||
| train_xs, train_ys, features, _ = load_pfs_data(fpath) | |||
| val_xs, val_ys, _, _ = load_pfs_data(fpath_val) | |||
| print(sid, train_xs.shape, train_ys.shape) | |||
| if s == 0: | |||
| feature_weight = np.zeros((K, len(features))) | |||
| if algo == "lgb": | |||
| model = lgb.LGBMModel( | |||
| boosting_type="gbdt", | |||
| num_leaves=2**7 - 1, | |||
| learning_rate=0.01, | |||
| objective="rmse", | |||
| metric="rmse", | |||
| feature_fraction=0.75, | |||
| bagging_fraction=0.75, | |||
| bagging_freq=5, | |||
| seed=1, | |||
| verbose=1, | |||
| n_estimators=1000, | |||
| ) | |||
| # train regu data | |||
| # train_xs = (train_xs - train_xs.min(0)) / (train_xs.max(0) - train_xs.min(0) + 0.0001) | |||
| # val_xs = (val_xs - val_xs.min(0)) / (val_xs.max(0) - val_xs.min(0) + 0.0001) | |||
| model.fit(train_xs, train_ys, eval_set=[(val_xs, val_ys)], early_stopping_rounds=100, verbose=100) | |||
| # grid search | |||
| # para = {'learning_rate': [0.005, 0.01, 0.015], 'num_leaves' : [128, 224, 300], 'max_depth' : [50, 66, 80]} | |||
| # grid_search = GridSearchCV(model, para, scoring='neg_mean_squared_error') | |||
| # grid_result = grid_search.fit(train_xs, train_ys, eval_set=[(val_xs, val_ys)], verbose = 1000, early_stopping_rounds=1000) | |||
| # model = grid_result.best_estimator_ | |||
| joblib.dump(model, os.path.join(model_dir, "{}_Shop{:0>2d}.out".format(algo, sid))) | |||
| importances = model.feature_importances_ | |||
| elif algo == "ridge": | |||
| # train_xs = (train_xs - train_xs.min(0)) / (train_xs.max(0) - train_xs.min(0) + 0.0001) | |||
| model = Ridge() | |||
| para = {"alpha": [0.01, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10, 20, 30]} | |||
| grid_search = GridSearchCV(model, para) | |||
| grid_result = grid_search.fit(train_xs, train_ys) | |||
| model = grid_result.best_estimator_ | |||
| importances = model.coef_ | |||
| joblib.dump(model, os.path.join(model_dir, "{}_Shop{:0>2d}.out".format(algo, sid))) | |||
| feature_weight[s] = importances | |||
| # leave one out test | |||
| for t, tid in enumerate(shop_ids): | |||
| # load test data | |||
| fpath = os.path.join(pfs_split_dir, "Shop{:0>2d}-val.csv".format(tid)) | |||
| test_xs, test_ys, _, _ = load_pfs_data(fpath) | |||
| # data regu | |||
| # test_xs = (test_xs - test_xs.min(0)) / (test_xs.max(0) - test_xs.min(0) + 0.0001) | |||
| pred_ys = model.predict(test_xs) | |||
| rmse = np.sqrt(((test_ys - pred_ys) ** 2).mean()) | |||
| print("Shop{} --> Shop{}: {}".format(s, t, rmse)) | |||
| errs[s][t] = rmse | |||
| np.savetxt(os.path.join(pfs_res_dir, "PFS_{}_weights.txt".format(algo)), feature_weight) | |||
| return errs | |||
| def plot_heatmap(mat, algo): | |||
| x_labels = [f"Model{i}" for i in range(mat.shape[1])] | |||
| y_labels = [f"Task{i}" for i in range(mat.shape[0])] | |||
| fig = plt.figure(figsize=(10, 9)) | |||
| plt.subplot(1, 1, 1) | |||
| ax = plt.gca() | |||
| im = plt.imshow(mat) | |||
| divider = make_axes_locatable(ax) | |||
| cax = divider.append_axes("right", size="4%", pad=0.3) | |||
| plt.colorbar(im, cax=cax) | |||
| ax.set_xticks(range(len(x_labels))) | |||
| ax.set_xticklabels(x_labels) | |||
| ax.set_yticks(range(len(y_labels))) | |||
| ax.set_yticklabels(y_labels) | |||
| ax.xaxis.set_major_locator(ticker.MultipleLocator(base=5)) | |||
| ax.yaxis.set_major_locator(ticker.MultipleLocator(base=5)) | |||
| ax.set_title(f"RMSE on Test set ({algo})") | |||
| plt.tight_layout() | |||
| plt.savefig(os.path.join(pfs_res_dir, "PFS_{}_heatmap.jpg".format(algo)), dpi=700) | |||
| def plot_var(errs, algo): | |||
| avg_err = [] | |||
| min_err = [] | |||
| med_err = [] | |||
| max_err = [] | |||
| std_err = [] | |||
| cnts = [] | |||
| improves = [] | |||
| for j in range(len(errs)): | |||
| inds = [i for i in range(len(errs)) if i != j] | |||
| ys = errs[:, j][inds] | |||
| avg_err.append(np.mean(ys)) | |||
| min_err.append(np.min(ys)) | |||
| med_err.append(np.median(ys)) | |||
| max_err.append(np.max(ys)) | |||
| std_err.append(np.std(ys)) | |||
| cnts.append(np.sum(ys >= np.mean(ys))) | |||
| improves.append((np.mean(ys) - np.min(ys)) / np.mean(ys)) | |||
| avg_err = np.array(avg_err) | |||
| min_err = np.array(min_err) | |||
| med_err = np.array(med_err) | |||
| max_err = np.array(max_err) | |||
| std_err = np.array(std_err) | |||
| cnts = np.array(cnts) | |||
| improves = np.array(improves) | |||
| inds = np.argsort(avg_err) | |||
| avg_err = avg_err[inds] | |||
| min_err = min_err[inds] | |||
| med_err = med_err[inds] | |||
| max_err = max_err[inds] | |||
| std_err = std_err[inds] | |||
| cnts = cnts[inds] | |||
| improves = improves[inds] | |||
| xs = list(range(len(inds))) | |||
| fig = plt.figure(figsize=(8, 8)) | |||
| ax = plt.subplot(3, 1, 1) | |||
| ax.plot(xs, avg_err, color="red", linestyle="solid", linewidth=2.5) | |||
| ax.plot(xs, min_err, color="blue", linestyle="dotted", linewidth=1.5) | |||
| ax.plot(xs, med_err, color="purple", linestyle="solid", linewidth=1.0) | |||
| ax.plot(xs, max_err, color="green", linestyle="dashed", linewidth=1.5) | |||
| ax.legend(["Avg", "Min", "Median", "Max"], fontsize=14) | |||
| ax.fill_between(xs, avg_err - std_err, avg_err + std_err, alpha=0.2) | |||
| gap = np.mean(avg_err - min_err) | |||
| ax.set_ylabel("RMSE", fontsize=14) | |||
| ax.set_title("RMSE of Source Models ({}) [Avg-Min:{:.3f}]".format(algo, gap), fontsize=18) | |||
| ax = plt.subplot(3, 1, 2) | |||
| ax.bar(xs, cnts) | |||
| ax.set_ylabel("Number", fontsize=14) | |||
| ax.set_title("Number of sources above average", fontsize=18) | |||
| ax = plt.subplot(3, 1, 3) | |||
| ax.plot(xs, improves) | |||
| ax.set_xlabel("Sorted Shop ID by Avg.Err", fontsize=14) | |||
| ax.set_ylabel("Ratio", fontsize=14) | |||
| ax.set_title("Best Improve Ratio: (Avg - Min) / Avg", fontsize=18) | |||
| fig.tight_layout() | |||
| fig.savefig(os.path.join(pfs_res_dir, "{}-var.jpg".format(algo))) | |||
| plt.show() | |||
| def plot_performance(errs, weights, algo): | |||
| avg_err = [] | |||
| min_err = [] | |||
| med_err = [] | |||
| max_err = [] | |||
| std_err = [] | |||
| cnts = [] | |||
| improves = [] | |||
| for i in range(errs.shape[0]): | |||
| inds = [j for j in range(errs.shape[1]) if j != i] | |||
| arr = errs[i][inds] | |||
| avg_err.append(np.mean(arr)) | |||
| min_err.append(np.min(arr)) | |||
| med_err.append(np.median(arr)) | |||
| max_err.append(np.max(arr)) | |||
| std_err.append(np.std(arr)) | |||
| cnts.append(np.sum(arr >= np.mean(arr))) | |||
| improves.append((np.mean(arr) - np.min(arr)) / np.mean(arr)) | |||
| avg_err = np.array(avg_err) | |||
| min_err = np.array(min_err) | |||
| med_err = np.array(med_err) | |||
| max_err = np.array(max_err) | |||
| std_err = np.array(std_err) | |||
| cnts = np.array(cnts) | |||
| improves = np.array(improves) | |||
| inds = np.argsort(avg_err) | |||
| avg_err = avg_err[inds] | |||
| min_err = min_err[inds] | |||
| med_err = med_err[inds] | |||
| max_err = max_err[inds] | |||
| std_err = std_err[inds] | |||
| cnts = cnts[inds] | |||
| improves = improves[inds] | |||
| xs = list(range(len(inds))) | |||
| fig = plt.figure(figsize=(12, 9)) | |||
| ax = plt.subplot(2, 2, 1) | |||
| ax.plot(xs, avg_err, color="red", linestyle="solid", linewidth=2.5) | |||
| ax.plot(xs, min_err, color="blue", linestyle="dotted", linewidth=1.5) | |||
| ax.plot(xs, med_err, color="purple", linestyle="solid", linewidth=1.0) | |||
| ax.plot(xs, max_err, color="green", linestyle="dashed", linewidth=1.5) | |||
| ax.legend(["Avg", "Min", "Median", "Max"], fontsize=14) | |||
| ax.fill_between(xs, avg_err - std_err, avg_err + std_err, alpha=0.2) | |||
| gap = np.mean(avg_err - min_err) | |||
| ax.set_ylabel("RMSE", fontsize=14) | |||
| ax.set_title("RMSE of Source Models ({}) [Avg-Min:{:.3f}]".format(algo, gap), fontsize=18) | |||
| ax = plt.subplot(2, 2, 2) | |||
| ax.bar(xs, cnts) | |||
| ax.set_ylabel("Number", fontsize=14) | |||
| ax.set_title("Number of sources above average", fontsize=18) | |||
| ax = plt.subplot(2, 2, 3) | |||
| ax.plot(xs, improves) | |||
| ax.set_xlabel("Sorted Shop ID by Avg.Err", fontsize=14) | |||
| ax.set_ylabel("Ratio", fontsize=14) | |||
| ax.set_title("Best Improve Ratio: (Avg - Min) / Avg", fontsize=18) | |||
| ax = plt.subplot(2, 2, 4) | |||
| weights = np.mean(weights, axis=0) / weights.sum() | |||
| weights = np.sort(weights) | |||
| xs = list(range(len(weights))) | |||
| ax.plot(xs, weights) | |||
| # ax.set_xlabel("Sorted Feature ID by Avg.Feature_Importance", fontsize=14) | |||
| ax.set_ylabel("Proportion", fontsize=14) | |||
| ax.set_title("Avg.Feature_Importances", fontsize=18) | |||
| fig.tight_layout() | |||
| fig.savefig(os.path.join(pfs_res_dir, "PFS_{}_performance.png".format(algo)), dpi=700) | |||
| # fig.savefig(f"{algo}_performance.png", dpi=700) | |||
| plt.show() | |||
| if __name__ == "__main__": | |||
| # for algo in ["ridge", "lgb", "xgboost_125"]: | |||
| for algo in ["ridge"]: | |||
| fpath = os.path.join(pfs_res_dir, "{}_errs.pkl".format(algo)) | |||
| if os.path.exists(fpath): | |||
| with open(fpath, "rb") as fr: | |||
| errs = pickle.load(fr) | |||
| else: | |||
| errs = get_errors(algo=algo) | |||
| with open(fpath, "wb") as fw: | |||
| pickle.dump(errs, fw) | |||
| index = ["Source{}".format(k) for k in range(len(errs))] | |||
| columns = ["Target{}".format(k) for k in range(len(errs[0]))] | |||
| df = pd.DataFrame(errs, index=index, columns=columns) | |||
| fpath = os.path.join(pfs_res_dir, "PFS_{}_errs.txt".format(algo)) | |||
| # df.to_csv(fpath, index=True) | |||
| np.savetxt(fpath, errs.T) | |||
| # plot_var(errs, algo) | |||
| plot_heatmap(errs.T, algo) | |||
| weights = np.loadtxt(os.path.join(pfs_res_dir, "PFS_{}_weights.txt".format(algo))) | |||
| plot_performance(errs.T, weights, algo) | |||
| @@ -1,384 +0,0 @@ | |||
| import os | |||
| import pickle | |||
| import pandas as pd | |||
| import numpy as np | |||
| from itertools import product | |||
| from sklearn.preprocessing import LabelEncoder | |||
| from sklearn.preprocessing import MinMaxScaler | |||
| import calendar | |||
| from .paths import pfs_data_dir | |||
| from .paths import pfs_split_dir | |||
| def feature_engineering(): | |||
| # read data | |||
| sales = pd.read_csv(os.path.join(pfs_data_dir, "sales_train.csv")) | |||
| shops = pd.read_csv(os.path.join(pfs_data_dir, "shops.csv")) | |||
| items = pd.read_csv(os.path.join(pfs_data_dir, "items.csv")) | |||
| item_cats = pd.read_csv(os.path.join(pfs_data_dir, "item_categories.csv")) | |||
| test = pd.read_csv(os.path.join(pfs_data_dir, "test.csv")) | |||
| # remove outliers | |||
| train = sales[(sales.item_price < 10000) & (sales.item_price > 0)] | |||
| train = train[sales.item_cnt_day < 1001] | |||
| print(train.shape, sales.shape) | |||
| print(train.tail(5)) | |||
| print(sales.tail(5)) | |||
| # combine shops with different id but the same name | |||
| train.loc[train.shop_id == 0, "shop_id"] = 57 | |||
| test.loc[test.shop_id == 0, "shop_id"] = 57 | |||
| train.loc[train.shop_id == 1, "shop_id"] = 58 | |||
| test.loc[test.shop_id == 1, "shop_id"] = 58 | |||
| train.loc[train.shop_id == 40, "shop_id"] = 39 | |||
| test.loc[test.shop_id == 40, "shop_id"] = 39 | |||
| # obtain shop_id, item_id, month information | |||
| index_cols = ["shop_id", "item_id", "date_block_num"] | |||
| df = [] | |||
| for block_num in train["date_block_num"].unique(): | |||
| cur_shops = train.loc[sales["date_block_num"] == block_num, "shop_id"].unique() | |||
| cur_items = train.loc[sales["date_block_num"] == block_num, "item_id"].unique() | |||
| df.append(np.array(list(product(*[cur_shops, cur_items, [block_num]])), dtype="int32")) | |||
| df = pd.DataFrame(np.vstack(df), columns=index_cols, dtype=np.int32) | |||
| print("df.shape: ", df.shape) | |||
| print(df.head(5)) | |||
| # Add month sales | |||
| group = train.groupby(["date_block_num", "shop_id", "item_id"]).agg({"item_cnt_day": ["sum"]}) | |||
| group.columns = ["item_cnt_month"] | |||
| group.reset_index(inplace=True) | |||
| print("group.shape: ", group.shape) | |||
| print(group.head(5)) | |||
| df = pd.merge(df, group, on=index_cols, how="left") | |||
| df["item_cnt_month"] = ( | |||
| df["item_cnt_month"] | |||
| .fillna(0) | |||
| .astype(np.float32) | |||
| # df['item_cnt_month'].fillna(0).clip(0, 20).astype(np.float32) | |||
| ) | |||
| # fill test data | |||
| test["date_block_num"] = 34 | |||
| test["date_block_num"] = test["date_block_num"].astype(np.int8) | |||
| test["shop_id"] = test["shop_id"].astype(np.int8) | |||
| test["item_id"] = test["item_id"].astype(np.int16) | |||
| df = pd.concat([df, test], ignore_index=True, sort=False, keys=index_cols) | |||
| df.fillna(0, inplace=True) | |||
| # shop location features | |||
| shops["city"] = shops["shop_name"].apply(lambda x: x.split()[0].lower()) | |||
| shops.loc[shops.city == "!якутск", "city"] = "якутск" | |||
| shops["city_code"] = LabelEncoder().fit_transform(shops["city"]) | |||
| coords = dict() | |||
| coords["якутск"] = (62.028098, 129.732555, 4) | |||
| coords["адыгея"] = (44.609764, 40.100516, 3) | |||
| coords["балашиха"] = (55.8094500, 37.9580600, 1) | |||
| coords["волжский"] = (53.4305800, 50.1190000, 3) | |||
| coords["вологда"] = (59.2239000, 39.8839800, 2) | |||
| coords["воронеж"] = (51.6720400, 39.1843000, 3) | |||
| coords["выездная"] = (0, 0, 0) | |||
| coords["жуковский"] = (55.5952800, 38.1202800, 1) | |||
| coords["интернет-магазин"] = (0, 0, 0) | |||
| coords["казань"] = (55.7887400, 49.1221400, 4) | |||
| coords["калуга"] = (54.5293000, 36.2754200, 4) | |||
| coords["коломна"] = (55.0794400, 38.7783300, 4) | |||
| coords["красноярск"] = (56.0183900, 92.8671700, 4) | |||
| coords["курск"] = (51.7373300, 36.1873500, 3) | |||
| coords["москва"] = (55.7522200, 37.6155600, 1) | |||
| coords["мытищи"] = (55.9116300, 37.7307600, 1) | |||
| coords["н.новгород"] = (56.3286700, 44.0020500, 4) | |||
| coords["новосибирск"] = (55.0415000, 82.9346000, 4) | |||
| coords["омск"] = (54.9924400, 73.3685900, 4) | |||
| coords["ростовнадону"] = (47.2313500, 39.7232800, 3) | |||
| coords["спб"] = (59.9386300, 30.3141300, 2) | |||
| coords["самара"] = (53.2000700, 50.1500000, 4) | |||
| coords["сергиев"] = (56.3000000, 38.1333300, 4) | |||
| coords["сургут"] = (61.2500000, 73.4166700, 4) | |||
| coords["томск"] = (56.4977100, 84.9743700, 4) | |||
| coords["тюмень"] = (57.1522200, 65.5272200, 4) | |||
| coords["уфа"] = (54.7430600, 55.9677900, 4) | |||
| coords["химки"] = (55.8970400, 37.4296900, 1) | |||
| coords["цифровой"] = (0, 0, 0) | |||
| coords["чехов"] = (55.1477000, 37.4772800, 4) | |||
| coords["ярославль"] = (57.6298700, 39.8736800, 2) | |||
| shops["city_coord_1"] = shops["city"].apply(lambda x: coords[x][0]) | |||
| shops["city_coord_2"] = shops["city"].apply(lambda x: coords[x][1]) | |||
| shops["country_part"] = shops["city"].apply(lambda x: coords[x][2]) | |||
| shops = shops[["shop_id", "city_code", "city_coord_1", "city_coord_2", "country_part"]] | |||
| df = pd.merge(df, shops, on=["shop_id"], how="left") | |||
| # process items category name | |||
| map_dict = { | |||
| "Чистые носители (штучные)": "Чистые носители", | |||
| "Чистые носители (шпиль)": "Чистые носители", | |||
| "PC ": "Аксессуары", | |||
| "Служебные": "Служебные ", | |||
| } | |||
| items = pd.merge(items, item_cats, on="item_category_id") | |||
| items["item_category"] = items["item_category_name"].apply(lambda x: x.split("-")[0]) | |||
| items["item_category"] = items["item_category"].apply(lambda x: map_dict[x] if x in map_dict.keys() else x) | |||
| items["item_category_common"] = LabelEncoder().fit_transform(items["item_category"]) | |||
| items["item_category_code"] = LabelEncoder().fit_transform(items["item_category_name"]) | |||
| items = items[["item_id", "item_category_common", "item_category_code"]] | |||
| df = pd.merge(df, items, on=["item_id"], how="left") | |||
| # Weekends count / number of days in a month | |||
| def count_days(date_block_num): | |||
| year = 2013 + date_block_num // 12 | |||
| month = 1 + date_block_num % 12 | |||
| weeknd_count = len([1 for i in calendar.monthcalendar(year, month) if i[6] != 0]) | |||
| days_in_month = calendar.monthrange(year, month)[1] | |||
| return weeknd_count, days_in_month, month | |||
| map_dict = {i: count_days(i) for i in range(35)} | |||
| df["weeknd_count"] = df["date_block_num"].apply(lambda x: map_dict[x][0]) | |||
| df["days_in_month"] = df["date_block_num"].apply(lambda x: map_dict[x][1]) | |||
| # Interation features: Item is new / Item was bought in this shop before | |||
| first_item_block = df.groupby(["item_id"])["date_block_num"].min().reset_index() | |||
| first_item_block["item_first_interaction"] = 1 | |||
| first_shop_item_buy_block = ( | |||
| df[df["date_block_num"] > 0].groupby(["shop_id", "item_id"])["date_block_num"].min().reset_index() | |||
| ) | |||
| first_shop_item_buy_block["first_date_block_num"] = first_shop_item_buy_block["date_block_num"] | |||
| df = pd.merge( | |||
| df, | |||
| first_item_block[["item_id", "date_block_num", "item_first_interaction"]], | |||
| on=["item_id", "date_block_num"], | |||
| how="left", | |||
| ) | |||
| df = pd.merge( | |||
| df, | |||
| first_shop_item_buy_block[["item_id", "shop_id", "first_date_block_num"]], | |||
| on=["item_id", "shop_id"], | |||
| how="left", | |||
| ) | |||
| df["first_date_block_num"].fillna(100, inplace=True) | |||
| df["shop_item_sold_before"] = (df["first_date_block_num"] < df["date_block_num"]).astype("int8") | |||
| df.drop(["first_date_block_num"], axis=1, inplace=True) | |||
| df["item_first_interaction"].fillna(0, inplace=True) | |||
| df["shop_item_sold_before"].fillna(0, inplace=True) | |||
| df["item_first_interaction"] = df["item_first_interaction"].astype("int8") | |||
| df["shop_item_sold_before"] = df["shop_item_sold_before"].astype("int8") | |||
| def lag_feature(df, lags, col): | |||
| tmp = df[["date_block_num", "shop_id", "item_id", col]] | |||
| for i in lags: | |||
| shifted = tmp.copy() | |||
| shifted.columns = ["date_block_num", "shop_id", "item_id", col + "_lag_" + str(i)] | |||
| shifted["date_block_num"] += i | |||
| df = pd.merge(df, shifted, on=["date_block_num", "shop_id", "item_id"], how="left") | |||
| lag_name = col + "_lag_" + str(i) | |||
| df[lag_name] = df[lag_name].astype("float32") | |||
| return df | |||
| df = lag_feature(df, [1, 2, 3], "item_cnt_month") | |||
| index_cols = ["shop_id", "item_id", "date_block_num"] | |||
| group = ( | |||
| train.groupby(index_cols)["item_price"] | |||
| .mean() | |||
| .reset_index() | |||
| .rename(columns={"item_price": "avg_shop_price"}, errors="raise") | |||
| ) | |||
| df = pd.merge(df, group, on=index_cols, how="left") | |||
| df["avg_shop_price"] = df["avg_shop_price"].fillna(0).astype(np.float32) | |||
| index_cols = ["item_id", "date_block_num"] | |||
| group = ( | |||
| train.groupby(["date_block_num", "item_id"])["item_price"] | |||
| .mean() | |||
| .reset_index() | |||
| .rename(columns={"item_price": "avg_item_price"}, errors="raise") | |||
| ) | |||
| df = pd.merge(df, group, on=index_cols, how="left") | |||
| df["avg_item_price"] = df["avg_item_price"].fillna(0).astype(np.float32) | |||
| df["item_shop_price_avg"] = (df["avg_shop_price"] - df["avg_item_price"]) / df["avg_item_price"] | |||
| df["item_shop_price_avg"].fillna(0, inplace=True) | |||
| df = lag_feature(df, [1, 2, 3], "item_shop_price_avg") | |||
| df.drop(["avg_shop_price", "avg_item_price", "item_shop_price_avg"], axis=1, inplace=True) | |||
| item_id_target_mean = ( | |||
| df.groupby(["date_block_num", "item_id"])["item_cnt_month"] | |||
| .mean() | |||
| .reset_index() | |||
| .rename(columns={"item_cnt_month": "item_target_enc"}, errors="raise") | |||
| ) | |||
| df = pd.merge(df, item_id_target_mean, on=["date_block_num", "item_id"], how="left") | |||
| df["item_target_enc"] = df["item_target_enc"].fillna(0).astype(np.float32) | |||
| df = lag_feature(df, [1, 2, 3], "item_target_enc") | |||
| df.drop(["item_target_enc"], axis=1, inplace=True) | |||
| item_id_target_mean = ( | |||
| df.groupby(["date_block_num", "item_id", "city_code"])["item_cnt_month"] | |||
| .mean() | |||
| .reset_index() | |||
| .rename(columns={"item_cnt_month": "item_loc_target_enc"}, errors="raise") | |||
| ) | |||
| df = pd.merge(df, item_id_target_mean, on=["date_block_num", "item_id", "city_code"], how="left") | |||
| df["item_loc_target_enc"] = df["item_loc_target_enc"].fillna(0).astype(np.float32) | |||
| df = lag_feature(df, [1, 2, 3], "item_loc_target_enc") | |||
| df.drop(["item_loc_target_enc"], axis=1, inplace=True) | |||
| item_id_target_mean = ( | |||
| df.groupby(["date_block_num", "item_id", "shop_id"])["item_cnt_month"] | |||
| .mean() | |||
| .reset_index() | |||
| .rename(columns={"item_cnt_month": "item_shop_target_enc"}, errors="raise") | |||
| ) | |||
| df = pd.merge(df, item_id_target_mean, on=["date_block_num", "item_id", "shop_id"], how="left") | |||
| df["item_shop_target_enc"] = df["item_shop_target_enc"].fillna(0).astype(np.float32) | |||
| df = lag_feature(df, [1, 2, 3], "item_shop_target_enc") | |||
| df.drop(["item_shop_target_enc"], axis=1, inplace=True) | |||
| item_id_target_mean = ( | |||
| df[df["item_first_interaction"] == 1] | |||
| .groupby(["date_block_num", "item_category_code"])["item_cnt_month"] | |||
| .mean() | |||
| .reset_index() | |||
| .rename(columns={"item_cnt_month": "new_item_cat_avg"}, errors="raise") | |||
| ) | |||
| df = pd.merge(df, item_id_target_mean, on=["date_block_num", "item_category_code"], how="left") | |||
| df["new_item_cat_avg"] = df["new_item_cat_avg"].fillna(0).astype(np.float32) | |||
| df = lag_feature(df, [1, 2, 3], "new_item_cat_avg") | |||
| df.drop(["new_item_cat_avg"], axis=1, inplace=True) | |||
| # For new items add avg category sales in a separate store for last 3 months | |||
| item_id_target_mean = ( | |||
| df[df["item_first_interaction"] == 1] | |||
| .groupby(["date_block_num", "item_category_code", "shop_id"])["item_cnt_month"] | |||
| .mean() | |||
| .reset_index() | |||
| .rename(columns={"item_cnt_month": "new_item_shop_cat_avg"}, errors="raise") | |||
| ) | |||
| df = pd.merge(df, item_id_target_mean, on=["date_block_num", "item_category_code", "shop_id"], how="left") | |||
| df["new_item_shop_cat_avg"] = df["new_item_shop_cat_avg"].fillna(0).astype(np.float32) | |||
| df = lag_feature(df, [1, 2, 3], "new_item_shop_cat_avg") | |||
| df.drop(["new_item_shop_cat_avg"], axis=1, inplace=True) | |||
| def lag_feature_adv(df, lags, col): | |||
| tmp = df[["date_block_num", "shop_id", "item_id", col]] | |||
| for i in lags: | |||
| shifted = tmp.copy() | |||
| shifted.columns = ["date_block_num", "shop_id", "item_id", col + "_lag_" + str(i) + "_adv"] | |||
| shifted["date_block_num"] += i | |||
| shifted["item_id"] -= 1 | |||
| df = pd.merge(df, shifted, on=["date_block_num", "shop_id", "item_id"], how="left") | |||
| lag_name = col + "_lag_" + str(i) + "_adv" | |||
| df[lag_name] = df[lag_name].astype("float32") | |||
| return df | |||
| df = lag_feature_adv(df, [1, 2, 3], "item_cnt_month") | |||
| # df.fillna(0, inplace=True) | |||
| df = df[(df["date_block_num"] > 2)] | |||
| df.drop(["ID"], axis=1, inplace=True, errors="ignore") | |||
| print(df.shape) | |||
| print(df.columns) | |||
| print(df.head(10)) | |||
| fill_dict = {} | |||
| for col in df.columns: | |||
| fill_dict[col] = df[col].mean() | |||
| group_df = df.groupby(["shop_id"]) | |||
| for shop_id, shop_df in group_df: | |||
| # remove data of data_block_num=34, i.e., 2015.11 | |||
| # this is test set in competition | |||
| shop_df = shop_df[shop_df.date_block_num <= 33] | |||
| # fill the null | |||
| cols = shop_df.isnull().any() | |||
| idx = list(cols[cols.values].index) | |||
| shop_df[idx] = shop_df.groupby("item_id", sort=False)[idx].apply( | |||
| lambda x: x.fillna(method="ffill").fillna(method="bfill") | |||
| ) | |||
| shop_df[idx] = shop_df[idx].fillna(shop_df[idx].mean()) | |||
| for col in idx: | |||
| shop_df[col] = shop_df[col].fillna(fill_dict[col]) | |||
| # min-max scale | |||
| drop_fea_list = [ | |||
| "shop_id", | |||
| "city_code", | |||
| "city_coord_1", | |||
| "city_coord_2", | |||
| "country_part", | |||
| "item_cnt_month", | |||
| "date_block_num", | |||
| ] | |||
| fea_list = [col for col in shop_df.columns if col not in drop_fea_list] | |||
| mms = MinMaxScaler() | |||
| shop_df[fea_list] = mms.fit_transform(shop_df[fea_list]) | |||
| shop_df = shop_df[fea_list + ["item_cnt_month", "date_block_num"]] | |||
| date_split = 29 | |||
| split = False | |||
| while split is False: | |||
| df1 = shop_df[shop_df["date_block_num"] <= date_split] | |||
| df2 = shop_df[shop_df["date_block_num"] > date_split] | |||
| if df2.shape[0] > 0 and df1.shape[0] > 0: | |||
| split = True | |||
| else: | |||
| date_split -= 1 | |||
| if date_split < 0: | |||
| break | |||
| if split is True: | |||
| print("ShopID:{}, split block:{}".format(shop_id, date_split)) | |||
| print(df1.shape, df2.shape) | |||
| # save train csv | |||
| fpath = os.path.join(pfs_split_dir, "Shop{:0>2d}-train.csv".format(shop_id)) | |||
| df1.to_csv(fpath, index=False) | |||
| # save val csv | |||
| fpath = os.path.join(pfs_split_dir, "Shop{:0>2d}-val.csv".format(shop_id)) | |||
| df2.to_csv(fpath, index=False) | |||
| @@ -1,90 +0,0 @@ | |||
| import hashlib | |||
| import requests | |||
| import os | |||
| import random | |||
| import json | |||
| import time | |||
| from tqdm import tqdm | |||
| email = "liujd@lamda.nju.edu.cn" | |||
| password = hashlib.md5(b"liujdlamda").hexdigest() | |||
| login_url = "http://210.28.134.201:8089/auth/login" | |||
| submit_url = "http://210.28.134.201:8089/user/add_learnware" | |||
| all_data_type = ["Table", "Image", "Video", "Text", "Audio"] | |||
| all_task_type = [ | |||
| "Classification", | |||
| "Regression", | |||
| "Clustering", | |||
| "Feature Extraction", | |||
| "Generation", | |||
| "Segmentation", | |||
| "Object Detection", | |||
| ] | |||
| all_device_type = ["CPU", "GPU"] | |||
| all_scenario = [ | |||
| "Business", | |||
| "Financial", | |||
| "Health", | |||
| "Politics", | |||
| "Computer", | |||
| "Internet", | |||
| "Traffic", | |||
| "Nature", | |||
| "Fashion", | |||
| "Industry", | |||
| "Agriculture", | |||
| "Education", | |||
| "Entertainment", | |||
| "Architecture", | |||
| ] | |||
| # ############### | |||
| # 以上部分无需修改 # | |||
| # ############### | |||
| def main(): | |||
| session = requests.Session() | |||
| res = session.post(login_url, json={"email": email, "password": password}) | |||
| # /path/to/learnware/folder 修改为学件文件夹地址 | |||
| learnware_pool = os.listdir(os.path.join(os.path.abspath("."), "learnware_pool")) | |||
| for learnware in learnware_pool: | |||
| # 修改相应的语义规约 | |||
| name = "PFS_Shop" + "%02d" % int(learnware.split(".")[0].split("_")[1]) | |||
| name = name + "_" + time.strftime("%Y%m%d%H%M%S", time.localtime()) | |||
| description = f"This is a description of learnware {name}" | |||
| data = random.choice(all_data_type) | |||
| task = random.choice(all_task_type) | |||
| device = list(set(random.choices(all_device_type, k=2))) | |||
| scenario = list(set(random.choices(all_scenario, k=5))) | |||
| semantic_specification = { | |||
| "Data": {"Values": ["Table"], "Type": "Class"}, | |||
| "Library": {"Values": ["Scikit-learn"], "Type": "Class"}, | |||
| "Task": {"Values": ["Regression"], "Type": "Class"}, | |||
| "Scenario": {"Values": ["Business"], "Type": "Tag"}, | |||
| "Description": { | |||
| "Values": "A sales-forecasting model from Predict Future Sales Competition on Kaggle", | |||
| "Type": "String", | |||
| }, | |||
| "Name": {"Values": name, "Type": "String"}, | |||
| "License": {"Values": ["MIT"], "Type": "Class"}, | |||
| } | |||
| res = session.post( | |||
| submit_url, | |||
| data={ | |||
| "semantic_specification": json.dumps(semantic_specification), | |||
| }, | |||
| files={ | |||
| "learnware_file": open( | |||
| os.path.join(os.path.abspath("."), "learnware_pool", learnware), | |||
| "rb", | |||
| ) | |||
| }, | |||
| ) | |||
| assert json.loads(res.text)["code"] == 0, "Upload error" | |||
| if __name__ == "__main__": | |||
| main() | |||