2018年7月7日土曜日

Deep Learningの回帰における出力分布の重要性

以前から気になっていた事なのですが、Deep Learningはデータセットの分布がかなり重要です。

主に正規分布を仮定する事になる訳ですが、その重要性について書いてみようと思います。 sin波の予測を例にすると非常にわかりやすいので、まずは簡単なコードを以下に載せます。

上記のコードは過去のinputs = 400の動きを元にplen = 400後の数値を予測します。 これを実行すると多少のノイズがあるsin波でも正負の判定なら92%くらい、誤差なら0.04くらいの精度で予測できる事が確認できると思います。 さすがはDeep Learning…で話が終われば良いのですが、本当にそうでしょうか。 例えば以下のコードのようにplenをランダムにするとどうなるでしょう。
def generate_dataset(dataframe, plen, inputs):
    x, y = [], []
    for i in range(len(dataframe)-inputs*2):
        tmp_x = dataframe[["sine_wave"]].iloc[i:i+inputs].values.flatten()
        tmp_x = np.append(tmp_x, 1.0/plen)  # +1特徴
        # tmp_x = np.append(tmp_x, np_utils.to_categorical(plen, inputs))  # +n特徴
        x.append(tmp_x)
        y.append(dataframe[["sine_wave"]].iloc[i+inputs+plen].values.flatten())
    return np.array(x), np.array(y)

def load_data(data, test_size, inputs):
    n = int(round(len(data) * (1 - test_size)))
    x_train, y_train = generate_dataset(data.iloc[0:n], random.randrange(inputs), inputs)
    x_test, y_test = generate_dataset(data.iloc[n:], random.randrange(inputs), inputs)
    return (x_train, y_train), (x_test, y_test)
plenの特徴量が何もないと悲惨な事になるのは明白なので、上記では2つの方法で特徴量として追加しています。 さて上記のコードはどのくらいの精度が出るでしょう。 結論だけ言ってしまえば10%〜80%くらいの不安定な精度になるはずです。 この程度の変更でもDeep Learningは簡単に学習できなくなってしまうのです。


「plenを特徴で追加したのになんで?」と思う方は居るかも知れません。 これが今回述べたかった分布の重要性。 plenと過去の数値から出力される1つの出力は、plenに対して正規分布にまったく従わない事が何となくわかるはずです。 一番最初のコードはplenが固定されていたため予測値が正規分布に従い、うまく予測できていただけなのでした。

ではどうすれば良いかと言うと、以下のコードのようにplenごとの出力を見ます。 この場合、各出力の誤差が正規分布に従う事が予想できるので、うまく学習する事ができます。 ちなみに+1特徴でも+n特徴でもさほど性能差は出ません。 とにかく出力を正規分布に従わせる事が重要なのです。
def generate_dataset(dataframe, plen, inputs=400):
    x, y = [], []
    for i in range(len(dataframe)-inputs*2):
        tmp_x = dataframe[["sine_wave"]].iloc[i:i+inputs].values.flatten()
        tmp_x = np.append(tmp_x, 1.0/plen)
        # tmp_x = np.append(tmp_x, np_utils.to_categorical(plen, inputs))
        x.append(tmp_x)
        y.append(dataframe[["sine_wave"]].iloc[i+inputs:i+inputs*2].values.flatten())  # 変更
    return np.array(x), np.array(y)

model.add(Dense(400))  # 1出力から400出力へ変更
上記のコードに変更すれば、任意のplenにおいても92%くらいの精度で予測できる事が確認できるはずです。 Deep Learningが神経を使う予測器である事、そして精度が出ない時の傾向と対策がよくわかる例だと思ったのでメモしてみました。

0 件のコメント: