【问题标题】:Multiclass classification LSTM keras多类分类 LSTM keras
【发布时间】:2021-07-07 13:02:12
【问题描述】:

我一直在为多类分类问题编写 keras 代码。我会暴露我的问题。

我在单个 csv 文件中有一个数据集,其中包含以下形式的行

1.45    -10.09  1.02    1   0   0   0

前 3 列代表来自加速度计的 X、Y、Z 加速度。最后 4 列代表类标签。我有 4 节课

[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]

每个向量都是一个类标签,对应于单个手势(握手、旋转手、举手、非先前手势)

我想要的是有一个 LSTM 回顾前面的 N 个步骤(比如说 20 个),将 N 个 3D 向量 [X,Y,Z] 作为输入并在每个序列的末尾(由这 20 个 3D向量)吐出该序列属于我拥有的四个类别中的任何一个的概率。

问题1:根据我的理解,模型应该是“多对一”,对吗? 问题2:如何使用 keras API for python 实现这样的网络?

我是 keras 编码的新手,到目前为止我所做的是这段代码(我在 colab 工作):

    # load dataset
    from google.colab import files
    uploaded = files.upload()
    
    dataframe = pd.read_csv(io.BytesIO(uploaded['data_new.csv']), header=None)
    
  
    dataset = dataframe.values
    X = dataset[:,0:3].astype(float)
    Y = dataset[:,3:].astype(int)
    print(X.shape)
    print(Y.shape)
    model = Sequential()
    ...
    ...

打印语句的输出是:

(48886, 3)
(48886, 4)

我还会在这里发布数据集的一些行:

1.45    -10.09  1.02    1   0   0   0   
1.06    -10.13  1.06    1   0   0   0   
1.22    -10.09  1.02    1   0   0   0   
1.38    -10.05  1.06    1   0   0   0   
1.03    -10.25  1.18    1   0   0   0   
0.04    -10.17  1.11    1   0   0   0   
0.55    -9.57   1.30    1   0   0   0   
1.18    -9.38   1.26    1   0   0   0   
2.36    -9.22   0.35    1   0   0   0
...
... 

我必须以某种方式重塑输入吗?我真的卡住了,请帮帮我

编辑 我正在使用真实数据集尝试以下代码

dataframe = pd.read_csv(io.BytesIO(uploaded['data_new.csv']), header=None)

#dataframe = pandas.read_csv("iris.data", header=None)
dataset = dataframe.values
X = dataset[:,0:3].astype(float)
Y = dataset[:,3:].astype(int)

X_train = tf.expand_dims(X, axis=-1)


BATCH_SIZE = 20 
EPOCHS = 2 # Used less epochs for testing purposes

model = tf.keras.Sequential()
model.add(tf.keras.layers.LSTM(100, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(100, activation="relu"))
model.add(tf.keras.layers.Dense(4, activation="softmax"))
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
model.summary()
print("Fit the model on training data")
history = model.fit(X_train, Y, epochs=EPOCHS, batch_size=BATCH_SIZE, verbose=0)

sample_input = np.random.randint(0,100, size=(20, 3))
print(sample_input)
sample_input_reshaped = tf.expand_dims(sample_input, axis=1)
print(sample_input_reshaped.shape)
predictions = model.predict(sample_input_reshaped)
print('Model predictions', predictions)

我收到了这个错误

ValueError: Input 0 is incompatible with layer sequential_11: expected shape=(None, None, 1), found shape=(None, 1, 3)

【问题讨论】:

  • 是的!确切地说:)如何编码?

标签: python tensorflow keras lstm tf.keras


【解决方案1】:

我根据您拥有的数据的输入形状制作了一些虚拟数据,并运行了您需要的模型。你可以有一个比这更复杂的模型,但对于初学者来说这已经足够了。

import pandas as pd
import tensorflow as tf
import numpy as np
from sklearn.model_selection import train_test_split

# Dummy data 
X = pd.DataFrame(np.random.randint(0, 100, size=(48886, 3)), columns=list("ABC"))
y = pd.DataFrame(np.random.randint(0, 2, size=(48886, 4)), columns=list("abcd"))
assert X.shape == (48886, 3)
assert y.shape == (48886, 4)

