Kaggle competition: Bengali.AI Handwritten Grapheme Classification
<SOS> metric: WeightedCategorizationAccuracy Kaggle data source: bengali.ai-handwritten-grapheme-classification<choose_model_class>
!pip install '.. /input/kerasefficientnetb3/efficientnet-1.0.0-py3-none-any.whl'
best = stochastic_product_search(
 choice_matrix=choice_matrix,
top_k=8,
fam_size=3,
original=best,
n_iter=50000,
disable_tqdm=False,
verbose=5000
)<save_to_csv>
HEIGHT = 137
WIDTH = 236
FACTOR = 0.60
HEIGHT_NEW = int(HEIGHT * FACTOR)
 WIDTH_NEW = int(WIDTH * FACTOR)
 CHANNELS = 3
BATCH_SIZE = 16
DIR = '.. /input/bengaliai-cv19'
submission['assigned_day'] = best
final_score = cost_function(best)
 submission.to_csv(f'submission_{final_score}.csv' )<load_from_csv>
print(HEIGHT_NEW)
 print(WIDTH_NEW)
 def resize_image(img, WIDTH_NEW, HEIGHT_NEW):
img = 255 - img
img =(img *(255.0 / img.max())).astype(np.uint8)
 img = img.reshape(HEIGHT, WIDTH)
 image_resized = cv2.resize(img,(WIDTH_NEW, HEIGHT_NEW), interpolation = cv2.INTER_AREA)
 return image_resized.reshape(-1 )
fam = pd.read_csv('.. /input/santa-workshop-tour-2019/family_data.csv')
 sub = pd.read_csv('.. /input/santa-ip/submission.csv')
 fam = pd.merge(fam,sub, how='left', on='family_id')
 choices = fam[['choice_'+str(i)for i in range(10)]].values
fam = fam[['n_people','assigned_day']].values
fam[:1]<find_best_params>
gm_exp = tf.Variable(3.0, dtype = tf.float32)
 def generalized_mean_pool_2d(X):
pool =(tf.reduce_mean(tf.abs(X**(gm_exp)) , axis = [1, 2], keepdims = False)+ 1.e-7)**(1./gm_exp)
 return pool
fam_costs = np.zeros(( 5000,101))
for f in range(5000):
for d in range(1,101):
l = list(choices[f])
 if d in l:
if l.index(d)== 0:
fam_costs[f,d] = 0
elif l.index(d)== 1:
fam_costs[f,d] = 50
elif l.index(d)== 2:
fam_costs[f,d] = 50 + 9 * fam[f,0]
elif l.index(d)== 3:
fam_costs[f,d] = 100 + 9 * fam[f,0]
elif l.index(d)== 4:
fam_costs[f,d] = 200 + 9 * fam[f,0]
elif l.index(d)== 5:
fam_costs[f,d] = 200 + 18 * fam[f,0]
elif l.index(d)== 6:
fam_costs[f,d] = 300 + 18 * fam[f,0]
elif l.index(d)== 7:
fam_costs[f,d] = 300 + 36 * fam[f,0]
elif l.index(d)== 8:
fam_costs[f,d] = 400 + 36 * fam[f,0]
elif l.index(d)== 9:
fam_costs[f,d] = 500 + 235 * fam[f,0]
else:
fam_costs[f,d] = 500 + 434 * fam[f,0]<find_best_params>
def create_model(input_shape):
input = Input(shape = input_shape)
 x_model = efn.EfficientNetB3(weights = None, include_top = False, input_tensor = input, pooling = None, classes = None)
 for layer in x_model.layers:
layer.trainable = True
lambda_layer = Lambda(generalized_mean_pool_2d)
 lambda_layer.trainable_weights.extend([gm_exp])
 x = lambda_layer(x_model.output)
 grapheme_root = Dense(168, activation = 'softmax', name = 'root' )(x)
 vowel_diacritic = Dense(11, activation = 'softmax', name = 'vowel' )(x)
 consonant_diacritic = Dense(7, activation = 'softmax', name = 'consonant' )(x)
 model = Model(inputs = x_model.input, outputs = [grapheme_root, vowel_diacritic, consonant_diacritic])
 return model
@njit(fastmath=True)
 def fclip(p,l=0.) :
for i in range(len(p)) :
if p[i]<l:
p[i]=l
return p
@njit(fastmath=True)
 def cost_function(pred, p1=1_000_000_000, p2=4000):
days = np.array(list(range(100,0,-1)))
 daily_occupancy = np.zeros(101)
 penalty = 0
