CoolFace
Apppublic

seai2526-uniba-TheClouds/Code-Comment-Classification-Api

sourceHugging Facemitupdated 9mo agoView on Hugging Face
1likes
train.py204 linesDownload Raw Back to modeling
1"""Module for training different types of models for code comment classification."""
2
3import argparse
4import logging
5import os
6
7import dagshub
8from datasets import Dataset
9import mlflow
10import yaml
11
12from .utils import load_dataset_splits, parse_labels_column
13
14logging.basicConfig(
15    level=logging.INFO,
16    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
17)
18logger = logging.getLogger(__name__)
19
20
21dagshub.init(repo_owner="se4ai2526-uniba", repo_name="TheClouds", mlflow=True)
22
23
24def train_model(lang, model_type, data_path, model_output_path, params):
25    """Trains and saves a model for a specific language and model type."""
26    print(f"--- Starting training for language: {lang} with model: {model_type} ---")
27
28    ds = load_dataset_splits(data_path)
29
30    train_df = ds[f"{lang}_train"]
31    eval_df = ds[f"{lang}_test"]
32
33    train_df = parse_labels_column(train_df)
34    eval_df = parse_labels_column(eval_df)
35
36    # converto i DataFrame in HuggingFace Dataset
37    train_dataset = Dataset.from_pandas(train_df, preserve_index=False)
38    eval_dataset = Dataset.from_pandas(eval_df, preserve_index=False)
39
40    if model_type == "setfit":
41        from setfit import SetFitModel, Trainer, TrainingArguments
42
43        mlflow.set_experiment("SetFit Training")
44        with mlflow.start_run(run_name=f"train-{lang}-{model_type}"):
45            mlflow.log_param("language", lang)
46            mlflow.log_param("model_type", model_type)
47            model = SetFitModel.from_pretrained(
48                "sentence-transformers/paraphrase-MiniLM-L6-v2",
49                multi_target_strategy="multi-output",
50            )
51            args = TrainingArguments(**params)
52            trainer = Trainer(
53                model=model,
54                args=args,
55                train_dataset=train_dataset,
56                eval_dataset=eval_dataset,
57                column_mapping={"combo": "text", "labels": "label"},
58            )
59
60            mlflow.log_param("num_epochs", args.num_epochs)
61            mlflow.log_param("num_iterations", args.num_iterations)
62
63            trainer.train()
64
65            eval_metrics = trainer.evaluate()
66            for metric_name, metric_value in eval_metrics.items():
67                mlflow.log_metric(metric_name, metric_value)
68
69            trainer.model.save_pretrained(model_output_path)
70
71            mlflow.transformers.log_model(
72                transformers_model=model_output_path,
73                artifact_path=f"{lang}_setfit_model",
74                task="text-classification",
75            )
76            mlflow.end_run()
77
78    elif model_type == "random_forest":
79        import joblib
80        import numpy as np
81        from sklearn.ensemble import RandomForestClassifier
82        from sklearn.feature_extraction.text import TfidfVectorizer
83        from sklearn.multioutput import MultiOutputClassifier
84        from sklearn.pipeline import Pipeline
85
86        mlflow.set_experiment("Random Forest Training")
87        with mlflow.start_run(run_name=f"train-{lang}-{model_type}"):
88            mlflow.log_param("language", lang)
89            mlflow.log_param("model_type", model_type)
90            mlflow.log_params(params)
91
92            tfidf_params = {
93                "ngram_range": tuple(params.pop("ngram_range", (1, 1))),
94                "max_features": params.pop("max_features", None),
95                "min_df": params.pop("min_df", 1),
96                "max_df": params.pop("max_df", 1.0),
97            }
98
99            rf_params = params
100            pipeline = Pipeline(
101                [
102                    ("tfidf", TfidfVectorizer(**tfidf_params)),
103                    (
104                        "clf",
105                        MultiOutputClassifier(
106                            RandomForestClassifier(
107                                random_state=42, class_weight="balanced", **rf_params
108                            )
109                        ),
110                    ),
111                ]
112            )
113
114            X_train = train_dataset["combo"]
115            y_train = np.array(train_dataset["labels"])
116
117            pipeline.fit(X_train, y_train)
118
119            X_test = eval_dataset["combo"]
120            y_test = np.array(eval_dataset["labels"])
121
122            score = pipeline.score(X_test, y_test)
123            mlflow.log_metric("accuracy", score)
124
125            os.makedirs(os.path.dirname(model_output_path), exist_ok=True)
126            joblib.dump(pipeline, f"{model_output_path}.joblib")
127
128            mlflow.sklearn.log_model(
129                sk_model=pipeline, artifact_path=f"{lang}_random_forest_model"
130            )
131            mlflow.end_run()
132
133    elif model_type == "transformer":
134        from .transformer import (
135            TransformerConfig,
136            TransformerTrainer,
137        )
138
139        mlflow.set_experiment("Transformer Training")
140        with mlflow.start_run(run_name=f"train-{lang}-{model_type}"):
141            mlflow.log_param("language", lang)
142            mlflow.log_param("model_type", model_type)
143            mlflow.log_params(params)
144
145            cfg = TransformerConfig(
146                lang=lang,
147                raw_data_dir="data/raw",
148                processed_data_dir="data/processed/transformer",
149                model_output_path=model_output_path,
150                pretrained_model_name=params.get(
151                    "pretrained_model_name", "microsoft/codebert-base"
152                ),
153                max_length=params.get("max_length", 128),
154                batch_size=params.get("batch_size", 16),
155                lr=params.get("lr", 2e-5),
156                num_epochs=params.get("num_epochs", 5),
157                warmup_ratio=params.get("warmup_ratio", 0.1),
158                pos_weight_cap=params.get("pos_weight_cap", 30.0),
159                threshold=params.get("threshold", 0.5),
160                preprocessing=params.get("preprocessing", False),
161                preprocessing_factor=params.get("preprocessing_factor", 1.0),
162            )
163
164            logger.info(
165                "Starting transformer training for language '%s' with config: %s",
166                lang,
167                cfg,
168            )
169
170            trainer = TransformerTrainer(cfg)
171            metrics = trainer.run()
172
173            logger.info("Final transformer metrics for %s: %s", lang, metrics)
174
175            for name, value in metrics.items():
176                mlflow.log_metric(f"final_{name}", value)
177
178            mlflow.end_run()
179
180    else:
181        raise ValueError(f"Unsupported model_type: {model_type}")
182
183    print(f"Model for {lang}-{model_type} saved to {model_output_path}")
184
185
186if __name__ == "__main__":
187    parser = argparse.ArgumentParser()
188    parser.add_argument("--lang", type=str, required=True)
189    parser.add_argument("--model_type", type=str, required=True)
190    args = parser.parse_args()
191
192    with open("params.yaml", "r") as f:
193        all_params = yaml.safe_load(f)
194
195    model_params = all_params[args.model_type].copy()
196
197    train_model(
198        lang=args.lang,
199        model_type=args.model_type,
200        data_path="data/raw",
201        model_output_path=f"models/{args.lang}/{args.model_type}",
202        params=model_params,
203    )
204