【发布时间】:2019-01-02 21:05:24
【问题描述】:
我正在尝试使用由 Tensorflow 支持的 Keras 中的 Conv3D 神经网络进行可变长度的多类序列分类。
我创建了一个小示例,在该示例中,我根据预期输出的标签生成输入分布。使用输入生成器训练网络后,预测结果始终是相同的值。
复制:
import numpy as np
import keras
from keras.utils import to_categorical
from keras.layers import Conv3D, Input, Flatten, Dense, Lambda, MaxPool3D, Dropout, Activation
from keras.regularizers import l2
from keras.optimizers import Adam
from random import randint
from keras.models import Model, Sequential
import keras.backend as K
#import os
#os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
HEIGHT = 40
WIDTH = 40
NDIMS = 1
NUM_CLASSES = 10
def get_data():
nframes = randint(3,6)
label = randint(0,NUM_CLASSES-1)
x = np.array( ((label + 1) * 2) * np.random.randn(nframes, HEIGHT, WIDTH, NDIMS))
#print(np.std(x), label)
x = np.expand_dims(x, axis=0)
y = keras.utils.to_categorical([label], num_classes=NUM_CLASSES)
return x,y
def input_generator():
while True:
x,y = get_data()
yield (x, y)
def c3d():
weight_decay = 0.005
inputs = Input((None, HEIGHT, WIDTH, NDIMS))
x = Conv3D(64,(3,3,3),strides=(1,1,1),padding='same',
activation='relu',kernel_regularizer=l2(weight_decay))(inputs)
x = MaxPool3D((2,2,1),strides=(2,2,1),padding='same')(x)
x = Conv3D(128,(3,3,3),strides=(1,1,1),padding='same',
activation='relu',kernel_regularizer=l2(weight_decay))(x)
x = Lambda(lambda xa: K.sum(xa, axis=1))(x)
x = Flatten()(x)
x = Dense(64,activation='relu',kernel_regularizer=l2(weight_decay))(x)
x = Dropout(0.5)(x)
x = Dense(32,activation='relu',kernel_regularizer=l2(weight_decay))(x)
x = Dropout(0.5)(x)
x = Dense(NUM_CLASSES,kernel_regularizer=l2(weight_decay))(x)
x = Activation('softmax')(x)
lr = 0.005
optimizer = Adam(lr=lr)
model = Model(inputs, x)
model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
return model
if __name__ == '__main__':
model = c3d()
model.fit_generator(input_generator(), samples_per_epoch=10, nb_epoch=50, verbose=1)
values = []
argmaxes = []
for i in range(100):
x,_ = get_data()
val = model.predict(x)
values.append(val)
argmaxes.append(np.argmax(val))
print(argmaxes)
对于最后一个打印语句,输出如下:
[ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, ...
它在 (0, NUM_CLASSES-1) 范围内选择一个随机数,并将其用于每个预测。特征与其标签之间应该有一个模式。
更新:解决问题:
我已将问题简化为更基本的元素,但还不能在原始问题 (c3d) 中得到这些结果。我已经用重复的标签替换了特征数据,并且我能够让网络在一定程度上了解到重复 n 次的值实际上是分类。无论是可变长度还是非可变长度,从每 5 个 epoch 500 个样本的 3 次激活中观察最佳的最后 10 次平均准确度:
Input, activation, learning rate, layer size, activation, accuracy, sequence
np.repeat: tanh 0.001 48 adagrad 0.46319999999999995 False
np.repeat: sigmoid 0.001 64 adam 0.4720000000000001 False
np.repeat: relu 0.001 64 adam 0.30519999999999997 False
复制:
import numpy as np
import keras
from keras.utils import to_categorical
from keras.layers import Input, Dense, Lambda
from keras.optimizers import Adam, SGD, Adagrad, RMSprop
from random import randint
from keras.models import Model
import keras.backend as K
WIDTH = 40
NUM_CLASSES = 10
DIMENSIONS = 1
NO_SEQUENCE = False
def get_data():
nframes = randint(3,6)
label = randint(0,NUM_CLASSES-1)
x = np.repeat(label, WIDTH * nframes).reshape(nframes, WIDTH).astype(np.float32)
# x = np.array(((label + 1) * 2) * np.random.randn(nframes, WIDTH))
if NO_SEQUENCE:
x = x[0]
# print(x, label)
x = np.expand_dims(x, axis=0)
y = keras.utils.to_categorical([label], num_classes=NUM_CLASSES)
return x,y
def input_generator():
while True:
x,y = get_data()
yield (x, y)
def cd(activation='relu', lr=0.0001, dense_size=16, optimizer=Adam()):
if NO_SEQUENCE:
inputs = Input((WIDTH,))
x = Dense(dense_size, activation=activation)(inputs)
else:
inputs = Input((None, WIDTH))
x = Dense(dense_size, activation=activation)(inputs)
x = Lambda(lambda xa: K.sum(xa, axis=1))(x)
x = Dense(NUM_CLASSES, activation='softmax')(x)
optimizer.lr = lr
model = Model(inputs, x)
model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
return model
if __name__ == '__main__':
activations = ['sigmoid', 'tanh', 'relu']
learning_rates = [.01, .001, .0001, .00001]
layer_sizes = [16, 32, 48, 64]
optimizers = [('adagrad', Adagrad()), ('sgd', SGD()), ('rmsprop', RMSprop()), ('adam', Adam())]
model = cd()
print(model.summary())
for a in activations:
for lr in learning_rates:
for ls in layer_sizes:
for name, op in optimizers:
model = cd(a, lr, ls, op)
h = model.fit_generator(input_generator(), samples_per_epoch=500, nb_epoch=5, verbose=0)
print(a, lr, ls, name, np.average(h.history.get('acc')[-10:])) #average last 10 accuracies
问题:
为什么我的预测结果会这样?我该如何解决这个问题? 似乎增加训练量会产生更好的结果,但即使给定标签数组的输入,仍需要大量时间才能达到 50% 的准确度。我怎样才能减少这个?
任何指针将不胜感激。
【问题讨论】:
-
可以分享一下训练进度吗?
-
数据很多。今晚我会尝试发布它的要点。运行也需要一段时间。你有什么具体的要求吗?
-
只是训练的演变(损失、指标等)。
fit的输出
标签: neural-network keras classification