Отображение разреженной категориальной точности некорректно.

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

Я новичок в области нейронных сетей и машинного обучения, поэтому, пожалуйста, помогите мне. Я пытаюсь воссоздать проблему многоклассовой классификации из статьи, которую читаю. В статье предоставлены точные матрицы и значения векторов смещения и доказано, почему точность составит 100%. Мои проблемы следующие:

  1. Я получаю примерно 75% точности вместо 100.
  2. Точность меняется с каждой эпохой, чего не должно происходить, так как мои веса фиксированы и не обучаемы.
  3. Я повторно передал обучающие данные по отдельности в “model.predict()” и сравнил с правильными предсказаниями, используя оператор if-else, в результате чего не было несовпадений, или, другими словами, обучающие данные классифицируются правильно, но, как я сказал ранее, точность показывается как 75%.

Вот фрагмент моего кода:

W1 = np.array([
    [0,1,-2,1],
    [1, -2, 1, 0],
    [0,-1, 2, -1],
    [-1,2,-1,0],

])
W1 = W1.T  

W2 = np.array([
    [-1, 1, -1,1],
    [1,-1,1,-1]
])
W2 = W2.T  

W3 = np.array([
    [1,0],
    [0,1],

])
W3 = W3.T  

model = Sequential([
    tf.keras.Input(shape=(4,)),

    Dense(4, activation='relu',
          kernel_initializer=tf.keras.initializers.Constant(W1),
          bias_initializer=tf.keras.initializers.Zeros(),
          trainable=False),


    Dense(2, activation='relu',
          kernel_initializer=tf.keras.initializers.Constant(W2),
          bias_initializer=tf.keras.initializers.Zeros(),
          trainable=False),

    Dense(2, activation='softmax',
          kernel_initializer=tf.keras.initializers.Constant(W3),
          bias_initializer=tf.keras.initializers.Zeros(),
          trainable=False, name="dense_2"),

])
model.compile(
    loss=tf.keras.losses.SparseCategoricalCrossentropy(),  # Используем разреженные метки (в целочисленной форме)
    optimizer=tf.keras.optimizers.Adam(0.01),
    metrics=['sparse_categorical_accuracy']
)
model.summary()

