Мультиклассовая классификация с использованием данных последовательности с LSTM Keras не работает - PullRequest
1 голос
/ 11 октября 2019

Я пытаюсь выполнить мультиклассовую классификацию последовательных данных, чтобы узнать, что является источником определенных событий на основе совокупного чтения источников.

Я использую простой слой LSTM с64 юнитов и плотный слой с тем же количеством юнитов, что и у целей. Модель, кажется, ничего не изучает, так как точность остается около 1% от всей мысли. def create_model (): model = Sequential ()

model.add(LSTM(64, return_sequences=False))

model.add(Dense(8))
model.add(Activation("softmax"))

model.compile(
    loss="categorical_crossentropy",
    optimizer=Adam(lr=0.00001),
    metrics=["accuracy"],
)

return model

Я пытался изменить скорость обучения на очень маленькие значения (0,001, 0,0001, 1e-5) и тренироваться для больших эпох, но изменений в точности не наблюдалось. Я что-то здесь упускаю? Неправильная предварительная обработка данных или создание модели?

Заранее спасибо за помощь.

Набор данных


Accumulated- Source-1   Source-2    Source-3  
Reading   
217             0       0       0  
205             0       0       0  
206             0       0       0  
231             0       0       0  
308             0       0       1  
1548            0       0       1  
1547            0       0       1  
1530            0       0       1  
1545            0       0       1  
1544            0       0       1   
1527            0       0       1  
1533            0       0       1  
1527            0       0       1  
1527            0       0       1  
1534            0       0       1  
1520            0       0       1  
1524            0       0       1  
1523            0       0       1  
205             0       0       0  
209             0       0       0  
.  
.  
.  

Я создалнабор данных скользящего окна с SEQ_LEN = 5 для подачи в сеть LSTM:


rolling_window                   labels
[205, 206, 217, 205, 206]       [0, 0, 0]
[206, 217, 205, 206, 231]       [0, 0, 0]
[217, 205, 206, 231, 308]       [0, 0, 1]
[205, 206, 231, 308, 1548]      [0, 0, 1]
[206, 231, 308, 1548, 1547]     [0, 0, 1]
[231, 308, 1548, 1547, 1530]    [0, 0, 1]
[308, 1548, 1547, 1530, 1545]   [0, 0, 1]
[1548, 1547, 1530, 1545, 1544]  [0, 0, 1]
[1547, 1530, 1545, 1544, 1527]  [0, 0, 1]
[1530, 1545, 1544, 1527, 1533]  [0, 0, 1]
[1545, 1544, 1527, 1533, 1527]  [0, 0, 1]
[1544, 1527, 1533, 1527, 1527]  [0, 0, 1]
[1527, 1533, 1527, 1527, 1534]  [0, 0, 1]
[1533, 1527, 1527, 1534, 1520]  [0, 0, 1]
[1527, 1527, 1534, 1520, 1524]  [0, 0, 1]
[1527, 1534, 1520, 1524, 1523]  [0, 0, 1]
[1534, 1520, 1524, 1523, 1520]  [0, 0, 1]
[1520, 1524, 1523, 1520, 205]   [0, 0, 0]
.  
.  
.

набор данных измененной формы

X_train = train_df.rolling_window.values
X_train = X_train.reshape(X_train.shape[0], 1, SEQ_LEN)

Y_train = train_df.labels.values
Y_train = Y_train.reshape(Y_train.shape[0], 3)

модель

def create_model():
    model = Sequential()

    model.add(LSTM(64, input_shape=(1, SEQ_LEN), return_sequences=True))
    model.add(Activation("relu"))

    model.add(Flatten())
    model.add(Dense(3))
    model.add(Activation("softmax"))

    model.compile(
        loss="categorical_crossentropy", optimizer=Adam(lr=0.01), metrics=["accuracy"]
    )

    return model

Обучение

model = create_model()
model.fit(X_train, Y_train, batch_size=512, epochs=5)

Обучение

Epoch 1/5
878396/878396 [==============================] - 37s 42us/step - loss: 0.2586 - accuracy: 0.0173
Epoch 2/5
878396/878396 [==============================] - 36s 41us/step - loss: 0.2538 - accuracy: 0.0175
Epoch 3/5
878396/878396 [==============================] - 36s 41us/step - loss: 0.2538 - accuracy: 0.0176
Epoch 4/5
878396/878396 [==============================] - 37s 42us/step - loss: 0.2537 - accuracy: 0.0177
Epoch 5/5
878396/878396 [==============================] - 38s 43us/step - loss: 0.2995 - accuracy: 0.0174

[EDIT-1]
После попытки предложений Макса, вот результаты (потери и точность все еще не меняются)

Предлагаемая модель

def create_model():
    model = Sequential()

    model.add(LSTM(64, return_sequences=False))

    model.add(Dense(8))
    model.add(Activation("softmax"))

    model.compile(
        loss="categorical_crossentropy",
        optimizer=Adam(lr=0.001),
        metrics=["accuracy"],
    )

    return model

