Kaggle competition: Titanic - Machine Learning from Disaster
<SOS> metric: categorizationaccuracy Kaggle data source: titanic-machine-learning-from-disaster<train_model>
warnings.filterwarnings('ignore' )
THRESHOLD = 0.35
class EpochMetricsCallback(keras.callbacks.Callback):
def on_train_begin(self, logs={}):
self.f1s = []
self.precisions = []
self.recalls = []
def on_epoch_end(self, epoch, logs={}):
predictions = self.model.predict(self.validation_data[0])
 predictions =(predictions > THRESHOLD ).astype(int)
 predictions = np.asarray(predictions)
 targets = self.validation_data[1]
f1 = metrics.f1_score(targets, predictions)
 precision = metrics.precision_score(targets, predictions)
 recall = metrics.recall_score(targets, predictions)
 print(" - F1 score: {0:.4f}, Precision: {1:.4f}, Recall: {2:.4f}" 
.format(f1, precision, recall))
self.f1s.append(f1)
 self.precisions.append(precision)
 self.recalls.append(recall)
 return
def display_model_history(history):
data = pd.DataFrame(data={'Train': history.history['loss'], 'Test': history.history['val_loss']})
 ax = sns.lineplot(data=data, palette="pastel", linewidth=2.5, dashes=False)
 ax.set(xlabel='Epoch', ylabel='Loss', title='Loss')
 sns.despine()
plt.show()
def display_model_epoch_metrics(epoch_callback):
data = pd.DataFrame(data = {
'F1': epoch_callback.f1s,
'Precision': epoch_callback.precisions,
'Recall': epoch_callback.recalls})
 sns.lineplot(data=data, palette='muted', linewidth=2.5, dashes=False)
 sns.despine()
plt.show()<prepare_x_and_y>
Xy_train = pd.read_csv(".. /input/titanic/train.csv", index_col="PassengerId")
 class CC:
def __init__(self, dataframe):
for col in dataframe.columns: setattr(self, col, col)
 cc = CC(Xy_train)
 X_train = Xy_train.drop(columns=[cc.Survived])
 y_train = Xy_train[cc.Survived]
X = pad_sequences(tokenizer.texts_to_sequences(question_texts),
maxlen=MAX_SEQUENCE_LENGTH)
 Y = question_targets
test_word_tokens = pad_sequences(tokenizer.texts_to_sequences(test_texts),
maxlen=MAX_SEQUENCE_LENGTH )<choose_model_class>
class GenericTransformer(BaseEstimator, TransformerMixin):

 def __init__(self, transformer, fitter=None):
self.transformer = transformer
self.fitter = fitter
def fit(self, X, y=None):
self.fit_val = None if self.fitter is None else self.fitter(X)
 return self
def transform(self, X):
return self.transformer(X)if self.fit_val is None else self.transformer(X, self.fit_val )
def make_model(filter_size, num_filters):
tokenized_input = Input(shape=(MAX_SEQUENCE_LENGTH,), name="tokenized_input")
 pretrained = Embedding(MAX_WORDS,
EMBEDDINGS_LOADED_DIMENSIONS,
weights=[pretrained_emb_weights],
trainable=False )(tokenized_input)
 pretrained = Reshape(( MAX_SEQUENCE_LENGTH, EMBEDDINGS_LOADED_DIMENSIONS, 1))(pretrained)
 pretrained = Dropout(0.1 )(pretrained)
 conv_0 = Conv2D(num_filters, kernel_size=(filter_size, EMBEDDINGS_LOADED_DIMENSIONS),
kernel_initializer='he_normal', activation='tanh' )(pretrained)
 maxpool_0 = MaxPool2D(pool_size=(MAX_SEQUENCE_LENGTH - filter_size + 1, 1))(conv_0)
 d0 = Dropout(0.15 )(maxpool_0)
 d0 = Dense(10 )(d0)
 x = Flatten()(d0)
 x = Dropout(0.3 )(x)
 x = BatchNormalization()(x)
 out = Dense(1, activation="sigmoid" )(x)
 model = Model(inputs=[tokenized_input], outputs=out)
 model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
 model.summary()
