Базовая бинарная классификация с Керасом не работает - PullRequest
0 голосов
/ 18 декабря 2018

Я новичок в ML и хочу выполнить простейшую классификацию с помощью Keras: если y> 0,5, то label = 1 (x неважно), а y <0.5, затем label = 0 (x неважно) </p>

Насколько я понимаю, 1 нейрон с сигмовидной активацией может выполнять эту линейную классификацию.

import tensorflow.keras as keras
import math

import numpy as np
import matplotlib as mpl

train_data = np.empty((0,2),float)
train_labels = np.empty((0,1),float)


train_data = np.append(train_data, [[0, 0]], axis=0)
train_labels = np.append(train_labels, 0)

train_data = np.append(train_data, [[1, 0]], axis=0)
train_labels = np.append(train_labels, 0)

train_data = np.append(train_data, [[0, 1]], axis=0)
train_labels = np.append(train_labels, 1)

train_data = np.append(train_data, [[1, 1]], axis=0)
train_labels = np.append(train_labels, 1)


model = keras.models.Sequential()
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Dense(1, input_dim = 2, activation='sigmoid'))

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

model.fit(train_data, train_labels, epochs=20)

Обучение:

Epoch 1/5
4/4 [==============================] - 1s 150ms/step - loss: 0.4885 - acc: 0.7500
Epoch 2/5
4/4 [==============================] - 0s 922us/step - loss: 0.4880 - acc: 0.7500
Epoch 3/5
4/4 [==============================] - 0s 435us/step - loss: 0.4875 - acc: 0.7500
Epoch 4/5
4/4 [==============================] - 0s 396us/step - loss: 0.4869 - acc: 0.7500
Epoch 5/5
4/4 [==============================] - 0s 465us/step - loss: 0.4863 - acc: 0.7500

И предсказание не очень хорошее:

predict_data = np.empty((0,2),float)
predict_data = np.append(predict_data, [[0, 0]], axis=0)
predict_data = np.append(predict_data, [[1, 0]], axis=0)
predict_data = np.append(predict_data, [[1, 1]], axis=0)
predict_data = np.append(predict_data, [[1, 1]], axis=0)

predict_labels = model.predict(predict_data)
print(predict_labels)

[[0.49750862]
 [0.51616406]
 [0.774486  ]
 [0.774486  ]]

Как решить эту проблему?

В конце концов, я пытался тренировать модель на 2000 баллов (на мой взгляд, более чем достаточно для этой простой задачи), но безуспешно ...

train_data = np.empty((0,2),float)
train_labels = np.empty((0,1),float)

for i in range(0, 1000):
  train_data = np.append(train_data, [[i, 0]], axis=0)
  train_labels = np.append(train_labels, 0)
  train_data = np.append(train_data, [[i, 1]], axis=0)
  train_labels = np.append(train_labels, 1)

model = keras.models.Sequential()
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Dense(1, input_dim = 2, activation='sigmoid'))

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

model.fit(train_data, train_labels, epochs=5)

Epoch 1/5
2000/2000 [==============================] - 1s 505us/step - loss: 7.9669 - acc: 0.5005
Epoch 2/5
2000/2000 [==============================] - 0s 44us/step - loss: 7.9598 - acc: 0.5010
Epoch 3/5
2000/2000 [==============================] - 0s 45us/step - loss: 7.9511 - acc: 0.5010
Epoch 4/5
2000/2000 [==============================] - 0s 50us/step - loss: 7.9408 - acc: 0.5010
Epoch 5/5
2000/2000 [==============================] - 0s 53us/step - loss: 7.9279 - acc: 0.5015

<tensorflow.python.keras.callbacks.History at 0x7f4bdbdbda90>

Прогноз:

predict_data = np.empty((0,2),float)
predict_data = np.append(predict_data, [[0, 0]], axis=0)
predict_data = np.append(predict_data, [[1, 0]], axis=0)
predict_data = np.append(predict_data, [[1, 1]], axis=0)
predict_data = np.append(predict_data, [[1, 1]], axis=0)

