Help us understand the problem. What is going on with this article?

Sample Dataset Generator

創薬やマテリアルインフォはじめ、様々な分野に機械学習が浸透していますね。

機械学習の基礎を学ぼうとしたときや、自分の手法をテストしようとしたときに、良いデータセットを見つけるのに苦労したことはありませんか?

Sample Dataset Generatorはサンプルデータを自動生成するツールで、まさにそんな時に便利に使えるように自作しました。似たようなツールとして sklearn.datasets.make_regressionsklearn.datasets.make_classification などがありますが、それらより自由度が高く理解しやすいものを作ったつもりです。

以下のコードは https://github.com/maskot1977/sampledataset_generator.git で公開しており、 Open In Colab で動作確認済みです。

インストール

次のようにしてインストールできます。

!pip install git+https://github.com/maskot1977/sampledataset_generator.git

基本的な使い方

以下のような方法で、説明変数 X と目的変数 Y を自動的に作成できます。

from sampledataset_generator import generator

dataset = generator.SampleDatasetGenerator()
dataset.generate()
import pandas as pd

pd.DataFrame(dataset.X)
0 1 2 3 4 5 6 7 8 9
0 -0.874719 0.228159 1.043060 -0.064032 0.062203 2.938519 -0.366674 1.087626 0.271206 1.396527
1 -0.380454 0.070878 0.181825 -0.172262 0.080013 0.420896 0.734195 -0.340716 -0.571168 1.437683
2 -1.624316 -0.312386 -0.007409 -0.001500 -0.085444 -0.117991 -2.223847 -0.318631 0.389458 -0.217023
3 -0.379374 -0.058680 -0.496479 0.541437 0.121997 -0.468587 -0.250380 0.038416 0.646550 0.869240
4 2.187036 -0.014006 0.363903 -0.509491 0.001101 1.084016 1.328812 -1.241679 0.703932 -0.157089
... ... ... ... ... ... ... ... ... ... ...
95 -0.236994 -0.159133 0.807234 -0.083568 0.078701 -0.105214 -2.761139 0.043162 -0.096247 -0.106179
96 -0.391223 -0.014557 0.804878 0.040324 0.022574 0.717083 -1.149362 1.051754 -0.471551 0.333957
97 0.481387 -0.038779 0.380662 0.857424 0.067420 1.599628 -0.529226 0.071804 -0.201889 -0.087362
98 1.422031 0.021933 -0.180896 0.644405 -0.012918 -1.929145 -0.598751 -1.371636 0.812930 0.000721
99 -0.176868 -0.003792 0.662571 -0.799834 -0.011456 -2.083081 -0.144673 0.154913 0.250457 0.331734

100 rows × 10 columns

pd.DataFrame(dataset.Y)
0
0 8.584018
1 1.502417
2 -0.355069
3 -2.698677
4 2.331078
... ...
95 6.929988
96 6.780913
97 4.847613
98 -0.441276
99 4.126107

100 rows × 1 columns

デフォルトでは、X から Y を計算する式は多項式の一次式です。最初の5つの項のみが Y を導出するために使用され、残りの項は Y から独立しています。

pd.DataFrame(dataset.coef)
0
0 0.060915
1 -0.548520
2 8.244854
3 1.599333
4 4.259971
5 0.000000
6 0.000000
7 0.000000
8 0.000000
9 0.000000

パラメーターと関数

デフォルトでは、n_samples=100, n_features=10, n_informative=5, noise=0.0, function=linear, independence=1.0となっています。

  • n_samples はサンプル数です。
  • n_features は特徴量の数です。
  • n_informative はデフォルトの多項式線形関数で Y を導出する際に用いられる「意味のある」特徴量 X の数です.
  • noise はノイズの強さを表します。
  • independenceは、Yの導出に用いられない「無関係な」特徴量が、「意味のある」特徴量からどれだけ独立しているかを表します。

非線形関数が必要な場合は、以下のような関数 friedman1, friedman2, friedman3 を用いることができます。

dataset = generator.SampleDatasetGenerator(function=generator.friedman1)
dataset.generate()

あるいは、任意の関数を定義して以下のように使用することもできます。

