我正在处理分类问题。数据集有9个类,所以我想获得9个类的概率,但是keras中的model.predict()看起来仅输出最大的一个。我认为yprob的形状应为(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.]
答案 0 :(得分:2)
Occam的剃刀永远是您最好的初始调试工具,请在此行中查看模型的最后一层:
self.layers += [Dense(1, activation='sigmoid')(self.layers[-1])]
您的模型只有一个输出神经元,而不是9个类的9个神经元。这就是为什么keras预测每个样本只有一个概率的原因。
还请注意,对于多类分类,除非要进行使用softmax
的多标签分类,否则应在最后一层使用sigmoid
激活。