predict_labels = model.predict(predict_data)
print(predict_labels)

[[0.6280617 ]
 [0.48020774]
 [0.8395983 ]
 [0.8395983 ]]

0,6280617 для (0,0) очень плохо.

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

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

sigmoid(w1*x1+w2+x2+b0) = y

Итак, с вашими тренировочными данными вы получите:

1) sigmoid(b0) = 0 => b0 = -infinite
2) sigmoid(w1+b0) = 0 => w1 = constant
3) sigmoid(w2+b0) = 1 => w2 >> |b0| (already starting to break...)
4) sigmoid(w1+w2+b0) = 1 => same as 3

Так что, по моему мнению, тренер начнет колебаться между 2и 3, начиная увеличиваться каждый на один выше, чем другой, и вы никогда не достигнете своего прогноза с этой моделью

И если вы посмотрите на точность 75%, это будет иметь смысл, потому что у вас есть 4 примера обучения и как указановыше одного прогноза будет невозможно, поэтому вы получите 3/4 соотв.

0 голосов
/ 18 декабря 2018

Установка вашей проблемы немного странная в том смысле, что у вас есть только четыре точки данных, но вы хотите узнать вес модели с градиентным спуском (или Адамом).Кроме того, batchnorm здесь не имеет смысла, поэтому я бы предложил удалить его.

Кроме того, ваша сеть прогнозирует числа от 0 до 1 («вероятности»), а не метки классов.Чтобы получить предсказанные метки классов, вы можете использовать model.predict_classes(predict_data) вместо model.predict().

Если вы новичок в ML и хотите поэкспериментировать с игрушечными наборами данных, вы также можете взглянуть на scikit-learn, библиотеку, которая реализует более традиционные алгоритмы ML, тогда как Keras специально для глубокого изучения.,Рассмотрим, например, логистическую регрессию, которая аналогична одиночному нейрону с сигмовидной активацией, но реализована с различными решателями в sklearn:

from sklearn.linear_model import LogisticRegression

model  = LogisticRegression()
model = model.fit(train_data, train_labels)
model.predict(predict_data)
> array([0., 0., 1., 1.])

На сайте scikit-learn есть множество примеров, иллюстрирующих эти разныеалгоритмы на игрушечных наборах данных.

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

import keras
import numpy as np
import matplotlib.pyplot as plt

# Generate toy dataset
train_data = np.random.randint(0, 2, size=(1000, 2))
# Add gaussian noise
train_data = train_data + np.random.normal(scale=2e-1, size=train_data.shape)
train_labels = (train_data[:, 1] > 0.5).astype(int)

# Visualize the data, color-coded by their classes
fig, ax = plt.subplots()
ax.scatter(train_data[:, 0], train_data[:, 1], c=train_labels)

enter image description here

# Train a simple neural net
model = keras.models.Sequential()
model.add(keras.layers.Dense(1, input_shape= (2,), activation='sigmoid'))
model.compile(optimizer='sgd', loss='binary_crossentropy', metrics=['accuracy'])

history = model.fit(train_data, train_labels, epochs=20)

Вы можете использовать объект истории, чтобы визуализировать, как потеря или точность развивались во время обучения:

fig, ax = plt.subplots()
ax.plot(history.history['acc'])

enter image description here

Наконец,протестируйте модель на некоторых тестовых данных:

from sklearn.metrics import accuracy_score
# Test on test data
test_data = np.random.randint(0, 2, size=(100, 2))
# Add gaussion noise
test_data = test_data + np.random.normal(scale=2e-1, size=test_data.shape)
test_labels = (test_data[:, 1] > 0.5).astype(int)

accuracy_score(test_labels, model.predict_classes(test_data[:, 1]))

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

# Use only second coordinate
model = keras.models.Sequential()
model.add(keras.layers.Dense(1, input_shape= (1,), activation='sigmoid'))
model.compile(optimizer='sgd', loss='binary_crossentropy', metrics=['accuracy'])

history = model.fit(train_data[:,1], train_labels, epochs=20)

Эта модель быстро достигает высокой точности: enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...