import numpy as np
my_func = lambda X, coef: np.arctan((X[:, 1] * X[:, 2] - 1 / (X[:, 1] * X[:, 3])) / X[:, 0])

dataset = generator.SampleDatasetGenerator(function=my_func)
dataset.generate()

欠損値を持つデータの作成

欠損値を含むデータは、以下の方法で作成することができます。欠損値の発生率を調整することができ、例えば rate = 0.05 とすることができます。

dataset = generator.SampleDatasetGenerator()
dataset.generate()
dataset.fill_nan_randomly()
pd.DataFrame(dataset.X)
0 1 2 3 4 5 6 7 8 9
0 NaN -0.717267 0.466119 0.157829 0.403057 0.261670 1.621723 -2.384312 -0.419102 -0.187467
1 -0.226485 0.529230 -1.417389 -0.108385 0.108098 0.217466 1.137134 0.839975 -0.329924 NaN
2 -0.213283 -0.980020 NaN -0.031286 0.252950 -1.684535 1.525129 -1.228553 -0.815602 NaN
3 -0.610736 -0.601983 0.129403 -0.041961 -0.834912 -0.447463 1.315553 -0.935183 NaN -1.116784
4 -0.550343 -0.148456 NaN 0.757180 0.731174 -0.562547 0.425136 -0.848524 -1.284881 -0.720632
... ... ... ... ... ... ... ... ... ... ...
95 -0.400990 0.010573 -0.017612 0.323151 0.257867 0.008553 -0.781648 0.031025 -1.071831 1.435444
96 -0.008266 -0.945571 -1.367276 0.396686 0.434881 -0.684910 -0.845351 -0.597488 -1.066122 0.822694
97 0.154777 NaN NaN 0.259955 0.008274 -0.866544 -1.278649 -0.711525 -0.105661 1.192752
98 0.174639 0.208390 2.833820 0.352648 -0.131895 1.685485 1.342137 -0.594071 0.882873 -1.190221
99 0.784510 0.443287 -0.836974 0.000743 0.439658 -2.741350 0.887365 -0.530844 0.677080 -0.525392

100 rows × 10 columns

疎なデータの作成

以下のようにゼロ値を持つデータを作成することができます。 例えば、rate=0.9 のように、ゼロ値の出現率を調整することができます。

dataset = generator.SampleDatasetGenerator()
dataset.generate()
dataset.fill_zero_randomly()
pd.DataFrame(dataset.X)
0 1 2 3 4 5 6 7 8 9
0 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.000000
1 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.000000
2 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.000000
3 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.000000
4 0.0 0.0 1.290429 0.0 0.000000 0.000000 -0.620650 0.0 0.0 0.000000
... ... ... ... ... ... ... ... ... ... ...
95 0.0 0.0 0.000000 0.0 2.746314 0.000000 0.000000 0.0 0.0 0.000000
96 0.0 0.0 0.000000 0.0 0.000000 0.254578 0.000000 0.0 0.0 1.269509
97 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.000000
98 0.0 0.0 0.000000 0.0 0.000000 0.000000 0.000000 0.0 0.0 0.000000
99 0.0 0.0 1.480686 0.0 0.000000 0.000000 0.673103 0.0 0.0 0.000000

100 rows × 10 columns

分類問題の目的変数

デフォルトでは、目的変数は連続であり、回帰問題を解くことを想定していますが、以下のようにすることで、目的変数を離散値として分類問題として扱うことができます。

dataset = generator.SampleDatasetGenerator()
dataset.generate()
dataset.categoricalize()
pd.DataFrame(dataset.Y)
0
0 1
1 1
2 0
3 1
4 0
... ...
95 0
96 0
97 0
98 0
99 0

100 rows × 1 columns

以下のようにすることで、任意のバイアスを持つ任意の数のカテゴリデータを生成できます。

dataset = generator.SampleDatasetGenerator()
dataset.generate()
dataset.categoricalize(
    labels=["beer", "wine", "whiskey"], 
    classification_ratio=0.4
)
pd.DataFrame(dataset.Y)
0
0 whiskey
1 whiskey
2 whiskey
3 whiskey
4 whiskey
... ...
95 whiskey
96 whiskey
97 beer
98 wine
99 whiskey