# You would just need to add the code below to yours
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size=0.25)

X_train = tf.expand_dims(X_train, axis=1)
X_test = tf.expand_dims(X_test, axis=1)

BATCH_SIZE = 20 
EPOCHS = 2 # Used less epochs for testing purposes

model = tf.keras.Sequential()
model.add(tf.keras.layers.LSTM(100, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(100, activation="relu"))
model.add(tf.keras.layers.Dense(4, activation="softmax"))
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
model.summary()
print("Fit the model on training data")
history = model.fit(X_train, y_train, epochs=EPOCHS, batch_size=BATCH_SIZE, verbose=0)
print(f"History: {history.history}")
print("Evaluating on test data")
results = model.evaluate(X_test, y_test, batch_size=BATCH_SIZE)
print("test loss, test acc:", results)

sample_input = np.random.randint(0, 100, size=(20, 3))
sample_input_reshaped = tf.expand_dims(sample_input, axis=1)
predictions = model.predict(sample_input_reshaped)
print('Model predictions', predictions)
prediction_class = tf.argmax(predictions, axis=1)
print('Class of predictions', prediction_class)
most_frequent = np.bincount(prediction_class).argmax()
print('Most frequent class: ', most_frequent)

输出:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm (LSTM)                  (None, 100)               41600     
_________________________________________________________________
dropout (Dropout)            (None, 100)               0         
_________________________________________________________________
dense (Dense)                (None, 100)               10100     
_________________________________________________________________
dense_1 (Dense)              (None, 4)                 404       
=================================================================
Total params: 52,104
Trainable params: 52,104
Non-trainable params: 0
_________________________________________________________________
Fit the model on training data
2021-07-08 21:23:52.292396: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:176] None of the MLIR Optimization Passes are enabled (registered 2)
History: {'loss': [4.253803730010986, 7.2851409912109375], 'accuracy': [0.25578224658966064, 0.24983635544776917]}
Evaluating on test data
612/612 [==============================] - 1s 964us/step - loss: 15.3499 - accuracy: 0.2468
test loss, test acc: [15.3499116897583, 0.24676811695098877]
Model predictions [[6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.8483874e-03 9.9284607e-01 3.0563556e-04 2.0347565e-08]
 [6.7954701e-03 9.9290127e-01 3.0327393e-04 2.0033218e-08]
 [6.7954701e-03 9.9290127e-01 3.0327393e-04 2.0033218e-08]]
Class of predictions tf.Tensor([1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1], shape=(20,), dtype=int64)
Most frequent class: 1

【讨论】:

  • 好的....首先非常感谢!你实际上救了我的命。其次,假设我有一个没有标签的 20 个 3D 向量序列,我如何测试该序列是否正确分类并打印出每个类的概率?另外,expand_dims函数的作用是什么?
  • @MatteoSirizzotti 我现在更新了答案,它对一些随机 3D 向量进行预测,并输出原始预测和具有最佳预测的类。 tf.expandDims() 获取您拥有的 2D 输入并添加一个维度,使其成为 LSTM 所需的 3D。进行预测时也必须这样做,样本数据为(20,3),然后变为(1,20,3),您甚至可以使用tf.reshape(1, 20, 3)
  • 所以让我检查一下我是否理解正确:打印出的每个向量代表 20 个 3D 向量的每个序列属于每个类的概率。但是通过这种方式,我看到您已经生成了 100 个维度 (20, 3) 的随机样本。所以我应该有 5 个概率向量(100/20 = 5 个长度为 20 的 3D 向量序列)。我在困惑什么? p.s.你是最棒的!!
  • 在主答案中编辑,我收到错误
  • @MatteoSirizzotti 您需要按照我添加的代码将数据集拆分为训练和测试部分。实际上,我正在生成一个大小为 (20,3) 的矩阵,其值随机从 0 到 99,因此对此的预测会生成一个大小为 (20,4) 的矩阵,其中每一行包含基于索引的每个类的概率。
猜你喜欢
  • 2018-03-08
  • 2021-05-04
  • 1970-01-01
  • 2019-06-24
  • 2019-01-28
  • 2021-05-02
  • 2018-01-26
  • 1970-01-01
  • 2018-11-23
相关资源
最近更新 更多