Укладка RBMs для создания сети глубокого убеждения в sklearn - PullRequest
0 голосов
/ 04 сентября 2018

Согласно этому веб-сайту , сеть глубокого доверия просто объединяет несколько RBM, используя выходные данные предыдущего RBM в качестве входных данных следующего RBM. enter image description here

В документации scikit-learn есть один пример использования RBM для классификации набора данных MNIST. Они добавляют RBM и LogisticRegression в конвейер для достижения большей точности.

Поэтому мне интересно, могу ли я добавить несколько RBM в этот конвейер для создания Deep Belief Networks, как показано в следующем коде.

from sklearn.neural_network import BernoulliRBM
import numpy as np
from sklearn import linear_model, datasets, metrics
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline

digits = datasets.load_digits()
X = np.asarray(digits.data, 'float32')
Y = digits.target
X = (X - np.min(X, 0)) / (np.max(X, 0) + 0.0001)  # 0-1 scaling

X_train, X_test, Y_train, Y_test = train_test_split(X, Y,
                                                    test_size=0.2,
                                                    random_state=0)

logistic = linear_model.LogisticRegression(C=100)
rbm1 = BernoulliRBM(n_components=100, learning_rate=0.06, n_iter=100, verbose=1, random_state=101)
rbm2 = BernoulliRBM(n_components=80, learning_rate=0.06, n_iter=100, verbose=1, random_state=101)
rbm3 = BernoulliRBM(n_components=60, learning_rate=0.06, n_iter=100, verbose=1, random_state=101)
DBN3 = Pipeline(steps=[('rbm1', rbm1),('rbm2', rbm2), ('rbm3', rbm3), ('logistic', logistic)])

DBN3.fit(X_train, Y_train)

print("Logistic regression using RBM features:\n%s\n" % (
    metrics.classification_report(
        Y_test,
        DBN3.predict(X_test))))

Однако я обнаружил, что чем больше RBM я добавляю в конвейер, тем меньше точность.

1 RBM в трубопроводе -> 95%

2 УКР в трубопроводе -> 93%

3 УКР в трубопроводе -> 89%

Тренировочная кривая ниже показывает, что 100 итераций как раз подходят для конвергенции. Дополнительные итерации приведут к переобучению, и вероятность снова снизится.

Размер партии = 10

enter image description here

Размер партии = 256 или выше

Я заметил одну интересную вещь. Если я использую пакет большего размера, производительность сети сильно ухудшается. Когда размер партии превышает 256, точность падает до менее чем 10%. Кривая обучения почему-то не имеет смысла для меня, с первым и вторым RBM не учатся многому, но третий RBM внезапно учится быстро. enter image description here

Похоже, что 89% является узким местом для сети с 3 RBM.

Интересно, я что-то здесь не так делаю? Верно ли мое понимание сети глубоких убеждений?

1 Ответ

0 голосов
/ 27 ноября 2018

Следующий ответ не совсем однозначен, так как ему не хватает статистической строгости. Тем не менее, для оптимизации и оценки необходимых параметров все равно потребуется несколько дней процессорного времени. До этого я представляю в качестве ответа следующее доказательство принципа.

Tl, др

Большие уровни + гораздо более длительное обучение => производительность логистической регрессии сама по себе <+ 1 уровень RBM <+ стек RBM / DBN </p>

Введение

Как я уже отмечал в одном из моих комментариев к сообщению OP, использование стековых RBM / DBN для неконтролируемой предварительной подготовки систематически изучалось в Erhan et al. (2010) . Если быть точным, их настройка отличается от настройки OP тем, что после обучения DBN они добавляют последний слой выходных нейронов и настраивают всю сеть с помощью backprop. OP оценивает преимущество добавления одного или нескольких уровней RBM, используя производительность логистической регрессии на выходе конечного уровня. Кроме того, Erhan et al. также не используйте 64-пиксельный набор данных digits в scikit-learn, но 784-пиксельные изображения MNIST (и их варианты).

При этом сходства достаточно существенны, чтобы их выводы послужили отправной точкой для оценки реализации DBN с помощью scikit-learn, что я и сделал: я также использую набор данных MNIST и Я использую оптимальные параметры (где сообщается), Erhan et al. Эти параметры существенно отличаются от параметров, приведенных в примере OP, и, вероятно, являются причиной плохой работы модели OP: в частности, размеры слоев намного больше, а количество обучающих выборок на несколько порядков больше. Однако, как OP, я использую логистическую регрессию на последнем этапе конвейера, чтобы оценить, улучшают ли преобразования изображения с помощью RBM или стека RBM / DBN.

Кстати, наличие (приблизительно) такого же количества единиц в слоях RBM (800 единиц), что и в исходном изображении (784 пикселя), также делает чистую логистическую регрессию для пикселей необработанного изображения подходящей эталонной моделью.

Поэтому я сравниваю следующие 3 модели:

  1. логистическая регрессия сама по себе (т.е. базовая / эталонная модель),

  2. логистическая регрессия на выходах RBM и

  3. логистическая регрессия на выходах стеков RBMs / DBN.

Результаты