for i in range(5000):
penalty += fam_costs[i,pred[i,1]]
daily_occupancy[pred[i,1]] += pred[i,0]
for v in daily_occupancy[1:]:
if(v < 125)or(v >300):
if v > 300:
penalty += p1 + abs(v-300)*p2
else:
penalty += p1 + abs(v-125)*p2
penalty += max(0,(daily_occupancy[days[0]]-125.0)/ 400.0 * daily_occupancy[days[0]]**(0.5))
do = daily_occupancy[::-1]
p =(do[1:] - 125.) / 400.* do[1:] **(0.5 +(np.abs(do[1:]-do[:-1])/ 50.0))
penalty += np.sum(fclip(p))
return penalty<compute_test_metric>
model1 = create_model(input_shape =(HEIGHT_NEW, WIDTH_NEW, CHANNELS))
model2 = create_model(input_shape =(HEIGHT_NEW, WIDTH_NEW, CHANNELS))
model3 = create_model(input_shape =(HEIGHT_NEW, WIDTH_NEW, CHANNELS))
model4 = create_model(input_shape =(HEIGHT_NEW, WIDTH_NEW, CHANNELS))
model5 = create_model(input_shape =(HEIGHT_NEW, WIDTH_NEW, CHANNELS))
best = cost_function(fam)
 best<compute_train_metric>
model1.load_weights('.. /input/kerasefficientnetb3/Train1_model_59.h5')
 model2.load_weights('.. /input/kerasefficientnetb3/Train1_model_64.h5')
 model2.load_weights('.. /input/kerasefficientnetb3/Train1_model_66.h5')
 model3.load_weights('.. /input/kerasefficientnetb3/Train1_model_68.h5')
 model5.load_weights('.. /input/kerasefficientnetb3/Train1_model_70.h5' )
@njit(fastmath=True)
 def penalty_score_(d, cp, dc):
penalty = 0
yc, tc = dc[d + 1], dc[d] + cp
penalty += max(0,(tc-125.0)/ 400.0 * tc**(0.5 + abs(tc - yc)/ 50.0))
yc, tc = dc[d] + cp, dc[d -1]
penalty += max(0,(tc-125.0)/ 400.0 * tc**(0.5 + abs(tc - yc)/ 50.0))
return penalty
@njit(fastmath=True)
 def penalty_score(f,cd,d,cp, dc):
old = penalty_score_(int(cd), 0, dc)+ penalty_score_(int(d), 0, dc)+ fam_costs[f][cd]
new = penalty_score_(int(cd), -int(cp), dc)+ penalty_score_(int(d), int(cp), dc)+ fam_costs[f][d]
return new - old
@njit(fastmath=True)
 def penalty_score2(f1,f2,d1,d2,c1,c2, dc):
old = penalty_score_(int(d1), 0, dc)+ penalty_score_(int(d2), 0, dc)+ fam_costs[f1][d1] + fam_costs[f2][d2]
new = penalty_score_(int(d1), int(c2-c1), dc)+ penalty_score_(int(d2), int(c1-c2), dc)+ fam_costs[f1][d2] + fam_costs[f2][d1]
return new - old<define_search_space>
class TestDataGenerator(keras.utils.Sequence):
def __init__(self, X, batch_size = 16, img_size =(512, 512, 3), *args, **kwargs):
self.X = X
self.indices = np.arange(len(self.X))
self.batch_size = batch_size
self.img_size = img_size
def __len__(self):
return int(ceil(len(self.X)/ self.batch_size))
def __getitem__(self, index):
indices = self.indices[index*self.batch_size:(index+1)*self.batch_size]
X = self.__data_generation(indices)
 return X
def __data_generation(self, indices):
X = np.empty(( self.batch_size, *self.img_size))
for i, index in enumerate(indices):
image = self.X[index]
image = np.stack(( image,)*CHANNELS, axis=-1)
 image = image.reshape(-1, HEIGHT_NEW, WIDTH_NEW, CHANNELS)
 X[i,] = image
return X
@njit(fastmath=True)
 def optimizer(pred):
days = np.array(list(range(100,1,-1)))
 days_count = np.zeros(101)
 for i in range(5000):
days_count[pred[i,1]] += pred[i,0]
for f in range(5000):
cd = int(pred[f,1])
 if cd > 1 and cd < 100:
cp = int(pred[f,0])
 for d in days[1:-1]:
if d != cd:
if days_count[d]+cp>=125 and days_count[d]+cp<=300 and days_count[cd]-cp >= 125 and days_count[cd]-cp<=300:
if penalty_score(f, int(cd), int(d), int(cp), days_count)<0:
days_count[d] += cp
days_count[cd] -= cp
pred[f,1] = int(d)
 cd = int(d)
 elif fam_costs[f,d] <= fam_costs[f,cd]:
dtf = [fx for fx in range(5000)if(( pred[fx,1]==d)and(pred[fx,0]==cp)) ]
for j in dtf:
if j != f:
if fam_costs[f,d] + fam_costs[j,cd] <= fam_costs[f,cd] + fam_costs[j,d]:
pred[f,1] = int(d)
 pred[j,1] = int(cd)
 cd = int(d)
 return pred
