Kaggle competition: NFL Big Data Bowl
<SOS> metric: CRPS Kaggle data source: nfl-big-data-bowl<define_variables>
pd.set_option('display.max_columns', 50)
 pd.set_option('display.max_rows', 150)
 sns.set_style('darkgrid')
 mpl.rcParams['figure.figsize'] = [15,10]
NUM_TRAINING_IMAGES = int(count_data_items(TRAINING_FILENAMES)*(FOLDS-1.) /FOLDS)
 NUM_VALIDATION_IMAGES = int(count_data_items(TRAINING_FILENAMES)*(1./FOLDS))
NUM_TEST_IMAGES = count_data_items(TEST_FILENAMES)
 STEPS_PER_EPOCH = int(NUM_TRAINING_IMAGES/BATCH_SIZE)
 print('Dataset: {} training images, {} validation images, {} unlabeled test images'.format(NUM_TRAINING_IMAGES, NUM_VALIDATION_IMAGES, NUM_TEST_IMAGES))<prepare_x_and_y>
env = nflrush.make_env()
def cutmix(image, label, PROBABILITY = 1.0):
DIM = IMAGE_SIZE[0]
CLASSES = 104
imgs = []; labs = []
for j in range(AUG_BATCH):
P = tf.cast(tf.random.uniform([],0,1)<=PROBABILITY, tf.int32)
 k = tf.cast(tf.random.uniform([],0,AUG_BATCH),tf.int32)
 x = tf.cast(tf.random.uniform([],0,DIM),tf.int32)
 y = tf.cast(tf.random.uniform([],0,DIM),tf.int32)
 b = tf.random.uniform([],0,1)
 WIDTH = tf.cast(DIM * tf.math.sqrt(1-b),tf.int32)* P
