Как научить keras нейронную сеть решать sqrt - PullRequest
1 голос
/ 17 октября 2019

Я изучаю машинное обучение с python и keras. Я создал нейронную сеть для предсказания квадратного корня из четных целых чисел из диапазона {1, 4, 9, 16, 25, 36, ..., 100}. Я написал код для этого, но результаты далеки от истины (какое бы число я ни предоставил сети, оно предсказывает, что оно равно 1,0).

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

Вот код, который я написал до сих пор:

from numpy import loadtxt
from keras.models import Sequential
from keras.layers import Dense
from keras import optimizers

# laod dataset
# dataset = loadtxt('pima-indians-diabetes.csv', delimiter=',')
dataset = loadtxt('sqrt.csv', delimiter=',')

# split into input (X) and output (y) variables
X = dataset[:,0:1] * 1.0
y = dataset[:,1] * 1.0

# define the keras model
model = Sequential()
model.add(Dense(6, input_dim=1, activation='relu'))
model.add(Dense(1, activation='linear'))

# compile the keras model
opt = optimizers.adam(lr=0.01)
model.compile(loss='mean_squared_error', optimizer=opt, metrics=['accuracy'])

# fit the keras model on the dataset (CPU)
model.fit(X, y, epochs=150, batch_size=10, verbose=0)

# evaluate the keras model
_, accuracy = model.evaluate(X, y, verbose=0)
print('Accuracy: %.2f' % (accuracy*100))

# make class predictions with the model
predicitions = model.predict_classes(X)

# summarize the first 10 cases
for i in range(10):
    print('%s => %.2f (expected %.2f)' % (X[i].tolist(), predicitions[i], y[i]))

А вот набор данных:

1,1
4,2
9,3
16,4
25,5
36,6
49,7
64,8
81,9
100,10

Когда я запускаю эту сеть, я получаю следующие результаты:

[1.0] => 0.00 (expected 1.00)
[4.0] => 0.00 (expected 2.00)
[9.0] => 1.00 (expected 3.00)
[16.0] => 1.00 (expected 4.00)
[25.0] => 1.00 (expected 5.00)
[36.0] => 1.00 (expected 6.00)
[49.0] => 1.00 (expected 7.00)
[64.0] => 1.00 (expected 8.00)
[81.0] => 1.00 (expected 9.00)
[100.0] => 1.00 (expected 10.00)

Что я делаю не так?

1 Ответ

6 голосов
/ 17 октября 2019

Это проблема регрессии. Поэтому вы должны использовать model.predict() вместо model.predict_classes().

Набор данных также недостаточно велик. Однако вы можете получить некоторые разумные прогнозы с помощью следующего кода.

from numpy import loadtxt
from keras.models import Sequential
from keras.layers import Dense
from keras import optimizers

# laod dataset
# dataset = loadtxt('pima-indians-diabetes.csv', delimiter=',')
dataset = loadtxt('sqrt.csv', delimiter=',')

# split into input (X) and output (y) variables
X = dataset[:,0:1] * 1.0
y = dataset[:,1] * 1.0

# define the keras model
model = Sequential()
model.add(Dense(6, input_dim=1, activation='relu'))
model.add(Dense(10, activation='relu'))
model.add(Dense(1))

# compile the keras model
opt = optimizers.adam(lr=0.001)
model.compile(loss='mean_squared_error', optimizer=opt)

# fit the keras model on the dataset (CPU)
model.fit(X, y, epochs=1500, batch_size=10, verbose=0)

# evaluate the keras model
_, accuracy = model.evaluate(X, y, verbose=0)
print('Accuracy: %.2f' % (accuracy*100))

# make class predictions with the model
predicitions = model.predict(X)

# summarize the first 10 cases
for i in range(10):
    print('%s => %.2f (expected %.2f)' % (X[i].tolist(), predicitions[i], y[i]))

Вывод:

[1.0] => 1.00 (expected 1.00)
[4.0] => 2.00 (expected 2.00)
[9.0] => 3.32 (expected 3.00)
[16.0] => 3.89 (expected 4.00)
[25.0] => 4.61 (expected 5.00)
[36.0] => 5.49 (expected 6.00)
[49.0] => 6.52 (expected 7.00)
[64.0] => 7.72 (expected 8.00)
[81.0] => 9.07 (expected 9.00)
[100.0] => 10.58 (expected 10.00)

РЕДАКТИРОВАНИЕ:

As @desertnautв комментариях указано, что показатель accuracy не имеет значения в задаче регрессии. Поэтому в качестве метрики обычно используется пользовательское значение R_squared (коэффициент определения АКА). Значение R_squared представляет качество соответствия в регрессионной модели. Ниже приведен код для расчета R_squared.

def r_squared(y_true, y_pred):
    from keras import backend as K
    SS_res =  K.sum(K.square(y_true - y_pred)) 
    SS_tot = K.sum(K.square(y_true - K.mean(y_true))) 
    return ( 1 - SS_res/(SS_tot + K.epsilon()) )

Теперь вы можете скомпилировать модель с помощью:

model.compile(loss='mean_squared_error', optimizer=opt, metrics=[r_squared])
...