@njit(fastmath=True)
 def optimizer_a(pred, annealing=5, seed=10):
np.random.seed(seed)
 days = np.array(list(range(100,1,-1)))
 days_count = np.zeros(101)
 for i in range(5000):
days_count[pred[i,1]] += pred[i,0]
for f in range(4999,0,-1):
cd = int(pred[f,1])
 if cd > 1 and cd < 100:
cp = int(pred[f,0])
 for d in days[1:-1]:
if d != cd:
if days_count[d]+cp>=125 and days_count[d]+cp<=300 and days_count[cd]-cp >= 125 and days_count[cd]-cp<=300:
if penalty_score(f, int(cd), int(d), int(cp), days_count)< np.random.randint(0, annealing):
days_count[d] += cp
days_count[cd] -= cp
pred[f,1] = int(d)
 cd = int(d)
 elif fam_costs[f,d] <= fam_costs[f,cd]:
dtf = [fx for fx in range(5000)if(( pred[fx,1]==d)and(pred[fx,0]==cp)) ]
for j in dtf:
if j != f:
if fam_costs[f,d] + fam_costs[j,cd] <= fam_costs[f,cd] + fam_costs[j,d] + np.random.randint(0, annealing):
pred[f,1] = int(d)
 pred[j,1] = int(cd)
 cd = int(d)
 return pred
@njit(fastmath=True)
 def optimizer_a2(fam, annealing=5., seed=10):
np.random.seed(seed)
 days_count = np.zeros(101)
 for i in range(5000):
days_count[fam[i,1]] += fam[i,0]
for f1 in range(0,5000,1):
for f2 in range(f1+1,5000,1):
d1, d2 = int(fam[f1,1]), int(fam[f2,1])
 c1, c2 = int(fam[f1,0]), int(fam[f2,0])
 if f1 != f2 and d1 != d2 and min([d1,d2])>1 and max([d1,d2])<100:
if days_count[d1]+c2-c1>125 and days_count[d1]+c2-c1<300 and days_count[d2]+c1-c2 > 125 and days_count[d2]+c1-c2<300:
if penalty_score2(int(f1), int(f2), int(d1), int(d2), int(c1), int(c2), days_count)<= 0 + np.random.randint(0, annealing):
days_count[d2] += c1 - c2
days_count[d1] += c2 - c1
fam[f1,1] = int(d2)
 fam[f2,1] = int(d1)
 d1 = int(d2)
 return fam
@njit(fastmath=True)
 def optimizer_a3(fam, p1=1_000_000_000, p2=4000):
for f1 in range(5000):
for d in range(1,101):
temp = fam.copy()
temp[f1,1] = d
if cost_function(temp,p1,p2)< cost_function(fam,p1,p2):
fam = temp.copy()
if f1 % 1000 == 0:
print('...', f1, cost_function(fam))
return fam<choose_model_class>
tgt_cols = ['grapheme_root','vowel_diacritic','consonant_diacritic']
row_ids, targets = [], []
for i in range(0, 4):
test_files = []
df = pd.read_parquet(os.path.join(DIR, 'test_image_data_'+str(i)+'.parquet'))
image_ids = df['image_id'].values
df = df.drop(['image_id'], axis = 1)
 X = []
for image_id, index in zip(image_ids, range(df.shape[0])) :
test_files.append(image_id)
 X.append(resize_image(df.loc[df.index[index]].values, WIDTH_NEW, HEIGHT_NEW))
data_generator_test = TestDataGenerator(X, batch_size = BATCH_SIZE, img_size =(HEIGHT_NEW, WIDTH_NEW, CHANNELS))
preds1 = model1.predict_generator(data_generator_test, verbose = 1)
 preds2 = model2.predict_generator(data_generator_test, verbose = 1)
 preds3 = model3.predict_generator(data_generator_test, verbose = 1)
 preds4 = model4.predict_generator(data_generator_test, verbose = 1)
 preds5 = model5.predict_generator(data_generator_test, verbose = 1)
 for i, image_id in zip(range(len(test_files)) , test_files):
for subi, col in zip(range(len(preds1)) , tgt_cols):
sub_preds1 = preds1[subi]
sub_preds2 = preds2[subi]
sub_preds3 = preds3[subi]
sub_preds4 = preds4[subi]
sub_preds5 = preds5[subi]
row_ids.append(str(image_id)+'_'+col)
 sub_pred_value = np.argmax(( sub_preds1[i] + sub_preds2[i] + sub_preds3[i] + sub_preds4[i] + sub_preds5[i])/ 5)
 targets.append(sub_pred_value)
 del df
gc.collect()
<load_from_csv><EOS> 
submit_df = pd.DataFrame({'row_id':row_ids,'target':targets}, columns = ['row_id','target'])
 submit_df.to_csv('submission.csv', index = False)
 print(submit_df.head(40))