X_train


array([[[205],
        [217],
        [209],
        [215],
        [206]],

       [[217],
        [209],
        [215],
        [206],
        [206]],

       [[209],
        [215],
        [206],
        [206],
        [211]],

       ...,

       [[175],
        [175],
        [173],
        [176],
        [174]],

       [[175],
        [173],
        [176],
        [174],
        [176]],

       [[173],
        [176],
        [174],
        [176],
        [173]]])

Y_train (PS: на самом деле существует 8 целевых классов. Приведенный выше пример был упрощением реальной проблемы)


array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]])

Тренировочный вывод

Epoch 1/5
878396/878396 [==============================] - 15s 17us/step - loss: 0.1329 - accuracy: 0.0190
Epoch 2/5
878396/878396 [==============================] - 15s 17us/step - loss: 0.1313 - accuracy: 0.0190
Epoch 3/5
878396/878396 [==============================] - 16s 18us/step - loss: 0.1293 - accuracy: 0.0190
Epoch 4/5
878396/878396 [==============================] - 16s 18us/step - loss: 0.1355 - accuracy: 0.0195
Epoch 5/5
878396/878396 [==============================] - 15s 18us/step - loss: 0.1315 - accuracy: 0.0236

[РЕДАКТИРОВАТЬ-2]
Исходя из предположений Макса и Марцина, ниже точность в основном остается ниже 3%. Хотя 1 из 10 раз он достигает 95% точности. Все зависит от того, какова точность в начале первой эпохи. Если он не запускает градиентный спуск в нужном месте, он не достигает хорошей точности. Нужно ли использовать другой инициализатор? Изменение скорости обучения не дает повторяемых результатов.

Предложения:
1. Масштабировать / нормализовать X_train (сделано)
2. Не изменять форму Y_train (сделано)
3. Имеет меньшиеюниты в слое LSTM (уменьшено с 64 до 16)
4. имеют меньший размер batch_size (уменьшено с 512 до 64)

масштабированный X_train

array([[[ 0.01060734],
        [ 0.03920736],
        [ 0.02014085],
        [ 0.03444091],
        [ 0.01299107]],

       [[ 0.03920728],
        [ 0.02014073],
        [ 0.03444082],
        [ 0.01299095],
        [ 0.01299107]],

       [[ 0.02014065],
        [ 0.0344407 ],
        [ 0.01299086],
        [ 0.01299095],
        [ 0.02490771]],

       ...,

       [[-0.06089251],
        [-0.06089243],
        [-0.06565897],
        [-0.05850889],
        [-0.06327543]],

       [[-0.06089251],
        [-0.06565908],
        [-0.05850898],
        [-0.06327555],
        [-0.05850878]],

       [[-0.06565916],
        [-0.0585091 ],
        [-0.06327564],
        [-0.05850889],
        [-0.06565876]]])

Не измененный Y_train

array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]])

Модель с меньшими единицами LSTM

def create_model():
    model = Sequential()

    model.add(LSTM(16, return_sequences=False))

    model.add(Dense(8))
    model.add(Activation("softmax"))

    model.compile(
        loss="categorical_crossentropy", optimizer=Adam(lr=0.001), metrics=["accuracy"]
    )

    return model

Тренировочный выход

Epoch 1/5
878396/878396 [==============================] - 26s 30us/step - loss: 0.1325 - accuracy: 0.0190
Epoch 2/5
878396/878396 [==============================] - 26s 29us/step - loss: 0.1352 - accuracy: 0.0189
Epoch 3/5
878396/878396 [==============================] - 26s 30us/step - loss: 0.1353 - accuracy: 0.0192
Epoch 4/5
878396/878396 [==============================] - 26s 29us/step - loss: 0.1365 - accuracy: 0.0197
Epoch 5/5
878396/878396 [==============================] - 27s 31us/step - loss: 0.1378 - accuracy: 0.0201

1 Ответ

0 голосов
/ 11 октября 2019

Последовательность должна быть первым измерением LSTM (2-й входной массив), то есть:

Измененный набор данных

X_train = train_df.rolling_window.values
X_train = X_train.reshape(X_train.shape[0], SEQ_LEN, 1)

Y_train = train_df.labels.values
Y_train = Y_train.reshape(Y_train.shape[0], 3)

Форма ввода:не требуется для LSTM. По умолчанию в LSTM включена активация «tanh», что обычно является хорошим вариантом.

Модель

def create_model():
    model = Sequential()

    model.add(LSTM(64, return_sequences=True))

    model.add(Flatten())
    model.add(Dense(3))
    model.add(Activation("softmax"))

    model.compile(loss="categorical_crossentropy", optimizer=Adam(lr=0.01), metrics=["accuracy"])

    return model

Может быть, лучше не использовать Flatten(), но использовать return_sequence = False для LSTM. Просто попробуйте.

Редактировать

Также попробуйте предварительную обработку с точки зрения масштабирования данных. Значения данных кажутся довольно большими.

...