根据这个website,深度信念网络只是使用前一个RBM的输出作为下一个RBM的输入,将多个RBM堆叠在一起。
python - 堆叠RBM以在sklearn中创建深度信仰网络-LMLPHP

在scikit-learn documentation中,有一个使用RBM对MNIST数据集进行分类的示例。他们将RBMLogisticRegression放入管道中,以实现更好的准确性。

因此,我想知道是否可以在该管道中添加多个RBM来创建深度信任网络,如以下代码所示。

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个RBM-> 93%

管道中有3个RBM-> 89%

下面的训练曲线表明100次迭代恰好是收敛的。更多的迭代将导致过度拟合,并且可能性会再次下降。

批次大小= 10

python - 堆叠RBM以在sklearn中创建深度信仰网络-LMLPHP

批次大小= 256或以上

我注意到一件有趣的事。如果我使用较大的批处理大小,则网络性能会大大降低。当批次大小大于256时,准确度仅会降低到10%以下。训练曲线对我来说毫无意义,因为第一和第二个RBM并没有学到很多,但是第三个RBM突然学习很快。
python - 堆叠RBM以在sklearn中创建深度信仰网络-LMLPHP

看起来89%的带宽是3个RBM网络的瓶颈。

我想知道我在这里做错了什么。我对深度信仰网络的理解正确吗?

最佳答案

由于缺乏统计上的严格性,以下内容并不是一个确定的答案。
但是,必要的参数优化和评估仍将花费几天的CPU时间。在此之前,我将提交以下原理证明作为答案。

Tl;博士

更大的层+更长的训练时间=>逻辑回归本身的表现
介绍

正如我在OP帖子的评论之一中所述,在Erhan et al. (2010)中系统地探讨了使用堆叠式RBM/DBN进行无监督的预训练。确切地说,它们的设置与OP的设置不同之处在于,在训练DBN之后,他们添加了输出神经元的最后一层,并使用反向传播技术对整个网络进行了微调。 OP使用对最后一层的输出进行逻辑回归的性能来评估添加一个或多个RBM层的好处。
此外,Erhan等。也不使用scikit-learn中设置的64像素digits数据集,而是使用784像素的MNIST图像(及其变体)。

话虽如此,相似性足够大,足以将他们的发现作为评估DBN的scikit学习实现的起点,而这正是我所做的事情:我也使用MNIST数据集,并且我使用了Erhan等人的最佳参数(在报告的地方)。这些参数与OP实例中给出的参数大不相同,并且可能是OP模型性能不佳的根源:特别是,层大小更大,训练样本的数量大几个数量级。但是,作为OP,我在管道的最后一步中使用逻辑回归来评估RBM或RBM/DBN堆栈的图像转换是否可以改善分类。

顺便说一下,R​​BM层(约800个单元)中的单元数(约)与原始图像(784个像素)中的单元数大致相同,这也使对原始图像像素的纯逻辑回归成为合适的基准模型。

因此,我比较以下三种模型:

  • 本身的logistic回归(即基准/基准模型),
  • RBM输出的
  • logistic回归和
  • 对一堆RBM/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
    

    基于结果的管理的逻辑回归:
    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
    

    对一堆RBM/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
    

    10-07 23:51