100 rows × 1 columns

説明変数に離散値を含める

以下のようにすることで、与えられた列の説明変数をカテゴリ変数にできます。

dataset = generator.SampleDatasetGenerator()
dataset.generate()
dataset.categoricalize(column=3)
pd.DataFrame(dataset.X)
0 1 2 3 4 5 6 7 8 9
0 -0.069141 -0.152245 -0.069177 1.0 2.147144 1.683370 -1.406095 -0.288278 0.021179 0.386266
1 -0.017672 -0.330113 -0.233835 1.0 -1.383669 0.352960 0.937982 -1.835730 1.179513 -0.555153
2 -0.049318 0.672656 -0.694506 1.0 -0.250240 1.386238 1.016130 0.435432 -0.102031 -1.021133
3 -0.035957 -0.070815 0.086850 1.0 -0.044765 -0.424427 0.823290 -2.021052 -0.740976 0.774101
4 0.054945 0.316388 -0.937645 0.0 -1.004592 -1.727037 -0.325570 -0.185780 0.660687 -0.249081
... ... ... ... ... ... ... ... ... ... ...
95 -0.050984 0.218996 -0.436951 1.0 1.797569 1.522909 0.091088 1.819058 0.252704 1.506190
96 -0.040341 0.239490 -0.118325 1.0 -0.750467 -0.524603 1.785338 -0.590646 -0.311082 -0.588058
97 0.032199 0.652054 -0.293499 1.0 -0.526053 0.753688 1.558890 -1.672383 0.610953 -0.076587
98 -0.077576 0.222219 -0.018319 0.0 -0.393507 -0.626555 -0.160973 -0.469242 -0.435700 -1.651206
99 0.001802 0.383190 -0.018126 0.0 -1.859617 -0.601221 0.211747 -0.244071 -0.559714 -1.454075

100 rows × 10 columns

以下のようにすることで、任意のバイアスを持つ任意の数のカテゴリデータを生成できます。

dataset.categoricalize(
    column=5, 
    labels=["pen", "pineapple", "apple"], 
    classification_ratio=0.4
)
pd.DataFrame(dataset.X)
0 1 2 3 4 5 6 7 8 9
0 -0.0691405 -0.152245 -0.0691765 1 2.14714 pineapple -1.4061 -0.288278 0.0211786 0.386266
1 -0.0176721 -0.330113 -0.233835 1 -1.38367 pen 0.937982 -1.83573 1.17951 -0.555153
2 -0.0493178 0.672656 -0.694506 1 -0.25024 pineapple 1.01613 0.435432 -0.102031 -1.02113
3 -0.0359565 -0.0708147 0.0868503 1 -0.0447651 apple 0.82329 -2.02105 -0.740976 0.774101
4 0.0549453 0.316388 -0.937645 0 -1.00459 apple -0.32557 -0.18578 0.660687 -0.249081
... ... ... ... ... ... ... ... ... ... ...
95 -0.0509837 0.218996 -0.436951 1 1.79757 pineapple 0.0910875 1.81906 0.252704 1.50619
96 -0.0403408 0.23949 -0.118325 1 -0.750467 apple 1.78534 -0.590646 -0.311082 -0.588058
97 0.0321993 0.652054 -0.293499 1 -0.526053 pineapple 1.55889 -1.67238 0.610953 -0.0765871
98 -0.0775761 0.222219 -0.0183187 0 -0.393507 apple -0.160973 -0.469242 -0.4357 -1.65121
99 0.0018016 0.38319 -0.0181257 0 -1.85962 apple 0.211747 -0.244071 -0.559714 -1.45408

100 rows × 10 columns

整数や非負数にしたい場合は以下のようにします。

