Почему модель CNN не может хорошо выучить пик из данных

Вопрос или проблема

Здесь у меня есть два различных набора данных. dataset1 — это данные с платформы силы, а dataset2 — данные о подошвенном давлении. dataset1 имеет размер (2050,2), а dataset2 имеет размер(2050,89). Перед обучением я нормализовал данные, используя minmaxscaler() с масштабом от 0 до 1. После нормализации данных я выполнил предварительную обработку данных для dataset2, используя PCA. Здесь я собираюсь уменьшить размерность данных о подошвенном давлении до 12, так что текущий размер данных по подошвенному давлению составляет (2050,12).

Вот моя модель CNN:

import math
import numpy as np
import pandas as pd
import tensorflow as tf
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Activation, Dense, BatchNormalization, LeakyReLU, Conv2D, MaxPooling1D, Conv1D, Flatten, Dropout
from tensorflow.keras.losses import sparse_categorical_crossentropy
from tensorflow.keras.optimizers import Adam, RMSprop, SGD, Adadelta, Adagrad
from sklearn.decomposition import PCA
from sklearn.model_selection import KFold
from numpy import zeros, newaxis
from sklearn.feature_selection import mutual_info_regression
from sklearn.feature_selection import mutual_info_regression, SelectKBest
np.set_printoptions(suppress=True)
%matplotlib inline

Insole = pd.read_csv('1119_Rwalk40s2_list.txt', header=None, low_memory=False)
SIData = np.asarray(Insole)

df = pd.read_csv('1119_Rwalk40s2.csv', low_memory=False)
columns = ['Fx', 'Fz']
selected_df = df[columns]
FCDatas = selected_df[:2050]

SmartInsole = np.array(SIData[:2050])
FCData = np.array(FCDatas)

scaler_x = MinMaxScaler(feature_range=(0, 1))
scaler_x.fit(SmartInsole)
xscale = scaler_x.transform(SmartInsole)

scaler_y = MinMaxScaler(feature_range=(0, 1))
scaler_y.fit(FCData)
yscale = scaler_y.transform(FCData)

SIDataPCA = xscale
pca = PCA(n_components=0.99)
pca.fit(SIDataPCA)
SIdata_pca = pca.transform(SIDataPCA)

X_train, X_test, y_train, y_test = train_test_split(SIdata_pca, yscale, test_size=0.10, random_state=2)

model = Sequential()
model.add(Conv1D(64, kernel_size=2, strides=1, padding='same', data_format="channels_last", input_shape=(X_train.shape[1], 1)))
model.add(Activation('relu'))
model.add(MaxPooling1D(pool_size=2, strides=2))

