Kaggle competition: Jane Street Market Prediction
param2 = {'max_depth':4, 'eta':0.1, 'silent':1, 'objective':'multi:softprob','num_class':5,
'eval_metric':'mlogloss','subsample':0.85,'colsample_bytree':0.75}
x_train2, x_test2, y_train2, y_test2 = train_test_split(ypred_submit,y_test,test_size=0.80,
random_state=30,stratify=y_test)
 dtrain2 = xgb.DMatrix(x_train2,y_train2,missing = -9999)
 dtest2 = xgb.DMatrix(x_test2,missing = -9999)
 bst2 = xgb.train(param2, dtrain2, num_round)
 ypred_submit2 = bst2.predict(dtest2)
 print(log_loss(y_test2, ypred_submit2)) 
<train_model>
tf.random.set_seed(42)
dtrain = xgb.DMatrix(train_select,Target,missing = -9999)
 dtest = xgb.DMatrix(test_select,missing = -9999)
 num_round = 125
param1 = {'max_depth':7, 'eta':0.1, 'silent':1, 'objective':'multi:softprob','num_class':5,
'eval_metric':'mlogloss','subsample':0.75,'colsample_bytree':0.85}
param2 = {'max_depth':6, 'eta':0.1, 'silent':1, 'objective':'multi:softprob','num_class':5,
'eval_metric':'mlogloss','subsample':0.85,'colsample_bytree':0.75}
param3 = {'max_depth':8, 'eta':0.1, 'silent':1, 'objective':'multi:softprob','num_class':5,
'eval_metric':'mlogloss','subsample':0.65,'colsample_bytree':0.75}
param4 = {'max_depth':9, 'eta':0.1, 'silent':1, 'objective':'multi:softprob','num_class':5,
'eval_metric':'mlogloss','subsample':0.55,'colsample_bytree':0.65}
param5 = {'max_depth':12, 'eta':0.1, 'silent':1, 'objective':'multi:softprob','num_class':5,
'eval_metric':'mlogloss','subsample':1,'colsample_bytree':1}
bst1 = xgb.train(param1, dtrain, num_round)
 bst2 = xgb.train(param2, dtrain, num_round)
 bst3 = xgb.train(param3, dtrain, num_round)
 bst4 = xgb.train(param3, dtrain, num_round)
 bst5 = xgb.train(param3, dtrain, num_round)
 ypred_submit =(bst1.predict(dtest)+ bst2.predict(dtest)+ bst3.predict(dtest)+ bst4.predict(dtest)+ bst5.predict(dtest)) /5<save_to_csv>
train = dtable.fread('/kaggle/input/jane-street-market-prediction/train.csv' ).to_pandas()
ypred_submit=pd.DataFrame(ypred_submit)
 submission = pd.DataFrame()
submission["id"] = Id_ts.values
submission["Adoption"]= ypred_submit[2]
submission["Died"]= ypred_submit[4]
submission["Euthanasia"]= ypred_submit[1]
submission["Return_to_owner"]= ypred_submit[0]
submission["Transfer"]= ypred_submit[3]
submission.to_csv("sub.csv",index=False )<import_modules>
features = [c for c in train.columns if 'feature' in c]
f_mean = train.loc[:, features[1:]].mean()
train = train.query('weight > 0' ).reset_index(drop = True)
 train = train.query('date > 85' ).reset_index(drop = True)
 train.loc[:, features[1:]] = train.loc[:, features[1:]].fillna(f_mean)
 train.loc[:, 'action'] =(train.loc[:, 'resp'] > 0 ).astype('int')
 resp_cols = ['resp_1', 'resp_2', 'resp_3', 'resp', 'resp_4']
f_mean = f_mean.values
np.save('f_mean.npy', f_mean)
 X = train[features].values
y = np.stack([(train[c] > 0 ).astype('int')for c in resp_cols] ).T
import re
import time
import gc
import random
import os
import nltk
import multiprocess as mp
import numpy as np
import pandas as pd
from tqdm import tqdm
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import f1_score, roc_curve, precision_recall_curve
from sklearn.preprocessing import StandardScaler
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import torch
import torch.nn as nn
import torch.utils.data
from torch.nn import Parameter<define_variables>
class GroupTimeSeriesSplit(_BaseKFold):

 @_deprecate_positional_args
