{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":84493,"databundleVersionId":9871156,"sourceType":"competition"}],"dockerImageVersionId":30786,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np, pandas as pd, polars as pl\nimport pickle,gzip\nimport os, gc\nimport pyarrow.parquet as pq\nimport pyarrow as pa\nimport warnings\nfrom sklearn.linear_model import Ridge\nimport xgboost as xgb\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport random\nwarnings.filterwarnings('ignore')\n\nimport kaggle_evaluation.jane_street_inference_server\n\ndef seed_everything(seed):\n    np.random.seed(seed)\n    random.seed(seed)\nseed_everything(seed=2024)\n\ntarget = \"responder_6\"\ninput_path = '/kaggle/input/jane-street-real-time-market-data-forecasting/'\noutput_path = '/kaggle/working/'\nstate = 42\nmethod = \"LGBM1R\"\n\nnp.set_printoptions(precision=2, suppress=True)\npd.set_option('display.max_rows', None)\npd.set_option('display.max_columns', None)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T13:06:40.744069Z","iopub.execute_input":"2024-11-21T13:06:40.744346Z","iopub.status.idle":"2024-11-21T13:06:43.997433Z","shell.execute_reply.started":"2024-11-21T13:06:40.744318Z","shell.execute_reply":"2024-11-21T13:06:43.996737Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def reduce_mem_usage(df):\n    \"\"\" iterate through all the columns of a dataframe and modify the data type\n        to reduce memory usage.\n    \"\"\"\n    start_mem = df.memory_usage().sum() / 1024**2\n    print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))\n\n    for col in df.columns:\n        col_type = df[col].dtype.name\n\n        if col_type not in ['object', 'category', 'datetime64[ns, UTC]']:\n            c_min = df[col].min()\n            c_max = df[col].max()\n            if str(col_type)[:3] == 'int':\n                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n                    df[col] = df[col].astype(np.int8)\n                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                    df[col] = df[col].astype(np.int16)\n                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                    df[col] = df[col].astype(np.int32)\n                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                    df[col] = df[col].astype(np.int64)\n            else:\n                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                    df[col] = df[col].astype(np.float16)\n                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                    df[col] = df[col].astype(np.float32)\n                else:\n                    df[col] = df[col].astype(np.float64)\n\n    end_mem = df.memory_usage().sum() / 1024**2\n    print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))\n    print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))\n\n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T13:07:42.782174Z","iopub.execute_input":"2024-11-21T13:07:42.782918Z","iopub.status.idle":"2024-11-21T13:07:42.792567Z","shell.execute_reply.started":"2024-11-21T13:07:42.782882Z","shell.execute_reply":"2024-11-21T13:07:42.791712Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"read and resave data\")\n\ndata_frames = []\n\nfor i in range(0,10):\n    print(f'read part {i}')\n    train_tmp = pd.read_parquet(f\"{input_path}train.parquet/partition_id={i}/part-0.parquet\")\n    # Optimise DF\n    train_tmp = reduce_mem_usage(train_tmp)\n    \n    data_frames.append(train_tmp)\n\n    print('clean RAM')\n    del train_tmp\n    gc.collect() \n    print('------------------')\n    \n# Save all DF as parquet\nprint('Concat all DFs in one and save as parquet')\ndf = pd.concat(data_frames, ignore_index=True)\ndel data_frames\n\n# Lưu thành file .parquet\n#df.to_parquet(f'{output_path}partition_id=all.parquet', index=False, engine='pyarrow')\n#del df\n\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T13:07:46.168712Z","iopub.execute_input":"2024-11-21T13:07:46.169526Z","iopub.status.idle":"2024-11-21T13:10:02.750581Z","shell.execute_reply.started":"2024-11-21T13:07:46.169490Z","shell.execute_reply":"2024-11-21T13:10:02.749689Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.to_parquet(f'/kaggle/working/df_JSR_TUR.parquet', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T13:10:18.630647Z","iopub.execute_input":"2024-11-21T13:10:18.631713Z","iopub.status.idle":"2024-11-21T13:13:40.282419Z","shell.execute_reply.started":"2024-11-21T13:10:18.631666Z","shell.execute_reply":"2024-11-21T13:13:40.281348Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T13:14:29.360574Z","iopub.execute_input":"2024-11-21T13:14:29.360918Z","iopub.status.idle":"2024-11-21T13:14:29.428766Z","shell.execute_reply.started":"2024-11-21T13:14:29.360886Z","shell.execute_reply":"2024-11-21T13:14:29.427811Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#df = pd.read_parquet(f'{output_path}partition_id=all.parquet')\n#Số lượng ngày dùng cho dữ liệu xác thực\nnum_valid_dates = 100\n\n# Số ngày bỏ qua từ đầu bộ dữ liệu\n# skip_dates = 0\n\n# Xác định tên các đặc trưng dựa trên số lượng đặc trưng (79 trong trường hợp này)\nfeature_names = [f\"feature_{i:02d}\" for i in range(79)]\n\n# Lọc DataFrame để chỉ lấy các ngày lớn hơn hoặc bằng `skip_dates`\n# df = df[df['date_id'] >= skip_dates]\n# df.index = range(len(df))\n\n# Lấy các ngày duy nhất từ DataFrame\ndates = df['date_id'].unique()\n\n# Định nghĩa các ngày xác thực là 100 ngày cuối cùng\nvalid_dates = dates[-num_valid_dates:]\n\n# Định nghĩa các ngày huấn luyện là tất cả các ngày ngoại trừ 100 ngày cuối cùng\ntrain_dates = dates[:-num_valid_dates]\n\n#features_to_drop = [\n#    'feature_09', 'feature_10', 'feature_11', 'feature_21', 'feature_22', \n#    'feature_23', 'feature_24', 'feature_25', 'feature_26', 'feature_27', \n#    'feature_28', 'feature_29', 'feature_30', 'feature_31', 'feature_37', \n#    'feature_38', 'feature_61'\n#]\n\n\n# Xóa các cột tương ứng khỏi DataFrame 'df'\n#df.drop(columns=features_to_drop, inplace=True)\n\n#feature_names = [feature for feature in feature_names if feature not in features_to_drop]\n\n# Xác định các cột có giá trị thiếu (NaN)\nmissing_columns = df.columns[df.isnull().any()].tolist()  # Lấy danh sách các cột có giá trị thiếu\n\n# Điền giá trị thiếu cho tất cả các cột có giá trị thiếu bằng giá trị mean\nfor col in missing_columns:\n    mean_value = df[col].mode()[0]  # Tính giá trị mean của cột\n    df[col].fillna(mean_value, inplace=True)  # Điền giá trị thiếu bằng mean\n\nprint(\"Đã điền giá trị thiếu cho tất cả các cột bằng mean.\")\n\ndel missing_columns\n#del features_to_drop\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T10:17:53.540152Z","iopub.execute_input":"2024-11-21T10:17:53.540830Z","iopub.status.idle":"2024-11-21T10:19:04.014253Z","shell.execute_reply.started":"2024-11-21T10:17:53.540793Z","shell.execute_reply":"2024-11-21T10:19:04.013475Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Lấy các chỉ mục để phân chia tập huấn luyện và tập xác thực\nvalid_idx = df['date_id'].isin(valid_dates)\ntrain_idx = ~valid_idx  # Phần còn lại là tập huấn luyện\n\n# Lưu tập huấn luyện và tập xác thực thành tệp\ndf.loc[valid_idx].to_parquet('/kaggle/working/df_valid.parquet', index=False)\n\n# Lấy tập huấn luyện và chia thành 5 phần\ndf_train = df.loc[train_idx]\ntrain_len = len(df_train)\nbatch_size = train_len // 5\n\n# Lưu từng phần của tập huấn luyện vào các tệp df_0.parquet đến df_4.parquet\nfor i in range(5):\n    start = i * batch_size\n    end = (i + 1) * batch_size if i < 4 else train_len  # Đảm bảo phần cuối cùng bao gồm tất cả phần còn lại\n    df_train.iloc[start:end].to_parquet(f'/kaggle/working/df_{i}.parquet', index=False)\n\n# Xóa dữ liệu khỏi bộ nhớ RAM\ndel df, df_train\ngc.collect()\n\nprint(\"Đã lưu tập huấn luyện thành 5 phần và tập xác thực vào các tệp parquet\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T10:40:17.884093Z","iopub.execute_input":"2024-11-21T10:40:17.884670Z","iopub.status.idle":"2024-11-21T10:43:52.810790Z","shell.execute_reply.started":"2024-11-21T10:40:17.884630Z","shell.execute_reply":"2024-11-21T10:43:52.809979Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Hàm tính R2 tùy chỉnh cho XGBoost\ndef r2_xgb(y_true, y_pred, sample_weight):\n    r2 = 1 - np.average((y_pred - y_true) ** 2, weights=sample_weight) / (np.average((y_true) ** 2, weights=sample_weight) + 1e-38)\n    return -r2\n\n# Khởi tạo mô hình XGBRegressor\nmodel = xgb.XGBRegressor(\n    n_estimators=2000, \n    learning_rate=0.1, \n    max_depth=6, \n    tree_method='hist', \n    device=\"cuda\", \n    objective='reg:squarederror', \n    eval_metric=r2_xgb,  \n    early_stopping_rounds=100\n)\n\n# Đọc tập xác thực từ file và chuẩn bị dữ liệu xác thực\ndf_valid = pd.read_parquet('/kaggle/working/df_valid.parquet')\nX_valid = df_valid[feature_names]\ny_valid = df_valid['responder_6']\nw_valid = df_valid['weight']\n\n# Huấn luyện mô hình với từng tệp df_0.parquet đến df_4.parquet\nfor i in range(5):\n    # Đọc dữ liệu huấn luyện từ tệp\n    print(f'file {i}')\n    df_train = pd.read_parquet(f'/kaggle/working/df_{i}.parquet')\n    \n    # Chuẩn bị dữ liệu huấn luyện\n    X_train = df_train[feature_names]\n    y_train = df_train['responder_6']\n    w_train = df_train['weight']\n\n    # Huấn luyện mô hình trên dữ liệu hiện tại\n    model.fit(\n        X_train, y_train, \n        sample_weight=w_train,\n        eval_set=[(X_valid, y_valid)], \n        sample_weight_eval_set=[w_valid], \n        verbose=10\n    )\n\n    # Giải phóng bộ nhớ sau khi huấn luyện xong phần dữ liệu hiện tại\n    del df_train, X_train, y_train, w_train\n    gc.collect()\n\n# Xóa dữ liệu xác thực khỏi bộ nhớ để giải phóng RAM\ndel df_valid, X_valid, y_valid, w_valid\ngc.collect()\n\nprint(\"Mô hình đã được đào tạo\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T10:44:16.277831Z","iopub.execute_input":"2024-11-21T10:44:16.278876Z","iopub.status.idle":"2024-11-21T10:51:46.856442Z","shell.execute_reply.started":"2024-11-21T10:44:16.278838Z","shell.execute_reply":"2024-11-21T10:51:46.855495Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import joblib\n\n# joblib.dump(model, '/kaggle/working/xgb4model.pkl')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T08:06:52.795185Z","iopub.execute_input":"2024-11-21T08:06:52.795834Z","iopub.status.idle":"2024-11-21T08:06:52.809508Z","shell.execute_reply.started":"2024-11-21T08:06:52.795796Z","shell.execute_reply":"2024-11-21T08:06:52.807771Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# feature_train = ['feature_01', 'feature_02', 'feature_04', 'feature_05',\n#        'feature_06', 'feature_07', 'feature_08', 'feature_09',\n#        'feature_10', 'feature_11', 'feature_12', 'feature_14',\n#        'feature_15', 'feature_17', 'feature_19', 'feature_20',\n#        'feature_21', 'feature_22', 'feature_23', 'feature_24',\n#        'feature_25', 'feature_26', 'feature_27', 'feature_28',\n#        'feature_29', 'feature_30', 'feature_31', 'feature_32',\n#        'feature_34', 'feature_35', 'feature_36', 'feature_38',\n#        'feature_39', 'feature_42', 'feature_50', 'feature_52',\n#        'feature_56', 'feature_58', 'feature_60', 'feature_61',\n#        'feature_62', 'feature_66', 'feature_67', 'feature_69',\n#        'feature_70', 'feature_73', 'feature_74', 'feature_75',\n#        'feature_76']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-17T16:45:21.185657Z","iopub.execute_input":"2024-11-17T16:45:21.186041Z","iopub.status.idle":"2024-11-17T16:45:21.192562Z","shell.execute_reply.started":"2024-11-17T16:45:21.186006Z","shell.execute_reply":"2024-11-17T16:45:21.191543Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# importances = model.feature_importances_\n\n# # Chuyển sang DataFrame để dễ phân tích\n# importance_df = pd.DataFrame({\n#     'Feature': feature_names,\n#     'Importance': importances\n# })#.sort_values(by='Importance', ascending=False)\n# print(importance_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-17T16:44:19.410243Z","iopub.execute_input":"2024-11-17T16:44:19.410658Z","iopub.status.idle":"2024-11-17T16:44:19.423557Z","shell.execute_reply.started":"2024-11-17T16:44:19.410617Z","shell.execute_reply":"2024-11-17T16:44:19.422461Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# importance_df[importance_df['Importance'] > 0.01]['Feature'].values","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-17T16:44:28.796861Z","iopub.execute_input":"2024-11-17T16:44:28.797740Z","iopub.status.idle":"2024-11-17T16:44:28.807580Z","shell.execute_reply.started":"2024-11-17T16:44:28.797688Z","shell.execute_reply":"2024-11-17T16:44:28.806693Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# lags_ : pl.DataFrame | None = None\n\n\n# def predict(test: pl.DataFrame, lags: pl.DataFrame | None) -> pl.DataFrame | pd.DataFrame:\n\n#     global lags_\n#     if lags is not None:\n#         lags_ = lags\n\n#     predictions = test.select(\n#         'row_id',\n#         pl.lit(0.0).alias('responder_6'),  # Khởi tạo giá trị dự đoán ban đầu\n#     )\n\n#     feat = test[feature_names].to_numpy()  # Lấy các đặc trưng dưới dạng mảng numpy\n\n#      # Sử dụng mô hình duy nhất để dự đoán\n#     pred = model.predict(feat)\n\n#     # Thêm cột 'responder_6' với các giá trị dự đoán vào dataframe kết quả\n#     predictions = predictions.with_columns(pl.Series('responder_6', pred.ravel()))\n\n#     # Hàm predict phải trả về một DataFrame\n#     assert isinstance(predictions, pl.DataFrame | pd.DataFrame)\n\n#     # với các cột 'row_id', 'responder_6'\n#     assert list(predictions.columns) == ['row_id', 'responder_6']\n    \n#     # và có số hàng bằng với số hàng của dữ liệu kiểm tra.\n#     assert len(predictions) == len(test)\n\n#     return predictions\n\n# inference_server = kaggle_evaluation.jane_street_inference_server.JSInferenceServer(predict)\n\n# if os.getenv('KAGGLE_IS_COMPETITION_RERUN'):\n#     inference_server.serve()\n# else:\n#     inference_server.run_local_gateway(\n#         (\n#             '/kaggle/input/jane-street-real-time-market-data-forecasting/test.parquet',\n#             '/kaggle/input/jane-street-real-time-market-data-forecasting/lags.parquet',\n#         )\n#     )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T13:59:30.452224Z","iopub.execute_input":"2024-11-16T13:59:30.452493Z","iopub.status.idle":"2024-11-16T13:59:30.458706Z","shell.execute_reply.started":"2024-11-16T13:59:30.452463Z","shell.execute_reply":"2024-11-16T13:59:30.457767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cupy as cp  # Dùng để chuyển dữ liệu từ CPU sang GPU\n\nlags_: pl.DataFrame | None = None\n\ndef predict(test: pl.DataFrame, lags: pl.DataFrame | None) -> pl.DataFrame:\n    \"\"\"\n    Hàm dự đoán sử dụng mô hình đã huấn luyện, đảm bảo đồng bộ giữa thiết bị mô hình và dữ liệu.\n    \"\"\"\n    global lags_\n\n    # Cập nhật giá trị lags nếu có\n    if lags is not None:\n        lags_ = lags\n\n    # Khởi tạo DataFrame kết quả\n    predictions = test.select(\n        'row_id',\n        pl.lit(0.0).alias('responder_6')  # Khởi tạo giá trị dự đoán ban đầu\n    )\n\n    # Trích xuất các đặc trưng và chuyển sang GPU\n    feat = test[feature_names].to_numpy()\n    feat_gpu = cp.array(feat)  # Chuyển sang GPU bằng Cupy\n\n    # Sử dụng Booster để dự đoán trực tiếp trên GPU\n    booster = model.get_booster()  # Lấy Booster từ XGBRegressor\n    pred = booster.inplace_predict(feat_gpu)\n\n    # Thêm cột 'responder_6' vào DataFrame kết quả\n    predictions = predictions.with_columns(\n        pl.Series('responder_6', pred.ravel().tolist())  # Chuyển ndarray thành list trước khi tạo Series\n    )\n\n    # Kiểm tra tính hợp lệ của DataFrame kết quả\n    assert isinstance(predictions, pl.DataFrame), \"Kết quả phải là một Polars DataFrame\"\n    assert list(predictions.columns) == ['row_id', 'responder_6'], \"Các cột phải là ['row_id', 'responder_6']\"\n    assert len(predictions) == len(test), \"Số hàng phải khớp với dữ liệu đầu vào\"\n\n    return predictions\n\n\n# Tạo inference server\ninference_server = kaggle_evaluation.jane_street_inference_server.JSInferenceServer(predict)\n\n# Kiểm tra xem môi trường chạy là Kaggle hay cục bộ\nif os.getenv('KAGGLE_IS_COMPETITION_RERUN'):\n    inference_server.serve()\nelse:\n    inference_server.run_local_gateway(\n        (\n            '/kaggle/input/jane-street-real-time-market-data-forecasting/test.parquet',\n            '/kaggle/input/jane-street-real-time-market-data-forecasting/lags.parquet',\n        )\n    )\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T01:14:02.210593Z","iopub.execute_input":"2024-11-21T01:14:02.211056Z","iopub.status.idle":"2024-11-21T01:14:04.987606Z","shell.execute_reply.started":"2024-11-21T01:14:02.211018Z","shell.execute_reply":"2024-11-21T01:14:04.986535Z"}},"outputs":[],"execution_count":null}]}