history = model.fit(
    X_train, r,  # Разреженные метки (в целочисленной форме)
    epochs=50,
    verbose=1

Здесь я генерирую и передаю обучающие данные, которые представляют собой вектор размером 4*1, который нужно отнести к классу 0 или 1.

for k in range(s-3):
  X = x[k:k+4]
  for i in range(4):
    if (X[i]>0.5):
      Y[i]=1
    elif (X[i]<-0.5):
      Y[i]=-1
    elif(X[i] == 0):
      Y[i]=0
    else:
      Y[i] = np.sin(1/X[i])
    X_test = Y.reshape(1, -1)
  Y_test = np.array([r[k]])
  predictions[k] = np.argmax(model.predict(X_test)) # Получаем класс с наибольшей вероятностью
temp = 0
for i in range(len(r)):  
    if r[i] != predictions[i]:
        temp += 1  # Более лаконичный способ увеличения
        print(i)
print(f"Всего несовпадений: {temp}")

Ниже приводится вывод:

16/16 ━━━━━━━━━━━━━━━━━━━━ 2s 29ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7555
Epoch 2/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 1s 15ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7378
Epoch 3/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7542 
Epoch 4/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 18ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7465
Epoch 5/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 11ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7733
Epoch 6/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 21ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7469
Epoch 7/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 16ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7343
Epoch 8/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 1s 13ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7215
Epoch 9/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 1s 14ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7699
Epoch 10/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7491
Epoch 11/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7632
Epoch 12/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7369
Epoch 13/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7303 
Epoch 14/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7539 
Epoch 15/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7530 
Epoch 16/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7466 
Epoch 17/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7461 
Epoch 18/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7393 
Epoch 19/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7397 
Epoch 20/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7583 
Epoch 21/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7446 
Epoch 22/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7507 
Epoch 23/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7242 
Epoch 24/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7238 
Epoch 25/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 6ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7826
Epoch 26/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7471 
Epoch 27/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7477 
Epoch 28/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7350 
Epoch 29/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7578 
Epoch 30/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7669 
Epoch 31/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7306 
Epoch 32/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7580 
Epoch 33/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7495 
Epoch 34/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7416 
Epoch 35/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7346 
Epoch 36/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7346 
Epoch 37/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7420 
Epoch 38/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7570 
Epoch 39/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7490 
Epoch 40/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 6ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7414
Epoch 41/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7496 
Epoch 42/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7323 
Epoch 43/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7517 
Epoch 44/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7747 
Epoch 45/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7309 
Epoch 46/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7513 
Epoch 47/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7577 
Epoch 48/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7466 
Epoch 49/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7546 
Epoch 50/50
16/16 ━━━━━━━━━━━━━━━━━━━━ 0s 4ms/step - loss: 0.6931 - sparse_categorical_accuracy: 0.7784 

И вывод по несовпадениям

Всего несовпадений: 0

Пожалуйста, помогите мне и дайте знать, в чем я ошибаюсь. Большое спасибо!

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

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

Теория

Сначала рассмотрим некоторые теоретические аспекты, которые могут быть важны в вашем случае.

  1. Инициализация слоев: Вы задали фиксированные веса и не используете обучаемые параметры в модели. Это значит, что ваша модель должна воспроизводить точно такие же результаты при каждом запуске, если данные и порядок их подачи неизменны. Однако, если есть хоть малейшее расхождение в инициализации или передаче данных, это может вызвать проблемы.

  2. Аугментация данных или порядок их подачи: Похоже, что ваш порядок батчей не меняется (так как веса фиксированы), и это единственный способ объяснить изменение во время каждой эпохи. Однако, вы могли бы случайно варьировать порядок батчей или тип данных.

  3. Использование метрики Sparse Categorical Accuracy: Ваша метрика точности основана на сравнении правильных классов (в виде целых чисел) с предсказанными. Если тип представления классов некорректен или не совпадает с форматами данных, это может привести к ошибкам в расчетах.

  4. Проблемы с разбиением на кластеры: Даже если модель показывает 100% точность при индивидуальной проверке, возможно, проблема кроется в способе упаковки данных в батчи. Если хотя бы в одном батче есть ошибка, средняя точность по всем батчам снизится.

Пример

После описания проблем, связаннных с возможными ошибками, давайте сравним это с конкретными примерами из вашего кода:

  1. Вы инициализируете слои Dense с фиксированными весами при помощи kernel_initializer=tf.keras.initializers.Constant(W1), bias_initializer=tf.keras.initializers.Zeros() и вы установили trainable=False. Это гарантирует, что веса не будут обновляться во время обучения. Однако если где-то произошла ошибка в передаче данных или если данные аугментируются, это может вызвать изменение точности.

  2. Порядок данные на вход: исполняемые, к примеру, вызовы model.fit() и model.predict() зависят от настроек по умолчанию и передают данный в разном порядке, что может вызвать различия в расчетах на каждом этапе.

Применение

На основе понимания теории и конкретных примеров, давайте перейдем к практическим рекомендациям и решениям:

  1. Проверка данных: Убедитесь, что данные, которые вы передаете в model.fit() и model.predict(), идентичны и имеют одинаковый порядок. Убедитесь также, что ваши метки классов (r) представлены в правильном формате (например, целые числа, начиная с 0 для SparseCategoricalCrossentropy).

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

  3. Использование других метрик для проверки: Добавление дополнительных проверок точности, других метрик или даже интерпретации ошибок, таких как confusion matrix, может дать больше информации о том, где проблемы возникают.

  4. Убедитесь, что порядок передачи батчей фиксирован: Даже если у вас установлено trainable=False, некоторые скрытые процессы могут случайно изменять порядок, например, если используется случайная разбивка батчей или при вызове shuffle=True.

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

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

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