return model<split>
default_imputer = GenericTransformer(
 fitter = lambda X: {
col: "missing" if X[col].dtype == "object" else X[col].median() for col in X.columns},
transformer = lambda X, default_values:(
 X.assign(**{col: X[col].fillna(default_values[col])for col in X.columns})) , 
)
 assert not default_imputer.fit_transform(X_train ).isna().any().any()
filter_sizes = [1, 2, 3, 5]
num_filters = 45
test_predictions = []
kaggle_predictions = []
train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.025)
 for f in filter_sizes:
print("CNN MODEL WITH FILTER OF SIZE {0}".format(f))
epoch_callback = EpochMetricsCallback()
model = make_model(f, num_filters)
 x, val_x, y, val_y = train_test_split(train_X, train_Y, test_size=0.01)
 history = model.fit(
 x=x, y=y, validation_data=(val_x, val_y),
batch_size=512, epochs=23, callbacks=[epoch_callback], verbose=2)
 display_model_history(history)
 display_model_epoch_metrics(epoch_callback)
 kaggle_predictions.append(model.predict([test_word_tokens], batch_size=1024, verbose=2))
test_predictions.append(model.predict([test_X])) 
<save_to_csv>
class DummiesTransformer(BaseEstimator, TransformerMixin):

 def __init__(self, drop_first=False):
self.drop_first = drop_first
def fit_transform(self, x, y=None):
result = pd.get_dummies(x, drop_first=self.drop_first)
 self.output_cols = result.columns
return result
def fit(self, x, y = None):
self.fit_transform(x, y)
 return self
def transform(self, x):
x_dummies = pd.get_dummies(x, drop_first=self.drop_first)
 new_cols = set(x_dummies.columns)
 return pd.DataFrame({col: x_dummies[col] if col in new_cols else 0
for col in self.output_cols})
 add_dummies = DummiesTransformer()
assert(X_train.dtypes == "object" ).any()
assert not(add_dummies.fit_transform(X_train ).dtypes == "object" ).any()
avg = np.average(kaggle_predictions, axis=0)
 df_out = pd.DataFrame({"qid":df_test["qid"].values})
 df_out['prediction'] =(avg > THRESHOLD ).astype(int)
 df_out.to_csv("submission.csv", index=False )<save_to_csv>
drop_original = GenericTransformer(lambda X: X.drop(columns=X_train.columns))
assert len(drop_original.fit_transform(X_train ).columns)== 0
<define_variables>
feat_accumulator = pd.DataFrame()
model = RidgeClassifier(random_state=0)
 def test_features(label, isolated, combination, prev_label=None, extra_imputers=[]):
isolated_pipeline = make_pipeline(*extra_imputers, default_imputer, *isolated,
drop_original, add_dummies, model)
 iso_accuracy = cross_val_score(isolated_pipeline, X_train, y_train, cv=5 ).mean()
feat_accumulator.loc[label, "isolated"] = iso_accuracy
combo_pipeline = make_pipeline(*extra_imputers, default_imputer, *combination,
drop_original, add_dummies, model)
 combo_accuracy = cross_val_score(combo_pipeline, X_train, y_train, cv=5 ).mean()
feat_accumulator.loc[label, "combination"] = combo_accuracy
if prev_label is not None:
old_combo_accuracy = feat_accumulator.loc[prev_label, "combination"]
feat_accumulator.loc[label, "improvement"] = combo_accuracy - old_combo_accuracy
display(feat_accumulator)
 test_features("null", [add_const], [add_const] )
embed_size = 300
max_features = 95000
maxlen = 70<import_modules>
add_age = GenericTransformer(
 lambda X: X.assign(AGE_BINNED = pd.cut(
 X[cc.Age], [0,7,14,35,60,1000],
labels=["young child","child", "young adult", "adult", "old"])))
 test_features("age", [add_age], [add_age], "null" )