dataset.categoricalize(
    column=7, 
    labels=range(10), 
    classification_ratio=0.4
)
pd.DataFrame(dataset.X)
0 1 2 3 4 5 6 7 8 9
0 -0.0691405 -0.152245 -0.0691765 1 2.14714 pineapple -1.4061 0 0.0211786 0.386266
1 -0.0176721 -0.330113 -0.233835 1 -1.38367 pen 0.937982 5 1.17951 -0.555153
2 -0.0493178 0.672656 -0.694506 1 -0.25024 pineapple 1.01613 6 -0.102031 -1.02113
3 -0.0359565 -0.0708147 0.0868503 1 -0.0447651 apple 0.82329 5 -0.740976 0.774101
4 0.0549453 0.316388 -0.937645 0 -1.00459 apple -0.32557 2 0.660687 -0.249081
... ... ... ... ... ... ... ... ... ... ...
95 -0.0509837 0.218996 -0.436951 1 1.79757 pineapple 0.0910875 6 0.252704 1.50619
96 -0.0403408 0.23949 -0.118325 1 -0.750467 apple 1.78534 0 -0.311082 -0.588058
97 0.0321993 0.652054 -0.293499 1 -0.526053 pineapple 1.55889 5 0.610953 -0.0765871
98 -0.0775761 0.222219 -0.0183187 0 -0.393507 apple -0.160973 0 -0.4357 -1.65121
99 0.0018016 0.38319 -0.0181257 0 -1.85962 apple 0.211747 2 -0.559714 -1.45408

100 rows × 10 columns

実験

以下のコードは https://github.com/maskot1977/sampledataset_generator.git で公開しており、 Open In Colab で動作確認済みです。

ここからは、データセットの種類や性質を変えることが予測精度にどのように影響するかを確認するために、いくつかの代表的な機械学習手法を実験します。 Sample Dataset Generator リポジトリでは、以下の実験用スクリプトを提供しています。

from sampledataset_generator import experiment

以下に、代表的な回帰手法の結果を載せますので、回帰手法の性質と、データセットの性質を考えながら、何が起こっているのか考えてみましょう!

線形重回帰 Linear Regression

independencenoisen_features を変更した場合の影響を見てみましょう。

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression

experiment.benchmark(
    "LinearRegression", 
    make_pipeline(
        StandardScaler(), 
        LinearRegression()
        )
    )

線形関数

sampledataset_generator_experiment_6_0.png

非線形関数

sampledataset_generator_experiment_6_1.png

偏最小二乗回帰 Partial Least Square (PLS) Regression

independencenoisen_features を変更した場合の影響を見てみましょう。

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.cross_decomposition import PLSRegression

experiment.benchmark(
    "PLSRegression", 
    make_pipeline(
        StandardScaler(), 
        PLSRegression(n_components=10)
        )
    )

線形関数

sampledataset_generator_experiment_8_1.png

非線形関数

sampledataset_generator_experiment_8_2.png

サポートベクトル回帰 Support Vector Regression (SVR)

independencenoisen_features を変更した場合の影響を見てみましょう。

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR

experiment.benchmark(
    "SVR", 
    make_pipeline(
        StandardScaler(), 
        SVR(C=50, gamma='auto', epsilon=1e-05)
        )
    )

線形関数

sampledataset_generator_experiment_10_0.png

非線形関数

sampledataset_generator_experiment_10_1.png

ランダムフォレスト回帰 Random Forest Regression

independencenoisen_features を変更した場合の影響を見てみましょう。

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor

experiment.benchmark(
    "RandomForestRegressor", 
    make_pipeline(
        StandardScaler(), 
        RandomForestRegressor(
            random_state=1, 
            max_depth=8, 
            n_estimators=16
            )
        )
    )

線形関数

sampledataset_generator_experiment_12_0.png

非線形関数

sampledataset_generator_experiment_12_1.png

多層パーセプトロン回帰 Multi-Layer Perceptron (MLP) Regression

independencenoisen_features を変更した場合の影響を見てみましょう。

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.neural_network import MLPRegressor

experiment.benchmark(
    "MLPRegressor", 
    make_pipeline(
        StandardScaler(), 
        MLPRegressor(
            random_state=1, 
            max_iter=2000, 
            early_stopping=True,
            hidden_layer_sizes=(
                100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100
                )
            )
        )
    )

線形関数

sampledataset_generator_experiment_14_0.png

非線形関数

sampledataset_generator_experiment_14_1.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away