无监督学习自动编码器多输出 CNN,用于 MNIST 数据特征提取

问题描述 投票:0回答:1

我想从数据集(此处为 MNIST)中获取特征,并将它们放入 k-means 等聚类算法中。特征生成应该是无监督的,所以我选择自动编码来完成。我希望自动编码器仅通过第二个输出层“output_layer2”中的损失进行训练,训练后我想从第一个输出层“output_layer1”获取特征。为了获得两个输出层,我选择了 keras 中的功能 API。但我不知道如何获得这些特征以及如何仅针对一种损失进行训练。此外,我收到了像我的代码下的错误消息:

import numpy as np
import sys

import sklearn
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.layers import Input, Reshape, Conv2D, MaxPool2D, Conv2DTranspose
from tensorflow.keras.optimizers import SGD

assert sys.version_info >= (3, 5)
# Scikit-Learn ≥0.20 is required
assert sklearn.__version__ >= "0.20"
# TensorFlow ≥2.0-preview is required
assert tf.__version__ >= "2.0"


def get_MNISTdata(data_sz=10000):
    (X_train_full, y_train_full), (
        X_test,
        y_test,
    ) = keras.datasets.mnist.load_data()
    X_train_full = X_train_full.astype(np.float32) / 255
    X_test = X_test.astype(np.float32) / 255
    data_tr = X_train_full.shape[0] - data_sz
    X_train, X_valid = X_train_full[:-data_tr], X_train_full[-data_tr:]
    y_train, y_valid = y_train_full[:-data_tr], y_train_full[-data_tr:]
    return X_train, X_valid, y_train, y_valid


def rounded_accuracy(y_true, y_pred):
    return keras.metrics.binary_accuracy(tf.round(y_true), tf.round(y_pred))


def convoluntional_autoencoder(
    X_train,
    X_valid,
    shape1=28,
    shape2=28,
    channels=1,
    initial_features=16,
    kernel_sz=3,
    padding1="SAME",
    padding2="VALID",
    activation1="selu",
    activation2="sigmoid",
    pool_sz=2,
    strides=2,
    loss1="binary_crossentropy",
    loss2="softmax",
    lr=1.0,
    epochs=3,
):

    tf.random.set_seed(42)
    np.random.seed(42)

    # encoder
    input_layer = Input(shape=(shape1, shape2, channels))
    Layer1 = Conv2D(
        initial_features,
        kernel_size=kernel_sz,
        padding=padding1,
        activation=activation1,
    )(input_layer)
    Layer2 = MaxPool2D(pool_size=pool_sz)(Layer1)
    Layer3 = Conv2D(
        initial_features * 2,
        kernel_size=kernel_sz,
        padding=padding1,
        activation=activation1,
    )(Layer2)
    Layer4 = MaxPool2D(pool_size=pool_sz)(Layer3)
    Layer5 = Conv2D(
        initial_features * 4,
        kernel_size=kernel_sz,
        padding=padding1,
        activation=activation1,
    )(Layer4)
    output_layer1 = MaxPool2D(pool_size=pool_sz)(Layer5)

    n_poolingLayer = 3

    # decoder
    Layer7 = Conv2DTranspose(
        initial_features * 2,
        kernel_size=kernel_sz,
        strides=strides,
        padding=padding2,
        activation=activation1,
        input_shape=[
            int(shape1 / (2 ** n_poolingLayer)),
            int(shape2 / (2 ** n_poolingLayer)),
            initial_features * 2 ** (n_poolingLayer - 1),
        ],
    )(output_layer1)
    Layer8 = Conv2DTranspose(
        initial_features,
        kernel_size=kernel_sz,
        strides=strides,
        padding=padding1,
        activation=activation1,
    )(Layer7)
    output_layer2 = Conv2DTranspose(
        channels,
        kernel_size=kernel_sz,
        strides=strides,
        padding=padding1,
        activation=activation2,
    )(Layer8)

    conv_ae = Model(inputs=input_layer, outputs=[output_layer1, output_layer2])
    conv_ae.compile(
        loss={"output_layer1": loss1, "output_layer2": loss1},
        loss_weights=[0, 1],
        optimizer=SGD(lr=lr),
        metrics=[rounded_accuracy],
    )

    conv_ae.fit(
        X_train,
        X_train,
        epochs=epochs,
        validation_data=(X_valid, X_valid),
    )

    conv_ae.summary()

    # features = ?

    return # features

如果我这样做

X_train, X_valid, y_train, y_valid = get_MNISTdata(data_sz=10000)

还有这个

features = convoluntional_autoencoder(
    X_train,
    X_valid,
    shape1=28,
    shape2=28,
    channels=1,
    initial_features=16,
    kernel_sz=3,
    padding1="SAME",
    padding2="VALID",
    activation1="selu",
    activation2="sigmoid",
    pool_sz=2,
    strides=2,
    loss1="binary_crossentropy",
    loss2="softmax",
    lr=1.0,
    epochs=1,
)

我在

conv_ae.fit(...)
专栏中收到错误:

ValueError: Found unexpected losses or metrics that do not correspond to any Model 
output: dict_keys(['output_layer1', 'output_layer2']). Valid mode output names: ['max_pooling2d_5', 'conv2d_transpose_5']. 
Received struct is: {'output_layer1': 'binary_crossentropy', 'output_layer2': 'binary_crossentropy'}.

如果我将

conv_ae.compile
列更改为:

conv_ae.compile(
        loss=loss1,
        loss_weights=[0, 1],
        optimizer=SGD(lr=lr),
        metrics=[rounded_accuracy],
    )

我在

conv_ae.fit(...)
专栏中收到错误:

ValueError: Dimensions must be equal, but are 28 and 3 for '{{node binary_crossentropy/mul}} 
= Mul[T=DT_FLOAT](IteratorGetNext:1, binary_crossentropy/Log)' with input shapes: [?,28,28], [?,3,3,64].
python tensorflow feature-extraction autoencoder multipleoutputs
1个回答
0
投票

经常观察到,我们倾向于混合在 Scikit-learn 和 TensorFlow 中分割数据的方式。

X_Train , X_Valid , Y_train, Y_Valid
是scikit learn的train_test_split函数的输出。

然而,Tensorflow 的做法有所不同。如果您仍然想使用这种表示法,那么必须以正确的方式使用两者的组合。已经给出了明确的方法这里

就错误而言,我可能不太清楚,但 MNIST 数据集的聚类可以执行为:

  1. 从头开始为 MNIST 数据集训练 tf.keras 模型。 (以监督方式)

  2. 评估基线模型并保存以供以后使用

  3. 通过应用权重聚类 API 微调模型并查看准确性。 (这里使用无监督学习)

  4. 微调模型并根据基线评估准确性。 要点包含在本文中。

© www.soinside.com 2019 - 2024. All rights reserved.