ya = tf.math.maximum(0,y-WIDTH//2)
 yb = tf.math.minimum(DIM,y+WIDTH//2)
 xa = tf.math.maximum(0,x-WIDTH//2)
 xb = tf.math.minimum(DIM,x+WIDTH//2)
 one = image[j,ya:yb,0:xa,:]
two = image[k,ya:yb,xa:xb,:]
three = image[j,ya:yb,xb:DIM,:]
middle = tf.concat([one,two,three],axis=1)
 img = tf.concat([image[j,0:ya,:,:],middle,image[j,yb:DIM,:,:]],axis=0)
 imgs.append(img)
 a = tf.cast(WIDTH*WIDTH/DIM/DIM,tf.float32)
 if len(label.shape)==1:
lab1 = tf.one_hot(label[j],CLASSES)
 lab2 = tf.one_hot(label[k],CLASSES)
 else:
lab1 = label[j,]
lab2 = label[k,]
labs.append(( 1-a)*lab1 + a*lab2)
 image2 = tf.reshape(tf.stack(imgs),(AUG_BATCH,DIM,DIM,3))
label2 = tf.reshape(tf.stack(labs),(AUG_BATCH,CLASSES))
return image2,label2<categorify>
train = pd.read_csv('.. /input/nfl-big-data-bowl-2020/train.csv', dtype={'WindSpeed': 'object'} )
def mixup(image, label, PROBABILITY = 1.0):
DIM = IMAGE_SIZE[0]
CLASSES = 104
imgs = []; labs = []
for j in range(AUG_BATCH):
P = tf.cast(tf.random.uniform([],0,1)<=PROBABILITY, tf.float32)
 k = tf.cast(tf.random.uniform([],0,AUG_BATCH),tf.int32)
 a = tf.random.uniform([],0,1)*P
img1 = image[j,]
img2 = image[k,]
imgs.append(( 1-a)*img1 + a*img2)
 if len(label.shape)==1:
lab1 = tf.one_hot(label[j],CLASSES)
 lab2 = tf.one_hot(label[k],CLASSES)
 else:
lab1 = label[j,]
lab2 = label[k,]
labs.append(( 1-a)*lab1 + a*lab2)
 image2 = tf.reshape(tf.stack(imgs),(AUG_BATCH,DIM,DIM,3))
label2 = tf.reshape(tf.stack(labs),(AUG_BATCH,CLASSES))
return image2,label2<normalization>
train['Position'].value_counts()
def get_mat(rotation, shear, height_zoom, width_zoom, height_shift, width_shift):
rotation = math.pi * rotation / 180.
 shear = math.pi * shear / 180.
 c1 = tf.math.cos(rotation)
 s1 = tf.math.sin(rotation)
 one = tf.constant([1],dtype='float32')
 zero = tf.constant([0],dtype='float32')
 rotation_matrix = tf.reshape(tf.concat([c1,s1,zero, -s1,c1,zero, zero,zero,one],axis=0),[3,3])
 c2 = tf.math.cos(shear)
 s2 = tf.math.sin(shear)
 shear_matrix = tf.reshape(tf.concat([one,s2,zero, zero,c2,zero, zero,zero,one],axis=0),[3,3])
 zoom_matrix = tf.reshape(tf.concat([one/height_zoom,zero,zero, zero,one/width_zoom,zero, zero,zero,one],axis=0),[3,3])
 shift_matrix = tf.reshape(tf.concat([one,zero,height_shift, zero,one,width_shift, zero,zero,one],axis=0),[3,3])
 return K.dot(K.dot(rotation_matrix, shear_matrix), K.dot(zoom_matrix, shift_matrix))<normalization>
cat_features = []
int_features = []
float_features = []
bool_features = []
uint8_features = []
for col in train.columns:
if train[col].dtype =='object':
cat_features.append(( col, len(train[col].unique())))
 if train[col].dtype =='int64':
int_features.append(( col, len(train[col].unique())))
 if train[col].dtype =='float64':
float_features.append(( col, len(train[col].unique())))
 if train[col].dtype =='bool':
bool_features.append(( col, len(train[col].unique())))
 if train[col].dtype =='uint8':
uint8_features.append(( col, len(train[col].unique())))

print("{} Categorical Features found.".format(len(cat_features)))
 print("{} Integer Features found.".format(len(int_features)))
 print("{} Float Features found.".format(len(float_features)))
 print("{} Boolean Features found.".format(len(bool_features)))
 print("{} uint8 OneHot Features found.".format(len(uint8_features)) )
def apply_rotation(image,label):
DIM = IMAGE_SIZE[0]
XDIM = DIM%2
rot = 15.* tf.random.normal([1],dtype='float32')
 shr = 5.* tf.random.normal([1],dtype='float32')
 h_zoom = 1.0 + tf.random.normal([1],dtype='float32')/10.
 w_zoom = 1.0 + tf.random.normal([1],dtype='float32')/10.
 h_shift = 16.* tf.random.normal([1],dtype='float32')
 w_shift = 16.* tf.random.normal([1],dtype='float32')
 m = get_mat(rot,shr,h_zoom,w_zoom,h_shift,w_shift)
 x = tf.repeat(tf.range(DIM//2,-DIM//2,-1), DIM)
 y = tf.tile(tf.range(-DIM//2,DIM//2),[DIM])
 z = tf.ones([DIM*DIM],dtype='int32')
 idx = tf.stack([x,y,z])
 idx2 = K.dot(m,tf.cast(idx,dtype='float32'))
idx2 = K.cast(idx2,dtype='int32')
 idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)
 idx3 = tf.stack([DIM//2-idx2[0,], DIM//2-1+idx2[1,]])
 d = tf.gather_nd(image,tf.transpose(idx3))
return tf.reshape(d,[DIM,DIM,3]),label<categorify>
def convert_to_seconds(txt):
txt = txt.split(':')
 ans = int(txt[0])*60 + int(txt[1])+ int(txt[2])/60
return ans
CUTMIX = True
MIXUP = True
ROTATION = True
def transform(image,label):
DIM = IMAGE_SIZE[0]
CLASSES = 104
SWITCH = 0.5
CUTMIX_PROB = 0.666
MIXUP_PROB = 0.666
if CUTMIX and MIXUP:
image2, label2 = cutmix(image, label, CUTMIX_PROB)
 image3, label3 = mixup(image, label, MIXUP_PROB)
 imgs = []; labs = []
for j in range(AUG_BATCH):
P = tf.cast(tf.random.uniform([],0,1)<=SWITCH, tf.float32)
 imgs.append(P*image2[j,]+(1-P)*image3[j,])
 labs.append(P*label2[j,]+(1-P)*label3[j,])
 image4 = tf.reshape(tf.stack(imgs),(AUG_BATCH,DIM,DIM,3))
label4 = tf.reshape(tf.stack(labs),(AUG_BATCH,CLASSES))
return image4,label4
else:
return image, label<compute_test_metric>
def classify_offense_formation(txt):
if pd.isna(txt):
return "unknown"
txt = txt.lower()
if(txt.find("single")!= -1):
return "singleback"
elif(txt.find("shot")!= -1):
return "shotgun"
elif(txt.find("i_form")!= -1):
return "i_form"
elif(txt.find("pistol")!= -1):
return "pistol"
elif(txt.find("jumbo")!= -1):
return "jumbo"
elif(txt.find("wildcat")!= -1):
return "wildcat"
elif(txt.find("empty")!= -1):
return "empty"
elif(txt.find("ace")!= -1):
return "ace"
else:
return "unknown"
def FocalLoss(target, input):
gamma = 2.
 input = tf.cast(input, tf.float32)
 max_val = K.clip(-input, 0, 1)
 loss = input - input * target + max_val + K.log(K.exp(-max_val)+ K.exp(-input - max_val))
invprobs = tf.math.log_sigmoid(-input *(target * 2.0 - 1.0))
loss = K.exp(invprobs * gamma)* loss
return K.mean(K.sum(loss, axis=1))<choose_model_class>
offense_dict = {'DB' : "offense_DB", 'DL' : "offense_DL",
'LB' : "offense_LB", 'OL' : "offense_OL",
'QB' : "offense_QB", 'RB' : "offense_RB",
'TE' : "offense_TE", 'WR' : "offense_WR"}
def ProcessOffensePersonnel(row):
for whole_offense in row["OffensePersonnel"].split(","):
offense_item = whole_offense.strip().split(" ")
 if(offense_item[1] in offense_dict.keys()):
if offense_item[0].isdigit() :
row[offense_dict[offense_item[1]]] = int(offense_item[0])
 else:
row[offense_item[offense_item[1]]] = 0
else:
if offense_item[0].isdigit() :
row["offense_UNKNOWN"] += int(offense_item[0])
 else:
row["offense_UNKNOWN"] = 0
return row
def get_model(model_name):
with strategy.scope() :
if model_name == 'efn-b7':
efnet = efn.EfficientNetB7(input_shape=[512, 512, 3],
weights='noisy-student',
include_top=False)
 elif model_name == 'efn-b6':
efnet = efn.EfficientNetB6(input_shape=[512, 512, 3],
weights='noisy-student',
include_top=False)
 elif model_name == 'efn-b5':
efnet = efn.EfficientNetB5(input_shape=[512, 512, 3],
weights='noisy-student',
include_top=False)
 efnet.trainable = True
model = tf.keras.Sequential([
efnet,
tf.keras.layers.GlobalAveragePooling2D() ,
tf.keras.layers.Dense(len(CLASSES)) ,
tf.keras.layers.Activation("softmax", dtype='float32', name='predictions')
 ])
 model.compile(
 optimizer='adam',
loss = "categorical_crossentropy",
metrics=['categorical_accuracy',tfa.metrics.f_scores.F1Score(num_classes=104,average="macro")] 
)
 return model<init_hyperparams>
defense_dict = {'DB' : "defense_DB", 'DL' : "defense_DL",
'LB' : "defense_LB", 'OL' : "defense_OL"}
def ProcessDefensePersonnel(row):
for whole_defense in row["DefensePersonnel"].split(","):
defense_item = whole_defense.strip().split(" ")
 if(defense_item[1] in defense_dict.keys()):
if defense_item[0].isdigit() :
row[defense_dict[defense_item[1]]] = int(defense_item[0])
 else:
row[defense_dict[defense_item[1]]] = 0
else:
if defense_item[0].isdigit() :
row["defense_UNKNOWN"] += int(defense_item[0])
 else:
row["defense_UNKNOWN"] = 0
return row
if strategy.num_replicas_in_sync == 8:
start_lr = 0.00001
max_lr = 0.00005 * strategy.num_replicas_in_sync
min_lr = 0.00001
rampup_epochs = 5
sustain_epochs = 0
exp_decay =.8
elif strategy.num_replicas_in_sync == 1:
start_lr = 0.00001
min_lr = 0.00001
max_lr = 0.0002
rampup_epochs = 5
sustain_epochs = 0
exp_decay =.8
else:
start_lr = 0.00001
min_lr = 0.00001
max_lr = 0.00002 * strategy.num_replicas_in_sync
rampup_epochs = 7
sustain_epochs = 0
exp_decay =.8
def lrfn(epoch):
def lr(epoch, start_lr, min_lr, max_lr, rampup_epochs, sustain_epochs, exp_decay):
if epoch < rampup_epochs:
lr =(max_lr - start_lr)/rampup_epochs * epoch + start_lr
elif epoch < rampup_epochs + sustain_epochs:
lr = max_lr
else:
lr =(max_lr - min_lr)* exp_decay**(epoch-rampup_epochs-sustain_epochs)+ min_lr
return lr
return lr(epoch, start_lr, min_lr, max_lr, rampup_epochs, sustain_epochs, exp_decay)
 def get_callbacks(model_name):
if not os.path.exists(str(model_name)+"_callback_output"):
os.mkdir(str(model_name)+"_callback_output")
 lr_callback = tf.keras.callbacks.LearningRateScheduler(lambda epoch: lrfn(epoch), verbose=True)
 checkpoint = tf.keras.callbacks.ModelCheckpoint(str(model_name)+"_callback_output" + '/best.h5',
monitor = 'val_loss',
verbose = True, save_best_only=True,
mode = 'min',
save_weights_only = True)
 csv_logger = tf.keras.callbacks.CSVLogger(str(model_name)+"_callback_output" + '/log.csv')
 early = tf.keras.callbacks.EarlyStopping(monitor='val_loss', mode='min', patience=2,verbose=True)
 return [lr_callback, checkpoint, early, csv_logger]
rng = [i for i in range(25)]
y = [lrfn(x)for x in rng]
plt.plot(rng, [lrfn(x)for x in rng])
 print(y[0], y[-1] )<create_dataframe>
def classify_stadium_type(txt):
if pd.isna(txt):
return True
txt = txt.lower()
if(txt.find("ou")!= -1):
return True
if(txt.find("in")!= -1):
return False
if(txt.find("op")!= -1):
return True
if(txt.find("cl")!= -1):
return False
return True
def train_cross_validate(folds, model_name):
histories = []
models = []
kfold = KFold(folds, shuffle = True, random_state = SEED)
 for f,(trn_ind, val_ind)in enumerate(kfold.split(TRAINING_FILENAMES)) :
print() ; print('
train_dataset = load_dataset(list(pd.DataFrame({'TRAINING_FILENAMES': TRAINING_FILENAMES} ).loc[trn_ind]['TRAINING_FILENAMES']), labeled = True)
 val_dataset = load_dataset(list(pd.DataFrame({'TRAINING_FILENAMES': TRAINING_FILENAMES} ).loc[val_ind]['TRAINING_FILENAMES']), labeled = True, ordered = True)
 with strategy.scope() :
model = get_model(model_name)
 callbacks = get_callbacks(model_name)
 history = model.fit(
 get_training_dataset(train_dataset),
steps_per_epoch = STEPS_PER_EPOCH,
epochs = EPOCHS,
callbacks = callbacks,
validation_data = get_validation_dataset(val_dataset),
verbose=True 
)
 models.append(model)
 histories.append(history)
 tf.compat.v1.reset_default_graph()
del model
gc.collect()
if FIRST_FOLD_ONLY: break
return histories, models 
<find_best_model_class>
def classify_turf_type(txt):
if pd.isna(txt):
print("isna")
 return True
txt = txt.lower()
if(txt.find("gras")!= -1):
return True
if(txt.find("nat")!= -1):
return True
return False
def train_and_predict(folds, model_name):
test_ds = get_test_dataset(ordered=True)
 test_images_ds = test_ds.map(lambda image, idnum: image)
 print('Start training %i folds'%folds)
 histories, models = train_cross_validate(folds, model_name)
 print('Computing predictions...')
 if FIRST_FOLD_ONLY: probabilities = np.average([models[i].predict(test_images_ds)for i in range(1)], axis = 0)
 else: probabilities = np.average([models[i].predict(test_images_ds)for i in range(folds)], axis = 0)
 predictions = np.argmax(probabilities, axis=-1)
 print('Generating submission.csv file...')
 test_ids_ds = test_ds.map(lambda image, idnum: idnum ).unbatch()
test_ids = next(iter(test_ids_ds.batch(NUM_TEST_IMAGES)) ).numpy().astype('U')
 np.savetxt('submission.csv', np.rec.fromarrays([test_ids, predictions]), fmt=['%s', '%d'], delimiter=',', header='id,label', comments='')
 probs_df = pd.DataFrame(probabilities)
 probs_df['ID'] = test_ids
probs_df.to_csv('probs.csv',index=False)
 return histories, models<predict_on_test>
def new_X(x_coordinate, play_direction):
if play_direction == False:
return 120.0 - x_coordinate
else:
return x_coordinate
def new_orientation(angle, play_direction):
if play_direction == False:
new_angle = 360.0 - angle
if new_angle == 360.0:
return 0.0
else:
return new_angle
else:
if angle == 360.0:
return 0.0
else:
return angle
def line_of_scrimmage_in_coordinates(rush_team, field_position, yardline):
if rush_team == field_position:
return 10.0 + yardline
else:
return 60.0 +(50 - yardline)
 def euclidean_distance(x1,y1,x2,y2):
x_diff =(x1-x2)**2
y_diff =(y1-y2)**2
return np.sqrt(x_diff + y_diff)
 def is_looking_back(orientation):
if orientation > 180.0:
return True
else:
return False
def recalculate_yardline(df):
new_yardline = df[df['NflId'] == df['NflIdRusher']].copy()
new_yardline['YardLine'] = new_yardline[['PossessionTeam','FieldPosition','YardLine']].apply(lambda x: line_of_scrimmage_in_coordinates(x[0],x[1],x[2]), axis=1)
 new_yardline = new_yardline[['GameId','PlayId','YardLine']]
df = df.drop('YardLine', axis=1)
 df = pd.merge(df, new_yardline, on=['GameId','PlayId'], how='inner')
 return df
def recalculate_pos_and_dir(df):
df['X'] = df[['X','PlayDirection']].apply(lambda x: new_X(x[0],x[1]), axis=1)
 df['Orientation'] = df[['Orientation','PlayDirection']].apply(lambda x: new_orientation(x[0],x[1]), axis=1)
 df['Dir'] = df[['Dir','PlayDirection']].apply(lambda x: new_orientation(x[0],x[1]), axis=1)
 return df
model_name = 'efn-b7'
histories, models = train_and_predict(folds = FOLDS, model_name=model_name )<install_modules>
def features_relative_coordinates(df):
rusher_features = df[df['NflId'] == df['NflIdRusher']][['GameId','PlayId','NflIdRusher','X','Y','Orientation','Dir','YardLine']].copy()
rusher_features['rusher_yards_to_go'] = rusher_features['YardLine'] - rusher_features['X']
rusher_features['rusher_oriented_back'] = rusher_features['Orientation'].apply(lambda x: is_looking_back(x))
rusher_features['rusher_moving_back'] = rusher_features['Dir'].apply(lambda x: is_looking_back(x))
rusher_features = rusher_features.rename(columns={'X':'rusher_X', 'Y':'rusher_Y'})
 rusher_features = rusher_features[['GameId','PlayId','NflIdRusher','rusher_X','rusher_Y','rusher_yards_to_go',
'rusher_oriented_back','rusher_moving_back']]
player_distance = df[['GameId','PlayId','NflId','X','Y']].copy()
player_distance = pd.merge(player_distance, rusher_features, on=['GameId','PlayId'], how='inner')
 player_distance['dist_to_rusher'] = player_distance[['X','Y','rusher_X','rusher_Y']].apply(lambda x: euclidean_distance(x[0],x[1],x[2],x[3]), axis=1)
 player_distance = player_distance.groupby(['GameId','PlayId','rusher_yards_to_go','rusher_oriented_back','rusher_moving_back'])\ 
.agg({'dist_to_rusher':['min','max','mean','std']})\ 
.reset_index()
player_distance.columns = ['GameId','PlayId','rusher_yards_to_go','rusher_oriented_back','rusher_moving_back',
'min_dist','max_dist','mean_dist','std_dist']
df = pd.merge(player_distance,df,on=['GameId','PlayId'],how='inner')
 return df
def defense_features(df):
rusher = df[df['NflId'] == df['NflIdRusher']][['GameId','PlayId','Team','X','Y']].copy()
rusher.columns = ['GameId','PlayId','RusherTeam','RusherX','RusherY']
defense = pd.merge(df,rusher,on=['GameId','PlayId'],how='inner')
 defense = defense[defense['Team'] != defense['RusherTeam']][['GameId','PlayId','X','Y','RusherX','RusherY']]
defense['def_dist_to_rusher'] = defense[['X','Y','RusherX','RusherY']].apply(lambda x: euclidean_distance(x[0],x[1],x[2],x[3]), axis=1)
 defense = defense.groupby(['GameId','PlayId'])\ 
.agg({'def_dist_to_rusher':['min','max','mean','std']})\ 
.reset_index()
defense.columns = ['GameId','PlayId','def_min_dist','def_max_dist','def_mean_dist','def_std_dist']
df = pd.merge(defense,df,on=['GameId','PlayId'],how='inner')
 return df
def dist_to_rusher_features(df):
rusher = df[df['NflId'] == df['NflIdRusher']][['GameId','PlayId','X','Y']].copy()
rusher.columns = ['GameId','PlayId','RusherX','RusherY']
defense = pd.merge(df,rusher,on=['GameId','PlayId'],how='inner')
 defense = defense[['GameId','PlayId',"NflId",'X','Y','RusherX','RusherY']]
defense['dist_to_rusher'] = defense[['X','Y','RusherX','RusherY']].apply(lambda x: euclidean_distance(x[0],x[1],x[2],x[3]), axis=1)
 defense.drop(["X", "Y", "RusherX", "RusherY"], axis=1, inplace=True)
 df = pd.merge(defense,df,on=['GameId','PlayId',"NflId"],how='inner')
 return df
def calc_new_position(X, Y, S, A, Dir):
D1 = S + A/2
D3 = D1 + 2*S + 2*A
X1 = X + D1 * np.sin(Dir/180*np.pi)
 Y1 = Y + D1 * np.cos(Dir/180*np.pi)
 X3 = X + D3 * np.sin(Dir/180*np.pi)
 Y3 = Y + D3 * np.cos(Dir/180*np.pi)
 return X1, Y1, X3, Y3
def additional_time_series_features(df):
features = df[['GameId','PlayId','NflId','X','Y','S','A','Dir']].copy()
features[['X1sec', 'Y1sec', 'X3sec', 'Y3sec']] = features[['X','Y','S','A', 'Dir']].apply(lambda x: calc_new_position(x[0],x[1],x[2],x[3],x[4]), axis=1, result_type="expand")
 features.drop(["X", "Y", "S", "A", "Dir"], axis=1, inplace=True)
 df = pd.merge(features,df,on=['GameId','PlayId','NflId'],how='inner')
 return df
def line(p1, p2):
A =(p1[1] - p2[1])
 B =(p2[0] - p1[0])
 C =(p1[0]*p2[1] - p2[0]*p1[1])
 return A, B, -C
def calc_intersection(L1P1X, L1P1Y, L1P2X, L1P2Y, L2P1X, L2P1Y, L2P2X, L2P2Y):
L1 = line([L1P1X,L1P1Y],[L1P2X,L1P2Y])
 L2 = line([L2P1X,L2P1Y],[L2P2X,L2P2Y])
 D = L1[0] * L2[1] - L1[1] * L2[0]
Dx = L1[2] * L2[1] - L1[1] * L2[2]
Dy = L1[0] * L2[2] - L1[2] * L2[0]
if D != 0:
x = Dx / D
y = Dy / D
if(( x > L1P1X)and(x > L1P2X)) :
return False
elif(( x < L1P1X)and(x < L1P2X)) :
return False
elif(( x < L2P1X)and(x < L2P2X)) :
return False
elif(( x > L2P1X)and(x > L2P2X)) :
return False
else:
if(( y > L1P1Y)and(y > L1P2Y)) :
return False
elif(( y < L1P1Y)and(y < L1P2Y)) :
return False
if(( y > L2P1Y)and(y > L2P2Y)) :
return False
elif(( y < L2P1Y)and(y < L2P2Y)) :
return False
else:
return True
else:
return False
def calc_crossing_movements(df):
rusher_features = df[df['NflId'] == df['NflIdRusher']][['GameId','PlayId','X','Y','X1sec','Y1sec','X3sec','Y3sec']].copy()
rusher_features = rusher_features.rename(columns={'X':'rusher_X', 'Y':'rusher_Y', 'X1sec':'rusher_X1sec', 'Y1sec':'rusher_Y1sec', 'X3sec':'rusher_X3sec', 'Y3sec':'rusher_Y3sec'})
 features = df[['GameId','PlayId','NflId','X','Y','X1sec','Y1sec','X3sec','Y3sec']].copy()
features = pd.merge(features,rusher_features,on=['GameId','PlayId'],how='inner')
 df["CrossesWithin_1"] = features[['X','Y','X1sec','Y1sec','rusher_X','rusher_Y','rusher_X1sec','rusher_Y1sec']].apply(lambda x: calc_intersection(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7]), axis=1)
 df["CrossesWithin_3"] = features[['X','Y','X3sec','Y3sec','rusher_X','rusher_Y','rusher_X3sec','rusher_Y3sec']].apply(lambda x: calc_intersection(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7]), axis=1)
 return df
!pip install -q efficientnet<import_modules>
class CategoricalFeaturesProcessor(BaseEstimator, TransformerMixin):
def __init__(self):
pass
def fit(self, X):
return self
def transform(self, X):
X['Team'] = X['Team'].apply(lambda x: x.strip() =='home')
 X.drop(['DisplayName'], axis=1, inplace=True)
 X['GameClock'] = X['GameClock'].apply(convert_to_seconds)
 X["PossessionTeam"] = X["PossessionTeam"].replace("ARZ", "ARI")
 X["PossessionTeam"] = X["PossessionTeam"].replace("BLT", "BAL")
 X["PossessionTeam"] = X["PossessionTeam"].replace("CLV", "CLE")
 X["PossessionTeam"] = X["PossessionTeam"].replace("HST", "HOU")
 X["FieldPosition"] = X["FieldPosition"].replace("ARZ", "ARI")
 X["FieldPosition"] = X["FieldPosition"].replace("BLT", "BAL")
 X["FieldPosition"] = X["FieldPosition"].replace("CLV", "CLE")
 X["FieldPosition"] = X["FieldPosition"].replace("HST", "HOU")
 X["FieldPosition"] = X["FieldPosition"].replace(np.nan, "UNKNOWN")
 X['HomePossession'] = X['PossessionTeam'] == X['HomeTeamAbbr']
X['HomeField'] = X['FieldPosition'] == X['HomeTeamAbbr']
X['PossessionInOwnField'] = X['FieldPosition'] == X['PossessionTeam']
X = recalculate_yardline(X)
 X.drop(["PossessionTeam", "HomeTeamAbbr", "VisitorTeamAbbr", "FieldPosition"], axis=1, inplace=True)
 X["OffenseFormation"] = X["OffenseFormation"].replace(np.nan, "UNKNOWN")
 X['OffenseFormation'] = X['OffenseFormation'].apply(classify_offense_formation)
 X['off_form_singleback'] = X['OffenseFormation'] == "singleback"
X['off_form_shotgun'] = X['OffenseFormation'] == "shotgun"
X['off_form_i_form'] = X['OffenseFormation'] == "i_form"
X['off_form_pistol'] = X['OffenseFormation'] == "pistol"
X['off_form_jumbo'] = X['OffenseFormation'] == "jumbo"
X['off_form_wildcat'] = X['OffenseFormation'] == "wildcat"
X['off_form_empty'] = X['OffenseFormation'] == "empty"
X['off_form_ace'] = X['OffenseFormation'] == "ace"
X['off_form_unknown'] = X['OffenseFormation'] == "unknown"
X.drop(["OffenseFormation"], axis=1, inplace=True)
 offense_dict = {'DB' : "offense_DB", 'DL' : "offense_DL",
'LB' : "offense_LB", 'OL' : "offense_OL",
'QB' : "offense_QB", 'RB' : "offense_RB",
'TE' : "offense_TE", 'WR' : "offense_WR"}
for key in offense_dict.keys() :
X[offense_dict[key]] = np.zeros(( X.shape[0],1))
X["offense_UNKNOWN"] = np.zeros(( X.shape[0],1))
X = X.apply(ProcessOffensePersonnel, axis=1)
 defense_dict = {'DB' : "defense_DB", 'DL' : "defense_DL",
'LB' : "defense_LB", 'OL' : "defense_OL"}
for key in defense_dict.keys() :
X[defense_dict[key]] = np.zeros(( X.shape[0],1))
X["defense_UNKNOWN"] = np.zeros(( X.shape[0],1))
X = X.apply(ProcessDefensePersonnel, axis=1)
 X.drop(["OffensePersonnel", "DefensePersonnel"], axis=1, inplace=True)
 X['PlayDirection'] = X['PlayDirection'].apply(lambda x: x.strip() == 'right')
 X = recalculate_pos_and_dir(X)
 X = features_relative_coordinates(X)
 X = defense_features(X)
 X = dist_to_rusher_features(X)
 X = additional_time_series_features(X)
 X = calc_crossing_movements(X)
 X['TimeHandoff'] = X['TimeHandoff'].apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))
X['TimeSnap'] = X['TimeSnap'].apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))
X['PlayerBirthDate'] = X['PlayerBirthDate'].apply(lambda x: datetime.datetime.strptime(x, "%m/%d/%Y"))
X['TimeSnapToHandoff'] = X.apply(lambda row:(row['TimeHandoff'] - row['TimeSnap'] ).total_seconds() , axis=1)
 seconds_in_year = 60*60*24*365
X['PlayerAge'] = X.apply(lambda row:(row['TimeHandoff']-row['PlayerBirthDate'] ).total_seconds() /seconds_in_year, axis=1)
 X.drop(['TimeHandoff', 'TimeSnap', 'PlayerBirthDate'], axis=1, inplace=True)
 X['PlayerHeight'] = X['PlayerHeight'].apply(lambda x: 12*int(x.split('-')[0])+int(x.split('-')[1]))
X['PlayerBMI'] = 703*(X['PlayerWeight']/(X['PlayerHeight'])**2)
 X.drop(["PlayerCollegeName"], axis=1, inplace=True)
 X.drop(["Position"], axis=1, inplace=True)
 X.drop(["Stadium"], axis=1, inplace=True)
 X['StadiumType'] = X['StadiumType'].apply(classify_stadium_type)
 X['Turf'] = X['Turf'].apply(classify_turf_type)
 X.drop(["Location"], axis=1, inplace=True)
 X['GameWeather'] = X['GameWeather'].apply(classify_weather)
 X['weather_cloudy'] = X['GameWeather'] == "cloudy"
X['weather_sunny'] = X['GameWeather'] == "sunny"
X['weather_indoor'] = X['GameWeather'] == "indoor"
X['weather_rainy'] = X['GameWeather'] == "rainy"
X['weather_snow'] = X['GameWeather'] == "snow"
X.drop(["GameWeather"], axis=1, inplace=True)
 X.drop(["WindSpeed", "WindDirection"], axis=1, inplace=True)
 return X
cat_feat_processor = CategoricalFeaturesProcessor()
print("Tensorflow version " + tf.__version__)
 AUTO = tf.data.experimental.AUTOTUNE<set_options>
class NumericalFeatureProcessor(BaseEstimator, TransformerMixin):
def __init__(self):
pass
def fit(self, X):
return self
def transform(self, X):
X['IsRusher'] = X['NflId'] == X['NflIdRusher']
X.drop(['NflId', 'NflIdRusher'], axis=1, inplace=True)
 temp_train = X[X["IsRusher"]][["Team", "PlayId"]].rename(columns={"Team":"RusherTeam"})
 X = X.merge(temp_train, on = "PlayId")
 X["RusherTeam"] = X["Team"] == X["RusherTeam"]
X.drop(["Season", "Week"], axis=1, inplace=True)
 X['YardsLeft'] = X.apply(lambda row: 100-row['YardLine'] if row['HomeField'] else row['YardLine'], axis=1)
 X['YardsLeft'] = X.apply(lambda row: row['YardsLeft'] if row['PlayDirection'] else 100-row['YardsLeft'], axis=1)
 X["diffScoreBeforePlay"] = X["HomeScoreBeforePlay"] - X["VisitorScoreBeforePlay"]
X["Orientation"].fillna(0, inplace=True)
 X["Dir"].fillna(0, inplace=True)
 X["DefendersInTheBox"].fillna(train["DefendersInTheBox"].median() , inplace=True)
 X["Temperature"].fillna(train["Temperature"].mean() , inplace=True)
 X["Humidity"].fillna(train["Humidity"].mean() , inplace=True)
 X.fillna(-999, inplace=True)
 return X
num_feat_processor = NumericalFeatureProcessor()
try:
tpu = tf.distribute.cluster_resolver.TPUClusterResolver()
print('Running on TPU ', tpu.master())
 except ValueError:
tpu = None
if tpu:
tf.config.experimental_connect_to_cluster(tpu)
 tf.tpu.experimental.initialize_tpu_system(tpu)
 strategy = tf.distribute.experimental.TPUStrategy(tpu)
 else:
strategy = tf.distribute.get_strategy()
print("REPLICAS: ", strategy.num_replicas_in_sync )<train_model>
train[train["PlayId"] == 20170907000118]
GCS_DS_PATH = KaggleDatasets().get_gcs_path()
!gsutil ls $GCS_DS_PATH<define_variables>
train = cat_feat_processor.fit_transform(train)
 train = num_feat_processor.fit_transform(train)
 cat_features = []
int_features = []
float_features = []
bool_features = []
uint8_features = []
for col in train.columns:
if train[col].dtype =='object':
cat_features.append(( col, len(train[col].unique())))
 if train[col].dtype =='int64':
int_features.append(( col, len(train[col].unique())))
 if train[col].dtype =='float64':
float_features.append(( col, len(train[col].unique())))
 if train[col].dtype =='bool':
bool_features.append(( col, len(train[col].unique())))
 if train[col].dtype =='uint8':
uint8_features.append(( col, len(train[col].unique())))

print("{} columns in total".format(train.shape[1]))
print("{} Categorical Features found.".format(len(cat_features)))
 print("{} Integer Features found.".format(len(int_features)))
 print("{} Float Features found.".format(len(float_features)))
 print("{} Boolean Features found.".format(len(bool_features)))
 print("{} uint8 OneHot Features found.".format(len(uint8_features)))
 print("Integer Features:
{}".format(int_features))
print("Floating Features:
{}".format(float_features))
print("Boolean Features:
{}".format(bool_features))
print("Uint OneHot Features:
{}".format(uint8_features))
IMAGE_SIZE = [512, 512]
EPOCHS = 30
BATCH_SIZE = 32 * strategy.num_replicas_in_sync
GCS_PATH_SELECT = {
192: GCS_DS_PATH + '/tfrecords-jpeg-192x192',
224: GCS_DS_PATH + '/tfrecords-jpeg-224x224',
331: GCS_DS_PATH + '/tfrecords-jpeg-331x331',
512: GCS_DS_PATH + '/tfrecords-jpeg-512x512'
}
GCS_PATH = GCS_PATH_SELECT[IMAGE_SIZE[0]]
TRAINING_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/train/*.tfrec')
 VALIDATION_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/val/*.tfrec')
 TEST_FILENAMES = tf.io.gfile.glob(GCS_PATH + '/test/*.tfrec')
 CLASSES = ['pink primrose', 'hard-leaved pocket orchid', 'canterbury bells', 'sweet pea', 'wild geranium', 'tiger lily', 'moon orchid', 'bird of paradise', 'monkshood', 'globe thistle',
'snapdragon', "colt's foot", 'king protea', 'spear thistle', 'yellow iris', 'globe-flower', 'purple coneflower', 'peruvian lily', 'balloon flower', 'giant white arum lily',
'fire lily', 'pincushion flower', 'fritillary', 'red ginger', 'grape hyacinth', 'corn poppy', 'prince of wales feathers', 'stemless gentian', 'artichoke', 'sweet william',
'carnation', 'garden phlox', 'love in the mist', 'cosmos', 'alpine sea holly', 'ruby-lipped cattleya', 'cape flower', 'great masterwort', 'siam tulip', 'lenten rose',
'barberton daisy', 'daffodil', 'sword lily', 'poinsettia', 'bolero deep blue', 'wallflower', 'marigold', 'buttercup', 'daisy', 'common dandelion',
'petunia', 'wild pansy', 'primula', 'sunflower', 'lilac hibiscus', 'bishop of llandaff', 'gaura', 'geranium', 'orange dahlia', 'pink-yellow dahlia',
'cautleya spicata', 'japanese anemone', 'black-eyed susan', 'silverbush', 'californian poppy', 'osteospermum', 'spring crocus', 'iris', 'windflower', 'tree poppy',
'gazania', 'azalea', 'water lily', 'rose', 'thorn apple', 'morning glory', 'passion flower', 'lotus', 'toad lily', 'anthurium',
'frangipani', 'clematis', 'hibiscus', 'columbine', 'desert-rose', 'tree mallow', 'magnolia', 'cyclamen ', 'watercress', 'canna lily',
'hippeastrum ', 'bee balm', 'pink quill', 'foxglove', 'bougainvillea', 'camellia', 'mallow', 'mexican petunia', 'bromelia', 'blanket flower',
'trumpet creeper', 'blackberry lily', 'common tulip', 'wild rose']<categorify>
train[train["PlayId"] == 20170907000118]
np.set_printoptions(threshold=15, linewidth=80)
 def batch_to_numpy_images_and_labels(data):
images, labels = data
numpy_images = images.numpy()
numpy_labels = labels.numpy()
if numpy_labels.dtype == object:
numpy_labels = [None for _ in enumerate(numpy_images)]
return numpy_images, numpy_labels
def title_from_label_and_target(label, correct_label):
if correct_label is None:
return CLASSES[label], True
correct =(label == correct_label)
 return "{} [{}{}{}]".format(CLASSES[label], 'OK' if correct else 'NO', u"\u2192" if not correct else '',
CLASSES[correct_label] if not correct else ''), correct
def display_one_flower(image, title, subplot, red=False, titlesize=16):
plt.subplot(*subplot)
 plt.axis('off')
 plt.imshow(image)
 if len(title)> 0:
plt.title(title, fontsize=int(titlesize)if not red else int(titlesize/1.2), color='red' if red else 'black', fontdict={'verticalalignment':'center'}, pad=int(titlesize/1.5))
return(subplot[0], subplot[1], subplot[2]+1)
 def display_batch_of_images(databatch, predictions=None):

 images, labels = batch_to_numpy_images_and_labels(databatch)
 if labels is None:
labels = [None for _ in enumerate(images)]
rows = int(math.sqrt(len(images)))
 cols = len(images)//rows
FIGSIZE = 13.0
SPACING = 0.1
subplot=(rows,cols,1)
 if rows < cols:
plt.figure(figsize=(FIGSIZE,FIGSIZE/cols*rows))
else:
plt.figure(figsize=(FIGSIZE/rows*cols,FIGSIZE))
for i,(image, label)in enumerate(zip(images[:rows*cols], labels[:rows*cols])) :
title = '' if label is None else CLASSES[label]
correct = True
if predictions is not None:
title, correct = title_from_label_and_target(predictions[i], label)
 dynamic_titlesize = FIGSIZE*SPACING/max(rows,cols)*40+3
subplot = display_one_flower(image, title, subplot, not correct, titlesize=dynamic_titlesize)
 plt.tight_layout()
if label is None and predictions is None:
plt.subplots_adjust(wspace=0, hspace=0)
 else:
plt.subplots_adjust(wspace=SPACING, hspace=SPACING)
 plt.show()
def display_confusion_matrix(cmat, score, precision, recall):
plt.figure(figsize=(15,15))
ax = plt.gca()
ax.matshow(cmat, cmap='Reds')
 ax.set_xticks(range(len(CLASSES)))
 ax.set_xticklabels(CLASSES, fontdict={'fontsize': 7})
 plt.setp(ax.get_xticklabels() , rotation=45, ha="left", rotation_mode="anchor")
 ax.set_yticks(range(len(CLASSES)))
 ax.set_yticklabels(CLASSES, fontdict={'fontsize': 7})
 plt.setp(ax.get_yticklabels() , rotation=45, ha="right", rotation_mode="anchor")
 titlestring = ""
if score is not None:
titlestring += 'f1 = {:.3f} '.format(score)
 if precision is not None:
titlestring += '
precision = {:.3f} '.format(precision)
 if recall is not None:
titlestring += '
recall = {:.3f} '.format(recall)
 if len(titlestring)> 0:
ax.text(101, 1, titlestring, fontdict={'fontsize': 18, 'horizontalalignment':'right', 'verticalalignment':'top', 'color':'
plt.show()
def display_training_curves(training, validation, title, subplot):
if subplot%10==1:
plt.subplots(figsize=(10,10), facecolor='
plt.tight_layout()
ax = plt.subplot(subplot)
 ax.set_facecolor('
ax.plot(training)
 ax.plot(validation)
 ax.set_title('model '+ title)
 ax.set_ylabel(title)
 ax.set_xlabel('epoch')
 ax.legend(['train', 'valid.'] )<categorify>
train["CrossesWithin_1"].value_counts()
def decode_image(image_data):
image = tf.image.decode_jpeg(image_data, channels=3)
 image = tf.cast(image, tf.float32)/ 255.0
image = tf.reshape(image, [*IMAGE_SIZE, 3])
 return image
def read_labeled_tfrecord(example):
LABELED_TFREC_FORMAT = {
"image": tf.io.FixedLenFeature([], tf.string),
"class": tf.io.FixedLenFeature([], tf.int64),
}
example = tf.io.parse_single_example(example, LABELED_TFREC_FORMAT)
 image = decode_image(example['image'])
 label = tf.cast(example['class'], tf.int32)
 return image, label
def read_unlabeled_tfrecord(example):
UNLABELED_TFREC_FORMAT = {
"image": tf.io.FixedLenFeature([], tf.string),
"id": tf.io.FixedLenFeature([], tf.string),
}
example = tf.io.parse_single_example(example, UNLABELED_TFREC_FORMAT)
 image = decode_image(example['image'])
 idnum = example['id']
return image, idnum
def load_dataset(filenames, labeled=True, ordered=False):
ignore_order = tf.data.Options()
if not ordered:
ignore_order.experimental_deterministic = False
dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTO)
 dataset = dataset.with_options(ignore_order)
 dataset = dataset.map(read_labeled_tfrecord if labeled else read_unlabeled_tfrecord, num_parallel_calls=AUTO)
 return dataset
def data_augment(image, label):
image = tf.image.random_flip_left_right(image)
 image = tf.image.random_flip_up_down(image)
 image = tf.image.central_crop(image, central_fraction=0.9)
 image = tf.image.resize(image, [*IMAGE_SIZE])
 return image, label
def get_training_dataset() :
dataset = load_dataset(TRAINING_FILENAMES+VALIDATION_FILENAMES, labeled=True)
 dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
 dataset = dataset.repeat()
dataset = dataset.shuffle(2040)
 dataset = dataset.batch(BATCH_SIZE)
 dataset = dataset.prefetch(AUTO)
 return dataset
def get_validation_dataset(ordered=False):
dataset = load_dataset(VALIDATION_FILENAMES, labeled=True, ordered=ordered)
 dataset = dataset.batch(BATCH_SIZE)
 dataset = dataset.cache()
dataset = dataset.prefetch(AUTO)
 return dataset
def get_test_dataset(ordered=False):
dataset = load_dataset(TEST_FILENAMES, labeled=False, ordered=ordered)
 dataset = dataset.batch(BATCH_SIZE)
 dataset = dataset.prefetch(AUTO)
 return dataset
def count_data_items(filenames):
n = [int(re.compile(r"-([0-9]*)\." ).search(filename ).group(1)) for filename in filenames]
return np.sum(n)
 NUM_TRAINING_IMAGES = count_data_items(TRAINING_FILENAMES+VALIDATION_FILENAMES)
 NUM_VALIDATION_IMAGES = count_data_items(VALIDATION_FILENAMES)
 NUM_TEST_IMAGES = count_data_items(TEST_FILENAMES)
 STEPS_PER_EPOCH = NUM_TRAINING_IMAGES // BATCH_SIZE
print('Dataset: {} training images, {} validation images, {} unlabeled test images'.format(NUM_TRAINING_IMAGES, NUM_VALIDATION_IMAGES, NUM_TEST_IMAGES))<train_model>
class TrainingDataPreparation(BaseEstimator, TransformerMixin):
def __init__(self):
pass
def fit(self, X):
return self
def transform(self, X):
X = X.sort_values(by=['PlayId', 'RusherTeam', 'IsRusher', 'dist_to_rusher'] ).reset_index()
unused_columns = ["GameId","PlayId","Team","IsRusher", "index"]
unique_columns = ["X", "Y", "S", "A", "X1sec", "Y1sec", "X3sec", "Y3sec", "RusherTeam", "CrossesWithin_1", "CrossesWithin_3", "dist_to_rusher", "Dis", "Orientation", "Dir", "JerseyNumber", "PlayerHeight", "PlayerWeight", "PlayerAge", "PlayerBMI"]
training_cols = []
for c in X.columns:
if c not in unique_columns + unused_columns:
training_cols.append(c)
 for c in unique_columns:
for i in range(22):
training_cols.append(c+str(i))
{}".format(len(training_cols), training_cols))
training_data=np.zeros(( X.shape[0]//22,len(training_cols)))
 for i in range(0,X.shape[0],22):
count=0
for c in training_cols:
if c in X:
training_data[i//22][count] = X[c][i]
count+=1
for c in unique_columns:
for j in range(22):
training_data[i//22][count] = X[c][i+j]
count+=1
X = pd.DataFrame(data=training_data, columns=training_cols)
 return X
train_dat_prep = TrainingDataPreparation()
print("Training data shapes:")
 for image, label in get_training_dataset().take(3):
print(image.numpy().shape, label.numpy().shape)
 print("Training data label examples:", label.numpy())
 print("Validation data shapes:")
 for image, label in get_validation_dataset().take(3):
print(image.numpy().shape, label.numpy().shape)
 print("Validation data label examples:", label.numpy())
 print("Test data shapes:")
 for image, idnum in get_test_dataset().take(3):
print(image.numpy().shape, idnum.numpy().shape)
 print("Test data IDs:", idnum.numpy().astype('U'))<train_model>
y_train = train_transformed["Yards"]
X_train = train_transformed.drop(["Yards"], axis=1)
 print(y_train.shape)
 print(X_train.shape )
training_dataset = get_training_dataset()
training_dataset = training_dataset.unbatch().batch(20)
 train_batch = iter(training_dataset )<define_variables>
scaler_X = PowerTransformer()
X_train = scaler_X.fit_transform(X_train )
display_batch_of_images(next(train_batch))<define_variables>
test_dataset = get_test_dataset()
test_dataset = test_dataset.unbatch().batch(20)
 test_batch = iter(test_dataset )<define_variables>
def crps(y_true, y_pred):
return K.mean(K.square(y_true - K.cumsum(y_pred, axis=1)) , axis=1 )
display_batch_of_images(next(test_batch))<choose_model_class>


def get_model() :
x = keras.layers.Input(shape=[X_train.shape[1]])
 fc1 = keras.layers.Dense(units=384, activation="relu", input_shape=[X_train.shape[1]] )(x)
 bn1 = keras.layers.BatchNormalization()(fc1)
 dp1 = keras.layers.Dropout(0.5 )(bn1)
 fc2 = keras.layers.Dense(units=256, activation="relu" )(dp1)
 bn2 = keras.layers.BatchNormalization()(fc2)
 dp2 = keras.layers.Dropout(0.5 )(bn2)
 output = keras.layers.Dense(units=199, activation='softmax' )(dp2)
 model = keras.models.Model(inputs=[x], outputs=[output])
 return model


earlyStopping = EarlyStopping(
 monitor='val_loss',
patience=15,
verbose=1,
mode='min',
restore_best_weights=True,
min_delta=1e-5 
)
 reduceLR = ReduceLROnPlateau(
 monitor='val_loss',
factor=0.5,
patience=8,
min_lr=1e-6,
verbose=1,
mode='min' 
)
 def train_model(X_train, y_train, X_val, y_val):
model = get_model()
model.compile(optimizer=Adam(lr=1e-4), loss=crps)
 checkPoint = ModelCheckpoint('best_model.h5',monitor='val_loss',mode='min', save_best_only=True, verbose=1, save_weights_only=True)
 model.fit(X_train, y_train, epochs=150, callbacks=[earlyStopping, reduceLR, checkPoint], validation_data=[X_val, y_val], batch_size=batch_size)
 return model
def lrfn(epoch):
LR_START = 0.00001
LR_MAX = 0.00005 * strategy.num_replicas_in_sync
LR_MIN = 0.00001
LR_RAMPUP_EPOCHS = 5
LR_SUSTAIN_EPOCHS = 8
LR_EXP_DECAY =.8
if epoch < LR_RAMPUP_EPOCHS:
lr =(LR_MAX - LR_START)/ LR_RAMPUP_EPOCHS * epoch + LR_START
elif epoch < LR_RAMPUP_EPOCHS + LR_SUSTAIN_EPOCHS:
lr = LR_MAX
else:
lr =(LR_MAX - LR_MIN)* LR_EXP_DECAY**(epoch - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS)+ LR_MIN
return lr<choose_model_class>
rkf = RepeatedKFold(n_splits=5, n_repeats=1)
 models = []
for tr_idx, vl_idx in rkf.split(X_train_nn, y_train_nn):
x_tr, y_tr = X_train_nn[tr_idx], y_train_nn[tr_idx]
x_vl, y_vl = X_train_nn[vl_idx], y_train_nn[vl_idx]
model = train_model(x_tr, y_tr, x_vl, y_vl)
 model.load_weights("best_model.h5")
 models.append(model )
with strategy.scope() :
pretrained_model = efn.EfficientNetB7(weights='noisy-student', include_top=False ,input_shape=[*IMAGE_SIZE, 3])
 pretrained_model.trainable = True
model = tf.keras.Sequential([
pretrained_model,
tf.keras.layers.GlobalAveragePooling2D() ,
tf.keras.layers.Dense(len(CLASSES),activation='softmax', activity_regularizer=tf.keras.regularizers.l2(0.01))
])
 opt = tf.keras.optimizers.Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, amsgrad=False)
 model.compile(
 optimizer=opt,
loss = 'sparse_categorical_crossentropy',
metrics=['sparse_categorical_accuracy'] 
)
 model.summary() 
<set_options>
def make_pred_nn(df, models):
tdata_local = cat_feat_processor.fit_transform(df)
 tdata_local = num_feat_processor.fit_transform(tdata_local)
 tdata_local = train_dat_prep.fit_transform(tdata_local)
 if("Yards" in tdata_local.columns):
tdata_local = tdata_local.drop(["Yards"], axis=1)
 tdata_local = scaler_X.transform(tdata_local)
 y_pred = np.zeros(( tdata_local.shape[0], 199))
for model in models:
y_pred += np.cumsum(model.predict(tdata_local), axis=1)
 y_pred = y_pred/len(models)
 return y_pred
def make_pred_env_nn(df, sample_prediction, env, models):
y_pred = make_pred_nn(df, models)
 env.predict(pd.DataFrame(data=y_pred.clip(0,1),columns=sample_prediction.columns))
tf.keras.backend.clear_session()<train_model>
lr_schedule = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=1)
 early_stopping = tf.keras.callbacks.EarlyStopping(
 monitor='val_loss', min_delta=0, patience=3, verbose=1, mode='auto',
baseline=None, restore_best_weights=True)
 history = model.fit(get_training_dataset() ,
steps_per_epoch=STEPS_PER_EPOCH,
epochs=EPOCHS,
validation_data=get_validation_dataset() ,
callbacks=[lr_schedule, early_stopping] )<predict_on_test>
cmdataset = get_validation_dataset(ordered=True)
 images_ds = cmdataset.map(lambda image, label: image)
 labels_ds = cmdataset.map(lambda image, label: label ).unbatch()
cm_correct_labels = next(iter(labels_ds.batch(NUM_VALIDATION_IMAGES)) ).numpy()
cm_probabilities = model.predict(images_ds)
 cm_predictions = np.argmax(cm_probabilities, axis=-1)
 print("Correct labels: ", cm_correct_labels.shape, cm_correct_labels)
 print("Predicted labels: ", cm_predictions.shape, cm_predictions )<compute_train_metric>
cmat = confusion_matrix(cm_correct_labels, cm_predictions, labels=range(len(CLASSES)))
 score = f1_score(cm_correct_labels, cm_predictions, labels=range(len(CLASSES)) , average='macro')
 precision = precision_score(cm_correct_labels, cm_predictions, labels=range(len(CLASSES)) , average='macro')
 recall = recall_score(cm_correct_labels, cm_predictions, labels=range(len(CLASSES)) , average='macro')
 cmat =(cmat.T / cmat.sum(axis=1)).T
display_confusion_matrix(cmat, score, precision, recall)
 print('f1 score: {:.3f}, precision: {:.3f}, recall: {:.3f}'.format(score, precision, recall))<save_to_csv>
for test, sample_prediction in tqdm.tqdm(env.iter_test()):
make_pred_env_nn(test, sample_prediction, env, models )
test_ds = get_test_dataset(ordered=True)
 print('Computing predictions...')
 test_images_ds = test_ds.map(lambda image, idnum: image)
 probabilities = model.predict(test_images_ds)
 predictions = np.argmax(probabilities, axis=-1)
 print(predictions)
 print('Generating submission.csv file...')
 test_ids_ds = test_ds.map(lambda image, idnum: idnum ).unbatch()
test_ids = next(iter(test_ids_ds.batch(NUM_TEST_IMAGES)) ).numpy().astype('U')
 np.savetxt('submission.csv', np.rec.fromarrays([test_ids, predictions]), fmt=['%s', '%d'], delimiter=',', header='id,label', comments='')
 !head submission.csv<define_variables>
env.write_submission_file()