model.add(Conv1D(32, kernel_size=2, strides=1, padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling1D(pool_size=2, strides=2))

model.add(Conv1D(16, kernel_size=2, strides=1, padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling1D(pool_size=2, strides=2))

model.add(LSTM(units=16))
model.add(Dense(16, activation='relu'))
model.add(Dense(2, activation='sigmoid'))

model.summary()

model.compile(loss="mse", optimizer=Adam(), metrics=['mse'])

history = model.fit(X_train, y_train, batch_size=64, epochs=50, 
                    validation_data=(X_test, y_test), verbose=2)

model.evaluate(SIdata_pca, yscale)
ypred = model.predict(SIdata_pca)

plt.figure()
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Потеря модели')
plt.ylabel('Потеря')
plt.xlabel('эпоха')
plt.legend(['обучение', 'валидация'], loc="upper right")
# plt.show()
plt.savefig('Результат потерь.png')


x = []
colors = ['red', 'green', 'brown', 'teal', 'gray', 'black', 'maroon', 'orange', 'purple']
colors2 = ['green', 'red', 'orange', 'black', 'maroon', 'teal', 'blue', 'gray', 'brown']
for i in range(0, 2050):
    x.append(i)
for i in range(0, 2):
    plt.figure(figsize=(15, 6))
    # plt.figure()
    plt.plot(x, yscale[0:2050, i], color=colors[i])
    plt.plot(x, ypred[0:2050, i], markerfacecolor="none", color=colors2[i])
    plt.title('Результат для регрессии ResNet')
    plt.ylabel('Y значение')
    plt.xlabel('Экземпляр')
    plt.legend(['Реальное значение', 'Прогнозируемое значение'], loc="upper right")
    plt.savefig('Результат регрессии.png'[i])
    plt.show()

Ниже приведен график потерь модели
введите описание изображения здесь

Смотря на потери модели на обучении, я не думаю, что есть какие-либо признаки переобучения в обучении, но почему моя модель не может предсказать высокие пики из обучающих данных?

Результаты предсказаний:
введите описание изображения здесь
введите описание изображения здесь

Я не знаю содержание данных, но вот несколько советов на основе моего прошлого опыта:

  • Цикл данных составляет около 100 шагов. В общем, размер партии должен быть около цикла данных, чтобы модель могла понять поведение циклов. То же самое касается слоя LSTM: я бы увеличил его размер. 16 нейронов может быть недостаточно, чтобы запомнить размер 100.
  • Я не знаю, может ли смешивание Conv1D и LSTM снизить точность предсказания, так как они очень разные: Conv1D запоминает формы, а LSTM запоминает динамику. Возможно, вам стоит попробовать сначала один тип.
  • Пики, похоже, очень короткие (2 или 3 шага). Я бы предложил шаг 1 с размером ядра 3, чтобы убедиться, что нейроны учатся на каждом шаге.
  • Макс-пулинг может сгладить ваши данные и уменьшить обнаружение пиков, поскольку он уменьшает значения до ближайших.
  • SGD или AdamW могут также дать лучшие результаты, чем Adam.
  • Модель, похоже, слишком быстро сходится. Уменьшение скорости обучения и увеличение количества итераций может улучшить результаты.
  • Если ваши данные имеют 50% значений 0 или 1, возможно, вы можете игнорировать их и проводить обучение только на значениях, которые имеют значение. Это улучшит результаты обучения, поскольку «бесполезные» данные могут повлиять на эффективность обучения.
  • Вам может потребоваться больше данных для обучения. Я не могу объяснить, почему тестовые данные не так хороши. В общем, хорошее обучение имеет хорошую точность (около 80%) для хорошей генерализации. Ваша ситуация может быть переобучением.

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

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

Ответ или решение

Ваши наблюдения о том, что модель CNN (сверточная нейронная сеть) не может точно предсказать высокие пики в данных, могут быть объяснены несколькими факторами. Давайте рассмотрим основные причины и возможные решения.

Причины плохой детекции пиков:

  1. Структура данных и размер выборки:

    • Размер ваших данных может быть недостаточным для тренировки сложной модели. Даже если у вас 2050 выборок, если высокие пики встречаются редко, модель может не обучаться на этих примерах должным образом.
  2. Комбинация Conv1D и LSTM:

    • Смешивание сверточных слоев (Conv1D) и слоев LSTM может вызвать трудности в обучении, поскольку эти архитектуры предназначены для обработки различных типов данных. Conv1D хорошо работает с фиксированными паттернами, в то время как LSTM лучше справляется с временными зависимостями. Попробуйте использовать одну архитектуру за раз, чтобы посмотреть, какая из них лучше подходит для ваших данных.
  3. Параметры свертки и подвыборка:

    • Ваши параметры свертки (kernel_size) и размер подвыборки (pool_size) могут быть слишком агрессивными. Когда вы используете Max Pooling, вы уменьшаете размерность данных, что может привести к потере информации о пиках. Попробуйте уменьшить размер свертки и использовать более мелкие шаги (strides).
  4. Скорость обучения:

    • Модель может сходиться слишком быстро, что не позволяет ей достигнуть оптимальных значений. Попробуйте уменьшить скорость обучения и увеличить количество итераций.
  5. Дисбаланс данных:

    • Если ваша выборка имеет большой процент значений, равных 0 или 1, возможно, стоит исключить их при обучении, чтобы сосредоточиться на более значимых данных, что может повысить качество обучения.
  6. Переобучение:

    • Даже если вы не наблюдаете явного переобучения, модель может иметь недостаточную способность к обобщению. Возможно, вам стоит исследовать методы регуляризации или попробовать более простые модели.
  7. Параметры LSTM:

    • Параметры LSTM, такие как число нейронов, также могут быть слишком малы. Увеличение числа нейронов может помочь LSTM лучше запоминать важные временные зависимости, особенно если циклы в ваших данных около 100 шагов.

Рекомендации по улучшению модели:

  1. Увеличьте размер обучающей выборки:

    • Постарайтесь получить больше данных, если это возможно, чтобы обеспечить лучшее обучение модели.
  2. Измените архитектуру модели:

    • Попробуйте использовать только Conv1D или LSTM, чтобы избежать проблем с комбинированной архитектурой. Это поможет лучше понять, какая структура лучше подходит для вашей задачи.
  3. Адаптируйте параметры обучения:

    • Экспериментируйте с параметрами, такими как размер батча, количество эпох и скорость обучения.
  4. Используйте методы предобработки данных:

    • Обратите внимание на аугментацию данных. Это может помочь в увеличении разнообразия примеров и улучшении обучения модели.
  5. Проведите анализ ошибок:

    • Посмотрите на случаи, когда модель ошибилась, и попробуйте понять, почему это произошло. Визуализация предсказаний на данных может помочь узнать больше о том, какие аспекты модели требуют доработки.

В целом, анализируя вашу проблему, можно понять, что необходимость более глубокого изучения структуры модели и данных — это ключ к решению задачи. Экспериментирование и настройка параметров также играют важную роль в достижении лучших результатов.

Оцените материал
Добавить комментарий

Капча загружается...