TensorFlowデータセットを使ってAutoGluonを動かしてみた

構造化データセットを前処理なしで簡単に学習と予測ができるAutoGluonを使ってみました。
2022.11.04

皆さん、こんにちは。クルトンです。

今回は、前処理なしで構造化データを学習、予測ができるAutoGluonを使ってみました。データを用意できている状態で数行書くだけで予測まで可能なようです。今回、accuracyなどの結果を比較する対象としてLightGBMを簡単に実装して、動かしてみました。

AutoGluonについてですが、複数のモデルを使って学習を行なっています。どのようなモデルを使っているのかなどは学習時に表示されるログから知る事も可能です。

AutoGluonのアーキテクチャについて詳しくお知りになりたい方はこちらをご覧ください。

なお、環境はGoogleColabでランタイムはCPUです。

TensorFlowデータセットでデータ準備

こちらの内容を参考に実装も可能かと思いますが、少し異なる点もあるので、コードを記述します。

モジュールをimport

データセットをロード、変換するのに必要なモジュールをimportします。

from sklearn.model_selection import train_test_split
import tensorflow_datasets as tfds
import numpy as np

データセットのロードと中身を確認

今回使うデータセットはワインの品質がクラスとなっており、0~9の10段階です。アルコールなどの数値データが含まれています。 詳しくはこちらをご覧ください。

データセットのロードとデータセットの情報を見るためにinfo変数を用意します。

tf_dataset, info = tfds.load("wine_quality", as_supervised=True, with_info=True)

どういうデータの格納のされ方をされているかinfo変数をprintメソッドで出力して確認します。

print(info)
tfds.core.DatasetInfo(
    name='wine_quality',
    full_name='wine_quality/white/1.0.0',
    description="""
    Two datasets were created, using red and white wine samples.
    The inputs include objective tests (e.g. PH values) and the output is based on sensory data
    (median of at least 3 evaluations made by wine experts).
    Each expert graded the wine quality
    between 0 (very bad) and 10 (very excellent).
    Several data mining methods were applied to model
    these datasets under a regression approach. The support vector machine model achieved the
    best results. Several metrics were computed: MAD, confusion matrix for a fixed error tolerance (T),
    etc. Also, we plot the relative importances of the input variables (as measured by a sensitivity
    analysis procedure).
    
    The two datasets are related to red and white variants of the Portuguese "Vinho Verde" wine.
    For more details, consult: http://www.vinhoverde.pt/en/ or the reference [Cortez et al., 2009].
    Due to privacy and logistic issues, only physicochemical (inputs) and sensory (the output) variables
    are available (e.g. there is no data about grape types, wine brand, wine selling price, etc.).
    
    Number of Instances: red wine - 1599; white wine - 4898
    
    Input variables (based on physicochemical tests):
    
    1. fixed acidity
    2. volatile acidity
    3. citric acid
    4. residual sugar
    5. chlorides
    6. free sulfur dioxide
    7. total sulfur dioxide
    8. density
    9. pH
    10. sulphates
    11. alcohol
    
    Output variable (based on sensory data):
    
    12. quality (score between 0 and 10)
    """,
    config_description="""
    White Wine
    """,
    homepage='https://archive.ics.uci.edu/ml/datasets/wine+quality',
    data_path='~/tensorflow_datasets/wine_quality/white/1.0.0',
    file_format=tfrecord,
    download_size=258.23 KiB,
    dataset_size=1.87 MiB,
    features=FeaturesDict({
        'features': FeaturesDict({
            'alcohol': tf.float32,
            'chlorides': tf.float32,
            'citric acid': tf.float32,
            'density': tf.float32,
            'fixed acidity': tf.float32,
            'free sulfur dioxide': tf.float32,
            'pH': tf.float32,
            'residual sugar': tf.float32,
            'sulphates': tf.float64,
            'total sulfur dioxide': tf.float32,
            'volatile acidity': tf.float32,
        }),
        'quality': tf.int32,
    }),
    supervised_keys=('features', 'quality'),
    disable_shuffling=False,
    splits={
        'train': <SplitInfo num_examples=4898, num_shards=1>,
    },
    citation="""@ONLINE {cortezpaulo;cerdeiraantonio;almeidafernando;matostelmo;reisjose1999,
        author = "Cortez, Paulo; Cerdeira, Antonio; Almeida,Fernando;  Matos, Telmo;  Reis, Jose",
        title  = "Modeling wine preferences by data mining from physicochemical properties.",
        year   = "2009",
        url    = "https://archive.ics.uci.edu/ml/datasets/wine+quality"
    }""",
)

