Почему я получаю плохой результат с Keras против случайного леса или knn? - PullRequest
1 голос
/ 15 апреля 2020

Я изучаю глубокое обучение с keras и пытаюсь сравнить результаты (точность) с алгоритмами машинного обучения (sklearn) (то есть random forest, k_neighbors)

Кажется, что с keras я получаю худшие результаты. Я работаю над простой проблемой классификации: iris dataset Мой код keras выглядит так:

samples = datasets.load_iris()
X = samples.data
y = samples.target
df = pd.DataFrame(data=X)
df.columns = samples.feature_names
df['Target'] = y

# prepare data
X = df[df.columns[:-1]]
y = df[df.columns[-1]]

# hot encoding
encoder = LabelEncoder()
y1 = encoder.fit_transform(y)
y = pd.get_dummies(y1).values

# split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3)

# build model
model = Sequential()
model.add(Dense(1000, activation='tanh', input_shape = ((df.shape[1]-1),)))
model.add(Dense(500, activation='tanh'))
model.add(Dense(250, activation='tanh'))
model.add(Dense(125, activation='tanh'))
model.add(Dense(64, activation='tanh'))
model.add(Dense(32, activation='tanh'))
model.add(Dense(9, activation='tanh'))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train)
score, acc = model.evaluate(X_test, y_test, verbose=0)

#results:
#score = 0.77
#acc = 0.711

Я устал добавлять слои и / или изменять количество единиц на слой и / или изменять функцию активации (на relu) кажется, что результат не выше 0,85.

С помощью sklearn random forest или k_neighbors Я получаю результат (для того же набора данных) выше 0,95.

  1. Чего мне не хватает?

  2. С sklearn я приложил мало усилий и получил хорошие результаты, а с keras у меня было много обновлений, но не так же хорошо, как sklearn результаты. почему это так?

  3. Как получить те же результаты с keras?

Ответы [ 2 ]

6 голосов
/ 15 апреля 2020

Короче говоря, вам нужно:

  1. Активации ReLU
  2. Упрощенная модель
  3. Мормализация данных
  4. Больше эпох

Подробно:

Первая проблема заключается в том, что в настоящее время мы никогда не используем activation='tanh' для промежуточных сетевых уровней. В таких задачах мы практически всегда используем activation='relu'.

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

Большие нейронные сети действительно процветают, когда у нас есть лотов данных, но в случае небольших наборов данных, таких как здесь, их выразительность и гибкость могут стать вместо этого, по сравнению с более простыми алгоритмами, такими как RF или k-nn.

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

И последнее, но не менее важное: вы, кажется, запускаете модель Keras только для одной эпохи (значение по умолчанию, если вы ничего не указали в model.fit); это несколько эквивалентно созданию случайного леса с одним деревом (что, кстати, все еще намного лучше, чем с одним деревом решений ).

В целом, со следующими изменениями в Ваш код:

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

model = Sequential()
model.add(Dense(150, activation='relu', input_shape = ((df.shape[1]-1),)))
model.add(Dense(150, activation='relu'))
model.add(Dense(y.shape[1], activation='softmax'))

model.fit(X_train, y_train, epochs=100)

и все остальное, как есть, мы получаем:

score, acc = model.evaluate(X_test, y_test, verbose=0)
acc
# 0.9333333373069763

Мы можем сделать лучше: использовать немного больше данных тренировки и расслаивать их, т. е.

X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size = 0.20, # a few more samples for training
                                                    stratify=y)

И с теми же эпохами модели и обучения вы можете получить совершенную точность 1,0 в тестовом наборе:

score, acc = model.evaluate(X_test, y_test, verbose=0)
acc
# 1.0

(детали могут отличаться из-за некоторой случайности, налагаемой по умолчанию в таких экспериментах).

1 голос
/ 15 апреля 2020

Добавление некоторого отсева может помочь вам повысить точность. См. документацию Tensorflow для получения дополнительной информации.

По сути, способ добавления слоя Dropout очень похож на способ добавления этих слоев Dense ().

model.add(Dropout(0.2)

Примечание : Параметр «0.2» подразумевает, что 20% соединений в слое случайно опускаются, чтобы уменьшить взаимозависимости между ними, что уменьшает переоснащение.

...