Вопрос или проблема
Я новичок в области нейронных сетей и машинного обучения, поэтому, пожалуйста, помогите мне. Я пытаюсь воссоздать проблему многоклассовой классификации из статьи, которую читаю. В статье предоставлены точные матрицы и значения векторов смещения и доказано, почему точность составит 100%. Мои проблемы следующие:
- Я получаю примерно 75% точности вместо 100.
- Точность меняется с каждой эпохой, чего не должно происходить, так как мои веса фиксированы и не обучаемы.
- Я повторно передал обучающие данные по отдельности в “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
Пожалуйста, помогите мне и дайте знать, в чем я ошибаюсь. Большое спасибо!
Ответ или решение
Причиной расхождения результатов в вашем коде может быть несколько факторов. Давайте внимательно рассмотрим каждый из них и постараемся выявить, что могло пойти не так.
Теория
Сначала рассмотрим некоторые теоретические аспекты, которые могут быть важны в вашем случае.
-
Инициализация слоев: Вы задали фиксированные веса и не используете обучаемые параметры в модели. Это значит, что ваша модель должна воспроизводить точно такие же результаты при каждом запуске, если данные и порядок их подачи неизменны. Однако, если есть хоть малейшее расхождение в инициализации или передаче данных, это может вызвать проблемы.
-
Аугментация данных или порядок их подачи: Похоже, что ваш порядок батчей не меняется (так как веса фиксированы), и это единственный способ объяснить изменение во время каждой эпохи. Однако, вы могли бы случайно варьировать порядок батчей или тип данных.
-
Использование метрики Sparse Categorical Accuracy: Ваша метрика точности основана на сравнении правильных классов (в виде целых чисел) с предсказанными. Если тип представления классов некорректен или не совпадает с форматами данных, это может привести к ошибкам в расчетах.
-
Проблемы с разбиением на кластеры: Даже если модель показывает 100% точность при индивидуальной проверке, возможно, проблема кроется в способе упаковки данных в батчи. Если хотя бы в одном батче есть ошибка, средняя точность по всем батчам снизится.
Пример
После описания проблем, связаннных с возможными ошибками, давайте сравним это с конкретными примерами из вашего кода:
-
Вы инициализируете слои Dense с фиксированными весами при помощи
kernel_initializer=tf.keras.initializers.Constant(W1)
,bias_initializer=tf.keras.initializers.Zeros()
и вы установилиtrainable=False
. Это гарантирует, что веса не будут обновляться во время обучения. Однако если где-то произошла ошибка в передаче данных или если данные аугментируются, это может вызвать изменение точности. -
Порядок данные на вход: исполняемые, к примеру, вызовы
model.fit()
иmodel.predict()
зависят от настроек по умолчанию и передают данный в разном порядке, что может вызвать различия в расчетах на каждом этапе.
Применение
На основе понимания теории и конкретных примеров, давайте перейдем к практическим рекомендациям и решениям:
-
Проверка данных: Убедитесь, что данные, которые вы передаете в
model.fit()
иmodel.predict()
, идентичны и имеют одинаковый порядок. Убедитесь также, что ваши метки классов (r
) представлены в правильном формате (например, целые числа, начиная с 0 дляSparseCategoricalCrossentropy
). -
Проверка инициализации весов: Подтвердите, что веса действительно инициализируются так, как вы намереваетесь. Возможно, стоит проверить непосредственную инициализацию каждого слоя вне контекста модели, чтобы убедиться, что весовая инициализация ведет к ожидаемым результатам.
-
Использование других метрик для проверки: Добавление дополнительных проверок точности, других метрик или даже интерпретации ошибок, таких как
confusion matrix
, может дать больше информации о том, где проблемы возникают. -
Убедитесь, что порядок передачи батчей фиксирован: Даже если у вас установлено
trainable=False
, некоторые скрытые процессы могут случайно изменять порядок, например, если используется случайная разбивка батчей или при вызовеshuffle=True
.
Если все эти шаги не приведут к решению, возможно, стоит рассмотреть возможность создания упрощенной версии вашего проекта, чтобы изолировать и диагностировать проблему более детально. В процессей диагностики может быть полезно использовать другие, более простые наборы данных для проверки согласованности работы вашей модели.