Здесь мы использовали функциональный API Keras для создания моделей, которые более гибкие, чем tf.keras.Sequential
API. Функциональный API может обрабатывать модели с нелинейной топологией, модели с общими слоями и модели с несколькими входами или выходами.
столбцы 1-10 являются категориальными
def prepare_inputs(X_train, X_test):
from sklearn.preprocessing import OrdinalEncoder
oe = OrdinalEncoder()
oe.fit(X_train)
X_train_enc = oe.transform(X_train)
X_test_enc = oe.transform(X_test)
return X_train_enc, X_test_enc
def prepare_inputs(X_train, X_test):
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()
ohe.fit(X_train)
X_train_enc = ohe.transform(X_train)
X_test_enc = ohe.transform(X_test)
return X_train_enc, X_test_enc
Общие слои - это экземпляры слоев, которые многократно используются в одной и той же модели - они изучают функции, соответствующие нескольким путям в графе слоев. Общие слои часто используются для кодирования входных данных из одинаковых пространств (скажем, двух разных фрагментов текста с одинаковым словарем). Здесь он используется для обработки этой части:
столбцы 11-100 - это канал №1, а столбцы 101-190 - канал №1 (так что столбцы 11 и 101 являются та же функция, другой канал и т. д.).
Примечание: В этом коде я использовал несколько пользовательских функций, чтобы воспроизвести ваш вариант использования. Не стесняйтесь менять его при необходимости.
Модель 1
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.regularizers import l2
from tensorflow.keras.metrics import Precision
from tensorflow.keras import backend as K
from tensorflow.keras.utils import plot_model
# number of categories
categories = 10
# number of entries in data i.e. num of rows
entries = 1000
# Column 1-10: 10 categorical features
categorical = np.random.randint(categories, size=(entries, 10))
# Column 11-100: 90 numerical features
numerical1 = np.random.rand(entries, 90)
# Column 101-190: 90 numerical features
numerical2 = np.random.rand(entries, 90)
# output
output = np.random.rand(entries)
def f1_m(y_true, y_pred):
precision = precision_m(y_true, y_pred)
recall = recall_m(y_true, y_pred)
return 2*((precision*recall)/(precision+recall+K.epsilon()))
def recall_m(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
recall = true_positives / (possible_positives + K.epsilon())
return recall
def precision_m(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
precision = true_positives / (predicted_positives + K.epsilon())
return precision
def focal_loss(gamma=2., alpha=.25):
def focal_loss_fixed(y_true, y_pred):
pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))
pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))
pt_1 = K.clip(pt_1, 1e-3, .999)
pt_0 = K.clip(pt_0, 1e-3, .999)
return -K.sum(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1))-K.sum((1-alpha) * K.pow( pt_0, gamma) * K.log(1. - pt_0))
return focal_loss_fixed
def build(cat_shape, ch1_shape, ch2_shape):
cat_in = Input(shape=cat_shape, name='input1')
ch1_in = Input(shape=ch1_shape, name='input2')
ch2_in = Input(shape=ch2_shape, name='input3')
# model for categorical value inputs
cat_op1 = Dense(32, activation='tanh', activity_regularizer=l2(1e-2), name='cat_dense_1')(cat_in)
cat_op2 = Dense(16, activation='tanh', activity_regularizer=l2(1e-2), name='cat_dense_2')(cat_op1)
# defining keras shared layers for common features
shared_d1 = Dense(32, activation='tanh', activity_regularizer=l2(1e-2), name='shared_dense_1')
ch1_op1 = shared_d1(ch1_in)
ch2_op1 = shared_d1(ch2_in)
shared_d2 = Dense(16, activation='tanh', activity_regularizer=l2(1e-2), name='shared_dense_2')
ch1_op2 = shared_d2(ch1_op1)
ch2_op2 = shared_d2(ch2_op1)
# merging all the outputs
concat = tf.keras.layers.concatenate([cat_op2, ch1_op2, ch2_op2], name='concatenate')
pre = Dense(8, activation='tanh', activity_regularizer=l2(1e-2), name='dense_final_1')(concat)
out = Dense(1, activation='sigmoid', name='output')(pre)
# model with multiple inputs
model = Model(inputs=[cat_in, ch1_in, ch2_in],
outputs=out, name="EnhancedModel")
optimzier = tf.keras.optimizers.SGD(learning_rate=0.01, momentum=0.9, nesterov=True)
model.compile(loss=focal_loss(gamma=2), optimizer=optimzier, metrics = [f1_m, Precision(name='precision')])
return model
model = build(categorical.shape[1:], numerical1.shape[1:], numerical2.shape[1:])
model.fit([categorical, numerical1, numerical2], output, batch_size=4, epochs=5)
# plot_model(
# model,
# to_file='model.png',
# show_shapes=True,
# show_layer_names=True,
# rankdir='TB',
# expand_nested=True,
# dpi=96
# )
Обзор
Edit 1: As asked in the comments, changed the input vectors by concatenating categorical and numeric columns.
Model 2
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.regularizers import l2
from tensorflow.keras.metrics import Precision
from tensorflow.keras import backend as K
from tensorflow.keras.utils import plot_model
# number of categories
categories = 10
# number of entries in data i.e. num of rows
entries = 1000
# Column 1-10: 10 categorical features
categorical = np.random.randint(categories, size=(entries, 10))
# Column 11-100: 90 numerical features
numerical1 = np.random.rand(entries, 90)
# Column 101-190: 90 numerical features
numerical2 = np.random.rand(entries, 90)
# concatenating categorical and numeric vectors
cat_numerical1 = np.concatenate((categorical, numerical1), axis=-1)
cat_numerical2 = np.concatenate((categorical, numerical2), axis=-1)
# output
output = np.random.rand(entries)
def f1_m(y_true, y_pred):
precision = precision_m(y_true, y_pred)
recall = recall_m(y_true, y_pred)
return 2*((precision*recall)/(precision+recall+K.epsilon()))
def recall_m(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
recall = true_positives / (possible_positives + K.epsilon())
return recall
def precision_m(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
precision = true_positives / (predicted_positives + K.epsilon())
return precision
def focal_loss(gamma=2., alpha=.25):
def focal_loss_fixed(y_true, y_pred):
pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))
pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))
pt_1 = K.clip(pt_1, 1e-3, .999)
pt_0 = K.clip(pt_0, 1e-3, .999)
return -K.sum(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1))-K.sum((1-alpha) * K.pow( pt_0, gamma) * K.log(1. - pt_0))
return focal_loss_fixed
def build(ch1_shape, ch2_shape):
ch1_in = Input(shape=ch1_shape, name='input1')
ch2_in = Input(shape=ch2_shape, name='input2')
# defining keras shared layers for common features
shared_d1 = Dense(32, activation='tanh', activity_regularizer=l2(1e-2), name='shared_dense_1')
ch1_op1 = shared_d1(ch1_in)
ch2_op1 = shared_d1(ch2_in)
shared_d2 = Dense(16, activation='tanh', activity_regularizer=l2(1e-2), name='shared_dense_2')
ch1_op2 = shared_d2(ch1_op1)
ch2_op2 = shared_d2(ch2_op1)
# merging all the outputs
concat = tf.keras.layers.concatenate([ch1_op2, ch2_op2], name='concatenate')
pre = Dense(8, activation='tanh', activity_regularizer=l2(1e-2), name='dense_final_1')(concat)
out = Dense(1, activation='sigmoid', name='output')(pre)
# model with multiple inputs
model = Model(inputs=[ch1_in, ch2_in],
outputs=out, name="EnhancedModel")
optimzier = tf.keras.optimizers.SGD(learning_rate=0.01, momentum=0.9, nesterov=True)
model.compile(loss=focal_loss(gamma=2), optimizer=optimzier, metrics = [f1_m, Precision(name='precision')])
return model
model = build(cat_numerical1.shape[1:], cat_numerical2.shape[1:])
model.fit([cat_numerical1, cat_numerical2], output, batch_size=4, epochs=5)
plot_model(
model,
to_file='model.png',
show_shapes=True,
show_layer_names=True,
rankdir='TB',
expand_nested=True,
dpi=96
)
Обзор
введите описание изображения здесь Пожалуйста, дайте мне знать, работает ли это. Удачного кодирования!