我的模型权重(我将它们输出到weights_before.txt
和weights_after.txt
)在训练前后完全相同,也就是说,训练没有改变任何东西,没有进行任何拟合。
我的数据看起来像这样(我基本上希望模型预测特征的符号,如果特征为负数,结果为0,如果为正数,则为1):
,feature,zerosColumn,result0,-5,0,01,5,0,12,-3,0,03,5,0,14,3,0,15,3,0,16,-3,0,0...
我的方法简要总结如下:
- 加载数据。
- 按列将数据分割为
x
(特征)和y
(结果),然后按行将这两者分割为test
和validation
集合。 - 将这些集合转换为
TimeseriesGenerators
(在这个场景中不是必需的,但我希望这个设置能够工作,我看不出有任何理由不应该这样做)。 - 创建并编译一个简单的
Sequential
模型,包含几个Dense
层,最后一层的激活函数为softmax
,使用binary_crossentropy
作为损失函数。 - 训练模型…什么也没发生!
完整代码如下:
import kerasimport pandas as pdimport numpy as npnp.random.seed(570)TIMESERIES_LENGTH = 1TIMESERIES_SAMPLING_RATE = 1TIMESERIES_BATCH_SIZE = 1024TEST_SET_RATIO = 0.2 # the portion of total data to be used as test setVALIDATION_SET_RATIO = 0.2 # the portion of total data to be used as validation setRESULT_COLUMN_NAME = 'feature'FEATURE_COLUMN_NAME = 'result'def create_network(csv_path, save_model): before_file = open("weights_before.txt", "w") after_file = open("weights_after.txt", "w") data = pd.read_csv(csv_path) data[RESULT_COLUMN_NAME] = data[RESULT_COLUMN_NAME].shift(1) data = data.dropna() x = data.ix[:, 1:2] y = data.ix[:, 3] test_set_length = int(round(len(x) * TEST_SET_RATIO)) validation_set_length = int(round(len(x) * VALIDATION_SET_RATIO)) x_train_and_val = x[:-test_set_length] y_train_and_val = y[:-test_set_length] x_train = x_train_and_val[:-validation_set_length].values y_train = y_train_and_val[:-validation_set_length].values x_val = x_train_and_val[-validation_set_length:].values y_val = y_train_and_val[-validation_set_length:].values train_gen = keras.preprocessing.sequence.TimeseriesGenerator( x_train, y_train, length=TIMESERIES_LENGTH, sampling_rate=TIMESERIES_SAMPLING_RATE, batch_size=TIMESERIES_BATCH_SIZE ) val_gen = keras.preprocessing.sequence.TimeseriesGenerator( x_val, y_val, length=TIMESERIES_LENGTH, sampling_rate=TIMESERIES_SAMPLING_RATE, batch_size=TIMESERIES_BATCH_SIZE ) model = keras.models.Sequential() model.add(keras.layers.Dense(10, activation='relu', input_shape=(TIMESERIES_LENGTH, 1))) model.add(keras.layers.Dropout(0.2)) model.add(keras.layers.Dense(10, activation='relu')) model.add(keras.layers.Dropout(0.2)) model.add(keras.layers.Flatten()) model.add(keras.layers.Dense(1, activation='softmax')) for item in model.get_weights(): before_file.write("%s\n" % item) model.compile( loss=keras.losses.binary_crossentropy, optimizer="adam", metrics=[keras.metrics.binary_accuracy] ) history = model.fit_generator( train_gen, epochs=10, verbose=1, validation_data=val_gen ) for item in model.get_weights(): after_file.write("%s\n" % item) before_file.close() after_file.close()create_network("data/sign_data.csv", False)
你有什么想法吗?
回答:
问题在于你使用了softmax
作为最后一层的激活函数。实际上,softmax会将其输入标准化,使元素之和为1。因此,如果你在一个只有一个单元的层上使用它(即Dense(1,...)
),那么它总是会输出1。为了解决这个问题,将最后一层的激活函数改为sigmoid
,它会输出一个在(0,1)
范围内的值。