import os
import time
import numpy as np
import pandas as pd
from tqdm import tqdm
import math
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.model_selection import GridSearchCV, StratifiedKFold
from sklearn.metrics import f1_score, roc_auc_score
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.layers import Dense, Input, CuDNNLSTM, Embedding, Dropout, Activation, CuDNNGRU, Conv1D
from keras.layers import Bidirectional, GlobalMaxPool1D, GlobalMaxPooling1D, GlobalAveragePooling1D
from keras.layers import Input, Embedding, Dense, Conv2D, MaxPool2D, concatenate
from keras.layers import Reshape, Flatten, Concatenate, Dropout, SpatialDropout1D
from keras.optimizers import Adam
from keras.models import Model
from keras import backend as K
from keras.engine.topology import Layer
from keras import initializers, regularizers, constraints, optimizers, layers
from keras.layers import concatenate
from keras.callbacks import *<load_from_csv>
add_class = GenericTransformer(lambda X: X.assign(CLASS_BINNED=X[cc.Pclass].astype(str)))
 test_features("class", [add_class], [add_age, add_class], "age" )
def load_and_prec() :
train_df = pd.read_csv(".. /input/train.csv")
 test_df = pd.read_csv(".. /input/test.csv")
 print("Train shape : ",train_df.shape)
 print("Test shape : ",test_df.shape)
 train_X = train_df["question_text"].fillna("_
test_X = test_df["question_text"].fillna("_
tokenizer = Tokenizer(num_words=max_features)
 tokenizer.fit_on_texts(list(train_X))
train_X = tokenizer.texts_to_sequences(train_X)
 test_X = tokenizer.texts_to_sequences(test_X)
 train_X = pad_sequences(train_X, maxlen=maxlen)
 test_X = pad_sequences(test_X, maxlen=maxlen)
 train_y = train_df['target'].values
np.random.seed(2018)
 trn_idx = np.random.permutation(len(train_X))
train_X = train_X[trn_idx]
train_y = train_y[trn_idx]
return train_X, test_X, train_y, tokenizer.word_index<statistical_test>
class TicketSurvivalTransformer(BaseEstimator, TransformerMixin):

 def __init__(self, xy):
self.xy = xy
def fit(self, X, y=None):
X_with_survival = X.assign(Survived = self.xy.reindex(X.index)[cc.Survived])
 self.mean_survival = X_with_survival[cc.Survived].mean()
self.group_stats =(X_with_survival.groupby(cc.Ticket)[cc.Survived].agg(["count", "sum"]))
self.fit_X = X.copy()
return self
def transform(self, X):
X_with_survival = X.assign(Survived = self.xy.reindex(X.index)[cc.Survived])
 group_stats_by_passenger = self.group_stats.reindex(X[cc.Ticket].unique() , fill_value=0)
 X_counts = group_stats_by_passenger.loc[X[cc.Ticket]].set_index(X.index)
 is_overlap = np.array([x in self.fit_X.index for x in X.index])
 other_counts =(X_counts["count"]-1 ).where(is_overlap, X_counts["count"])
 other_survivor_count =(( X_counts["sum"] - self.xy[cc.Survived].reindex(X.index)) 
.where(is_overlap, X_counts["sum"]))
survival_fraction =(other_survivor_count + self.mean_survival)/(other_counts + 1)
 return X.assign(SurvivorFraction=survival_fraction)
 assert np.isclose(( TicketSurvivalTransformer(Xy_train ).fit(X_train.loc[:400])
.transform(X_train.loc[400:])["SurvivorFraction"].mean()),
Xy_train.loc[400:][cc.Survived].mean() , rtol=0.1 )
def load_glove(word_index):
EMBEDDING_FILE = '.. /input/embeddings/glove.840B.300d/glove.840B.300d.txt'
def get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')
 embeddings_index = dict(get_coefs(*o.split(" ")) for o in open(EMBEDDING_FILE))
all_embs = np.stack(embeddings_index.values())
 emb_mean,emb_std = all_embs.mean() , all_embs.std()
embed_size = all_embs.shape[1]
nb_words = min(max_features, len(word_index))
embedding_matrix = np.random.normal(emb_mean, emb_std,(nb_words, embed_size))
for word, i in word_index.items() :
if i >= max_features: continue
embedding_vector = embeddings_index.get(word)
 if embedding_vector is not None: embedding_matrix[i] = embedding_vector
return embedding_matrix
def load_fasttext(word_index):
EMBEDDING_FILE = '.. /input/embeddings/wiki-news-300d-1M/wiki-news-300d-1M.vec'
def get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')
 embeddings_index = dict(get_coefs(*o.split(" ")) for o in open(EMBEDDING_FILE)if len(o)>100)
 all_embs = np.stack(embeddings_index.values())
 emb_mean,emb_std = all_embs.mean() , all_embs.std()
embed_size = all_embs.shape[1]
nb_words = min(max_features, len(word_index))
embedding_matrix = np.random.normal(emb_mean, emb_std,(nb_words, embed_size))
for word, i in word_index.items() :
if i >= max_features: continue
embedding_vector = embeddings_index.get(word)
 if embedding_vector is not None: embedding_matrix[i] = embedding_vector
return embedding_matrix
def load_para(word_index):
EMBEDDING_FILE = '.. /input/embeddings/paragram_300_sl999/paragram_300_sl999.txt'
def get_coefs(word,*arr): return word, np.asarray(arr, dtype='float32')
 embeddings_index = dict(get_coefs(*o.split(" ")) for o in open(EMBEDDING_FILE, encoding="utf8", errors='ignore')if len(o)>100)
 all_embs = np.stack(embeddings_index.values())
 emb_mean,emb_std = all_embs.mean() , all_embs.std()
embed_size = all_embs.shape[1]
nb_words = min(max_features, len(word_index))
embedding_matrix = np.random.normal(emb_mean, emb_std,(nb_words, embed_size))
for word, i in word_index.items() :
if i >= max_features: continue
embedding_vector = embeddings_index.get(word)
 if embedding_vector is not None: embedding_matrix[i] = embedding_vector
return embedding_matrix<set_options>
add_tkt = TicketSurvivalTransformer(Xy_train)
 test_features("tkt", [add_tkt], [add_age, add_class, add_tkt], "class" )
class Attention(Layer):
def __init__(self, step_dim,
W_regularizer=None, b_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
self.supports_masking = True
self.init = initializers.get('glorot_uniform')
 self.W_regularizer = regularizers.get(W_regularizer)
 self.b_regularizer = regularizers.get(b_regularizer)
 self.W_constraint = constraints.get(W_constraint)
 self.b_constraint = constraints.get(b_constraint)
 self.bias = bias
self.step_dim = step_dim
self.features_dim = 0
super(Attention, self ).__init__(**kwargs)
 def build(self, input_shape):
assert len(input_shape)== 3
self.W = self.add_weight(( input_shape[-1],),
initializer=self.init,
name='{}_W'.format(self.name),
regularizer=self.W_regularizer,
constraint=self.W_constraint)
 self.features_dim = input_shape[-1]
if self.bias:
self.b = self.add_weight(( input_shape[1],),
initializer='zero',
name='{}_b'.format(self.name),
regularizer=self.b_regularizer,
constraint=self.b_constraint)
 else:
self.b = None
self.built = True
def compute_mask(self, input, input_mask=None):
return None
def call(self, x, mask=None):
features_dim = self.features_dim
step_dim = self.step_dim
eij = K.reshape(K.dot(K.reshape(x,(-1, features_dim)) ,
K.reshape(self.W,(features_dim, 1))),(-1, step_dim))
if self.bias:
eij += self.b
eij = K.tanh(eij)
 a = K.exp(eij)
 if mask is not None:
a *= K.cast(mask, K.floatx())
 a /= K.cast(K.sum(a, axis=1, keepdims=True)+ K.epsilon() , K.floatx())
 a = K.expand_dims(a)
 weighted_input = x * a
return K.sum(weighted_input, axis=1)
 def compute_output_shape(self, input_shape):
return input_shape[0], self.features_dim<choose_model_class>
test_features("sex", [add_sex], [add_age, add_class, add_tkt, add_sex], "tkt" )
class CyclicLR(Callback):

 def __init__(self, base_lr=0.001, max_lr=0.006, step_size=2000., mode='triangular',
gamma=1., scale_fn=None, scale_mode='cycle'):
super(CyclicLR, self ).__init__()
self.base_lr = base_lr
self.max_lr = max_lr
self.step_size = step_size
self.mode = mode
self.gamma = gamma
if scale_fn == None:
if self.mode == 'triangular':
self.scale_fn = lambda x: 1.
 self.scale_mode = 'cycle'
elif self.mode == 'triangular2':
self.scale_fn = lambda x: 1/(2.**(x-1))
self.scale_mode = 'cycle'
elif self.mode == 'exp_range':
self.scale_fn = lambda x: gamma**(x)
 self.scale_mode = 'iterations'
else:
self.scale_fn = scale_fn
self.scale_mode = scale_mode
self.clr_iterations = 0.
 self.trn_iterations = 0.
 self.history = {}
self._reset()
def _reset(self, new_base_lr=None, new_max_lr=None,
new_step_size=None):

 if new_base_lr != None:
self.base_lr = new_base_lr
if new_max_lr != None:
self.max_lr = new_max_lr
if new_step_size != None:
self.step_size = new_step_size
self.clr_iterations = 0.
 def clr(self):
cycle = np.floor(1+self.clr_iterations/(2*self.step_size))
x = np.abs(self.clr_iterations/self.step_size - 2*cycle + 1)
 if self.scale_mode == 'cycle':
return self.base_lr +(self.max_lr-self.base_lr)*np.maximum(0,(1-x)) *self.scale_fn(cycle)
 else:
return self.base_lr +(self.max_lr-self.base_lr)*np.maximum(0,(1-x)) *self.scale_fn(self.clr_iterations)
 def on_train_begin(self, logs={}):
logs = logs or {}
if self.clr_iterations == 0:
K.set_value(self.model.optimizer.lr, self.base_lr)
 else:
K.set_value(self.model.optimizer.lr, self.clr())
 def on_batch_end(self, epoch, logs=None):
logs = logs or {}
self.trn_iterations += 1
self.clr_iterations += 1
self.history.setdefault('lr', [] ).append(K.get_value(self.model.optimizer.lr))
self.history.setdefault('iterations', [] ).append(self.trn_iterations)
 for k, v in logs.items() :
self.history.setdefault(k, [] ).append(v)
 K.set_value(self.model.optimizer.lr, self.clr())
 def f1(y_true, y_pred):

 def recall(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(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
precision = precision(y_true, y_pred)
 recall = recall(y_true, y_pred)
 return 2*(( precision*recall)/(precision+recall+K.epsilon()))<define_search_model>
impute_age = TitleAgeImputer()
test_features("age_from_title", [add_age], [add_age, add_class, add_tkt, add_sex], "sex",
extra_imputers=[impute_age] )
def model_lstm_atten(embedding_matrix):
inp = Input(shape=(maxlen,))
x = Embedding(max_features, embed_size, weights=[embedding_matrix], trainable=False )(inp)
 x = SpatialDropout1D(0.1 )(x)
 x = Bidirectional(CuDNNLSTM(40, return_sequences=True))(x)
 y = Bidirectional(CuDNNGRU(40, return_sequences=True))(x)
 atten_1 = Attention(maxlen )(x)
 atten_2 = Attention(maxlen )(y)
 avg_pool = GlobalAveragePooling1D()(y)
 max_pool = GlobalMaxPooling1D()(y)
 conc = concatenate([atten_1, atten_2, avg_pool, max_pool])
 conc = Dense(16, activation="relu" )(conc)
 conc = Dropout(0.1 )(conc)
 outp = Dense(1, activation="sigmoid" )(conc)
 model = Model(inputs=inp, outputs=outp)
 model.compile(loss='binary_crossentropy', optimizer='adam', metrics=[f1])
 return model<predict_on_test>
final_model = RidgeClassifier(random_state=0)
 final_X_train = final_pipeline.fit_transform(X_train)
 cvscore = cross_val_score(final_model, final_X_train, y_train, cv=4)
 print(f"cv = {np.mean(cvscore)}:
{list(cvscore)}")
 final_model.fit(final_X_train, y_train)
 X_test = pd.read_csv(".. /input/titanic/test.csv", index_col="PassengerId")
 final_X_test = final_pipeline.transform(X_test)
 preds_test = final_model.predict(final_X_test)
 output = pd.DataFrame({'PassengerID': X_test.index,
'Survived': preds_test})
 file = 'submission.csv'
output.to_csv(file, index=False)
 print(f"Wrote predictions to '{file}'" )