керас: 98% точности, но NN всегда предсказывает одно и то же. Что может быть причиной? - PullRequest
1 голос
/ 22 февраля 2020

У нас есть следующая проблема при обучении модели DL для прогнозирования оценки кредита (классификация на 0,1 или 3).

Это шаги:

step1: Создать новый столбец «скоринг» (вывод)

conditions = [
(df2['Credit Score'] >= 0) & (df2['Credit Score'] < 1000),
(df2['Credit Score'] >= 1000) & (df2['Credit Score'] < 6000),
(df2['Credit Score'] >= 6000) & (df2['Credit Score'] <= 7000)]
choices = [0,1,2]
df2['Scoring'] = np.select(conditions, choices) 

шаг 2: подготовка обучения

array = df2.values
X = np.vstack((array[:,2:3].T, array[:,5:15].T)).T
Y = array[:,15:]
N = Y.shape[0]
T = np.zeros((N, np.max(Y)+1))
for i in range(N):
  T[i,Y[i]] = 1

x_train, x_test, y_train, y_test = train_test_split(X, T, test_size=0.2, random_state=42)

шаг 3: топология

model = Sequential()

model.add(Dense(80, input_shape=(11,), activation='tanh'))
model.add(Dropout(0.2))
model.add(Dense(80, activation='tanh'))
model.add(Dropout(0.1))
model.add(Dense(40, activation='relu'))
model.add(Dense(3, activation='softmax'))

epochs =200
learning_rate = 0.00001
decay_rate = learning_rate / epochs
momentum = 0.002
sgd = SGD(lr=learning_rate, momentum=momentum, decay=decay_rate, nesterov=False)
ad = Adamax(lr=learning_rate)

шаг 4: обучение

 epochs = 200 
 batch_size = 16 

 history = model.fit(x_train, y_train, validation_data=(x_test, y_test), nb_epoch=epochs, 
 batch_size=batch_size,validation_split=0.1) 
 print ('fit done!')

метрики

365/365 [============================ =======] - 0 с 60 мкс / образец - потеря: 0,0963 - cc: 0,9808 Тестовый набор Потеря: 0,096 Точность: 0,981

точность

step5: прогноз

text1 = [1358,1555,1,3,1741,8,0,1596,1518,0,0] #scoring 0 
text2 = [1454,1601,3,11,1763,10,0,685,1044,0,0] #scoring 1 
text3 = [1209,1437,3,11,199,18,1,761,1333,1,0] #scoring 2

tmp = np.vstack(text1).T
textA = tmp.reshape(1,-1)

tmp = np.vstack(text2).T
textB = tmp.reshape(1,-1)

tmp = np.vstack(text3).T
print(tmp)
textC = tmp.reshape(1,-1)

p = model.predict(textA)
t = p[0]
print(textA,np.argmax(t))


p = model.predict(textB)
t = p[0]
print(textB,np.argmax(t))

p = model.predict(textC)
t = p[0]
print(textC,np.argmax(t))

Проблема: выход всегда одинаков в прогнозе !!!

[9.9205679e-01 3.8634153e- 04 7.5568780e-03] [[1358 1555 1 3 1741 8 0 1596 1518 0 0]] 0 --- оценка 0

[0,9862417 0,00205712 0,01170125] [[1454 1601 3 11 1763 10 0 685 1044 0 0]] 0 --- оценка 0

[9.9251783e-01 2.5733517e-04 7.2247880e-03] [[1209 1437 3 11 199 18 1 761 1333 1 0]] 0 ---- оценка 0

¿в чем может быть причина такого поведения?

Заранее спасибо!

1 Ответ

0 голосов
/ 22 февраля 2020

У вас чрезвычайно несбалансированный набор данных. Хороший способ взглянуть на это: если всегда прогнозирование 0 дает вам точность 98%, то довольно рискованно (или должно быть очень очевидно) сказать, что что-то принадлежит другому классу. Каждый шаблон, который может найти NN, отличающий любой класс меньшинства от класса большинства (0), должен быть довольно уникальным, потому что даже при небольшом перекрытии стоимость непредсказания 0 слишком высока.

Рассмотрим этот пример: у вас есть набор данных с двумя классами, A и B, каждый из которых соответствует нормальному распределению. Класс A имеет среднее значение 1 и стандарт 1, класс B имеет среднее значение 3 и стандарт 0,1. У вас есть 1 000 000 выборок класса 0 и 20 000 выборок класса 1, поэтому прогнозирование всегда А дает вам точность 98%. Все образцы класса B будут l ie между 2,743 и 3,257 с вероятностью 99%. Между этими значениями ожидается, что класс A будет иметь 29 300 выборок, поэтому стоимость прогнозирования любого наблюдения, как класс B, допускает ошибку в 29 300 выборках A, но стоимость прогнозирования всего как A будет иметь ошибку только в 20 000 выборок B .

Вот как этот пример выглядит графически:

import numpy as np
import matplotlib.pyplot as plt

# Get A and B
A = np.random.normal(1, 1, 1000000)
B = np.random.normal(3, 0.1, 20000)

# Count the number of observations in A for each B
B.sort()
a = A[np.logical_and(A >= B.min(), A <= B.max())]
a = [(a<i).sum() for i in B]

# Plot results
plt.plot(B, np.arange(B.shape[0]), label='Class B')
plt.plot(B, a, label='Class A')
plt.ylabel('Count of samples')
plt.xlabel('Values')
plt.legend()
plt.show()

Unbalance example

См. Эту статью о балансировке наборов данных: https://www.kdnuggets.com/2017/06/7-techniques-handle-imbalanced-data.html

...