Python 在二元分类问题中,Keras的准确率停留在50%

Python 在二元分类问题中,Keras的准确率停留在50%,python,tensorflow,machine-learning,keras,lstm,Python,Tensorflow,Machine Learning,Keras,Lstm,我想使用两种资产(BTC、eth)历史数据来预测第二天的价格。 历史数据包括OHLCV数据、市值和这两项资产的主导地位。因此,有一组数字数据。 对次日价格的预测将是二进制的(0或1),其中0表示价格将下降,1表示明天价格将上升。 以下是初始数据的屏幕截图: 最后一列值向上移动了-1。因此,今天的数据将用于查看第二天是绿色日还是红色日。 我使用MinMaxScaler缩放数据,如下所示: min_max_scaler = MinMaxScaler() clean_df_scaled = min_

我想使用两种资产(BTC、eth)历史数据来预测第二天的价格。
历史数据包括OHLCV数据、市值和这两项资产的主导地位。因此,有一组数字数据。
对次日价格的预测将是二进制的(0或1),其中0表示价格将下降,1表示明天价格将上升。

以下是初始数据的屏幕截图:

最后一列值向上移动了-1。因此,今天的数据将用于查看第二天是绿色日还是红色日。
我使用MinMaxScaler缩放数据,如下所示:

min_max_scaler = MinMaxScaler()
clean_df_scaled = min_max_scaler.fit_transform(all_data)
dataset = pd.DataFrame(clean_df_scaled)

#train test validation split
x_train, x_test, y_train, y_test = train_test_split(dataset.iloc[:, :15], dataset.iloc[:, 15], test_size=0.2)

x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size=0.2)

y_train = np.array(y_train, dtype=np.int)
y_test = np.array(y_test, dtype=np.int)
y_val = np.array(y_val, dtype=np.int)

x_train = np.reshape(np.asarray(x_train), (x_train.shape[0], x_train.shape[1], 1))
x_test = np.reshape(np.asarray(x_test), (x_test.shape[0], x_test.shape[1], 1))
x_val = np.reshape(np.asarray(x_val), (x_val.shape[0], x_val.shape[1], 1))
模型如下:

model = Sequential()
model.add(LSTM(64, input_shape=(x_train.shape[1], x_train.shape[2]), return_sequences=True))
model.add(LSTM(32))
model.add(Dense(8, input_dim=16, activation='relu'))
model.add(Dense(4, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

history = model.fit(x_train, y_train, epochs=100)

test_loss, test_acc = model.evaluate(x_val, y_val)
print('Test accuracy:', test_acc)
输出结果显示:

...
Epoch 98/100
24/24 [==============================] - 0s 12ms/step - loss: 0.6932 - accuracy: 0.4968
Epoch 99/100
24/24 [==============================] - 0s 12ms/step - loss: 0.6932 - accuracy: 0.4998
Epoch 100/100
24/24 [==============================] - 0s 13ms/step - loss: 0.6929 - accuracy: 0.5229
6/6 [==============================] - 1s 4ms/step - loss: 0.6931 - accuracy: 0.5027
Test accuracy: 0.5027027130126953
我不明白这里有什么问题!我也使用了softmax激活,但运气不好(我知道,我应该使用Sigmoid来实现这个)。
我甚至尝试移除LSTM层,只使用密集层。但还是没有运气。

附笔: 当我使用模型进行预测时:

predictions = model.predict(x_test)
它不返回二进制值,它返回如下浮点数:

...
[0.5089301 ],
       [0.5093736 ],
       [0.5081916 ],
       [0.50889516],
       [0.5077091 ],
       [0.5088633 ]], dtype=float32)

这正常吗?我应该根据平均值将其转换为二进制(0或1)吗?

以下答案基于您对获得
.predict
返回分数的好奇


当您通过
model.predict(x_测试)
时,它将为您提供矩阵,其中每一行表示这些输入进入
类别1的概率。这样,您就得到了
x_test
的每个实例进入
class 1
的概率

...
[0.5089301 ],
       [0.5093736 ],
       [0.5081916 ],
       [0.50889516],
       [0.5077091 ],
       [0.5088633 ]], dtype=float32)
为了获得二进制输出,通常我们设置一个阈值(比如0.5),大于该阈值的被视为
class 1
,小于该阈值的被视为
class 0
。因此,您可以执行以下操作以获得二进制输出(
1
0

这里,
0.5
是我们选择的阈值。查看更多详细信息。

Safari

我相信正如Horace Lee在一篇评论中指出的那样,问题出在
列车测试的分割上。但数据安排也有问题。在示例数据和
train\u test\u split
的使用方式上,每行代表一个样本,每列包含一个数据特征。但是,您试图建模的时间序列是按列编码的。当数据输入到模型中时,由于样本包含相同数据点的信息,因此不存在时间依赖关系。因此,LSTM层无法找到任何关系,因为序列相关性不是按行编码的

您可以按相同的比例分割数据,但不需要洗牌即可获取数据

x_train, x_test, y_train, y_test =dataset.iloc[0:int(len(dataset)*0.8), :15],dataset.iloc[0:int(len(dataset)*0.8), 15], dataset.iloc[int(len(dataset)*0.8):-1, :15],dataset.iloc[int(len(dataset)*0.8):-1, 15]
并在
model.fit中更改
shuffle=False
,以防止数据的任何混乱。这将在数据中保留序列依赖关系

此外,由于数据集中的每列都是一个时间序列,因此可以使用窗口方法对每个时间序列进行独立建模。只需一次一个窗口大小的片段,在数据中滑动一次

window_dataset=[dataset.iloc[k:k+window, “any feature column”] for k in range(int(len(dataset)*0.8))]

target=[dataset.iloc[k+window, 15] for k in range(int(len(dataset)*0.8))]
但在尝试LSTM体系结构之前,请尝试使用仅密集层的顺序模型或单层LSTM,并检查数据与
data['target\u header']的不平衡性。value\u counts()

获取连续的数据片段可以获取一个特定类的更多样本。

关于最后的问题,二进制分类器返回浮点值而不是二进制值是正常的,因为该分类器应该预测0到1之间的概率。Keras中的“准确度”度量是通过将任何高于0.5的值视为1,将任何低于0.5的值视为0来计算的。@HoraceLee谢谢,我搜索并发现它与您所说的一样。你对第一部分有什么想法吗?我想问题可能是
train\u test\u split()
函数会洗牌你的数据,这样序列的“连续性”就不会被保留,如果这有意义的话。也许可以尝试在调用
train\u test\u split()
时添加
shuffle=False
。(我在训练序列模型方面没有太多经验,所以我可能错了)我相信你不需要在密集层中使用
input\u dim
,你也尝试过只使用密集层的更复杂的网络?从损失来看,网络似乎根本没有学习。(0.6931是香草BCE AFAIK的最大值)。@Frifhtera我刚刚从第一个密集层中删除了
input\u dim
,它的精确度仍然为0.51。我不明白你的意思,尝试一个只有密集层的更复杂的网络?
window_dataset=[dataset.iloc[k:k+window, “any feature column”] for k in range(int(len(dataset)*0.8))]

target=[dataset.iloc[k+window, 15] for k in range(int(len(dataset)*0.8))]