Share |

суббота, 29 июля 2017 г.

Тренируем нейронную сеть для прогноза эффективности работников

На моем семинаре по аналитике есть задачка в 87 строк, где выходная переменная - эффективность работника (категориальная переменная их трех классов: 1 - звезда, 2 - середняк, 3 - лузер), а факторы - несколько шкал теста CPI (калифорнийский чего-то там) и пол. Все.
Данных мало, зато данные реальные реальной компании. Надеюсь, что этот датасет будет "ирисами" HR-аналитики.
Эту задачу я уже решал с помощью логистической регрессии, деревьев решений, случайными лесами, градиентным бустингом. Сегодня покажу код в Python, как настраивать нейронную сеть для этой задачи. На самом деле есть несколько подходов к созданию нейронной сети, отдельно можно пользоваться библиотекой Microsoft, можно было добавлять скрытые слои, можно было тренировать больше параметров, все можно было сделать. Я преследую цель показать просто шаблон, как можно тренировать модель использую sklearn обертку - в этом варианте есть одно очень важное преимущество - простота в тренировке параметров сетки.
Итак
Загружаем пакеты
import numpy
import pandas
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from keras.utils import np_utils
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline
from sklearn import model_selection, preprocessing, metrics
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV, ShuffleSplit
from sklearn.metrics import confusion_matrix
Закладываем воспроизводимость
seed = 7
numpy.random.seed(seed)

Загружаем данные (здесь уже простите, участники семинара сами могут достать этот датасет)
разбиваем на X, Y
dataset = df.values
X = dataset[:,0:7].astype(float)
Y = dataset[:,7]
Далее Y мы из формата (1,2, 3) превращаем в матрицу фиктивных переменных
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
# convert integers to dummy variables (i.e. one hot encoded)
dummy_y = np_utils.to_categorical(encoded_Y)

Собственно модель

# baseline model
def baseline_model():
    # create model
    model = Sequential()
    model.add(Dense(6, input_dim=7, kernel_initializer='normal', activation='relu'))
    model.add(Dense(3, kernel_initializer='normal', activation='sigmoid'))
    # Compile model
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model
Здесь model.add обозначает слой нейронной сети, input_dim - размерность входных данных (у нас 7 переменных: 6 шкал теста + пол), во втором слое model.add тройка обозначает размерность выходной переменной (у нас три возможных класса работников - звезды, середняки и лузеры).
Про остальные параметры рекомендую читать в специальной литературе. Далее разбиваем данные на трейн и тест сет
X_train,  X_test, y_train, y_test = model_selection.train_test_split(X, Y, test_size = 0.3,random_state = 12)
Задаем модель, кросс валидацию и параметры, которые требуется натренировать
# create model
model = KerasClassifier(build_fn=baseline_model, verbose=0)
cv = KFold(n_splits=3, shuffle=True, random_state=1)
# grid search epochs, batch size
epochs = [ 150, 170, 200, 250, 300, 350]
batches = [ 5, 10, 20, 25, 30]
param_grid = dict(epochs=epochs, batch_size=batches)
grid = GridSearchCV(estimator=model, param_grid=param_grid, cv = cv)
Эпохи в нейронной сети соответствуют n_estimators в бустинге или случайном лесе. Батчи - это размер выборки, на которой происходит обучение. Далее закладываем в сетку (grid) и обучаем.
%%time
grid_result = grid.fit(X_train, y_train)
({'batch_size': 5, 'epochs': 300}, 0.73333334922790527)
На тестовом сете точность почти один в один, хотя при датасете в 87 строк мы ни на что не можем надеяться)
confusion_matrix(y_test, grid_result.predict(X_test))
array([[ 9,  2,  0],
       [ 1, 11,  0],
       [ 1,  3,  0]])

В качестве визуализации confusion_matrix

Тренируем нейронную сеть для прогноза эффективности работников
В строках реальные значения, 1 - звезда, 2 - середняк, 3 - лузер, в колонках прогнозные значения. Заметно, что нейронная сеть не увидела лузеров.
Не вспомню уже ссылки на предыдущие решения этого кейса, но precision и recall для нейронной сети для звезд вполне сопоставимы для алгоритмов случайного леса и бустинга.
Но интересная штука: многослойный персептрон дает прогноз хуже, чем тот, что я использовал в примере. Дело даже не в хужести, а в том, что алгоритм все прогнозные значения загоняет в один класс, в нашем случае это класс середняков - он самый большой. Т.е. многослойный персептрон все прогнозные значения к одному классу причисляет. Если есть кто в теме, подскажите, что это за эффект?
И сравнил эти данные с данными библиотеки Microsoft CNTK - не увидел различий (причем, я говорю не о датасете в 87 строк, а проверил также на другой HR задачке в 1500 строк).

Понравился пост? 

и Вы захотите выразить мне благодарность, просто покликайте на директ рекламу ниже на странице - у вас это отнимет несколько секунд, а мне принесет немного денег.

Комментариев нет:

Отправить комментарий