データの格納のされ方をfeatures=FeaturesDict({の部分で確認します。どうやらクラスであるquality以外のデータを見るとalcoholchloridesなどが入っているようです。

学習に必要なデータについてですが、dict型でそれぞれのキー、例えばalcoholで入っているので、これを使いやすいようにnumpy.ndarray型に変換していきます。

ロードしたデータセットを使いやすいように型を変換

まずnumpy型に変換しておきます。

dataset=tfds.as_numpy(tf_dataset['train'])

次のコードが参考URLと違うところで、dict型で格納されているので、数値情報のみで使いやすいようにvaluesメソッドでdict_value型として取り出したところをlist型に変換します。

feature_data, label_data= np.array([list(x.values()) for x,y in dataset]), np.array([y for x,y in dataset])

ここまでのコードを実行する事で、データをまとめた変数feature_dataとクラスのデータをまとめた変数label_dataに分割できました。

LightGBMで学習

pipでLightGBMで使うモジュールをインストールとimport

GoogleColabそのままでは入っていない必要なモジュールをpipを使ってインストールします。

!pip install optuna

次にLightGBMモデルを使うのに必要なモジュールをimportします。

import optuna.integration.lightgbm as lgb

これでLightGBMを使えるようになったので次にデータの準備をします。

データの分割とLightGBM用のデータセット作成

データを学習用、検証用、テスト用の3種類に分けます。

x_train, x_test, y_train, y_test = train_test_split(feature_data, label_data, test_size=0.2)
x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size=0.2)

LightGBM用のデータセットを作成します。

lgb_train = lgb.Dataset(x_train, y_train)
lgb_val = lgb.Dataset(x_val, y_val, reference=lgb_train)

用意したデータを使って学習と予測

学習を行います。今回は、qualityが0~9の10段階のクラスであるため、パラメータのクラス数'num_class'を10に設定しておきます。

また、学習時間が長くならないよう'early_stopping_rounds'を設定しておきます。

params = {
    'objective': 'multiclass',
    'num_class': 10,
    'metric': 'multi_logloss',
    } 

lgb_model = lgb.train(params,
                      lgb_train,
                      valid_sets=lgb_val,
                      early_stopping_rounds=20,
                      )

今回学習したモデルを使って予測を行ないます。

y_pred=lgb_model.predict(x_test,num_iteration=lgb_model.best_iteration)
accuracy = sum(y_test==np.argmax(y_pred,axis=1))/len(y_test)
print('accuracy: ', accuracy)

accuracyは0.6642857142857143でした。

AutoGluonで動かす

AutoGluonを動かすのに必要なモジュールのインストールとimport

AutoGluonを動かすのに必要なモジュールをpipを使ってインストールします。

!pip3 install autogluon

今回、データを与えるのにDataFrame型にする必要があったのでモジュールをimportしておきます。またAutoGluonを使うときに必要なモジュールもこの際にimportしておきます。

import pandas as pd
from autogluon.tabular import TabularPredictor

DataFrame型への変換

DataFrame型に変換をするときにカラム名を設定するので、変数に保持をしておきます。

df_columns_name=['alcohol', 'chlorides', 'citric acid', 'density', 'fixed acidity', 'free sulfur dioxide', 'pH', 'residual sugar', 'sulphates', 'total sulfur dioxide', 'volatile acidity']

TensorFlowのデータセットを学習用とテスト用に分けた上で、DataFrame型に変換します。

x_train, x_test, y_train, y_test = train_test_split(feature_data, label_data, test_size=0.2)
df_train=pd.concat([pd.DataFrame(x_train, columns=df_columns_name), pd.Series(y_train, name='label')], axis=1)
df_test=pd.concat([pd.DataFrame(x_test,columns=df_columns_name), pd.Series(y_test, name='label')], axis=1)

ここまででデータの準備ができました。あとは学習と予測などを行ないます。クラスを格納しているカラムの名前はlabelとしています。

AutoGluonの学習

学習を行うのはこの1行で完了します。注意点としては、データを渡すときにクラスの部分を落とさずに、TabularPredictorメソッドの引数で名前をstr型で入れる事です。

predictor = TabularPredictor(label='label').fit(train_data=df_train)

学習が始まると次のようなログが流れます。ログの途中をみてみるとFitting model: NeuralNetFastAIなどと書かれており、複数のモデルを使って学習している様子を見てとれます。また、それぞれのモデルの学習にかかった時間なども簡易的ですが表示されています。

Level 25:autogluon.common.utils.utils:No path specified. Models will be saved in: "AutogluonModels/ag-20221104_112735/"
INFO:autogluon.tabular.learner.default_learner:Beginning AutoGluon training ...
INFO:autogluon.tabular.learner.default_learner:AutoGluon will save models to "AutogluonModels/ag-20221104_112735/"
INFO:autogluon.tabular.learner.default_learner:AutoGluon Version:  0.5.2
INFO:autogluon.tabular.learner.default_learner:Python Version:     3.7.15
INFO:autogluon.tabular.learner.default_learner:Operating System:   Linux
INFO:autogluon.tabular.learner.default_learner:Train Data Rows:    3918
INFO:autogluon.tabular.learner.default_learner:Train Data Columns: 11
INFO:autogluon.tabular.learner.default_learner:Label Column: label
INFO:autogluon.tabular.learner.default_learner:Preprocessing data ...
Level 25:autogluon.core.utils.utils:AutoGluon infers your prediction problem is: 'multiclass' (because dtype of label-column == int, but few unique label-values observed).
INFO:autogluon.core.utils.utils:	7 unique label values:  [6, 5, 7, 3, 8, 4, 9]
Level 25:autogluon.core.utils.utils:	If 'multiclass' is not the correct problem_type, please manually specify the problem_type parameter during predictor init (You may specify problem_type as one of: ['binary', 'multiclass', 'regression'])
Level 25:autogluon.core.data.cleaner:Warning: Some classes in the training set have fewer than 10 examples. AutoGluon will only keep 6 out of 7 classes for training and will not try to predict the rare classes. To keep more classes, increase the number of datapoints from these rare classes in the training data or reduce label_count_threshold.
Level 25:autogluon.core.data.cleaner:Fraction of data from classes with at least 10 examples that will be kept for training models: 0.9992343032159265
INFO:autogluon.tabular.learner.default_learner:Train Data Class Count: 6
INFO:autogluon.tabular.learner.default_learner:Using Feature Generators to preprocess the data ...
INFO:autogluon.features.generators.abstract:Fitting AutoMLPipelineFeatureGenerator...
INFO:autogluon.features.generators.abstract:	Available Memory:                    11628.78 MB
INFO:autogluon.features.generators.abstract:	Train Data (Original)  Memory Usage: 0.34 MB (0.0% of available memory)
INFO:autogluon.features.generators.abstract:	Inferring data type of each feature based on column values. Set feature_metadata_in to manually specify special dtypes of the features.
INFO:autogluon.features.generators.abstract:	Stage 1 Generators:
INFO:autogluon.features.generators.abstract:		Fitting AsTypeFeatureGenerator...
INFO:autogluon.features.generators.abstract:	Stage 2 Generators:
INFO:autogluon.features.generators.abstract:		Fitting FillNaFeatureGenerator...
INFO:autogluon.features.generators.abstract:	Stage 3 Generators:
INFO:autogluon.features.generators.abstract:		Fitting IdentityFeatureGenerator...
INFO:autogluon.features.generators.abstract:	Stage 4 Generators:
INFO:autogluon.features.generators.abstract:		Fitting DropUniqueFeatureGenerator...
INFO:autogluon.features.generators.abstract:	Types of features in original data (raw dtype, special dtypes):
INFO:autogluon.common.features.feature_metadata:		('float', []) : 11 | ['alcohol', 'chlorides', 'citric acid', 'density', 'fixed acidity', ...]
INFO:autogluon.features.generators.abstract:	Types of features in processed data (raw dtype, special dtypes):
INFO:autogluon.common.features.feature_metadata:		('float', []) : 11 | ['alcohol', 'chlorides', 'citric acid', 'density', 'fixed acidity', ...]
INFO:autogluon.features.generators.abstract:	0.1s = Fit runtime
INFO:autogluon.features.generators.abstract:	11 features in original data used to generate 11 features in processed data.
INFO:autogluon.features.generators.abstract:	Train Data (Processed) Memory Usage: 0.34 MB (0.0% of available memory)
INFO:autogluon.tabular.learner.default_learner:Data preprocessing and feature engineering runtime = 0.2s ...
Level 25:autogluon.core.trainer.abstract_trainer:AutoGluon will gauge predictive performance using evaluation metric: 'accuracy'
INFO:autogluon.core.trainer.abstract_trainer:	To change this, specify the eval_metric parameter of Predictor()
INFO:autogluon.tabular.trainer.auto_trainer:Automatically generating train/validation split with holdout_frac=0.1276161306789178, Train Rows: 3415, Val Rows: 500
INFO:autogluon.core.trainer.abstract_trainer:Fitting 13 L1 models ...
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: KNeighborsUnif ...
INFO:autogluon.core.trainer.abstract_trainer:	0.452	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	0.02s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.1s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: KNeighborsDist ...
INFO:autogluon.core.trainer.abstract_trainer:	0.562	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	0.01s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.1s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: NeuralNetFastAI ...
INFO:autogluon.core.trainer.abstract_trainer:	0.592	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	8.72s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.04s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: LightGBMXT ...
INFO:autogluon.core.trainer.abstract_trainer:	0.612	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	5.7s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.13s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: LightGBM ...
INFO:autogluon.core.trainer.abstract_trainer:	0.666	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	5.16s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.08s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: RandomForestGini ...
INFO:autogluon.core.trainer.abstract_trainer:	0.66	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	2.13s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.2s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: RandomForestEntr ...
INFO:autogluon.core.trainer.abstract_trainer:	0.652	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	3.44s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.2s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: CatBoost ...
INFO:autogluon.core.trainer.abstract_trainer:	0.636	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	15.38s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.01s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: ExtraTreesGini ...
INFO:autogluon.core.trainer.abstract_trainer:	0.656	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	1.54s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.2s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: ExtraTreesEntr ...
INFO:autogluon.core.trainer.abstract_trainer:	0.652	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	1.64s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.2s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: XGBoost ...
INFO:autogluon.core.trainer.abstract_trainer:	0.666	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	4.65s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.02s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: NeuralNetTorch ...
INFO:autogluon.core.trainer.abstract_trainer:	0.616	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	23.63s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.02s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: LightGBMLarge ...
INFO:autogluon.core.trainer.abstract_trainer:	0.666	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	6.67s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.02s	 = Validation runtime
INFO:autogluon.core.trainer.abstract_trainer:Fitting model: WeightedEnsemble_L2 ...
INFO:autogluon.core.trainer.abstract_trainer:	0.684	 = Validation score   (accuracy)
INFO:autogluon.core.trainer.abstract_trainer:	0.46s	 = Training   runtime
INFO:autogluon.core.trainer.abstract_trainer:	0.0s	 = Validation runtime
INFO:autogluon.tabular.learner.default_learner:AutoGluon training complete, total runtime = 82.77s ... Best model: "WeightedEnsemble_L2"
INFO:autogluon.tabular.predictor.predictor:TabularPredictor saved. To load, use: predictor = TabularPredictor.load("AutogluonModels/ag-20221104_112735/")

余談ですが、実行するとAutogluonModelsフォルダが作成されるので、学習したモデルの結果が保存されています。必要そうなモデルがあれば、ログの最後に表示されているようにloadメソッドを使う事で呼び出せます。

モデル名を確認するには、次のようなコードを実行してください。

!ls AutogluonModels/

学習した結果を使って予測

学習が完了したので、予測を行ないます。注意点が一つあり、予測タスクのため、ここはデータセットのクラス部分を消したものをpredictメソッドに渡します。(DataFrame型を使っているのでdropメソッドを使います。)

y_pred = predictor.predict(df_test.drop('label', axis=1))
print("Predictions:  \n", y_pred)
perf = predictor.evaluate_predictions(y_true=df_test['label'], y_pred=y_pred, auxiliary_metrics=True)

最終的に上記コードから出力されたaccuracyは0.6571428571428571でした。

おまけ

ここまでの予測のコードまでを実行した上で次のコードを実行すると、各モデル名、学習時間や予測の結果などを確認できます。

predictor.leaderboard(df_test, silent=True)

自分の実行環境では、ExtraTreesGiniというモデルが一番より良く予測をしていたようです。

さらに次のコードをデータセットの中でどのデータが分類するときにより貢献したか、重要度を確認できます。

feature_importances = predictor.feature_importance(df_test)
print("特徴量の重要度:")
print(feature_importances)

実行すると、どれくらいの時間がかかりそうなのか次のようなログが最初に出てきます。自分が使っていた環境では53秒ほどかかりそうと出た後に18秒で完了しました。とても処理が早いですね。

NFO:autogluon.core.utils.utils:Computing feature importance via permutation shuffling for 11 features using 978 rows with 5 shuffle sets...
INFO:autogluon.core.utils.utils:	52.7s	= Expected runtime (10.54s per shuffle set)
INFO:autogluon.core.utils.utils:	18.77s	= Actual runtime (Completed 5 of 5 shuffle sets)

処理が終わると、重要度(importanceの数値)順に、カラム名が表示されます。今回の学習結果から、ワインの品質を決めるのに一番重要そうなデータはalcoholである事が分かりました!

p値などの値も確認する事ができるので、データを深く知るのに使えそうです。

終わりに

今回はAutoGluonを使って構造化データセットの学習を行ないました。accuracyのみで比べるとLightGBMの勝利という事になったのですが、簡単に記述できる事やデータセットのどのカラムがより分類において重要そうなのかp値を確認できる事なども考えると、今後もデータを深く知るためにも使っていきたいと思いました。

今回はここまで。

それでは、また!

参考にしたサイト