def __init__(self,
n_splits=5,
*,
max_train_size=None 
):
super().__init__(n_splits, shuffle=False, random_state=None)
 self.max_train_size = max_train_size
def split(self, X, y=None, groups=None):

 if groups is None:
raise ValueError(
 "The 'groups' parameter should not be None")
 X, y, groups = indexable(X, y, groups)
 n_samples = _num_samples(X)
 n_splits = self.n_splits
n_folds = n_splits + 1
group_dict = {}
u, ind = np.unique(groups, return_index=True)
 unique_groups = u[np.argsort(ind)]
n_samples = _num_samples(X)
 n_groups = _num_samples(unique_groups)
 for idx in np.arange(n_samples):
if(groups[idx] in group_dict):
group_dict[groups[idx]].append(idx)
 else:
group_dict[groups[idx]] = [idx]
if n_folds > n_groups:
raise ValueError(
("Cannot have number of folds={0} greater than"
" the number of groups={1}" ).format(n_folds,
n_groups))
group_test_size = n_groups // n_folds
group_test_starts = range(n_groups - n_splits * group_test_size,
n_groups, group_test_size)
 for group_test_start in group_test_starts:
train_array = []
test_array = []
for train_group_idx in unique_groups[:group_test_start]:
train_array_tmp = group_dict[train_group_idx]
train_array = np.sort(np.unique(
 np.concatenate(( train_array,
train_array_tmp)) ,
axis=None), axis=None)
 train_end = train_array.size
if self.max_train_size and self.max_train_size < train_end:
train_array = train_array[train_end -
self.max_train_size:train_end]
for test_group_idx in unique_groups[group_test_start:
group_test_start +
group_test_size]:
test_array_tmp = group_dict[test_group_idx]
test_array = np.sort(np.unique(
 np.concatenate(( test_array,
test_array_tmp)) ,
axis=None), axis=None)
 yield [int(i)for i in train_array], [int(i)for i in test_array]
embed_size = 300
max_features = 120000
maxlen = 50
batch_size = 512
train_epochs = 6
SEED = 1029<set_options>
class LearningRateLogger(tf.keras.callbacks.Callback):
def __init__(self):
super().__init__()
self._supports_tf_logs = True
def on_epoch_end(self, epoch, logs=None):
if logs is None or "learning_rate" in logs:
return
logs["learning_rate"] = self.model.optimizer.lr
def get_callbacks(name, fold):
return [
ReduceLROnPlateau(monitor = 'val_AUC', factor = 0.5, patience = 5, verbose = 0, min_delta = 1e-4, mode = 'max'),
ModelCheckpoint(f'JSModel_{fold}.hdf5' , monitor = 'val_AUC', verbose = 0, save_best_only = True,
save_weights_only = True, mode = 'max'),
EarlyStopping(monitor = 'val_AUC', min_delta = 1e-4, patience = 15, mode = 'max',
baseline = None, restore_best_weights = True, verbose = 0),
LearningRateLogger() ,
]
def seed_torch(seed=1029):
random.seed(seed)
 os.environ['PYTHONHASHSEED'] = str(seed)
 np.random.seed(seed)
 torch.manual_seed(seed)
 torch.cuda.manual_seed(seed)
 torch.backends.cudnn.deterministic = True
seed_torch(SEED )<define_variables>
def utility_score_bincount(date, weight, resp, action):
count_i = len(np.unique(date))
Pi = np.bincount(date, weight * resp * action)
 t = np.sum(Pi)/ np.sqrt(np.sum(Pi ** 2)) * np.sqrt(250 / count_i)
 u = np.clip(t, 0, 6)* np.sum(Pi)
 return u