В соответствии с предыдущей литературой, мои предварительные результаты действительно указывают на то, что использование вывода RBM для логистической регрессии улучшает производительность по сравнению с простым использованием необработанных значений пикселей, а преобразование DBN все же улучшает RBM, хотя и улучшает меньше.

Логистическая регрессия сама по себе:

Model performance:
             precision    recall  f1-score   support

        0.0       0.95      0.97      0.96       995
        1.0       0.96      0.98      0.97      1121
        2.0       0.91      0.90      0.90      1015
        3.0       0.90      0.89      0.89      1033
        4.0       0.93      0.92      0.92       976
        5.0       0.90      0.88      0.89       884
        6.0       0.94      0.94      0.94       999
        7.0       0.92      0.93      0.93      1034
        8.0       0.89      0.87      0.88       923
        9.0       0.89      0.90      0.89      1020

avg / total       0.92      0.92      0.92     10000

Логистическая регрессия на выходах RBM:

Model performance:
             precision    recall  f1-score   support

        0.0       0.98      0.98      0.98       995
        1.0       0.98      0.99      0.99      1121
        2.0       0.95      0.97      0.96      1015
        3.0       0.97      0.96      0.96      1033
        4.0       0.98      0.97      0.97       976
        5.0       0.97      0.96      0.96       884
        6.0       0.98      0.98      0.98       999
        7.0       0.96      0.97      0.97      1034
        8.0       0.96      0.94      0.95       923
        9.0       0.96      0.96      0.96      1020

avg / total       0.97      0.97      0.97     10000

Логистическая регрессия на выходах стеков RBMs / DBN:

Model performance:
             precision    recall  f1-score   support

        0.0       0.99      0.99      0.99       995
        1.0       0.99      0.99      0.99      1121
        2.0       0.97      0.98      0.98      1015
        3.0       0.98      0.97      0.97      1033
        4.0       0.98      0.97      0.98       976
        5.0       0.96      0.97      0.97       884
        6.0       0.99      0.98      0.98       999
        7.0       0.98      0.98      0.98      1034
        8.0       0.98      0.97      0.97       923
        9.0       0.96      0.97      0.96      1020

avg / total       0.98      0.98      0.98     10000

Код

#!/usr/bin/env python

"""
Using MNIST, compare classification performance of:
1) logistic regression by itself,
2) logistic regression on outputs of an RBM, and
3) logistic regression on outputs of a stacks of RBMs / a DBN.
"""

import numpy as np
import matplotlib.pyplot as plt

from sklearn.datasets import fetch_mldata
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.neural_network import BernoulliRBM
from sklearn.base import clone
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report


def norm(arr):
    arr = arr.astype(np.float)
    arr -= arr.min()
    arr /= arr.max()
    return arr


if __name__ == '__main__':

    # load MNIST data set
    mnist = fetch_mldata('MNIST original')
    X, Y = mnist.data, mnist.target

    # normalize inputs to 0-1 range
    X = norm(X)

    # split into train, validation, and test data sets
    X_train, X_test, Y_train, Y_test = train_test_split(X,       Y,       test_size=10000, random_state=0)
    X_train, X_val,  Y_train, Y_val  = train_test_split(X_train, Y_train, test_size=10000, random_state=0)

    # --------------------------------------------------------------------------------
    # set hyperparameters

    learning_rate = 0.02 # from Erhan et el. (2010): median value in grid-search
    total_units   =  800 # from Erhan et el. (2010): optimal for MNIST / only slightly worse than 1200 units when using InfiniteMNIST
    total_epochs  =   50 # from Erhan et el. (2010): optimal for MNIST
    batch_size    =  128 # seems like a representative sample; backprop literature often uses 256 or 512 samples

    C = 100. # optimum for benchmark model according to sklearn docs: https://scikit-learn.org/stable/auto_examples/neural_networks/plot_rbm_logistic_classification.html#sphx-glr-auto-examples-neural-networks-plot-rbm-logistic-classification-py)

    # TODO optimize using grid search, etc

    # --------------------------------------------------------------------------------
    # construct models

    # RBM
    rbm = BernoulliRBM(n_components=total_units, learning_rate=learning_rate, batch_size=batch_size, n_iter=total_epochs, verbose=1)

    # "output layer"
    logistic = LogisticRegression(C=C, solver='lbfgs', multi_class='multinomial', max_iter=200, verbose=1)

    models = []
    models.append(Pipeline(steps=[('logistic', clone(logistic))]))                                              # base model / benchmark
    models.append(Pipeline(steps=[('rbm1', clone(rbm)), ('logistic', clone(logistic))]))                        # single RBM
    models.append(Pipeline(steps=[('rbm1', clone(rbm)), ('rbm2', clone(rbm)), ('logistic', clone(logistic))]))  # RBM stack / DBN

    # --------------------------------------------------------------------------------
    # train and evaluate models

    for model in models:
        # train
        model.fit(X_train, Y_train)

        # evaluate using validation set
        print("Model performance:\n%s\n" % (
            classification_report(Y_val, model.predict(X_val))))

    # TODO: after parameter optimization, evaluate on test set
...