mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-27 23:47:46 +00:00
feat: implement isolated model feature selection loop (#370)
* rename meta_tpl * use a isolated coder to deal with model feature selection and refine the structure * fix CI * fix: fix some errors in scenario.py, proposal.py and runner.py and several complex competition scenarios(#365) * fix several bugs in proposal and runner * fix a bug in feedback-prize-english-language-learning * fix some bugs and templates * fix the bug in optiver and nlp problem * delete unnecessary codes * remove unnecessary codes * complete forest and s4e8 * push * feedback & s4e8 & forest * optiver finished * s3e11 & s3e26 * s4e9 finished * sf-crime finished * the last one finished --------- Co-authored-by: WinstonLiyt <104308117+WinstonLiyt@users.noreply.github.com> Co-authored-by: WinstonLiyte <1957922024@qq.com>
This commit is contained in:
@@ -32,6 +32,9 @@ class KaggleBasePropSetting(BasePropSetting):
|
||||
feature_coder: str = "rdagent.scenarios.kaggle.developer.coder.KGFactorCoSTEER"
|
||||
"""Feature Coder class"""
|
||||
|
||||
model_feature_selection_coder: str = "rdagent.scenarios.kaggle.developer.coder.KGModelFeatureSelectionCoder"
|
||||
"""Model Feature Selection Coder class"""
|
||||
|
||||
model_coder: str = "rdagent.scenarios.kaggle.developer.coder.KGModelCoSTEER"
|
||||
"""Model Coder class"""
|
||||
|
||||
@@ -57,8 +60,6 @@ class KaggleBasePropSetting(BasePropSetting):
|
||||
|
||||
if_action_choosing_based_on_UCB: bool = False
|
||||
|
||||
if_using_feature_selection: bool = False
|
||||
|
||||
if_using_graph_rag: bool = False
|
||||
|
||||
if_using_vector_rag: bool = False
|
||||
|
||||
@@ -23,6 +23,7 @@ from rdagent.scenarios.kaggle.kaggle_crawler import download_data
|
||||
from rdagent.scenarios.kaggle.proposal.proposal import (
|
||||
KG_ACTION_FEATURE_ENGINEERING,
|
||||
KG_ACTION_FEATURE_PROCESSING,
|
||||
KG_ACTION_MODEL_FEATURE_SELECTION,
|
||||
KGTrace,
|
||||
)
|
||||
|
||||
@@ -49,6 +50,10 @@ class KaggleRDLoop(RDLoop):
|
||||
|
||||
self.feature_coder: Developer = import_class(PROP_SETTING.feature_coder)(scen)
|
||||
logger.log_object(self.feature_coder, tag="feature coder")
|
||||
self.model_feature_selection_coder: Developer = import_class(PROP_SETTING.model_feature_selection_coder)(
|
||||
scen
|
||||
)
|
||||
logger.log_object(self.model_feature_selection_coder, tag="model feature selection coder")
|
||||
self.model_coder: Developer = import_class(PROP_SETTING.model_coder)(scen)
|
||||
logger.log_object(self.model_coder, tag="model coder")
|
||||
|
||||
@@ -67,6 +72,8 @@ class KaggleRDLoop(RDLoop):
|
||||
with logger.tag("d"): # develop
|
||||
if prev_out["propose"].action in [KG_ACTION_FEATURE_ENGINEERING, KG_ACTION_FEATURE_PROCESSING]:
|
||||
exp = self.feature_coder.develop(prev_out["exp_gen"])
|
||||
elif prev_out["propose"].action == KG_ACTION_MODEL_FEATURE_SELECTION:
|
||||
exp = self.model_feature_selection_coder.develop(prev_out["exp_gen"])
|
||||
else:
|
||||
exp = self.model_coder.develop(prev_out["exp_gen"])
|
||||
logger.log_object(exp.sub_workspace_list, tag="coder result")
|
||||
|
||||
@@ -21,6 +21,7 @@ from rdagent.core.evolving_framework import EvolvingStrategy
|
||||
from rdagent.core.prompts import Prompts
|
||||
from rdagent.core.utils import multiprocessing_wrapper
|
||||
from rdagent.oai.llm_utils import APIBackend
|
||||
from rdagent.scenarios.kaggle.experiment.kaggle_experiment import KG_MODEL_MAPPING
|
||||
|
||||
coder_prompts = Prompts(file_path=Path(__file__).parent.parent / "prompts.yaml")
|
||||
|
||||
@@ -41,14 +42,8 @@ class ModelCoderEvolvingStrategy(EvolvingStrategy):
|
||||
current_code = ""
|
||||
sota_exp_code_dict = current_exp.based_experiments[-1].experiment_workspace.code_dict
|
||||
if target_task.version == 2:
|
||||
model_file_mapping = {
|
||||
"XGBoost": "model/model_xgboost.py",
|
||||
"RandomForest": "model/model_randomforest.py",
|
||||
"LightGBM": "model/model_lightgbm.py",
|
||||
"NN": "model/model_nn.py",
|
||||
}
|
||||
if model_type in model_file_mapping:
|
||||
current_code = sota_exp_code_dict.get(model_file_mapping[model_type], None)
|
||||
if model_type in KG_MODEL_MAPPING:
|
||||
current_code = sota_exp_code_dict.get(KG_MODEL_MAPPING[model_type], None)
|
||||
elif "model.py" in sota_exp_code_dict:
|
||||
current_code = sota_exp_code_dict["model.py"]
|
||||
else:
|
||||
|
||||
@@ -4,7 +4,7 @@ import pickle
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import torch
|
||||
from model import fit, predict, select
|
||||
from model import fit, predict
|
||||
|
||||
train_X = pd.DataFrame(np.random.randn(8, 30), columns=[f"{i}" for i in range(30)])
|
||||
train_y = pd.Series(np.random.randint(0, 2, 8))
|
||||
|
||||
@@ -12,7 +12,7 @@ hypothesis_gen:
|
||||
{{ hypothesis_output_format }}
|
||||
|
||||
user_prompt: |-
|
||||
{% if hypothesis_and_feedback|length == 0 %} It is the first round of hypothesis generation. The user has no hypothesis on this scenario yet.
|
||||
{% if hypothesis_and_feedback|length == 0 %}It is the first round of hypothesis generation. The user has no hypothesis on this scenario yet.
|
||||
{% else %}It is not the first round, the user has made several hypothesis on this scenario and did several evaluation on them.
|
||||
The former hypothesis and the corresponding feedbacks are as follows (focus on the last one & the new hypothesis that it provides and reasoning to see if you agree):
|
||||
{{ hypothesis_and_feedback }}
|
||||
|
||||
@@ -1,5 +1,72 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from jinja2 import Environment, StrictUndefined
|
||||
|
||||
from rdagent.components.coder.factor_coder.CoSTEER import FactorCoSTEER
|
||||
from rdagent.components.coder.model_coder.CoSTEER import ModelCoSTEER
|
||||
from rdagent.core.developer import Developer
|
||||
from rdagent.core.prompts import Prompts
|
||||
from rdagent.oai.llm_utils import APIBackend
|
||||
from rdagent.scenarios.kaggle.experiment.kaggle_experiment import (
|
||||
KG_SELECT_MAPPING,
|
||||
KGModelExperiment,
|
||||
)
|
||||
|
||||
KGModelCoSTEER = ModelCoSTEER
|
||||
KGFactorCoSTEER = FactorCoSTEER
|
||||
|
||||
prompt_dict = Prompts(file_path=Path(__file__).parent.parent / "prompts.yaml")
|
||||
|
||||
DEFAULT_SELECTION_CODE = """
|
||||
import pandas as pd
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
\"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
\"""
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
{% if feature_index_list is not none %}
|
||||
X = X.loc[:, X.columns.levels[0][{{feature_index_list}}].tolist()]
|
||||
{% endif %}
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
"""
|
||||
|
||||
|
||||
class KGModelFeatureSelectionCoder(Developer[KGModelExperiment]):
|
||||
def develop(self, exp: KGModelExperiment) -> KGModelExperiment:
|
||||
target_model_type = exp.sub_tasks[0].model_type
|
||||
assert target_model_type in KG_SELECT_MAPPING
|
||||
if len(exp.experiment_workspace.data_description) == 1:
|
||||
code = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(DEFAULT_SELECTION_CODE)
|
||||
.render(feature_index_list=None)
|
||||
)
|
||||
else:
|
||||
system_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["model_feature_selection"]["system"])
|
||||
.render(scenario=self.scen.get_scenario_all_desc(), model_type=exp.sub_tasks[0].model_type)
|
||||
)
|
||||
user_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["model_feature_selection"]["user"])
|
||||
.render(feature_groups=[desc[0] for desc in exp.experiment_workspace.data_description])
|
||||
)
|
||||
|
||||
chosen_index = json.loads(
|
||||
APIBackend().build_messages_and_create_chat_completion(
|
||||
user_prompt=user_prompt, system_prompt=system_prompt, json_mode=True
|
||||
)
|
||||
).get("Selected Group Index", [i + 1 for i in range(len(exp.experiment_workspace.data_description))])
|
||||
chosen_index_to_list_index = [i - 1 for i in chosen_index]
|
||||
|
||||
code = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(DEFAULT_SELECTION_CODE)
|
||||
.render(feature_index_list=chosen_index_to_list_index)
|
||||
)
|
||||
exp.experiment_workspace.inject_code(**{KG_SELECT_MAPPING[target_model_type]: code})
|
||||
return exp
|
||||
|
||||
@@ -117,9 +117,9 @@ class KGHypothesisExperiment2Feedback(HypothesisExperiment2Feedback):
|
||||
"last_hypothesis": trace.hist[-1][0] if trace.hist else None,
|
||||
"last_task_and_code": last_task_and_code,
|
||||
"last_result": trace.hist[-1][1].result if trace.hist else None,
|
||||
"sota_task_and_code": exp.based_experiments[-1].experiment_workspace.data_description
|
||||
if exp.based_experiments
|
||||
else None,
|
||||
"sota_task_and_code": (
|
||||
exp.based_experiments[-1].experiment_workspace.data_description if exp.based_experiments else None
|
||||
),
|
||||
"sota_result": exp.based_experiments[-1].result if exp.based_experiments else None,
|
||||
"hypothesis": hypothesis,
|
||||
"exp": exp,
|
||||
@@ -150,6 +150,7 @@ class KGHypothesisExperiment2Feedback(HypothesisExperiment2Feedback):
|
||||
decision = convert2bool(response_json.get("Replace Best Result", "no"))
|
||||
|
||||
experiment_feedback = {
|
||||
"current_competition": self.scen.get_competition_full_desc(),
|
||||
"hypothesis_text": hypothesis_text,
|
||||
"current_result": current_result,
|
||||
"model_code": model_code,
|
||||
@@ -163,7 +164,7 @@ class KGHypothesisExperiment2Feedback(HypothesisExperiment2Feedback):
|
||||
self.scen.vector_base.add_experience_to_vector_base(experiment_feedback)
|
||||
self.scen.vector_base.save()
|
||||
elif self.scen.if_using_graph_rag:
|
||||
trace.knowledge_base.load_from_documents([experiment_feedback], self.scen)
|
||||
trace.knowledge_base.add_document(experiment_feedback, self.scen)
|
||||
|
||||
return HypothesisFeedback(
|
||||
observations=observations,
|
||||
|
||||
@@ -3,17 +3,12 @@ import pickle
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from jinja2 import Environment, StrictUndefined
|
||||
|
||||
from rdagent.app.kaggle.conf import KAGGLE_IMPLEMENT_SETTING
|
||||
from rdagent.components.coder.factor_coder.factor import FactorTask
|
||||
from rdagent.components.coder.model_coder.model import ModelTask
|
||||
from rdagent.components.runner import CachedRunner
|
||||
from rdagent.components.runner.conf import RUNNER_SETTINGS
|
||||
from rdagent.core.exception import CoderError, FactorEmptyError, ModelEmptyError
|
||||
from rdagent.core.experiment import ASpecificExp
|
||||
from rdagent.core.prompts import Prompts
|
||||
from rdagent.oai.llm_utils import APIBackend, md5_hash
|
||||
from rdagent.oai.llm_utils import md5_hash
|
||||
from rdagent.scenarios.kaggle.experiment.kaggle_experiment import (
|
||||
KGFactorExperiment,
|
||||
KGModelExperiment,
|
||||
@@ -32,48 +27,6 @@ class KGCachedRunner(CachedRunner[ASpecificExp]):
|
||||
codes = "\n".join(codes)
|
||||
return md5_hash(codes)
|
||||
|
||||
def extract_model_task_from_code(self, code: str) -> str:
|
||||
sys_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["extract_model_task_from_code"]["system"])
|
||||
.render()
|
||||
)
|
||||
|
||||
user_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["extract_model_task_from_code"]["user"])
|
||||
.render(file_content=code)
|
||||
)
|
||||
|
||||
model_task_description = APIBackend().build_messages_and_create_chat_completion(
|
||||
user_prompt=user_prompt,
|
||||
system_prompt=sys_prompt,
|
||||
json_mode=True,
|
||||
)
|
||||
|
||||
try:
|
||||
response_json_analysis = json.loads(model_task_description)
|
||||
task_desc = f"""name: {response_json_analysis['name']}
|
||||
description: {response_json_analysis['description']}
|
||||
"""
|
||||
task_desc += (
|
||||
f"formulation: {response_json_analysis['formulation']}\n"
|
||||
if response_json_analysis.get("formulation")
|
||||
else ""
|
||||
)
|
||||
task_desc += f"architecture: {response_json_analysis['architecture']}\n"
|
||||
task_desc += (
|
||||
f"variables: {json.dumps(response_json_analysis['variables'], indent=4)}\n"
|
||||
if response_json_analysis.get("variables")
|
||||
else ""
|
||||
)
|
||||
task_desc += f"hyperparameters: {json.dumps(response_json_analysis['hyperparameters'], indent=4)}\n"
|
||||
task_desc += f"model_type: {response_json_analysis['model_type']}\n"
|
||||
except json.JSONDecodeError:
|
||||
task_desc = "Failed to parse LLM's response as JSON"
|
||||
|
||||
return task_desc
|
||||
|
||||
def init_develop(self, exp: KGFactorExperiment | KGModelExperiment) -> KGFactorExperiment | KGModelExperiment:
|
||||
"""
|
||||
For the initial development, the experiment serves as a benchmark for feature engineering.
|
||||
@@ -89,39 +42,6 @@ class KGCachedRunner(CachedRunner[ASpecificExp]):
|
||||
result = exp.experiment_workspace.execute(run_env=env_to_use)
|
||||
|
||||
exp.result = result
|
||||
sub_task = FactorTask(
|
||||
factor_name="original features", factor_description="here is the original features", factor_formulation=""
|
||||
)
|
||||
|
||||
org_data_path = (
|
||||
Path(KAGGLE_IMPLEMENT_SETTING.local_data_path) / KAGGLE_IMPLEMENT_SETTING.competition / "X_valid.pkl"
|
||||
)
|
||||
with open(org_data_path, "rb") as f:
|
||||
org_data = pickle.load(f)
|
||||
feature_shape = org_data.shape[-1]
|
||||
exp.experiment_workspace.data_description.append((sub_task.get_task_information(), feature_shape))
|
||||
|
||||
model_map = {
|
||||
"XGBoost": "model_xgboost.py",
|
||||
"RandomForest": "model_randomforest.py",
|
||||
"LightGBM": "model_lightgbm.py",
|
||||
"NN": "model_nn.py",
|
||||
}
|
||||
|
||||
workspace_path = exp.experiment_workspace.workspace_path / "model"
|
||||
|
||||
for model_name, model_file in model_map.items():
|
||||
model_file_path = workspace_path / model_file
|
||||
|
||||
if model_file_path.exists():
|
||||
model_description = (
|
||||
self.extract_model_task_from_code(model_file_path.read_text())
|
||||
+ f"""code: {model_file_path.read_text()}"""
|
||||
)
|
||||
else:
|
||||
model_description = ""
|
||||
|
||||
exp.experiment_workspace.model_description[model_name] = model_description
|
||||
|
||||
if RUNNER_SETTINGS.cache_result:
|
||||
self.dump_cache_result(exp, result)
|
||||
@@ -135,17 +55,15 @@ class KGModelRunner(KGCachedRunner[KGModelExperiment]):
|
||||
exp.based_experiments[-1] = self.init_develop(exp.based_experiments[-1])
|
||||
|
||||
sub_ws = exp.sub_workspace_list[0]
|
||||
# TODO: There's a possibility of generating a hybrid model (lightgbm + xgboost), which results in having two items in the model_type list.
|
||||
model_type = sub_ws.target_task.model_type
|
||||
if sub_ws is not None:
|
||||
# TODO: There's a possibility of generating a hybrid model (lightgbm + xgboost), which results in having two items in the model_type list.
|
||||
model_type = sub_ws.target_task.model_type
|
||||
|
||||
if sub_ws.code_dict == {}:
|
||||
raise ModelEmptyError("No model is implemented.")
|
||||
else:
|
||||
model_file_name = f"model/model_{model_type.lower()}.py"
|
||||
exp.experiment_workspace.inject_code(**{model_file_name: sub_ws.code_dict["model.py"]})
|
||||
|
||||
model_description = sub_ws.target_task.get_task_information()
|
||||
exp.experiment_workspace.model_description[model_type] = model_description
|
||||
if sub_ws.code_dict == {}:
|
||||
raise ModelEmptyError("No model is implemented.")
|
||||
else:
|
||||
model_file_name = f"model/model_{model_type.lower()}.py"
|
||||
exp.experiment_workspace.inject_code(**{model_file_name: sub_ws.code_dict["model.py"]})
|
||||
|
||||
if RUNNER_SETTINGS.cache_result:
|
||||
cache_hit, result = self.get_cache_result(exp)
|
||||
|
||||
-1
@@ -3,7 +3,6 @@ import re
|
||||
|
||||
import numpy as np # linear algebra
|
||||
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
|
||||
from sklearn.feature_extraction.text import TfidfVectorizer
|
||||
from sklearn.model_selection import train_test_split
|
||||
|
||||
|
||||
|
||||
+2
-16
@@ -3,14 +3,6 @@ import pandas as pd
|
||||
from sklearn.ensemble import RandomForestRegressor
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
"""
|
||||
Define and train the Random Forest model. Merge feature selection into the pipeline.
|
||||
@@ -18,11 +10,8 @@ def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_vali
|
||||
# Initialize the Random Forest model
|
||||
model = RandomForestRegressor(n_estimators=100, random_state=32, n_jobs=-1)
|
||||
|
||||
# Select features (if any feature selection is needed)
|
||||
X_train_selected = select(X_train)
|
||||
|
||||
# Fit the model
|
||||
model.fit(X_train_selected, y_train)
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
return model
|
||||
|
||||
@@ -31,10 +20,7 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature selection's consistency and make predictions.
|
||||
"""
|
||||
# Select features (if any feature selection is needed)
|
||||
X_selected = select(X)
|
||||
|
||||
# Predict using the trained model
|
||||
y_pred = model.predict(X_selected)
|
||||
y_pred = model.predict(X)
|
||||
|
||||
return y_pred
|
||||
|
||||
-8
@@ -7,11 +7,6 @@ import xgboost as xgb
|
||||
from sklearn.multioutput import MultiOutputRegressor
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def is_sparse_df(df: pd.DataFrame) -> bool:
|
||||
# 检查 DataFrame 中的每一列是否为稀疏类型
|
||||
return any(isinstance(dtype, pd.SparseDtype) for dtype in df.dtypes)
|
||||
@@ -19,8 +14,6 @@ def is_sparse_df(df: pd.DataFrame) -> bool:
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
|
||||
xgb_estimator = xgb.XGBRegressor(
|
||||
n_estimators=500, random_state=0, objective="reg:squarederror", tree_method="hist", device="cuda"
|
||||
)
|
||||
@@ -38,7 +31,6 @@ def predict(model, X_test):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X_test = select(X_test)
|
||||
if is_sparse_df(X_test):
|
||||
X_test = X_test.sparse.to_coo()
|
||||
y_pred = model.predict(X_test)
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+19
-26
@@ -34,53 +34,46 @@ for f in DIRNAME.glob("feature/feat*.py"):
|
||||
X_valid_f = cls.transform(X_valid)
|
||||
X_test_f = cls.transform(X_test)
|
||||
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
if X_train_f.shape[-1] == X_valid_f.shape[-1] and X_train_f.shape[-1] == X_test_f.shape[-1]:
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
X_test = pd.concat(X_test_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_test_l))])
|
||||
|
||||
print(X_train.shape, X_valid.shape, X_test.shape)
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(str(col)).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func]]
|
||||
model_l = [] # list[tuple[model, predict_func,]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
metrics_all = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred = predict_func(model, X_valid)
|
||||
y_valid_pred_l.append(y_valid_pred)
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
metrics = MCRMSE(y_valid, y_valid_pred)
|
||||
print(f"MCRMSE on valid set: {metrics}")
|
||||
metrics_all.append(metrics)
|
||||
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmin(metrics_all)
|
||||
pd.Series(data=[metrics_all[min_index]], index=["MCRMSE"]).to_csv("submission_score.csv")
|
||||
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test)
|
||||
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = select_m.select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected)
|
||||
|
||||
# 7) Submit predictions for the test set
|
||||
submission_result = pd.read_csv("/kaggle/input/sample_submission.csv")
|
||||
submission_result["cohesion"] = y_test_pred[:, 0]
|
||||
submission_result["syntax"] = y_test_pred[:, 1]
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
import pandas as pd
|
||||
from catboost import CatBoostClassifier
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
# Define CatBoost parameters
|
||||
cat_params = {
|
||||
"iterations": 5000,
|
||||
"learning_rate": 0.03,
|
||||
"od_wait": 1000,
|
||||
"depth": 7,
|
||||
"task_type": "GPU",
|
||||
"l2_leaf_reg": 3,
|
||||
"eval_metric": "Accuracy",
|
||||
"devices": "0",
|
||||
"verbose": 1000,
|
||||
}
|
||||
|
||||
# Initialize and train the CatBoost model
|
||||
model = CatBoostClassifier(**cat_params)
|
||||
model.fit(X_train, y_train, eval_set=(X_valid, y_valid))
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def predict(model, X: pd.DataFrame):
|
||||
# Predict using the trained model
|
||||
y_pred = model.predict(X)
|
||||
return y_pred.reshape(-1, 1)
|
||||
+3
-18
@@ -10,14 +10,6 @@ from sklearn.ensemble import RandomForestClassifier
|
||||
from sklearn.metrics import accuracy_score
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
"""
|
||||
Define and train the Random Forest model. Merge feature selection into the pipeline.
|
||||
@@ -25,15 +17,11 @@ def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_vali
|
||||
# Initialize the Random Forest model
|
||||
model = RandomForestClassifier(n_estimators=200, random_state=32, n_jobs=-1)
|
||||
|
||||
# Select features (if any feature selection is needed)
|
||||
X_train_selected = select(X_train)
|
||||
X_valid_selected = select(X_valid)
|
||||
|
||||
# Fit the model
|
||||
model.fit(X_train_selected, y_train)
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
# Validate the model
|
||||
y_valid_pred = model.predict(X_valid_selected)
|
||||
y_valid_pred = model.predict(X_valid)
|
||||
accuracy = accuracy_score(y_valid, y_valid_pred)
|
||||
print(f"Validation Accuracy: {accuracy:.4f}")
|
||||
|
||||
@@ -44,10 +32,7 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature selection's consistency and make predictions.
|
||||
"""
|
||||
# Select features (if any feature selection is needed)
|
||||
X_selected = select(X)
|
||||
|
||||
# Predict using the trained model
|
||||
y_pred = model.predict(X_selected)
|
||||
y_pred = model.predict(X)
|
||||
|
||||
return y_pred.reshape(-1, 1)
|
||||
|
||||
-8
@@ -6,15 +6,8 @@ import pandas as pd
|
||||
import xgboost as xgb
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
dtrain = xgb.DMatrix(X_train, label=y_train)
|
||||
dvalid = xgb.DMatrix(X_valid, label=y_valid)
|
||||
|
||||
@@ -37,7 +30,6 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X = select(X)
|
||||
dtest = xgb.DMatrix(X)
|
||||
y_pred = model.predict(dtest)
|
||||
return y_pred.astype(int).reshape(-1, 1)
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+48
-99
@@ -4,11 +4,8 @@ from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from scipy import stats
|
||||
from sklearn.impute import SimpleImputer
|
||||
from sklearn.metrics import accuracy_score
|
||||
from sklearn.model_selection import KFold
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
from fea_share_preprocess import clean_and_impute_data, preprocess_script
|
||||
from sklearn.metrics import accuracy_score, matthews_corrcoef
|
||||
|
||||
# Set random seed for reproducibility
|
||||
SEED = 42
|
||||
@@ -17,6 +14,12 @@ np.random.seed(SEED)
|
||||
DIRNAME = Path(__file__).absolute().resolve().parent
|
||||
|
||||
|
||||
def compute_metrics_for_classification(y_true, y_pred):
|
||||
"""Compute MCC for classification."""
|
||||
mcc = matthews_corrcoef(y_true, y_pred)
|
||||
return mcc
|
||||
|
||||
|
||||
def import_module_from_path(module_name, module_path):
|
||||
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
@@ -25,117 +28,63 @@ def import_module_from_path(module_name, module_path):
|
||||
|
||||
|
||||
# 1) Preprocess the data
|
||||
data_df = pd.read_csv("/kaggle/input/train.csv")
|
||||
data_df = data_df.drop(["Id"], axis=1)
|
||||
X_train, X_valid, y_train, y_valid, X_test, ids = preprocess_script()
|
||||
|
||||
X_train = data_df.drop(["Cover_Type"], axis=1)
|
||||
y_train = data_df["Cover_Type"] - 1
|
||||
# 2) Auto feature engineering
|
||||
X_train_l, X_valid_l = [], []
|
||||
X_test_l = []
|
||||
|
||||
submission_df = pd.read_csv("/kaggle/input/test.csv")
|
||||
ids = submission_df["Id"]
|
||||
X_test = submission_df.drop(["Id"], axis=1)
|
||||
|
||||
# Set up KFold
|
||||
kf = KFold(n_splits=5, shuffle=True, random_state=SEED)
|
||||
|
||||
# Store results
|
||||
accuracies = []
|
||||
y_test_pred_l = []
|
||||
scaler = StandardScaler()
|
||||
|
||||
# 3) Train and evaluate using KFold
|
||||
fold_number = 1
|
||||
for train_index, valid_index in kf.split(X_train):
|
||||
print(f"Starting fold {fold_number}...")
|
||||
|
||||
X_train_l, X_valid_l, X_test_l = [], [], [] # Reset feature lists for each fold
|
||||
X_tr, X_val = X_train.iloc[train_index], X_train.iloc[valid_index]
|
||||
y_tr, y_val = y_train.iloc[train_index], y_train.iloc[valid_index]
|
||||
X_te = X_test
|
||||
|
||||
# Feature engineering
|
||||
for f in DIRNAME.glob("feature/feat*.py"):
|
||||
cls = import_module_from_path(f.stem, f).feature_engineering_cls()
|
||||
cls.fit(X_tr)
|
||||
X_train_f = cls.transform(X_tr)
|
||||
X_valid_f = cls.transform(X_val)
|
||||
X_test_f = cls.transform(X_te)
|
||||
for f in DIRNAME.glob("feature/feat*.py"):
|
||||
cls = import_module_from_path(f.stem, f).feature_engineering_cls()
|
||||
cls.fit(X_train)
|
||||
X_train_f = cls.transform(X_train)
|
||||
X_valid_f = cls.transform(X_valid)
|
||||
X_test_f = cls.transform(X_test)
|
||||
|
||||
if X_train_f.shape[-1] == X_valid_f.shape[-1] and X_train_f.shape[-1] == X_test_f.shape[-1]:
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_tr = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_val = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
X_te = pd.concat(X_test_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_test_l))])
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
X_test = pd.concat(X_test_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_test_l))])
|
||||
|
||||
print("Shape of X_tr: ", X_tr.shape, " Shape of X_val: ", X_val.shape, " Shape of X_te: ", X_te.shape)
|
||||
print(X_train.shape, X_valid.shape, X_test.shape)
|
||||
|
||||
# Replace inf and -inf with NaN
|
||||
X_tr.replace([np.inf, -np.inf], np.nan, inplace=True)
|
||||
X_val.replace([np.inf, -np.inf], np.nan, inplace=True)
|
||||
X_te.replace([np.inf, -np.inf], np.nan, inplace=True)
|
||||
# Handle inf and -inf values
|
||||
X_train, X_valid, X_test = clean_and_impute_data(X_train, X_valid, X_test)
|
||||
|
||||
# Impute missing values
|
||||
imputer = SimpleImputer(strategy="mean")
|
||||
X_tr = pd.DataFrame(imputer.fit_transform(X_tr), columns=X_tr.columns)
|
||||
X_val = pd.DataFrame(imputer.transform(X_val), columns=X_val.columns)
|
||||
X_te = pd.DataFrame(imputer.transform(X_te), columns=X_te.columns)
|
||||
|
||||
# Standardize the data
|
||||
X_tr = pd.DataFrame(scaler.fit_transform(X_tr), columns=X_tr.columns)
|
||||
X_val = pd.DataFrame(scaler.transform(X_val), columns=X_val.columns)
|
||||
X_te = pd.DataFrame(scaler.transform(X_te), columns=X_te.columns)
|
||||
model_l = [] # list[tuple[model, predict_func]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
# Remove duplicate columns
|
||||
X_tr = X_tr.loc[:, ~X_tr.columns.duplicated()]
|
||||
X_val = X_val.loc[:, ~X_val.columns.duplicated()]
|
||||
X_te = X_te.loc[:, ~X_te.columns.duplicated()]
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict, select_m))
|
||||
|
||||
# Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
# 4) Evaluate the model on the validation set
|
||||
metrics_all = []
|
||||
for model, predict_func, select_m in model_l:
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
accuracy = accuracy_score(y_valid, y_valid_pred)
|
||||
print(f"final accuracy on valid set: {accuracy}")
|
||||
metrics_all.append(accuracy)
|
||||
|
||||
X_tr = flatten_columns(X_tr)
|
||||
X_val = flatten_columns(X_val)
|
||||
X_te = flatten_columns(X_te)
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmax(metrics_all)
|
||||
pd.Series(data=[metrics_all[min_index]], index=["multi-class accuracy"]).to_csv("submission_score.csv")
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_tr, y_tr, X_val, y_val), m.predict))
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = model_l[min_index][2].select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected).flatten() + 1
|
||||
|
||||
# Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred = predict_func(model, X_val)
|
||||
y_valid_pred_l.append(y_valid_pred)
|
||||
y_test_pred_l.append(predict_func(model, X_te))
|
||||
|
||||
# Majority vote ensemble
|
||||
y_valid_pred_ensemble = stats.mode(y_valid_pred_l, axis=0)[0].flatten()
|
||||
|
||||
# Compute metrics
|
||||
accuracy = accuracy_score(y_val, y_valid_pred_ensemble)
|
||||
accuracies.append(accuracy)
|
||||
print(f"Fold {fold_number} accuracy: {accuracy}")
|
||||
|
||||
fold_number += 1
|
||||
|
||||
# Print average accuracy
|
||||
accuracy = np.mean(accuracies)
|
||||
print(f"Average accuracy across folds: {accuracy}")
|
||||
pd.Series(data=[accuracy], index=["multi-class accuracy"]).to_csv("submission_score.csv")
|
||||
|
||||
y_test_pred = stats.mode(y_test_pred_l, axis=0)[0].flatten() + 1
|
||||
|
||||
# 7) Submit predictions for the test set
|
||||
submission_result = pd.DataFrame(y_test_pred, columns=["Cover_Type"])
|
||||
submission_result.insert(0, "Id", ids)
|
||||
|
||||
|
||||
+101
-86
@@ -1,12 +1,13 @@
|
||||
import importlib.util
|
||||
import random
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from fea_share_preprocess import clean_and_impute_data, preprocess_script
|
||||
from scipy import stats
|
||||
from sklearn.metrics import accuracy_score, matthews_corrcoef
|
||||
from sklearn.impute import SimpleImputer
|
||||
from sklearn.metrics import accuracy_score
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
|
||||
# Set random seed for reproducibility
|
||||
SEED = 42
|
||||
@@ -15,19 +16,6 @@ np.random.seed(SEED)
|
||||
DIRNAME = Path(__file__).absolute().resolve().parent
|
||||
|
||||
|
||||
# support various method for metrics calculation
|
||||
def compute_metrics_for_classification(y_true, y_pred):
|
||||
"""Compute accuracy metric for classification."""
|
||||
accuracy = accuracy_score(y_true, y_pred)
|
||||
return accuracy
|
||||
|
||||
|
||||
def compute_metrics_for_classification(y_true, y_pred):
|
||||
"""Compute MCC for classification."""
|
||||
mcc = matthews_corrcoef(y_true, y_pred)
|
||||
return mcc
|
||||
|
||||
|
||||
def import_module_from_path(module_name, module_path):
|
||||
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
@@ -36,81 +24,108 @@ def import_module_from_path(module_name, module_path):
|
||||
|
||||
|
||||
# 1) Preprocess the data
|
||||
X_train, X_valid, y_train, y_valid, X_test, ids = preprocess_script()
|
||||
|
||||
# 2) Auto feature engineering
|
||||
X_train_l, X_valid_l = [], []
|
||||
X_test_l = []
|
||||
|
||||
for f in DIRNAME.glob("feature/feat*.py"):
|
||||
cls = import_module_from_path(f.stem, f).feature_engineering_cls()
|
||||
cls.fit(X_train)
|
||||
X_train_f = cls.transform(X_train)
|
||||
X_valid_f = cls.transform(X_valid)
|
||||
X_test_f = cls.transform(X_test)
|
||||
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
X_test = pd.concat(X_test_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_test_l))])
|
||||
|
||||
print(X_train.shape, X_valid.shape, X_test.shape)
|
||||
|
||||
# Handle inf and -inf values
|
||||
X_train, X_valid, X_test = clean_and_impute_data(X_train, X_valid, X_test)
|
||||
print("-1")
|
||||
data_df = pd.read_csv("/kaggle/input/train.csv")
|
||||
data_df = data_df.drop(["Id"], axis=1)
|
||||
print("0")
|
||||
X_train = data_df.drop(["Cover_Type"], axis=1)
|
||||
y_train = data_df["Cover_Type"] - 1
|
||||
print("81")
|
||||
submission_df = pd.read_csv("/kaggle/input/test.csv")
|
||||
ids = submission_df["Id"]
|
||||
X_test = submission_df.drop(["Id"], axis=1)
|
||||
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred = predict_func(model, X_valid)
|
||||
y_valid_pred_l.append(y_valid_pred)
|
||||
print(y_valid_pred)
|
||||
print(y_valid_pred.shape)
|
||||
|
||||
# 5) Ensemble
|
||||
# Majority vote ensemble
|
||||
y_valid_pred_ensemble = stats.mode(y_valid_pred_l, axis=0)[0].flatten()
|
||||
|
||||
# Compute metrics
|
||||
accuracy = accuracy_score(y_valid, y_valid_pred_ensemble)
|
||||
print(f"final accuracy on valid set: {accuracy}")
|
||||
|
||||
# 6) Save the validation metrics
|
||||
pd.Series(data=[accuracy], index=["multi-class accuracy"]).to_csv("submission_score.csv")
|
||||
|
||||
# 7) Make predictions on the test set and save them
|
||||
# Store results
|
||||
accuracies = []
|
||||
y_test_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_test_pred_l.append(predict_func(model, X_test))
|
||||
scaler = StandardScaler()
|
||||
|
||||
# For multiclass classification, use the mode of the predictions
|
||||
y_test_pred = stats.mode(y_test_pred_l, axis=0)[0].flatten() + 1
|
||||
print("12")
|
||||
# 3) Train and evaluate using KFold
|
||||
fold_number = 1
|
||||
model_count = defaultdict(int)
|
||||
print("123")
|
||||
for train_index, valid_index in kf.split(X_train):
|
||||
print(f"Starting fold {fold_number}...")
|
||||
|
||||
X_train_l, X_valid_l, X_test_l = [], [], [] # Reset feature lists for each fold
|
||||
X_tr, X_val = X_train.iloc[train_index], X_train.iloc[valid_index]
|
||||
y_tr, y_val = y_train.iloc[train_index], y_train.iloc[valid_index]
|
||||
X_te = X_test
|
||||
|
||||
# Feature engineering
|
||||
for f in DIRNAME.glob("feature/feat*.py"):
|
||||
cls = import_module_from_path(f.stem, f).feature_engineering_cls()
|
||||
cls.fit(X_tr)
|
||||
X_train_f = cls.transform(X_tr)
|
||||
X_valid_f = cls.transform(X_val)
|
||||
X_test_f = cls.transform(X_te)
|
||||
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_tr = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_val = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
X_te = pd.concat(X_test_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_test_l))])
|
||||
|
||||
print("Shape of X_tr: ", X_tr.shape, " Shape of X_val: ", X_val.shape, " Shape of X_te: ", X_te.shape)
|
||||
|
||||
# Replace inf and -inf with NaN
|
||||
X_tr.replace([np.inf, -np.inf], np.nan, inplace=True)
|
||||
X_val.replace([np.inf, -np.inf], np.nan, inplace=True)
|
||||
X_te.replace([np.inf, -np.inf], np.nan, inplace=True)
|
||||
|
||||
# Impute missing values
|
||||
imputer = SimpleImputer(strategy="mean")
|
||||
X_tr = pd.DataFrame(imputer.fit_transform(X_tr), columns=X_tr.columns)
|
||||
X_val = pd.DataFrame(imputer.transform(X_val), columns=X_val.columns)
|
||||
X_te = pd.DataFrame(imputer.transform(X_te), columns=X_te.columns)
|
||||
|
||||
# Standardize the data
|
||||
X_tr = pd.DataFrame(scaler.fit_transform(X_tr), columns=X_tr.columns)
|
||||
X_val = pd.DataFrame(scaler.transform(X_val), columns=X_val.columns)
|
||||
X_te = pd.DataFrame(scaler.transform(X_te), columns=X_te.columns)
|
||||
|
||||
# Remove duplicate columns
|
||||
X_tr = X_tr.loc[:, ~X_tr.columns.duplicated()]
|
||||
X_val = X_val.loc[:, ~X_val.columns.duplicated()]
|
||||
X_te = X_te.loc[:, ~X_te.columns.duplicated()]
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_tr.copy())
|
||||
X_valid_selected = select_m.select(X_val.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train_selected, y_tr, X_valid_selected, y_val), m.predict))
|
||||
|
||||
# 4) Evaluate the models on the validation set and choose the best one
|
||||
best_accuracy = -1
|
||||
best = None
|
||||
for model, predict_func in model_l:
|
||||
X_valid_selected = select_m.select(X_val.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
accuracy = accuracy_score(y_val, y_valid_pred)
|
||||
print(f"Accuracy on valid set: {accuracy}")
|
||||
|
||||
if accuracy > best_accuracy:
|
||||
best_accuracy = accuracy
|
||||
best = (model, predict_func)
|
||||
|
||||
model_count[best] += 1
|
||||
fold_number += 1
|
||||
|
||||
# 5) Save the validation accuracy
|
||||
final_model = max(model_count, key=model_count.get)
|
||||
pd.Series(data=best_accuracy, index=["multi-class accuracy"]).to_csv("submission_score.csv")
|
||||
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = select_m.select(X_te.copy())
|
||||
y_test_pred = final_model[1](final_model[0], X_test_selected).flatten() + 1
|
||||
|
||||
submission_result = pd.DataFrame(y_test_pred, columns=["Cover_Type"])
|
||||
submission_result.insert(0, "Id", ids)
|
||||
|
||||
@@ -14,9 +14,28 @@ from rdagent.components.coder.model_coder.model import (
|
||||
)
|
||||
from rdagent.scenarios.kaggle.experiment.workspace import KGFBWorkspace
|
||||
|
||||
KG_MODEL_TYPE_XGBOOST = "XGBoost"
|
||||
KG_MODEL_TYPE_RANDOMFOREST = "RandomForest"
|
||||
KG_MODEL_TYPE_LIGHTGBM = "LightGBM"
|
||||
KG_MODEL_TYPE_NN = "NN"
|
||||
|
||||
KG_MODEL_MAPPING = {
|
||||
KG_MODEL_TYPE_XGBOOST: "model/model_xgboost.py",
|
||||
KG_MODEL_TYPE_RANDOMFOREST: "model/model_randomforest.py",
|
||||
KG_MODEL_TYPE_LIGHTGBM: "model/model_lightgbm.py",
|
||||
KG_MODEL_TYPE_NN: "model/model_nn.py",
|
||||
}
|
||||
|
||||
KG_SELECT_MAPPING = {
|
||||
KG_MODEL_TYPE_XGBOOST: "model/select_xgboost.py",
|
||||
KG_MODEL_TYPE_RANDOMFOREST: "model/select_randomforest.py",
|
||||
KG_MODEL_TYPE_LIGHTGBM: "model/select_lightgbm.py",
|
||||
KG_MODEL_TYPE_NN: "model/select_nn.py",
|
||||
}
|
||||
|
||||
|
||||
class KGModelExperiment(ModelExperiment[ModelTask, KGFBWorkspace, ModelFBWorkspace]):
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
def __init__(self, *args, source_feature_size: int = None, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self.experiment_workspace = KGFBWorkspace(
|
||||
template_folder_path=Path(__file__).parent / f"{KAGGLE_IMPLEMENT_SETTING.competition}_template"
|
||||
@@ -26,13 +45,21 @@ class KGModelExperiment(ModelExperiment[ModelTask, KGFBWorkspace, ModelFBWorkspa
|
||||
self.experiment_workspace.data_description = deepcopy(
|
||||
self.based_experiments[-1].experiment_workspace.data_description
|
||||
)
|
||||
self.experiment_workspace.model_description = deepcopy(
|
||||
self.based_experiments[-1].experiment_workspace.model_description
|
||||
)
|
||||
else:
|
||||
self.experiment_workspace.data_description = [
|
||||
(
|
||||
FactorTask(
|
||||
factor_name="Original features",
|
||||
factor_description="The original features",
|
||||
factor_formulation="",
|
||||
).get_task_information(),
|
||||
source_feature_size,
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class KGFactorExperiment(FeatureExperiment[FactorTask, KGFBWorkspace, FactorFBWorkspace]):
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
def __init__(self, *args, source_feature_size: int = None, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self.experiment_workspace = KGFBWorkspace(
|
||||
template_folder_path=Path(__file__).parent / f"{KAGGLE_IMPLEMENT_SETTING.competition}_template"
|
||||
@@ -42,6 +69,14 @@ class KGFactorExperiment(FeatureExperiment[FactorTask, KGFBWorkspace, FactorFBWo
|
||||
self.experiment_workspace.data_description = deepcopy(
|
||||
self.based_experiments[-1].experiment_workspace.data_description
|
||||
)
|
||||
self.experiment_workspace.model_description = deepcopy(
|
||||
self.based_experiments[-1].experiment_workspace.model_description
|
||||
)
|
||||
else:
|
||||
self.experiment_workspace.data_description = [
|
||||
(
|
||||
FactorTask(
|
||||
factor_name="Original features",
|
||||
factor_description="The original features",
|
||||
factor_formulation="",
|
||||
).get_task_information(),
|
||||
source_feature_size,
|
||||
)
|
||||
]
|
||||
|
||||
+3
-18
@@ -4,14 +4,6 @@ from sklearn.ensemble import RandomForestRegressor
|
||||
from sklearn.metrics import mean_squared_error
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
"""
|
||||
Define and train the Random Forest model. Merge feature selection into the pipeline.
|
||||
@@ -19,15 +11,11 @@ def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_vali
|
||||
# Initialize the Random Forest model
|
||||
model = RandomForestRegressor(n_estimators=100, random_state=32, n_jobs=-1)
|
||||
|
||||
# Select features (if any feature selection is needed)
|
||||
X_train_selected = select(X_train)
|
||||
X_valid_selected = select(X_valid)
|
||||
|
||||
# Fit the model
|
||||
model.fit(X_train_selected, y_train)
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
# Validate the model
|
||||
y_valid_pred = model.predict(X_valid_selected)
|
||||
y_valid_pred = model.predict(X_valid)
|
||||
mse = mean_squared_error(y_valid, y_valid_pred)
|
||||
rmse = np.sqrt(mse)
|
||||
print(f"Validation RMSE: {rmse:.4f}")
|
||||
@@ -39,10 +27,7 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature selection's consistency and make predictions.
|
||||
"""
|
||||
# Select features (if any feature selection is needed)
|
||||
X_selected = select(X)
|
||||
|
||||
# Predict using the trained model
|
||||
y_pred = model.predict(X_selected)
|
||||
y_pred = model.predict(X)
|
||||
|
||||
return y_pred.reshape(-1, 1)
|
||||
|
||||
-8
@@ -2,15 +2,8 @@ import pandas as pd
|
||||
import xgboost as xgb
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
dtrain = xgb.DMatrix(X_train, label=y_train)
|
||||
dvalid = xgb.DMatrix(X_valid, label=y_valid)
|
||||
|
||||
@@ -33,7 +26,6 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X = select(X)
|
||||
dtest = xgb.DMatrix(X)
|
||||
y_pred = model.predict(dtest)
|
||||
return y_pred.reshape(-1, 1)
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+18
-27
@@ -42,9 +42,10 @@ for f in DIRNAME.glob("feature/feat*.py"):
|
||||
X_valid_f = cls.transform(X_valid)
|
||||
X_test_f = cls.transform(X_test)
|
||||
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
if X_train_f.shape[-1] == X_valid_f.shape[-1] and X_train_f.shape[-1] == X_test_f.shape[-1]:
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
@@ -70,42 +71,32 @@ X_test = X_test.loc[:, ~X_test.columns.duplicated()]
|
||||
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func,]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict, select_m))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
metrics_all = []
|
||||
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred_l.append(predict_func(model, X_valid))
|
||||
metrics = compute_rmspe(y_valid, y_valid_pred_l[-1].ravel())
|
||||
for model, predict_func, select_m in model_l:
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
metrics = compute_rmspe(y_valid, y_valid_pred.ravel())
|
||||
print(f"RMSPE on valid set: {metrics}")
|
||||
metrics_all.append(metrics)
|
||||
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmin(metrics_all)
|
||||
|
||||
pd.Series(data=[metrics_all[min_index]], index=["RMSPE"]).to_csv("submission_score.csv")
|
||||
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test).ravel()
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = model_l[min_index][2].select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected).ravel()
|
||||
|
||||
# 5) Submit predictions for the test set
|
||||
submission_result = pd.DataFrame({"row_id": ids, "target": y_test_pred})
|
||||
submission_result.to_csv("submission.csv", index=False)
|
||||
|
||||
-8
@@ -2,15 +2,8 @@ import pandas as pd
|
||||
from sklearn.ensemble import RandomForestRegressor
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the Random Forest model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
|
||||
rf_params = {
|
||||
"n_estimators": 100,
|
||||
"max_depth": 10,
|
||||
@@ -30,6 +23,5 @@ def predict(model, X_test):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X_test = select(X_test)
|
||||
y_pred = model.predict(X_test)
|
||||
return y_pred.reshape(-1, 1)
|
||||
|
||||
-8
@@ -6,15 +6,8 @@ import pandas as pd
|
||||
import xgboost as xgb
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
|
||||
xgb_params = {
|
||||
"n_estimators": 280,
|
||||
"learning_rate": 0.05,
|
||||
@@ -37,6 +30,5 @@ def predict(model, X_test):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X_test = select(X_test)
|
||||
y_pred = model.predict(X_test)
|
||||
return y_pred.reshape(-1, 1)
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
@@ -30,9 +30,10 @@ for f in DIRNAME.glob("feature/feat*.py"):
|
||||
X_valid_f = cls.transform(X_valid)
|
||||
X_test_f = cls.transform(X_test)
|
||||
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
if X_train_f.shape[-1] == X_valid_f.shape[-1] and X_train_f.shape[-1] == X_test_f.shape[-1]:
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
@@ -40,41 +41,34 @@ X_test = pd.concat(X_test_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_t
|
||||
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict, select_m))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
metrics_all = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred = predict_func(model, X_valid)
|
||||
y_valid_pred_l.append(y_valid_pred)
|
||||
for model, predict_func, select_m in model_l:
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
metrics = mean_squared_error(y_valid, y_valid_pred, squared=False)
|
||||
print(f"RMLSE on valid set: {metrics}")
|
||||
metrics_all.append(metrics)
|
||||
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmin(metrics_all)
|
||||
pd.Series(data=[metrics_all[min_index]], index=["RMLSE"]).to_csv("submission_score.csv")
|
||||
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test)
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = model_l[min_index][2].select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected)
|
||||
|
||||
# 7) Submit predictions for the test set
|
||||
submission_result = pd.DataFrame(np.expm1(y_test_pred), columns=["cost"])
|
||||
submission_result.insert(0, "id", ids)
|
||||
|
||||
|
||||
+2
-22
@@ -10,14 +10,6 @@ from sklearn.ensemble import RandomForestClassifier
|
||||
from sklearn.metrics import accuracy_score
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
"""
|
||||
Define and train the Random Forest model. Merge feature selection into the pipeline.
|
||||
@@ -25,17 +17,8 @@ def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_vali
|
||||
# Initialize the Random Forest model
|
||||
model = RandomForestClassifier(n_estimators=100, random_state=32, n_jobs=-1)
|
||||
|
||||
# Select features (if any feature selection is needed)
|
||||
X_train_selected = select(X_train)
|
||||
X_valid_selected = select(X_valid)
|
||||
|
||||
# Fit the model
|
||||
model.fit(X_train_selected, y_train)
|
||||
|
||||
# Validate the model
|
||||
y_valid_pred = model.predict(X_valid_selected)
|
||||
# accuracy = accuracy_score(y_valid, y_valid_pred)
|
||||
# print(f"Validation Accuracy: {accuracy:.4f}")
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
return model
|
||||
|
||||
@@ -44,11 +27,8 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature selection's consistency and make predictions.
|
||||
"""
|
||||
# Select features (if any feature selection is needed)
|
||||
X_selected = select(X)
|
||||
|
||||
# Predict using the trained model
|
||||
y_pred_prob = model.predict_proba(X_selected)
|
||||
y_pred_prob = model.predict_proba(X)
|
||||
|
||||
# Apply threshold to get boolean predictions
|
||||
return y_pred_prob
|
||||
|
||||
-8
@@ -7,15 +7,8 @@ import pandas as pd
|
||||
import xgboost as xgb
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
dtrain = xgb.DMatrix(X_train, label=y_train)
|
||||
dvalid = xgb.DMatrix(X_valid, label=y_valid)
|
||||
num_classes = len(np.unique(y_train))
|
||||
@@ -40,7 +33,6 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X = select(X)
|
||||
dtest = xgb.DMatrix(X)
|
||||
y_pred_prob = model.predict(dtest)
|
||||
return y_pred_prob
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
@@ -53,6 +53,7 @@ X_train = pd.concat(X_train_l, axis=1)
|
||||
X_valid = pd.concat(X_valid_l, axis=1)
|
||||
X_test = pd.concat(X_test_l, axis=1)
|
||||
|
||||
print(X_train.shape, X_valid.shape, X_test.shape)
|
||||
|
||||
# Handle inf and -inf values
|
||||
X_train.replace([np.inf, -np.inf], np.nan, inplace=True)
|
||||
@@ -72,62 +73,38 @@ X_train = X_train.loc[:, ~X_train.columns.duplicated()]
|
||||
X_valid = X_valid.loc[:, ~X_valid.columns.duplicated()]
|
||||
X_test = X_test.loc[:, ~X_test.columns.duplicated()]
|
||||
|
||||
print(X_train.shape, X_valid.shape, X_test.shape)
|
||||
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func]]
|
||||
model_l = [] # list[tuple[model, predict_func,]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict, select_m))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred_l.append(predict_func(model, X_valid))
|
||||
print(predict_func(model, X_valid))
|
||||
print(predict_func(model, X_valid).shape)
|
||||
metrics_all = []
|
||||
for model, predict_func, select_m in model_l:
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
logloss = compute_metrics_for_classification(y_valid, y_valid_pred)
|
||||
print(f"log_loss on valid set: {logloss}")
|
||||
metrics_all.append(logloss)
|
||||
|
||||
# 5) Ensemble
|
||||
from scipy import stats
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmin(metrics_all)
|
||||
pd.Series(data=[metrics_all[min_index]], index=["log_loss"]).to_csv("submission_score.csv")
|
||||
|
||||
# average probabilities ensemble
|
||||
y_valid_pred_proba = np.mean(y_valid_pred_l, axis=0)
|
||||
|
||||
# Compute metrics
|
||||
logloss = compute_metrics_for_classification(y_valid, y_valid_pred_proba)
|
||||
print(f"final log_loss on valid set: {logloss}")
|
||||
|
||||
# 6) Save the validation metrics
|
||||
pd.Series(data=[logloss], index=["log_loss"]).to_csv("submission_score.csv")
|
||||
|
||||
# 7) Make predictions on the test set and save them
|
||||
y_test_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_test_pred_l.append(predict_func(model, X_test))
|
||||
|
||||
# For multiclass classification, use the mode of the predictions
|
||||
y_test_pred_proba = np.mean(y_test_pred_l, axis=0)
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = model_l[min_index][2].select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected)
|
||||
|
||||
class_labels = ["Status_" + label for label in status_encoder.classes_]
|
||||
# modified_labels = ["Status_" + label for label in class_labels]
|
||||
|
||||
submission_result = pd.DataFrame(y_test_pred_proba, columns=class_labels)
|
||||
submission_result = pd.DataFrame(y_test_pred, columns=class_labels)
|
||||
submission_result.insert(0, "id", test_ids)
|
||||
|
||||
submission_result.to_csv("submission.csv", index=False)
|
||||
|
||||
+3
-18
@@ -10,14 +10,6 @@ from sklearn.ensemble import RandomForestClassifier
|
||||
from sklearn.metrics import accuracy_score
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
"""
|
||||
Define and train the Random Forest model. Merge feature selection into the pipeline.
|
||||
@@ -25,15 +17,11 @@ def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_vali
|
||||
# Initialize the Random Forest model
|
||||
model = RandomForestClassifier(n_estimators=100, random_state=32, n_jobs=-1)
|
||||
|
||||
# Select features (if any feature selection is needed)
|
||||
X_train_selected = select(X_train)
|
||||
X_valid_selected = select(X_valid)
|
||||
|
||||
# Fit the model
|
||||
model.fit(X_train_selected, y_train)
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
# Validate the model
|
||||
y_valid_pred = model.predict(X_valid_selected)
|
||||
y_valid_pred = model.predict(X_valid)
|
||||
accuracy = accuracy_score(y_valid, y_valid_pred)
|
||||
print(f"Validation Accuracy: {accuracy:.4f}")
|
||||
|
||||
@@ -44,11 +32,8 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature selection's consistency and make predictions.
|
||||
"""
|
||||
# Select features (if any feature selection is needed)
|
||||
X_selected = select(X)
|
||||
|
||||
# Predict using the trained model
|
||||
y_pred_prob = model.predict_proba(X_selected)[:, 1]
|
||||
y_pred_prob = model.predict_proba(X)[:, 1]
|
||||
|
||||
# Apply threshold to get boolean predictions
|
||||
return y_pred_prob.reshape(-1, 1)
|
||||
|
||||
-9
@@ -6,19 +6,11 @@ import pandas as pd
|
||||
import xgboost as xgb
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
dtrain = xgb.DMatrix(X_train, label=y_train)
|
||||
dvalid = xgb.DMatrix(X_valid, label=y_valid)
|
||||
|
||||
# TODO: for quick running....
|
||||
params = {
|
||||
"nthread": -1,
|
||||
"tree_method": "gpu_hist",
|
||||
@@ -36,7 +28,6 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X = select(X)
|
||||
dtest = xgb.DMatrix(X)
|
||||
y_pred_prob = model.predict(dtest)
|
||||
return y_pred_prob.reshape(-1, 1)
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
@@ -6,7 +6,6 @@ import numpy as np
|
||||
import pandas as pd
|
||||
from fea_share_preprocess import preprocess_script
|
||||
from sklearn.metrics import matthews_corrcoef
|
||||
from sklearn.preprocessing import LabelEncoder
|
||||
|
||||
# Set random seed for reproducibility
|
||||
SEED = 42
|
||||
@@ -43,9 +42,10 @@ for f in DIRNAME.glob("feature/feat*.py"):
|
||||
X_valid_f = cls.transform(X_valid)
|
||||
X_test_f = cls.transform(X_test)
|
||||
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
if X_train_f.shape[-1] == X_valid_f.shape[-1] and X_train_f.shape[-1] == X_test_f.shape[-1]:
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
@@ -71,55 +71,38 @@ X_train = X_train.loc[:, ~X_train.columns.duplicated()]
|
||||
X_valid = X_valid.loc[:, ~X_valid.columns.duplicated()]
|
||||
X_test = X_test.loc[:, ~X_test.columns.duplicated()]
|
||||
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func,]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict, select_m))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred_l.append(predict_func(model, X_valid))
|
||||
metrics_all = []
|
||||
for model, predict_func, select_m in model_l:
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
y_valid_pred = (y_valid_pred > 0.5).astype(int)
|
||||
metrics = compute_metrics_for_classification(y_valid, y_valid_pred)
|
||||
print("MCC on validation set: ", metrics)
|
||||
metrics_all.append(metrics)
|
||||
|
||||
# 5) Ensemble
|
||||
# TODO: ensemble method in a script
|
||||
# Average the predictions and apply a threshold to determine class labels
|
||||
y_valid_pred = np.mean(y_valid_pred_l, axis=0)
|
||||
y_valid_pred = (y_valid_pred > 0.5).astype(int)
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmin(metrics_all)
|
||||
pd.Series(data=[metrics_all[min_index]], index=["MCC"]).to_csv("submission_score.csv")
|
||||
|
||||
mcc = compute_metrics_for_classification(y_valid, y_valid_pred)
|
||||
print("MCC on validation set: ", mcc)
|
||||
|
||||
# 6) Save the validation accuracy
|
||||
pd.Series(data=[mcc], index=["MCC"]).to_csv("submission_score.csv")
|
||||
|
||||
# 7) Make predictions on the test set and save them
|
||||
y_test_pred_l = []
|
||||
for m, m_pred in model_l:
|
||||
y_test_pred_l.append(m_pred(m, X_test)) # TODO Make this an ensemble. Currently it uses the last prediction
|
||||
|
||||
y_test_pred = np.mean(y_test_pred_l, axis=0)
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = model_l[min_index][2].select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected)
|
||||
y_test_pred = (y_test_pred > 0.5).astype(int)
|
||||
|
||||
y_test_pred_labels = np.where(y_test_pred == 1, "p", "e") # 将整数转换回 'e' 或 'p'
|
||||
|
||||
# 8) Submit predictions for the test set
|
||||
# 7) Submit predictions for the test set
|
||||
submission_result = pd.DataFrame({"id": ids, "class": y_test_pred_labels.ravel()})
|
||||
submission_result.to_csv("submission.csv", index=False)
|
||||
|
||||
+3
-18
@@ -4,14 +4,6 @@ from sklearn.ensemble import RandomForestRegressor
|
||||
from sklearn.metrics import mean_squared_error
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
"""
|
||||
Define and train the Random Forest model. Merge feature selection into the pipeline.
|
||||
@@ -19,15 +11,11 @@ def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_vali
|
||||
# Initialize the Random Forest model
|
||||
model = RandomForestRegressor(n_estimators=100, random_state=32, n_jobs=-1)
|
||||
|
||||
# Select features (if any feature selection is needed)
|
||||
X_train_selected = select(X_train)
|
||||
X_valid_selected = select(X_valid)
|
||||
|
||||
# Fit the model
|
||||
model.fit(X_train_selected, y_train)
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
# Validate the model
|
||||
y_valid_pred = model.predict(X_valid_selected)
|
||||
y_valid_pred = model.predict(X_valid)
|
||||
mse = mean_squared_error(y_valid, y_valid_pred)
|
||||
rmse = np.sqrt(mse)
|
||||
print(f"Validation RMSE: {rmse:.4f}")
|
||||
@@ -39,10 +27,7 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature selection's consistency and make predictions.
|
||||
"""
|
||||
# Select features (if any feature selection is needed)
|
||||
X_selected = select(X)
|
||||
|
||||
# Predict using the trained model
|
||||
y_pred = model.predict(X_selected)
|
||||
y_pred = model.predict(X)
|
||||
|
||||
return y_pred.reshape(-1, 1)
|
||||
|
||||
-8
@@ -2,15 +2,8 @@ import pandas as pd
|
||||
import xgboost as xgb
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
dtrain = xgb.DMatrix(X_train, label=y_train)
|
||||
dvalid = xgb.DMatrix(X_valid, label=y_valid)
|
||||
|
||||
@@ -33,7 +26,6 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X = select(X)
|
||||
dtest = xgb.DMatrix(X)
|
||||
y_pred = model.predict(dtest)
|
||||
return y_pred.reshape(-1, 1)
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
@@ -29,10 +29,8 @@ def import_module_from_path(module_name, module_path):
|
||||
return module
|
||||
|
||||
|
||||
print("begin preprocess")
|
||||
# 1) Preprocess the data
|
||||
X_train, X_valid, y_train, y_valid, X_test, ids = preprocess_script()
|
||||
print("preprocess done")
|
||||
|
||||
# 2) Auto feature engineering
|
||||
X_train_l, X_valid_l = [], []
|
||||
@@ -45,9 +43,10 @@ for f in DIRNAME.glob("feature/feat*.py"):
|
||||
X_valid_f = cls.transform(X_valid)
|
||||
X_test_f = cls.transform(X_test)
|
||||
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
if X_train_f.shape[-1] == X_valid_f.shape[-1] and X_train_f.shape[-1] == X_test_f.shape[-1]:
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
@@ -75,48 +74,33 @@ X_test = X_test.loc[:, ~X_test.columns.duplicated()]
|
||||
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func,]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict, select_m))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred_l.append(predict_func(model, X_valid))
|
||||
print(predict_func(model, X_valid).shape)
|
||||
metrics_all = []
|
||||
for model, predict_func, select_m in model_l:
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
rmse = compute_rmse(y_valid, y_valid_pred)
|
||||
print(f"RMSE on valid set: {rmse}")
|
||||
metrics_all.append(rmse)
|
||||
|
||||
# 5) Ensemble
|
||||
y_valid_pred = np.mean(y_valid_pred_l, axis=0)
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmin(metrics_all)
|
||||
pd.Series(data=[metrics_all[min_index]], index=["RMSE"]).to_csv("submission_score.csv")
|
||||
|
||||
rmse = compute_rmse(y_valid, y_valid_pred)
|
||||
print("Final RMSE on validation set: ", rmse)
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = model_l[min_index][2].select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected).ravel()
|
||||
|
||||
# 6) Save the validation RMSE
|
||||
pd.Series(data=[rmse], index=["RMSE"]).to_csv("submission_score.csv")
|
||||
|
||||
# 7) Make predictions on the test set and save them
|
||||
y_test_pred_l = []
|
||||
for m, m_pred in model_l:
|
||||
y_test_pred_l.append(m_pred(m, X_test))
|
||||
|
||||
y_test_pred = np.mean(y_test_pred_l, axis=0).ravel()
|
||||
|
||||
# 8) Submit predictions for the test set
|
||||
# 7) Submit predictions for the test set
|
||||
submission_result = pd.DataFrame({"id": ids, "price": y_test_pred})
|
||||
submission_result.to_csv("submission.csv", index=False)
|
||||
|
||||
@@ -125,22 +125,19 @@ kg_feature_interface: |-
|
||||
kg_model_interface: |-
|
||||
Your code should contain several parts:
|
||||
1. The import part: import the necessary libraries.
|
||||
2. A select() function that handles feature selection for both training and prediction phases.
|
||||
The function should take the following arguments:
|
||||
- X: The features as a pandas DataFrame.
|
||||
The function should return the selected features as a pandas DataFrame.
|
||||
3. A function called fit() that trains the model and returns the trained model. If feature selection is applied, it should be done within this function.
|
||||
2. A function called fit() that trains the model and returns the trained model.
|
||||
The function should take the following arguments:
|
||||
- X_train: The training features as a pandas DataFrame.
|
||||
- y_train: The training labels as a pandas Series.
|
||||
- X_valid: The validation features as a pandas DataFrame.
|
||||
- y_valid: The validation labels as a pandas Series.
|
||||
The function should return the trained model.
|
||||
4. A function called predict() that makes predictions using the trained model. If feature selection is applied, it should be done within this function.
|
||||
3. A function called predict() that makes predictions using the trained model.
|
||||
The function should take the following arguments:
|
||||
- model: The trained model.
|
||||
- X: The features as a pandas DataFrame.
|
||||
The function should return the predicted probabilities or boolean predictions in numpy.ndarray format.
|
||||
"""
|
||||
|
||||
Here are some examples of how your Python code should be structured:
|
||||
|
||||
@@ -151,15 +148,9 @@ kg_model_interface: |-
|
||||
import xgboost
|
||||
from xgboost import DMatrix
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame: ... # Implement feature selection logic
|
||||
|
||||
|
||||
def fit(
|
||||
X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series
|
||||
) -> xgboost.Booster:
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
dtrain = DMatrix(X_train, label=y_train)
|
||||
dvalid = DMatrix(X_valid, label=y_valid)
|
||||
params = ... # Set parameters to XGBoost model
|
||||
@@ -171,7 +162,6 @@ kg_model_interface: |-
|
||||
|
||||
|
||||
def predict(model: xgboost.Booster, X: pd.DataFrame) -> np.ndarray:
|
||||
X = select(X)
|
||||
dtest = DMatrix(X)
|
||||
y_pred = model.predict(dtest)
|
||||
|
||||
@@ -185,15 +175,9 @@ kg_model_interface: |-
|
||||
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
|
||||
from sklearn.metrics import accuracy_score
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame: ... # Implement feature selection logic
|
||||
|
||||
|
||||
def fit(
|
||||
X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series
|
||||
) -> RandomForestClassifier | RandomForestRegressor:
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
model = RandomForestClassifier(...) # fir classification tasks
|
||||
model = RandomForestRegressor(...) # for regression tasks
|
||||
model.fit(X_train, y_train, ...) # Train the model
|
||||
@@ -202,7 +186,6 @@ kg_model_interface: |-
|
||||
|
||||
|
||||
def predict(model: RandomForestClassifier | RandomForestRegressor, X: pd.DataFrame) -> np.ndarray:
|
||||
X = select(X)
|
||||
y_pred = model.predict(X)
|
||||
|
||||
return y_pred
|
||||
@@ -214,15 +197,9 @@ kg_model_interface: |-
|
||||
import numpy as np
|
||||
from lightgbm import LGBMClassifier, LGBMRegressor
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame: ... # Implement feature selection logic
|
||||
|
||||
|
||||
def fit(
|
||||
X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series
|
||||
) -> LGBMClassifier | LGBMRegressor:
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
model = LGBMClassifier(...) # for classification tasks, please add parameters here
|
||||
model = LGBMRegressor(...) # for regression tasks, please add parameters here
|
||||
|
||||
@@ -231,7 +208,6 @@ kg_model_interface: |-
|
||||
|
||||
|
||||
def predict(model: LGBMClassifier | LGBMRegressor, X: pd.DataFrame) -> np.ndarray:
|
||||
X = select(X)
|
||||
y_pred = model.predict(X)
|
||||
|
||||
return y_pred
|
||||
@@ -254,13 +230,7 @@ kg_model_interface: |-
|
||||
# Define the forward pass
|
||||
return x
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame: ... # Implement feature selection logic
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame) -> torch.nn.Module:
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
model = NNModel() # Initialize the model, You can write your own model class
|
||||
|
||||
optimizer = torch.optim.Adam(model.parameters(), lr=0.01) # Example optimizer, you can use any optimizer
|
||||
@@ -293,7 +263,6 @@ kg_model_interface: |-
|
||||
|
||||
|
||||
def predict(model: torch.nn.Module, X: pd.DataFrame) -> np.ndarray:
|
||||
X = select(X)
|
||||
X = torch.tensor(X.values).float()
|
||||
model.eval()
|
||||
with torch.no_grad():
|
||||
|
||||
@@ -39,7 +39,6 @@ class KGScenario(Scenario):
|
||||
self.vector_base = None
|
||||
self._analysis_competition_description()
|
||||
self.if_action_choosing_based_on_UCB = KAGGLE_IMPLEMENT_SETTING.if_action_choosing_based_on_UCB
|
||||
self.if_using_feature_selection = KAGGLE_IMPLEMENT_SETTING.if_using_feature_selection
|
||||
self.if_using_graph_rag = KAGGLE_IMPLEMENT_SETTING.if_using_graph_rag
|
||||
self.if_using_vector_rag = KAGGLE_IMPLEMENT_SETTING.if_using_vector_rag
|
||||
|
||||
|
||||
@@ -7,15 +7,6 @@ baseline model for many classification tasks.
|
||||
|
||||
import pandas as pd
|
||||
from sklearn.ensemble import RandomForestClassifier
|
||||
from sklearn.metrics import accuracy_score
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
@@ -25,17 +16,8 @@ def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_vali
|
||||
# Initialize the Random Forest model
|
||||
model = RandomForestClassifier(n_estimators=10, random_state=32, n_jobs=-1)
|
||||
|
||||
# Select features (if any feature selection is needed)
|
||||
X_train_selected = select(X_train)
|
||||
X_valid_selected = select(X_valid)
|
||||
|
||||
# Fit the model
|
||||
model.fit(X_train_selected, y_train)
|
||||
|
||||
# Validate the model
|
||||
y_valid_pred = model.predict(X_valid_selected)
|
||||
# accuracy = accuracy_score(y_valid, y_valid_pred)
|
||||
# print(f"Validation Accuracy: {accuracy:.4f}")
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
return model
|
||||
|
||||
@@ -44,11 +26,8 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature selection's consistency and make predictions.
|
||||
"""
|
||||
# Select features (if any feature selection is needed)
|
||||
X_selected = select(X)
|
||||
|
||||
# Predict using the trained model
|
||||
y_pred_prob = model.predict_proba(X_selected)
|
||||
y_pred_prob = model.predict_proba(X)
|
||||
|
||||
# Apply threshold to get boolean predictions
|
||||
return y_pred_prob
|
||||
|
||||
@@ -7,15 +7,8 @@ import pandas as pd
|
||||
import xgboost as xgb
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
dtrain = xgb.DMatrix(X_train, label=y_train)
|
||||
dvalid = xgb.DMatrix(X_valid, label=y_valid)
|
||||
num_classes = len(np.unique(y_train))
|
||||
@@ -40,7 +33,6 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X = select(X)
|
||||
dtest = xgb.DMatrix(X)
|
||||
y_pred_prob = model.predict(dtest)
|
||||
return y_pred_prob
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
@@ -49,10 +49,11 @@ for f in DIRNAME.glob("feature/feat*.py"):
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_train = pd.concat(X_train_l, axis=1)
|
||||
X_valid = pd.concat(X_valid_l, axis=1)
|
||||
X_test = pd.concat(X_test_l, axis=1)
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
X_test = pd.concat(X_test_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_test_l))])
|
||||
|
||||
print(X_train.shape, X_valid.shape, X_test.shape)
|
||||
|
||||
# Handle inf and -inf values
|
||||
X_train.replace([np.inf, -np.inf], np.nan, inplace=True)
|
||||
@@ -72,61 +73,39 @@ X_train = X_train.loc[:, ~X_train.columns.duplicated()]
|
||||
X_valid = X_valid.loc[:, ~X_valid.columns.duplicated()]
|
||||
X_test = X_test.loc[:, ~X_test.columns.duplicated()]
|
||||
|
||||
print(X_train.shape, X_valid.shape, X_test.shape)
|
||||
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict, select_m))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred_l.append(predict_func(model, X_valid))
|
||||
# print(predict_func(model, X_valid))
|
||||
print(predict_func(model, X_valid).shape)
|
||||
metrics_all = []
|
||||
for model, predict_func, select_m in model_l:
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
metrics = compute_metrics_for_classification(y_valid, y_valid_pred)
|
||||
print(f"log_loss on valid set: {metrics}")
|
||||
metrics_all.append(metrics)
|
||||
|
||||
# 5) Ensemble
|
||||
from scipy import stats
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmin(metrics_all)
|
||||
pd.Series(data=[metrics_all[min_index]], index=["log_loss"]).to_csv("submission_score.csv")
|
||||
|
||||
# average probabilities ensemble
|
||||
y_valid_pred_proba = np.mean(y_valid_pred_l, axis=0)
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = model_l[min_index][2].select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected)
|
||||
|
||||
# Compute metrics
|
||||
logloss = compute_metrics_for_classification(y_valid, y_valid_pred_proba)
|
||||
print(f"final log_loss on valid set: {logloss}")
|
||||
|
||||
# 6) Save the validation metrics
|
||||
pd.Series(data=[logloss], index=["log_loss"]).to_csv("submission_score.csv")
|
||||
|
||||
# 7) Make predictions on the test set and save them
|
||||
y_test_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_test_pred_l.append(predict_func(model, X_test))
|
||||
|
||||
# For multiclass classification, use the mode of the predictions
|
||||
y_test_pred_proba = np.mean(y_test_pred_l, axis=0)
|
||||
|
||||
# 7) Submit predictions for the test set
|
||||
class_labels = category_encoder.classes_
|
||||
|
||||
submission_result = pd.DataFrame(y_test_pred_proba, columns=class_labels)
|
||||
submission_result = pd.DataFrame(y_test_pred, columns=class_labels)
|
||||
submission_result.insert(0, "Id", test_ids)
|
||||
|
||||
submission_result.to_csv("submission.csv", index=False)
|
||||
|
||||
@@ -49,8 +49,8 @@ def fit(X_train, y_train, X_valid, y_valid):
|
||||
|
||||
# Train the model
|
||||
model.train()
|
||||
for epoch in range(100):
|
||||
print(f"Epoch {epoch + 1}/100")
|
||||
for epoch in range(50):
|
||||
print(f"Epoch {epoch + 1}/50")
|
||||
epoch_loss = 0
|
||||
for X_batch, y_batch in tqdm(train_loader, desc="Training", leave=False):
|
||||
X_batch, y_batch = X_batch.to(device), y_batch.to(device) # Move data to the device
|
||||
|
||||
+2
-22
@@ -10,14 +10,6 @@ from sklearn.ensemble import RandomForestClassifier
|
||||
from sklearn.metrics import accuracy_score
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_valid: pd.Series):
|
||||
"""
|
||||
Define and train the Random Forest model. Merge feature selection into the pipeline.
|
||||
@@ -25,17 +17,8 @@ def fit(X_train: pd.DataFrame, y_train: pd.Series, X_valid: pd.DataFrame, y_vali
|
||||
# Initialize the Random Forest model
|
||||
model = RandomForestClassifier(n_estimators=100, random_state=32, n_jobs=-1)
|
||||
|
||||
# Select features (if any feature selection is needed)
|
||||
X_train_selected = select(X_train)
|
||||
X_valid_selected = select(X_valid)
|
||||
|
||||
# Fit the model
|
||||
model.fit(X_train_selected, y_train)
|
||||
|
||||
# Validate the model
|
||||
y_valid_pred = model.predict(X_valid_selected)
|
||||
accuracy = accuracy_score(y_valid, y_valid_pred)
|
||||
print(f"Validation Accuracy: {accuracy:.4f}")
|
||||
model.fit(X_train, y_train)
|
||||
|
||||
return model
|
||||
|
||||
@@ -44,11 +27,8 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature selection's consistency and make predictions.
|
||||
"""
|
||||
# Select features (if any feature selection is needed)
|
||||
X_selected = select(X)
|
||||
|
||||
# Predict using the trained model
|
||||
y_pred_prob = model.predict_proba(X_selected)[:, 1]
|
||||
y_pred_prob = model.predict_proba(X)[:, 1]
|
||||
|
||||
# Apply threshold to get boolean predictions
|
||||
return y_pred_prob.reshape(-1, 1)
|
||||
|
||||
@@ -6,19 +6,11 @@ import pandas as pd
|
||||
import xgboost as xgb
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
# Ignore feature selection logic
|
||||
return X
|
||||
|
||||
|
||||
def fit(X_train: pd.DataFrame, y_train: pd.DataFrame, X_valid: pd.DataFrame, y_valid: pd.DataFrame):
|
||||
"""Define and train the model. Merge feature_select"""
|
||||
X_train = select(X_train)
|
||||
X_valid = select(X_valid)
|
||||
dtrain = xgb.DMatrix(X_train, label=y_train)
|
||||
dvalid = xgb.DMatrix(X_valid, label=y_valid)
|
||||
|
||||
# TODO: for quick running....
|
||||
params = {
|
||||
"nthread": -1,
|
||||
"tree_method": "gpu_hist",
|
||||
@@ -36,7 +28,6 @@ def predict(model, X):
|
||||
"""
|
||||
Keep feature select's consistency.
|
||||
"""
|
||||
X = select(X)
|
||||
dtest = xgb.DMatrix(X)
|
||||
y_pred_prob = model.predict(dtest)
|
||||
return y_pred_prob.reshape(-1, 1)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def select(X: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Select relevant features. To be used in fit & predict function.
|
||||
"""
|
||||
# For now, we assume all features are relevant. This can be expanded to feature selection logic.
|
||||
if X.columns.nlevels == 1:
|
||||
return X
|
||||
X.columns = ["_".join(str(col)).strip() for col in X.columns.values]
|
||||
return X
|
||||
@@ -5,8 +5,7 @@ from pathlib import Path
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from fea_share_preprocess import preprocess_script
|
||||
from sklearn.metrics import accuracy_score, matthews_corrcoef
|
||||
from sklearn.preprocessing import LabelEncoder
|
||||
from sklearn.metrics import accuracy_score
|
||||
|
||||
# Set random seed for reproducibility
|
||||
SEED = 42
|
||||
@@ -30,7 +29,6 @@ def import_module_from_path(module_name, module_path):
|
||||
|
||||
|
||||
# 1) Preprocess the data
|
||||
# TODO 如果已经做过数据预处理了,不需要再做了
|
||||
X_train, X_valid, y_train, y_valid, X_test, passenger_ids = preprocess_script()
|
||||
|
||||
# 2) Auto feature engineering
|
||||
@@ -44,9 +42,10 @@ for f in DIRNAME.glob("feature/feat*.py"):
|
||||
X_valid_f = cls.transform(X_valid)
|
||||
X_test_f = cls.transform(X_test)
|
||||
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
if X_train_f.shape[-1] == X_valid_f.shape[-1] and X_train_f.shape[-1] == X_test_f.shape[-1]:
|
||||
X_train_l.append(X_train_f)
|
||||
X_valid_l.append(X_valid_f)
|
||||
X_test_l.append(X_test_f)
|
||||
|
||||
X_train = pd.concat(X_train_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_train_l))])
|
||||
X_valid = pd.concat(X_valid_l, axis=1, keys=[f"feature_{i}" for i in range(len(X_valid_l))])
|
||||
@@ -74,49 +73,34 @@ X_test = X_test.loc[:, ~X_test.columns.duplicated()]
|
||||
|
||||
|
||||
# 3) Train the model
|
||||
def flatten_columns(df: pd.DataFrame) -> pd.DataFrame:
|
||||
"""
|
||||
Flatten the columns of a DataFrame with MultiIndex columns,
|
||||
for (feature_0, a), (feature_0, b) -> feature_0_a, feature_0_b
|
||||
"""
|
||||
if df.columns.nlevels == 1:
|
||||
return df
|
||||
df.columns = ["_".join(col).strip() for col in df.columns.values]
|
||||
return df
|
||||
|
||||
|
||||
X_train = flatten_columns(X_train)
|
||||
X_valid = flatten_columns(X_valid)
|
||||
X_test = flatten_columns(X_test)
|
||||
|
||||
model_l = [] # list[tuple[model, predict_func,]]
|
||||
for f in DIRNAME.glob("model/model*.py"):
|
||||
select_python_path = f.with_name(f.stem.replace("model", "select") + f.suffix)
|
||||
select_m = import_module_from_path(select_python_path.stem, select_python_path)
|
||||
X_train_selected = select_m.select(X_train.copy())
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
|
||||
m = import_module_from_path(f.stem, f)
|
||||
model_l.append((m.fit(X_train, y_train, X_valid, y_valid), m.predict))
|
||||
model_l.append((m.fit(X_train_selected, y_train, X_valid_selected, y_valid), m.predict, select_m))
|
||||
|
||||
# 4) Evaluate the model on the validation set
|
||||
y_valid_pred_l = []
|
||||
for model, predict_func in model_l:
|
||||
y_valid_pred_l.append(predict_func(model, X_valid))
|
||||
metrics_all = []
|
||||
for model, predict_func, select_m in model_l:
|
||||
X_valid_selected = select_m.select(X_valid.copy())
|
||||
y_valid_pred = predict_func(model, X_valid_selected)
|
||||
y_valid_pred = (y_valid_pred > 0.5).astype(int)
|
||||
metrics = compute_metrics_for_classification(y_valid, y_valid_pred)
|
||||
print(f"Accuracy on valid set: {metrics}")
|
||||
metrics_all.append(metrics)
|
||||
|
||||
# 5) Ensemble
|
||||
# TODO: ensemble method in a script
|
||||
# Average the predictions and apply a threshold to determine class labels
|
||||
y_valid_pred = np.mean(y_valid_pred_l, axis=0)
|
||||
y_valid_pred = (y_valid_pred > 0.5).astype(int)
|
||||
|
||||
mcc = compute_metrics_for_classification(y_valid, y_valid_pred)
|
||||
print("Final on validation set: ", mcc)
|
||||
# 5) Save the validation accuracy
|
||||
min_index = np.argmax(metrics_all)
|
||||
pd.Series(data=[metrics_all[min_index]], index=["MCC"]).to_csv("submission_score.csv")
|
||||
|
||||
# 6) Save the validation accuracy
|
||||
pd.Series(data=[mcc], index=["MCC"]).to_csv("submission_score.csv")
|
||||
|
||||
# 7) Make predictions on the test set and save them
|
||||
y_test_pred_l = []
|
||||
for m, m_pred in model_l:
|
||||
y_test_pred_l.append(m_pred(m, X_test)) # TODO Make this an ensemble. Currently it uses the last prediction
|
||||
|
||||
y_test_pred = np.mean(y_test_pred_l, axis=0)
|
||||
# 6) Make predictions on the test set and save them
|
||||
X_test_selected = model_l[min_index][2].select(X_test.copy())
|
||||
y_test_pred = model_l[min_index][1](model_l[min_index][0], X_test_selected)
|
||||
y_test_pred = (y_test_pred > 0.5).astype(bool)
|
||||
y_test_pred = y_test_pred.ravel()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import subprocess
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Any, List, Tuple
|
||||
|
||||
import pandas as pd
|
||||
|
||||
@@ -29,8 +29,15 @@ class KGFBWorkspace(FBWorkspace):
|
||||
def __init__(self, template_folder_path: Path, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self.inject_code_from_folder(template_folder_path)
|
||||
self.data_description: list[str] = []
|
||||
self.model_description: dict[str, str] = {}
|
||||
self.data_description: List[Tuple[str, int]] = []
|
||||
|
||||
@property
|
||||
def model_description(self) -> dict[str, str]:
|
||||
model_description = {}
|
||||
for k, v in self.code_dict.items():
|
||||
if k.startswith("model/"):
|
||||
model_description[k] = v
|
||||
return model_description
|
||||
|
||||
def generate_preprocess_data(
|
||||
self,
|
||||
|
||||
@@ -39,7 +39,7 @@ hypothesis_and_feedback: |-
|
||||
hypothesis_output_format: |-
|
||||
The output should follow JSON format. The schema is as follows:
|
||||
{
|
||||
"action": "If "hypothesis_specification" provides the action you need to take, please follow "hypothesis_specification" to choose the action. Otherwise, based on previous experimental results, suggest the action you believe is most appropriate at the moment. It should be one of [{% if if_using_feature_selection %}"Feature engineering", "Feature processing", "Model feature selection", "Model tuning"{% else %}"Feature engineering", "Feature processing", "Model tuning"{% endif %}]",
|
||||
"action": "If "hypothesis_specification" provides the action you need to take, please follow "hypothesis_specification" to choose the action. Otherwise, based on previous experimental results, suggest the action you believe is most appropriate at the moment. It should be one of ["Feature engineering", "Feature processing", "Model feature selection", "Model tuning"]"
|
||||
"hypothesis": "The new hypothesis generated based on the information provided.",
|
||||
"reason": "The reason why you generate this hypothesis. It should be comprehensive and logical. It should cover the other keys below and extend them.",
|
||||
"concise_reason": "Two-line summary. First line focuses on a concise justification for the change. Second line generalizes a knowledge statement.",
|
||||
@@ -291,26 +291,28 @@ feature_selection_feedback_generation:
|
||||
3. How might we refine or change the feature selection approach to improve model performance?
|
||||
4. Are there any domain-specific considerations that should inform our feature selection?
|
||||
|
||||
extract_model_task_from_code:
|
||||
model_feature_selection:
|
||||
system: |-
|
||||
You are an expert in analyzing code for machine learning models.
|
||||
user: |-
|
||||
Given the following code, summarize the machine learning model including:
|
||||
- Model architecture
|
||||
- Hyperparameters
|
||||
- Formulation and variables
|
||||
- Model type (one of XGBoost, RandomForest, LightGBM, NN)
|
||||
You are an assistant for model feature selection in machine learning. Your task is to understand the current feature groups and choose the most relevant features for the model to get the best performance.
|
||||
|
||||
Code:
|
||||
{{ file_content }}
|
||||
The user is currently working on a Kaggle competition scenario as follows:
|
||||
{{ scenario }}
|
||||
|
||||
Return the information in JSON format with the following structure:
|
||||
The user is now working on the following model type:
|
||||
{{ model_type }}
|
||||
|
||||
The user will give you several feature groups and their descriptions. Your task is to select the most relevant features for the model to achieve the best performance. You should consider the following:
|
||||
1. How well do the selected features support the scenario?
|
||||
2. Are there any features that might be redundant or noisy?
|
||||
|
||||
Please answer the chosen group index in JSON format. Example JSON structure for Result Analysis:
|
||||
{
|
||||
"name": "",
|
||||
"description": "",
|
||||
"architecture": "",
|
||||
"hyperparameters": {},
|
||||
"formulation": "",
|
||||
"variables": {},
|
||||
"model_type": ""
|
||||
"Selected Group Index": [1, 3, 5], # List of selected group indices, notice: the index starts from 1
|
||||
}
|
||||
|
||||
user: |-
|
||||
Current feature groups:
|
||||
{% for feature in feature_groups %}
|
||||
Group {{ loop.index }}:
|
||||
{{ feature }}
|
||||
{% endfor %}
|
||||
@@ -36,7 +36,7 @@ KG_ACTION_MODEL_TUNING = "Model tuning"
|
||||
KG_ACTION_LIST = [
|
||||
KG_ACTION_FEATURE_PROCESSING,
|
||||
KG_ACTION_FEATURE_ENGINEERING,
|
||||
*([KG_ACTION_MODEL_FEATURE_SELECTION] if KAGGLE_IMPLEMENT_SETTING.if_using_feature_selection else []),
|
||||
KG_ACTION_MODEL_FEATURE_SELECTION,
|
||||
KG_ACTION_MODEL_TUNING,
|
||||
]
|
||||
|
||||
@@ -82,13 +82,9 @@ class KGHypothesisGen(ModelHypothesisGen):
|
||||
|
||||
def __init__(self, scen: Scenario) -> Tuple[dict, bool]:
|
||||
super().__init__(scen)
|
||||
actions = ["Feature engineering", "Feature processing", "Model tuning"]
|
||||
if KAGGLE_IMPLEMENT_SETTING.if_using_feature_selection:
|
||||
actions.insert(2, "Model feature selection")
|
||||
self.action_counts = dict.fromkeys(actions, 0)
|
||||
self.reward_estimates = {action: 0.0 for action in actions}
|
||||
if KAGGLE_IMPLEMENT_SETTING.if_using_feature_selection:
|
||||
self.reward_estimates["Model feature selection"] = 0.2
|
||||
self.action_counts = dict.fromkeys(KG_ACTION_LIST, 0)
|
||||
self.reward_estimates = {action: 0.0 for action in KG_ACTION_LIST}
|
||||
self.reward_estimates["Model feature selection"] = 0.2
|
||||
self.reward_estimates["Model tuning"] = 1.0
|
||||
self.confidence_parameter = 1.0
|
||||
self.initial_performance = 0.0
|
||||
@@ -239,9 +235,7 @@ class KGHypothesisGen(ModelHypothesisGen):
|
||||
context_dict = {
|
||||
"hypothesis_and_feedback": hypothesis_and_feedback,
|
||||
"RAG": self.generate_RAG_content(trace, hypothesis_and_feedback),
|
||||
"hypothesis_output_format": Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis_output_format"])
|
||||
.render(if_using_feature_selection=KAGGLE_IMPLEMENT_SETTING.if_using_feature_selection),
|
||||
"hypothesis_output_format": prompt_dict["hypothesis_output_format"],
|
||||
"hypothesis_specification": (
|
||||
f"next experiment action is {action}" if self.scen.if_action_choosing_based_on_UCB else None
|
||||
),
|
||||
@@ -319,7 +313,11 @@ class KGHypothesis2Experiment(ModelHypothesis2Experiment):
|
||||
)
|
||||
|
||||
exp = KGFactorExperiment(
|
||||
sub_tasks=tasks, based_experiments=([KGFactorExperiment(sub_tasks=[])] + [t[1] for t in trace.hist if t[2]])
|
||||
sub_tasks=tasks,
|
||||
based_experiments=(
|
||||
[KGFactorExperiment(sub_tasks=[], source_feature_size=trace.scen.input_shape[-1])]
|
||||
+ [t[1] for t in trace.hist if t[2]]
|
||||
),
|
||||
)
|
||||
return exp
|
||||
|
||||
@@ -337,7 +335,11 @@ class KGHypothesis2Experiment(ModelHypothesis2Experiment):
|
||||
)
|
||||
)
|
||||
exp = KGModelExperiment(
|
||||
sub_tasks=tasks, based_experiments=([KGModelExperiment(sub_tasks=[])] + [t[1] for t in trace.hist if t[2]])
|
||||
sub_tasks=tasks,
|
||||
based_experiments=(
|
||||
[KGModelExperiment(sub_tasks=[], source_feature_size=trace.scen.input_shape[-1])]
|
||||
+ [t[1] for t in trace.hist if t[2]]
|
||||
),
|
||||
)
|
||||
return exp
|
||||
|
||||
|
||||
Reference in New Issue
Block a user