puncts = [',', '.', '"', ':', ')', '(', '-', '!', '?', '|', ';', "'", '$', '&', '/', '[', ']', '>', '%', '=', '
'·', '_', '{', '}', '©', '^', '®', '`', '<', '→', '°', '€', '™', '›', '♥', '←', '×', '§', '″', '′', 'Â', '█', '½', 'à', '…',
'“', '★', '”', '–', '●', 'â', '►', '−', '¢', '²', '¬', '░', '¶', '↑', '±', '¿', '▾', '═', '¦', '║', '―', '¥', '▓', '—', '‹', '─',
'▒', '：', '¼', '⊕', '▼', '▪', '†', '■', '’', '▀', '¨', '▄', '♫', '☆', 'é', '¯', '♦', '¤', '▲', 'è', '¸', '¾', 'Ã', '⋅', '‘', '∞',
'∙', '）', '↓', '、', '│', '（', '»', '，', '♪', '╩', '╚', '³', '・', '╦', '╣', '╔', '╗', '▬', '❤', 'ï', 'Ø', '¹', '≤', '‡', '√', ]
def clean_text(x):
x = str(x)
 for punct in puncts:
x = x.replace(punct, f' {punct} ')
 return x
def clean_numbers(x):
x = re.sub('[0-9]{5,}', '
x = re.sub('[0-9]{4}', '
x = re.sub('[0-9]{3}', '
x = re.sub('[0-9]{2}', '
return x
mispell_dict = {"ain't": "is not", "aren't": "are not","can't": "cannot", "'cause": "because", "could've": "could have", "couldn't": "could not", "didn't": "did not", "doesn't": "does not", "don't": "do not", "hadn't": "had not", "hasn't": "has not", "haven't": "have not", "he'd": "he would","he'll": "he will", "he's": "he is", "how'd": "how did", "how'd'y": "how do you", "how'll": "how will", "how's": "how is", "I'd": "I would", "I'd've": "I would have", "I'll": "I will", "I'll've": "I will have","I'm": "I am", "I've": "I have", "i'd": "i would", "i'd've": "i would have", "i'll": "i will", "i'll've": "i will have","i'm": "i am", "i've": "i have", "isn't": "is not", "it'd": "it would", "it'd've": "it would have", "it'll": "it will", "it'll've": "it will have","it's": "it is", "let's": "let us", "ma'am": "madam", "mayn't": "may not", "might've": "might have","mightn't": "might not","mightn't've": "might not have", "must've": "must have", "mustn't": "must not", "mustn't've": "must not have", "needn't": "need not", "needn't've": "need not have","o'clock": "of the clock", "oughtn't": "ought not", "oughtn't've": "ought not have", "shan't": "shall not", "sha'n't": "shall not", "shan't've": "shall not have", "she'd": "she would", "she'd've": "she would have", "she'll": "she will", "she'll've": "she will have", "she's": "she is", "should've": "should have", "shouldn't": "should not", "shouldn't've": "should not have", "so've": "so have","so's": "so as", "this's": "this is","that'd": "that would", "that'd've": "that would have", "that's": "that is", "there'd": "there would", "there'd've": "there would have", "there's": "there is", "here's": "here is","they'd": "they would", "they'd've": "they would have", "they'll": "they will", "they'll've": "they will have", "they're": "they are", "they've": "they have", "to've": "to have", "wasn't": "was not", "we'd": "we would", "we'd've": "we would have", "we'll": "we will", "we'll've": "we will have", "we're": "we are", "we've": "we have", "weren't": "were not", "what'll": "what will", "what'll've": "what will have", "what're": "what are", "what's": "what is", "what've": "what have", "when's": "when is", "when've": "when have", "where'd": "where did", "where's": "where is", "where've": "where have", "who'll": "who will", "who'll've": "who will have", "who's": "who is", "who've": "who have", "why's": "why is", "why've": "why have", "will've": "will have", "won't": "will not", "won't've": "will not have", "would've": "would have", "wouldn't": "would not", "wouldn't've": "would not have", "y'all": "you all", "y'all'd": "you all would","y'all'd've": "you all would have","y'all're": "you all are","y'all've": "you all have","you'd": "you would", "you'd've": "you would have", "you'll": "you will", "you'll've": "you will have", "you're": "you are", "you've": "you have", 'colour': 'color', 'centre': 'center', 'favourite': 'favorite', 'travelling': 'traveling', 'counselling': 'counseling', 'theatre': 'theater', 'cancelled': 'canceled', 'labour': 'labor', 'organisation': 'organization', 'wwii': 'world war 2', 'citicise': 'criticize', 'youtu ': 'youtube ', 'Qoura': 'Quora', 'sallary': 'salary', 'Whta': 'What', 'narcisist': 'narcissist', 'howdo': 'how do', 'whatare': 'what are', 'howcan': 'how can', 'howmuch': 'how much', 'howmany': 'how many', 'whydo': 'why do', 'doI': 'do I', 'theBest': 'the best', 'howdoes': 'how does', 'mastrubation': 'masturbation', 'mastrubate': 'masturbate', "mastrubating": 'masturbating', 'pennis': 'penis', 'Etherium': 'Ethereum', 'narcissit': 'narcissist', 'bigdata': 'big data', '2k17': '2017', '2k18': '2018', 'qouta': 'quota', 'exboyfriend': 'ex boyfriend', 'airhostess': 'air hostess', "whst": 'what', 'watsapp': 'whatsapp', 'demonitisation': 'demonetization', 'demonitization': 'demonetization', 'demonetisation': 'demonetization'}
def _get_mispell(mispell_dict):
mispell_re = re.compile('(%s)' % '|'.join(mispell_dict.keys()))
return mispell_dict, mispell_re
mispellings, mispellings_re = _get_mispell(mispell_dict)
 def replace_typical_misspell(text):
def replace(match):
return mispellings[match.group(0)]
return mispellings_re.sub(replace, text )<feature_engineering>
c_1 = ["feature_0", "feature_1","feature_3","feature_5","feature_7","feature_9","feature_11","feature_13","feature_15","feature_17","feature_19","feature_21","feature_23","feature_25","feature_27","feature_29","feature_31","feature_33","feature_35","feature_37","feature_39","feature_41","feature_42","feature_43","feature_44","feature_45","feature_46","feature_47","feature_48","feature_49","feature_50","feature_51","feature_52","feature_53","feature_54","feature_55","feature_56","feature_57","feature_58","feature_59","feature_60","feature_61","feature_62","feature_63","feature_64","feature_65","feature_66","feature_67","feature_68","feature_69","feature_70","feature_71","feature_120","feature_121","feature_122","feature_123","feature_124","feature_125","feature_126","feature_127","feature_128","feature_129"]
c_2 = ["feature_0", "feature_78","feature_79","feature_80","feature_81","feature_82","feature_83","feature_90","feature_91","feature_92","feature_93","feature_94","feature_95","feature_102","feature_103","feature_104","feature_105","feature_106","feature_107","feature_114","feature_115","feature_116","feature_117","feature_118","feature_119"]
c_3 = ["feature_0", "feature_72","feature_73","feature_74","feature_75","feature_76","feature_77","feature_84","feature_85","feature_86","feature_87","feature_88","feature_89","feature_96","feature_97","feature_98","feature_99","feature_100","feature_101","feature_108","feature_109","feature_110","feature_111","feature_112","feature_113"]
c_4 = ["feature_0", "feature_2","feature_4","feature_6","feature_8","feature_10","feature_12","feature_14","feature_16","feature_18","feature_20","feature_22","feature_24","feature_26","feature_28","feature_30","feature_32","feature_34","feature_36","feature_38","feature_40"]
def preprocess(df):
df.question_text = df["question_text"].apply(lambda x: x.lower())
 df.question_text = df["question_text"].apply(lambda x: clean_text(x))
df.question_text = df["question_text"].apply(lambda x: clean_numbers(x))
df.question_text = df["question_text"].apply(lambda x: replace_typical_misspell(x))
df['total_length'] = df['question_text'].apply(len)
 df['capitals'] = df['question_text'].apply(lambda comment: sum(1 for c in comment if c.isupper()))
df['caps_vs_length'] = df.apply(lambda row: float(row['capitals'])/float(row['total_length']), axis=1)
 df['num_words'] = df.question_text.str.count('\S+')
 df['num_unique_words'] = df['question_text'].apply(lambda comment: len(set(w for w in comment.split())))
 df['words_vs_unique'] = df['num_unique_words'] / df['num_words']
texts = df.question_text.tolist()
tagged_texts = nltk.pos_tag_sents(map(nltk.word_tokenize, texts))
df["tagged_texts"] = tagged_texts
df.tagged_texts = df["tagged_texts"].apply(lambda x: " ".join([i[1] for i in x]))
return df
chunksize = 10000<load_from_csv>
c_1_ = np.array([int(x.split("_")[-1])for x in c_1])
 c_2_ = np.array([int(x.split("_")[-1])for x in c_2])
 c_3_ = np.array([int(x.split("_")[-1])for x in c_3])
 c_4_ = np.array([int(x.split("_")[-1])for x in c_4] )
train_reader = pd.read_csv(".. /input/train.csv", chunksize=chunksize)
 start_time = time.time()
pool = mp.Pool(4)
 funclist = []
for df in train_reader:
f = pool.apply_async(preprocess, [df])
 funclist.append(f)
 result = []
for f in funclist:
result.append(f.get(timeout=120))
train_df = pd.concat(result)
 elapsed_time =(time.time() - start_time)/ 60
print(elapsed_time )<load_from_csv>
def model_1(inp):
x = tf.keras.layers.BatchNormalization()(inp)
 x = tf.keras.layers.Dropout(0.1 )(x)
 x = tf.keras.layers.Dense(64 )(x)
 x = tf.keras.layers.BatchNormalization()(x)
 x = tf.keras.layers.Activation(tf.keras.activations.swish )(x)
 x = tf.keras.layers.Dropout(0.1 )(x)
 x = tf.keras.layers.Dense(64 )(x)
 x = tf.keras.layers.BatchNormalization()(x)
 x = tf.keras.layers.Activation(tf.keras.activations.swish )(x)
 out = tf.keras.layers.Dropout(0.1 )(x)
 return out
def model_2(inp):
x = tf.keras.layers.BatchNormalization()(inp)
 x = tf.keras.layers.Dropout(0.1 )(x)
 x = tf.keras.layers.Dense(32 )(x)
 x = tf.keras.layers.BatchNormalization()(x)
 x = tf.keras.layers.Activation(tf.keras.activations.swish )(x)
 x = tf.keras.layers.Dropout(0.1 )(x)
 x = tf.keras.layers.Dense(32 )(x)
 x = tf.keras.layers.BatchNormalization()(x)
 x = tf.keras.layers.Activation(tf.keras.activations.swish )(x)
 out = tf.keras.layers.Dropout(0.1 )(x)
 return out
def model_3(inp):
x = tf.keras.layers.BatchNormalization()(inp)
 x = tf.keras.layers.Dropout(0.1 )(x)
 x = tf.keras.layers.Dense(32 )(x)
 x = tf.keras.layers.BatchNormalization()(x)
 x = tf.keras.layers.Activation(tf.keras.activations.swish )(x)
 x = tf.keras.layers.Dropout(0.1 )(x)
 x = tf.keras.layers.Dense(32 )(x)
 x = tf.keras.layers.BatchNormalization()(x)
 x = tf.keras.layers.Activation(tf.keras.activations.swish )(x)
 out = tf.keras.layers.Dropout(0.1 )(x)
 return out
def model_4(inp):
x = tf.keras.layers.BatchNormalization()(inp)
 x = tf.keras.layers.Dropout(0.1 )(x)
 x = tf.keras.layers.Dense(32 )(x)
 x = tf.keras.layers.BatchNormalization()(x)
 x = tf.keras.layers.Activation(tf.keras.activations.swish )(x)
 x = tf.keras.layers.Dropout(0.1 )(x)
 x = tf.keras.layers.Dense(32 )(x)
 x = tf.keras.layers.BatchNormalization()(x)
 x = tf.keras.layers.Activation(tf.keras.activations.swish )(x)
 out = tf.keras.layers.Dropout(0.1 )(x)
 return out
def create_mlp(f_shape, num_labels, hidden_units, dropout_rates, label_smoothing, learning_rate):
inp1 = tf.keras.layers.Input(shape =(f_shape[0],))
inp2 = tf.keras.layers.Input(shape =(f_shape[1],))
inp3 = tf.keras.layers.Input(shape =(f_shape[2],))
inp4 = tf.keras.layers.Input(shape =(f_shape[3],))
mlp1 = model_1(inp1)
 mlp2 = model_2(inp2)
 mlp3 = model_3(inp3)
 mlp4 = model_4(inp4)
 combined = tf.keras.layers.Concatenate()([mlp1, mlp2, mlp3, mlp4])
 out = tf.keras.layers.Dense(num_labels, activation="sigmoid" )(combined)
 model = tf.keras.models.Model(inputs =[inp1, inp2, inp3, inp4], outputs = out)
 model.compile(optimizer = tf.keras.optimizers.Adam(learning_rate = learning_rate),
loss = tf.keras.losses.BinaryCrossentropy(label_smoothing = label_smoothing),
metrics = tf.keras.metrics.AUC(name = 'AUC'))
return model
test_reader = pd.read_csv(".. /input/test.csv", chunksize=chunksize)
 start_time = time.time()
pool = mp.Pool(4)
 funclist = []
for df in test_reader:
f = pool.apply_async(preprocess, [df])
 funclist.append(f)
 result = []
for f in funclist:
result.append(f.get(timeout=120))
test_df = pd.concat(result)
 elapsed_time =(time.time() - start_time)/ 60
print(elapsed_time )<string_transform>
name = "mlp"
batch_size = 4096*16
hidden_units = [64, 32, 64, 130, 256, 256, 128]
dropout_rates = [0.1, 0.2, 0.2, 0.2, 0.25, 0.25, 0.25, 0.25]
label_smoothing = 1e-2
learning_rate = 1e-3
scores_list = []
gtss = GroupTimeSeriesSplit(n_splits = 5)
start_time = time.time()
train_X = train_df["question_text"].fillna("_
test_X = test_df["question_text"].fillna("_
train_tag_X = train_df["tagged_texts"].fillna("_
test_tag_X = test_df["tagged_texts"].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)
 tag_tokenizer = Tokenizer(num_words=max_features)
 tag_tokenizer.fit_on_texts(list(train_tag_X))
train_tag_X = tag_tokenizer.texts_to_sequences(train_tag_X)
 test_tag_X = tag_tokenizer.texts_to_sequences(test_tag_X)
 train_X = pad_sequences(train_X, maxlen=maxlen)
 test_X = pad_sequences(test_X, maxlen=maxlen)
 train_tag_X = pad_sequences(train_tag_X, maxlen=maxlen)
 test_tag_X = pad_sequences(test_tag_X, maxlen=maxlen)
 train_features = train_df[['caps_vs_length', 'words_vs_unique']].fillna(0)
 test_features = test_df[['caps_vs_length', 'words_vs_unique']].fillna(0)
 ss = StandardScaler()
ss.fit(np.vstack(( train_features, test_features)))
 train_features = ss.transform(train_features)
 test_features = ss.transform(test_features)
 elapsed_time =(time.time() - start_time)/ 60
print(elapsed_time )<prepare_x_and_y>
models_idx = [0,1,2,3,4]
models = []
for i in models_idx:
clf = create_mlp(f_shape, 5, hidden_units, dropout_rates, label_smoothing, learning_rate)
 path = f'.. /input/stacknnmodels/JSModel_{i}.hdf5'
print(path)
 clf.load_weights(path)
 models.append(clf )
train_y = train_df['target'].values
np.random.seed(SEED)
 trn_idx = np.random.permutation(len(train_X))
train_X = train_X[trn_idx]
train_tag_X = train_tag_X[trn_idx]
train_features = train_features[trn_idx]
train_y = train_y[trn_idx]<statistical_test>
env = janestreet.make_env()
env_iter = env.iter_test()
<normalization><EOS> 
opt_th = 0.5
w = np.asarray([0.05,0.05,0.1,0.5,0.3])
 for(test_df, pred_df)in tqdm(env_iter):
if test_df['weight'].item() > 0:
x_tt = test_df.loc[:, features].values
if np.isnan(x_tt[:, 1:].sum()):
x_tt[:, 1:] = np.nan_to_num(x_tt[:, 1:])+ np.isnan(x_tt[:, 1:])* f_mean
x_tt_1 = x_tt[:, c_1_]
x_tt_2 = x_tt[:, c_2_]
x_tt_3 = x_tt[:, c_3_]
x_tt_4 = x_tt[:, c_4_]
x_tt_ = [x_tt_1, x_tt_2, x_tt_3, x_tt_4]
pred = np.mean(models[-2](x_tt_, training = False ).numpy().squeeze())
 pred_df.action = np.where(pred >= opt_th, 1, 0 ).astype(int)
 else:
pred_df.action = 0
env.predict(pred_df )