如何将此模型输出从float更改为string?

时间:2018-10-20 02:01:16

标签: machine-learning keras deep-learning

from __future__ import print_function

import numpy as np
from keras.callbacks import EarlyStopping
from keras.layers.core import Dense, Activation
from keras.models import Sequential
from keras.optimizers import SGD
from keras.layers import Layer
import keras.backend as K

np.random.seed(1337)  # for reproducibility

class Round(Layer):
    def __init__(self, **kwargs):
        super(Round, self).__init__(**kwargs)

    def get_output(self, train=False):
        X = self.get_input(train)
        return K.round(X)

    def get_config(self):
        config = {"name": self.__class__.__name__}
        base_config = super(Round, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))


def build_and_train_mlp_network(X_train, y_train, X_test, y_test):

    nb_epoch = 1000
    batch_size = 4

    model = Sequential()
    model.add(Dense(2, input_shape=(X_train.shape[1],)))
    model.add(Activation('sigmoid'))
    model.add(Dense(1))
    model.add(Activation('sigmoid'))
    model.add(Round()) # return K.round(X)

    sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='mean_squared_error', optimizer=sgd)  # or binary_crossentropy

    model.fit(X_train,
              y_train,
              batch_size=batch_size,
              nb_epoch=nb_epoch,
              verbose=0,
              validation_data=(X_test, y_test))
    return model


if __name__ == "__main__":

    X_test = X_train = np.array([[1, 1], [1, 0], [0, 1], [0, 0]])

    y_train = y_test = np.array([1, 2, 3, 4])

    model = build_and_train_mlp_network(X_train, y_train, X_test, y_test)
    print(model.predict(X_test))

如何将此模型输出从float更改为string?

输出为[[0.9999342 ] [0.99991477] [0.99989116] [0.9998405 ]]

现在我改变

y_train = y_test = np.array(['a', 'b', 'c', 'd'])

如何使输出(model.predict(X_test))成为字符串?

1 个答案:

答案 0 :(得分:1)

这里涉及一些猜测:我假设您的“舍入”层目的是获得一个整数的输出。但是,这样一来,您很有可能会破坏SGD中的梯度。

为避免梯度问题,您应该在后期处理步骤中进行操作。因此,我建议通过以下方式更改神经网络:

    model = Sequential()
    model.add(Dense(2, input_shape=(X_train.shape[1],)))
    model.add(Activation('sigmoid'))
    model.add(Dense(1))
#    model.add(Activation('sigmoid'))
    model.add(Activation('linear'))

线性激活以获得大于1的数字。此功能是您获得[[0.9999342 ] [0.99991477] [0.99989116] [0.9998405 ]]的原因  之后,您可以对输出进行后期处理

print(np.round(model.predict(X_test)))

或映射到可以使用的字符

maps = ['foo','a','b','c','d','bar'] # ugly what about -1...6,... etc
[maps[int(round(i))] for i in  model.predict(X_test).flatten()]

使用功能性API,您实际上可以将舍入推入NN。我不得不重新编写您的图层

class Round(Layer):
    def __init__(self, **kwargs):
        super(Round, self).__init__(**kwargs)

    def call(self,X):
        print(X)
        return K.round(X)

    def get_config(self):
        config = {"name": self.__class__.__name__}
        base_config = super(Round, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))


r = Round()(outputs)
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
modelr = Model(inputs=inputs, outputs=r)
modelr.compile(loss='mean_squared_error', optimizer=sgd)
modelr.predict(X_test)

说过,我认为您的模型存在根本缺陷。该模型假定字符中存在顺序。这意味着bac之间。从字母的角度来看,这是正确的,但是在语义上是错误的。

因此,您应该使用标准的一键编码方法。同样不会发生使foobar等不可拼写的字符出现的问题。查看标准TF / Keras Mnist示例

然后您可以通过以下方式构建模型

from keras.utils import np_utils

num_classes=5 # sorry but we need zero

def build_and_train_mlp_network(X_train, y_train, X_test, y_test):

    nb_epoch = 1000
    batch_size = 4

    inputs = Input(shape=(X_train.shape[1],))
    d1 = Dense(2)(inputs)
    a1 = Activation('sigmoid')(d1)
    d2 = Dense(num_classes)(a1)
    a2 = Activation(activation='softmax')(d2)


    model = Model(inputs=inputs, outputs=a2)

    sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='mean_squared_error', optimizer=sgd)  # or binary_crossentropy

    model.fit(X_train,
              y_train,
              batch_size=batch_size,
              nb_epoch=nb_epoch,
              verbose=0,
              validation_data=(X_test, y_test))
    return model,inputs,a2




X_test = X_train = np.array([[1, 1], [1, 0], [0, 1], [0, 0],[1, 1]])
y_train = y_test = np_utils.to_categorical(np.array([0, 1, 2, 3,0]),num_classes=5)
model,inputs,outputs = build_and_train_mlp_network(X_train, y_train, X_test, y_test)
print(model.summary())
model.predict(X_test)

,如果您想再次从计算图获取max class

class ArgMax(Layer):
    def __init__(self, **kwargs):
        super(ArgMax, self).__init__(**kwargs)

    def call(self,X):
        print(X)
        return K.argmax(X, axis=None)

    def get_config(self):
        config = {"name": self.__class__.__name__}
        base_config = super(Round, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

am = ArgMax()(outputs)
modelam=Model(inputs=inputs,outputs=[am,outputs])
clazzes,confidence = modelam.predict(X_test)