почему keras model.predict возвращает только одну вероятность? Как вывести все вероятности всех классов? - PullRequest
0 голосов
/ 08 мая 2019

Я работаю над проблемой классификации.Набор данных имеет 9 классов, поэтому я хочу получить вероятности для 9 классов, но model.predict () в keras выглядит так, что выводит только самый большой из них.Я думаю, что форма yprobs должна быть (3014,9), тогда я могу получить работу log_loss ().надеясь на помощь!Спасибо !!

'' 'код модели' ''

class AdaBNModel:

def __init__(self, nfeatures=50, arch=[8, 'abn', 'act'], activations='relu',
             droprate=0.0, noise=0.0, optimizer=None, val_data=None,
             validate_every=1, epochs=5000, batch_size=128, verbose=False):

    self.epochs = epochs
    self.batch_size = batch_size
    self.noise = noise
    self.verbose = verbose

    self.validate_every = validate_every
    if val_data is None:
        self.validate_every = 0
        self.Xval = None
        self.yval = None
    else:
        self.Xval = val_data[0]
        self.yval = val_data[1]

    self._build_model(arch, activations, nfeatures, droprate, noise, optimizer) 

def _build_model(self, arch, activations, nfeatures, droprate, noise, optimizer):

    self.layers = [Input(shape=(nfeatures,))]

    for i, nunits in enumerate(arch):

        if isinstance(nunits, int):
            self.layers += [Dense(nunits, activation='linear')(self.layers[-1])]

        elif nunits == 'noise':
            self.layers += [GaussianNoise(noise)(self.layers[-1])]

        elif nunits == 'bn':
            self.layers += [BatchNormalization()(self.layers[-1])]

        elif nunits == 'abn':
            self.layers += [AdaBN()(self.layers[-1])]

        elif nunits == 'drop':
            self.layers += [Dropout(droprate)(self.layers[-1])]

        elif nunits == 'act':
            if activations == 'prelu':
                self.layers += [PReLU()(self.layers[-1])]
            elif activations == 'elu':
                self.layers += [ELU()(self.layers[-1])]
            elif activations == 'leakyrelu':
                self.layers += [LeakyReLU()(self.layers[-1])]
            else:
                self.layers += [Activation(activations)(self.layers[-1])]

        else:
            print('Unrecognised layer {}, type: {}'.format(nunits, type(nunits)))

    self.layers += [Dense(1, activation='sigmoid')(self.layers[-1])]

    self.model = Model(self.layers[0], self.layers[-1])
    self.model.compile(loss='sparse_categorical_crossentropy', optimizer=optimizer)

def _fit(self, Xs, ys, Xt, yt, domains, Xval=None, yval=None, epochs=None, batch_size=None, verbose=None):

    if epochs is None: epochs = self.epochs
    if batch_size is None: batch_size = self.batch_size
    if Xval is None: 
        Xval = self.Xval
        yval = self.yval
    if verbose is None: verbose = self.verbose

    # batch generator that ensures that samples are always from the same domain
    S_batches = domain_batch_gen(Xs, ys, domains, batch_size=batch_size)

    # self.history = {'source_loss': [], 'target_loss': [], 'val_loss': []}
    self.history = {'source_loss': [], 'target_loss': []}
    for i in range(epochs):
        Xsource, ysource = S_batches.__next__()
        self.model.fit(Xsource, ysource, epochs=1, batch_size=batch_size, verbose=0) 

        #if self.validate_every > 0 and i % self.validate_every == 0:
        if True:
            if i == 0:
                print('Epoch  sloss tloss vloss')

            self.history['source_loss'] += [self.evaluate(Xs, ys)]
            self.history['target_loss'] += [self.evaluate(Xt, yt)]
            #self.history['val_loss'] += [self.evaluate(Xval, yval)]

            print('{:04d}  {:.5f} {:.5f}  '.format(i,
                                                         self.history['source_loss'][-1],
                                                         self.history['target_loss'][-1]))
            # print('{:04d}  {:.5f} {:.5f} {:.5f} '.format(i,
            #     self.history['source_loss'][-1], self.history['target_loss'][-1], self.history['val_loss'][-1]))


def fit(self, Xs, ys, Xt, yt, domains=None, Xval=None, yval=None, epochs=None, batch_size=None, verbose=None):

    if epochs is None: epochs = self.epochs
    if batch_size is None: batch_size = self.batch_size
    if Xval is None: 
        Xval = self.Xval
        yval = self.yval
    if verbose is None: verbose = self.verbose

    if domains is None: domains = np.ones_like(ys, dtype=int)
    self._fit(Xs, ys, Xt, yt, domains, Xval, yval, epochs, batch_size, verbose)         

def predict_proba(self, X, domains=None, batch_size=None):
    if batch_size is None: batch_size = self.batch_size
    if domains is None:
        return self.model.predict(X,batch_size,verbose=1)
    else:                               
        ypreds = np.zeros(X.shape[0])
        udomains = np.unique(domains)#[1]
        #print(udomains.shape)
        for i in range(udomains.shape[0]):
            idx = (domains == udomains[i])
            # print(idx)
            # print(idx.shape)  #(3014,)
            print('domain')
            thisX = X[idx]
            # print(thisX)
            # print(thisX.shape)    #(3014, 145)
            # ypreds[idx] = self.model.predict(thisX, batch_size=batch_size).flatten()
            ypreds[idx] = self.model.predict(thisX, batch_size=batch_size).flatten()

        return ypreds

def evaluate(self, X, y, domains=None, batch_size=None):
    #yprobs = self.predict_proba(X, domains, batch_size)
    yprobs = self.model.predict(X,batch_size,verbose=1)
    print(yprobs)
    print(yprobs.shape)#(3014,1)
    print(y.shape)     #(3014,)
    return log_loss(y, yprobs)

Traceback (most recent call last):

  32/3014 [..............................] - ETA: 1s
3014/3014 [==============================] - 0s 5us/step
[[0.99279547]**strong text**
  File "D:/cmWorks/AdaBN-1d/example_adabn.py", line 33, in <module>
    model.fit(Xs, ys, Xt, yt)
  File "D:\cmWorks\AdaBN-1d\adabn.py", line 124, in fit
    self._fit(Xs, ys, Xt, yt, domains, Xval, yval, epochs, batch_size, verbose)         
  File "D:\cmWorks\AdaBN-1d\adabn.py", line 103, in _fit
 [0.9899932 ]
    self.history['source_loss'] += [self.evaluate(Xs, ys)]
 [0.9922549 ]
  File "D:\cmWorks\AdaBN-1d\adabn.py", line 154, in evaluate
    return log_loss(y, yprobs)
 ...
 [0.9604445 ]
 [0.9100603 ]
 [0.95761013]]
(3014, 1)
(3014,)
[8. 8. 8. ... 6. 6. 6.]
  File "E:\Anaconda3\envs\keras\lib\site-packages\sklearn\metrics\classification.py", line 1809, in log_loss
    lb.classes_))
ValueError: y_true and y_pred contain different number of classes 9, 2. Please provide the true labels explicitly through the labels argument. Classes found in y_true: [0. 1. 2. 3. 4. 5. 6. 7. 8.]

1 Ответ

2 голосов
/ 08 мая 2019

Бритва Оккама - всегда ваш лучший инструмент для начальной отладки, посмотрите на эту строку последний слой вашей модели:

self.layers += [Dense(1, activation='sigmoid')(self.layers[-1])]

У вашей модели только один выходной нейрон, а не девять, как должно быть для 9классы.Вот почему keras предсказывает только одну вероятность для выборки.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...