sktime.benchmarking.experiments 源代码

"""Functions to perform classification and clustering experiments.

Results are saved a standardised format used by both tsml and sktime.
"""

__author__ = ["TonyBagnall"]
__all__ = [
    "run_clustering_experiment",
    "load_and_run_clustering_experiment",
    "run_classification_experiment",
    "load_and_run_classification_experiment",
]


import os
import time
from datetime import datetime

import numpy as np
from sklearn import preprocessing
from sklearn.metrics import accuracy_score
from sklearn.model_selection import cross_val_predict

from sktime.datasets import load_from_tsfile_to_dataframe as load_ts
from sktime.datasets import write_results_to_uea_format
from sktime.utils.sampling import stratified_resample


[文档]def run_clustering_experiment( trainX, clusterer, results_path, trainY=None, testX=None, testY=None, cls_name=None, dataset_name=None, resample_id=0, overwrite=True, ): """Run a clustering experiment and save the results to file. Method to run a basic experiment and write the results to files called testFold<resampleID>.csv and, if required, trainFold<resampleID>.csv. This version loads the data from file based on a path. The clusterer is always trained on the required input data trainX. Output to trainResample<resampleID>.csv will be the predicted clusters of trainX. If trainY is also passed, these are written to file. If the clusterer makes probabilistic predictions, these are also written to file. See write_results_to_uea_format for more on the output. Be warned, this method will always overwrite existing results, check bvefore calling or use load_and_run_clustering_experiment instead. Parameters ---------- trainX : pd.DataFrame or np.array The data to cluster. clusterer : BaseClusterer The clustering object results_path : str Where to write the results to trainY : np.array, default = None Train data tue class labels, only used for file writing, ignored by the clusterer testX : pd.DataFrame or np.array, default = None Test attribute data, if present it is used for predicting testY testY : np.array, default = None Test data true class labels, only used for file writing, ignored by the clusterer cls_name : str, default = None Name of the clusterer, written to the results file, ignored if None dataset_name : str, default = None Name of problem, written to the results file, ignored if None resample_id : int, default = 0 Resample identifier, defaults to 0 """ if not overwrite: full_path = ( results_path + "/" + cls_name + "/Predictions/" + dataset_name + "/testResample" + str(resample_id) + ".csv" ) if os.path.exists(full_path): return # Build the clusterer on train data, recording how long it takes le = preprocessing.LabelEncoder() le.fit(trainY) trainY = le.transform(trainY) testY = le.transform(testY) start = int(round(time.time() * 1000)) clusterer.fit(trainX) build_time = int(round(time.time() * 1000)) - start start = int(round(time.time() * 1000)) train_preds = clusterer.predict(trainX) build_time = int(round(time.time() * 1000)) - start train_probs = clusterer.predict_proba(trainX) start = int(round(time.time() * 1000)) test_preds = clusterer.predict(testX) test_time = int(round(time.time() * 1000)) - start test_probs = clusterer.predict_proba(testX) second = str(clusterer.get_params()) second.replace("\n", " ") second.replace("\r", " ") third = "0," + str(build_time) + "," + str(test_time) + ",-1,-1," "" + str( len(np.unique(trainY)) ) + "," + str(len(np.unique(trainY))) write_results_to_uea_format( first_line_comment="Generated by clustering_experiments on " + str(datetime.today()), second_line=second, third_line=third, output_path=results_path, estimator_name=cls_name, resample_seed=resample_id, y_pred=test_preds, predicted_probs=test_probs, dataset_name=dataset_name, y_true=testY, split="TEST", full_path=False, timing_type="MILLISECONDS", ) # preds = form_cluster_list(clusters, len(testY)) if "Composite" in cls_name: second = "Para info too long!" else: second = str(clusterer.get_params()) second.replace("\n", " ") second.replace("\r", " ") third = "0," + str(build_time) + "," + str(test_time) + ",-1,-1," "" + str( len(np.unique(trainY)) ) + "," + str(len(np.unique(trainY))) write_results_to_uea_format( first_line_comment="Generated by clustering_experiments on " + str(datetime.today()), second_line=second, third_line=third, output_path=results_path, estimator_name=cls_name, resample_seed=resample_id, y_pred=train_preds, predicted_probs=train_probs, dataset_name=dataset_name, y_true=trainY, split="TRAIN", full_path=False, timing_type="MILLISECONDS", )
[文档]def load_and_run_clustering_experiment( problem_path, results_path, dataset, clusterer, resample_id=0, cls_name=None, overwrite=False, format=".ts", train_file=False, ): """Run a clustering experiment. Method to run a basic experiment and write the results to files called testFold<resampleID>.csv and, if required, trainFold<resampleID>.csv. This version loads the data from file based on a path. The clusterer is always trained on the Parameters ---------- problem_path : str Location of problem files, full path. results_path : str Location of where to write results. Any required directories will be created dataset : str Name of problem. Files must be <problem_path>/<dataset>/<dataset>+ "_TRAIN"+format, same for "_TEST" clusterer : the clusterer cls_name : str, default =None determines what to call the write directory. If None, it is set to type(clusterer).__name__ resample_id : int, default = 0 Seed for resampling. If set to 0, the default train/test split from file is used. Also used in output file name. overwrite : boolean, default = False if False, this will only build results if there is not a result file already present. If True, it will overwrite anything already there. format: string, default = ".ts" Valid formats are ".ts", ".arff", ".tsv" and ".long". For more info on format, see examples/loading_data.ipynb train_file: boolean, default = False whether to generate train files or not. If true, it performs a 10xCV on the train and saves """ if cls_name is None: cls_name = type(clusterer).__name__ # Set up the file path in standard format if not overwrite: full_path = ( str(results_path) + "/" + str(cls_name) + "/Predictions/" + str(dataset) + "/testResample" + str(resample_id) + ".csv" ) if os.path.exists(full_path): build_test = False if train_file: full_path = ( str(results_path) + "/" + str(cls_name) + "/Predictions/" + str(dataset) + "/trainResample" + str(resample_id) + ".csv" ) if os.path.exists(full_path): train_file = False if train_file is False and build_test is False: return # currently only works with .ts trainX, trainY = load_ts(problem_path + dataset + "/" + dataset + "_TRAIN" + format) testX, testY = load_ts(problem_path + dataset + "/" + dataset + "_TEST" + format) if resample_id != 0: trainX, trainY, testX, testY = stratified_resample( trainX, trainY, testX, testY, resample_id ) run_clustering_experiment( trainX, clusterer, trainY=trainY, testX=testX, testY=testY, cls_name=cls_name, dataset_name=dataset, results_path=results_path, )
[文档]def run_classification_experiment( X_train, y_train, X_test, y_test, classifier, results_path, cls_name="", dataset="", resample_id=0, train_file=False, test_file=True, ): """Run a classification experiment and save the results to file. Method to run a basic experiment and write the results to files called testFold<resampleID>.csv and, if required, trainFold<resampleID>.csv. Parameters ---------- X_train : pd.DataFrame or np.array The data to train the classifier. y_train : np.array, default = None Training data class labels. X_test : pd.DataFrame or np.array, default = None The data used to test the trained classifier. y_test : np.array, default = None Testing data class labels. classifier : BaseClassifier Classifier to be used in the experiment. results_path : str Location of where to write results. Any required directories will be created. cls_name : str, default="" Name of the classifier. dataset : str, default="" Name of problem. resample_id : int, default=0 Seed for resampling. If set to 0, the default train/test split from file is used. Also used in output file name. train_file : bool, default=False Whether to generate train files or not. If true, it performs a 10-fold cross-validation on the train data and saves. If the classifier can produce its own estimates, those are used instead. test_file : bool, default=True: Whether to generate test files or not. If the classifier can generate its own train probabilities, the classifier will be built but no file will be output. """ if not test_file and not train_file: raise Exception( "Both test_file and train_file are set to False. " "At least one must be output." ) le = preprocessing.LabelEncoder() y_train = le.fit_transform(y_train) y_test = le.transform(y_test) encoder_dict = {label: i for i, label in enumerate(le.classes_)} classifier_train_probs = train_file and callable( getattr(classifier, "_get_train_probs", None) ) build_time = -1 if test_file or classifier_train_probs: start = int(round(time.time() * 1000)) classifier.fit(X_train, y_train) build_time = int(round(time.time() * 1000)) - start if test_file: start = int(round(time.time() * 1000)) probs = classifier.predict_proba(X_test) test_time = int(round(time.time() * 1000)) - start if "composite" in cls_name.lower(): second = "Para info too long!" else: second = str(classifier.get_params()) second.replace("\n", " ") second.replace("\r", " ") # Line 3 format: preds = classifier.classes_[np.argmax(probs, axis=1)] acc = accuracy_score(y_test, preds) third = ( str(acc) # 1. accuracy + "," + str(build_time) # 2. fit time + "," + str(test_time) # 3. predict time + ",-1,-1," # 4. 5. benchmark time, memory (to do) + str(len(classifier.classes_)) # 6. number of classes + ",,-1,-1" # 7. 8. 9. ) write_results_to_uea_format( second_line=second, third_line=third, first_line_comment="PREDICTIONS,Generated by experiments.py on " + datetime.now().strftime("%m/%d/%Y, %H:%M:%S") + ". Encoder dictionary: " + str(encoder_dict), timing_type="MILLISECONDS", output_path=results_path, estimator_name=cls_name, resample_seed=resample_id, y_pred=preds, predicted_probs=probs, dataset_name=dataset, y_true=y_test, split="TEST", full_path=False, ) if train_file: start = int(round(time.time() * 1000)) if classifier_train_probs: # Normally can only do this if test has been built train_probs = classifier._get_train_probs(X_train, y_train) else: cv_size = 10 _, counts = np.unique(y_train, return_counts=True) min_class = np.min(counts) if min_class < cv_size: cv_size = min_class train_probs = cross_val_predict( classifier, X_train, y=y_train, cv=cv_size, method="predict_proba" ) train_time = int(round(time.time() * 1000)) - start if "composite" in cls_name.lower(): second = "Para info too long!" else: second = str(classifier.get_params()) second.replace("\n", " ") second.replace("\r", " ") train_preds = classifier.classes_[np.argmax(train_probs, axis=1)] train_acc = accuracy_score(y_train, train_preds) third = ( str(train_acc) + "," + str(build_time) + ",-1,-1,-1," + str(len(classifier.classes_)) + ",," + str(train_time) + "," + str(build_time + train_time) ) write_results_to_uea_format( second_line=second, third_line=third, first_line_comment="PREDICTIONS,Generated by classification_experiments.py " "on " + datetime.now().strftime("%d/%m/%Y, %H:%M:%S") + ". Encoder dictionary: " + str(encoder_dict), timing_type="MILLISECONDS", output_path=results_path, estimator_name=cls_name, resample_seed=resample_id, y_pred=train_preds, predicted_probs=train_probs, dataset_name=dataset, y_true=y_train, split="TRAIN", full_path=False, )
[文档]def load_and_run_classification_experiment( problem_path, results_path, dataset, classifier, resample_id=0, cls_name=None, overwrite=False, build_train=False, predefined_resample=False, ): """Load a dataset and run a classification experiment. Method to run a basic experiment and write the results to files called testFold<resampleID>.csv and, if required, trainFold<resampleID>.csv. Parameters ---------- problem_path : str Location of problem files, full path. results_path : str Location of where to write results. Any required directories will be created. dataset : str Name of problem. Files must be <problem_path>/<dataset>/<dataset>+"_TRAIN.ts", same for "_TEST". classifier : BaseClassifier Classifier to be used in the experiment, if none is provided one is selected using cls_name using resample_id as a seed. cls_name : str, default = None Name of classifier used in writing results. If none the name is taken from the classifier resample_id : int, default=0 Seed for resampling. If set to 0, the default train/test split from file is used. Also used in output file name. overwrite : bool, default=False If set to False, this will only build results if there is not a result file already present. If True, it will overwrite anything already there. build_train : bool, default=False Whether to generate train files or not. If true, it performs a 10-fold cross-validation on the train data and saves. If the classifier can produce its own estimates, those are used instead. predefined_resample : bool, default=False Read a predefined resample from file instead of performing a resample. If True the file format must include the resample_id at the end of the dataset name i.e. <problem_path>/<dataset>/<dataset>+<resample_id>+"_TRAIN.ts". """ if cls_name is None: cls_name = type(classifier).__name__ # Check which files exist, if both exist, exit build_test = True if not overwrite: full_path = ( results_path + "/" + cls_name + "/Predictions/" + dataset + "/testResample" + str(resample_id) + ".csv" ) if os.path.exists(full_path): build_test = False if build_train: full_path = ( results_path + "/" + cls_name + "/Predictions/" + dataset + "/trainResample" + str(resample_id) + ".csv" ) if os.path.exists(full_path): build_train = False if build_train is False and not build_test: return if predefined_resample: X_train, y_train = load_ts( problem_path + dataset + "/" + dataset + str(resample_id) + "_TRAIN.ts" ) X_test, y_test = load_ts( problem_path + dataset + "/" + dataset + str(resample_id) + "_TEST.ts" ) else: X_train, y_train = load_ts(problem_path + dataset + "/" + dataset + "_TRAIN.ts") X_test, y_test = load_ts(problem_path + dataset + "/" + dataset + "_TEST.ts") if resample_id != 0: X_train, y_train, X_test, y_test = stratified_resample( X_train, y_train, X_test, y_test, resample_id ) run_classification_experiment( X_train, y_train, X_test, y_test, classifier, results_path, cls_name=cls_name, dataset=dataset, resample_id=resample_id, train_file=build_train, test_file=build_test, )