Kaggle competition: Traveling Santa 2018 - Prime Paths
<SOS> metric: TravelingSanta2 Kaggle data source: traveling-santa-2018-prime-paths<find_best_params>
import numpy as np
import pandas as pd
import numba
from sympy import isprime, primerange
from math import sqrt
from sklearn.neighbors import KDTree
from tqdm import tqdm
from itertools import combinations, permutations
from functools import lru_cache
best_thresh = 0.2
max_f1 = 0
for thresh in np.arange(0.2, 0.601, 0.01):
thresh = np.round(thresh, 2)
 current_f1 = metrics.f1_score(val_y,(pred_noemb_val_y>thresh ).astype(int))
print("ค่า F1 ที่ threshold %.2f is %.4f" %(thresh, current_f1))
if current_f1 > max_f1:
best_thresh = thresh
max_f1 = current_f1
print('ค่า threshold ที่ดีที่สุดคือ %.2f ให้ค่า F1 เท่ากับ %.4f' %(best_thresh,max_f1))<predict_on_test>
cities = pd.read_csv('.. /input/traveling-santa-2018-prime-paths/cities.csv', index_col=['CityId'])
 XY = np.stack(( cities.X.astype(np.float32), cities.Y.astype(np.float32)) , axis=1)
 is_not_prime = np.array([0 if isprime(i)else 1 for i in cities.index], dtype=np.int32 )
pred_noemb_test_y = model.predict([test_X], batch_size=1024, verbose=1 )<set_options>
@numba.jit('f8(i8, i8, i8)', nopython=True, parallel=False)
 def cities_distance(offset, id_from, id_to):
xy_from, xy_to = XY[id_from], XY[id_to]
dx, dy = xy_from[0] - xy_to[0], xy_from[1] - xy_to[1]
distance = sqrt(dx * dx + dy * dy)
 if offset % 10 == 9 and is_not_prime[id_from]:
return 1.1 * distance
return distance
@numba.jit('f8(i4, i8[:])', nopython=True, parallel=False)
 def score_chunk(offset, chunk):
pure_distance, penalty = 0.0, 0.0
penalty_modulo = 9 - offset % 10
for path_index in numba.prange(chunk.shape[0] - 1):
id_from, id_to = chunk[path_index], chunk[path_index+1]
xy_from, xy_to = XY[id_from], XY[id_to]
dx, dy = xy_from[0] - xy_to[0], xy_from[1] - xy_to[1]
distance = sqrt(dx * dx + dy * dy)
 pure_distance += distance
if path_index % 10 == penalty_modulo and is_not_prime[id_from]:
penalty += distance
return pure_distance + 0.1 * penalty
@numba.jit('f8(i8[:])', nopython=True, parallel=False)
 def score_path(path):
return score_chunk(0, path)
 @numba.jit
def chunk_scores(chunk):
scores = np.zeros(10)
 pure_distance = 0
for i in numba.prange(chunk.shape[0] - 1):
id_from, id_to = chunk[i], chunk[i+1]
xy_from, xy_to = XY[id_from], XY[id_to]
dx, dy = xy_from[0] - xy_to[0], xy_from[1] - xy_to[1]
distance = sqrt(dx * dx + dy * dy)
 pure_distance += distance
if is_not_prime[id_from]:
scores[9-i%10] += distance
scores *= 0.1
scores += pure_distance
return scores
def score_compound_chunk(offset, head, chunks, tail, scores, indexes_permutation=None):
if indexes_permutation is None:
indexes_permutation = range(len(chunks))
score = 0.0
last_city_id = head
for index in indexes_permutation:
chunk, chunk_scores = chunks[index], scores[index]
score += cities_distance(offset % 10, last_city_id, chunk[0])
 score += chunk_scores[(offset + 1)% 10]
last_city_id = chunk[-1]
offset += len(chunk)
 return score + cities_distance(offset % 10, last_city_id, tail)
del model, inp, x
time.sleep(10 )<define_variables>
kdt = KDTree(XY )
def load_glove_fast(word_index, max_words=max_features, embed_size=300):
EMBEDDING_FILE = '.. /input/embeddings/glove.840B.300d/glove.840B.300d.txt'
emb_mean, emb_std = -0.005838499, 0.48782197
embedding_matrix = np.random.normal(emb_mean, emb_std,(max_words, embed_size))
with open(EMBEDDING_FILE, 'r', encoding="utf8")as f:
for line in f:
word, vec = line.split(' ', 1)
 if word not in word_index:
continue
i = word_index[word]
if i >= max_words:
continue
embedding_vector = np.asarray(vec.split(' '), dtype='float32')[:300]
if len(embedding_vector)== 300:
embedding_matrix[i] = embedding_vector
return embedding_matrix
def load_fasttext_fast(word_index, max_words=max_features, embed_size=300):
EMBEDDING_FILE = '.. /input/embeddings/wiki-news-300d-1M/wiki-news-300d-1M.vec'
emb_mean, emb_std = -0.0033470048, 0.109855264
embedding_matrix = np.random.normal(emb_mean, emb_std,(max_words, embed_size))
with open(EMBEDDING_FILE, 'r', encoding="utf8")as f:
for line in f:
if len(line)<= 100:
continue
word, vec = line.split(' ', 1)
 if word not in word_index:
continue
i = word_index[word]
if i >= max_words:
continue
embedding_vector = np.asarray(vec.split(' '), dtype='float32')[:300]
if len(embedding_vector)== 300:
embedding_matrix[i] = embedding_vector
return embedding_matrix
def load_para_fast(word_index, max_words=max_features, embed_size=300):
EMBEDDING_FILE = '.. /input/embeddings/paragram_300_sl999/paragram_300_sl999.txt'
emb_mean, emb_std = -0.0053247833, 0.49346462
embedding_matrix = np.random.normal(emb_mean, emb_std,(max_words, embed_size))
with open(EMBEDDING_FILE, 'r', encoding="utf8", errors="ignore")as f:
for line in f:
if len(line)<= 100:
continue
word, vec = line.split(' ', 1)
 if word not in word_index:
continue
i = word_index[word]
if i >= max_words:
continue
embedding_vector = np.asarray(vec.split(' '), dtype='float32')[:300]
if len(embedding_vector)== 300:
embedding_matrix[i] = embedding_vector
return embedding_matrix<load_pretrained>
path = np.array(pd.read_csv('.. /input/close-ends-chunks-optimization-aka-2-opt/1515567.693648386.csv' ).Path )
%%time

 embedding_matrix = load_glove_fast(tokenizer.word_index)
<choose_model_class>
def not_trivial_permutations(iterable):
perms = permutations(iterable)
 next(perms)
 yield from perms
@lru_cache(maxsize=None)
 def not_trivial_indexes_permutations(length):
return np.array([list(p)for p in not_trivial_permutations(range(length)) ])
 path_index = np.argsort(path[:-1])
 print(f'Total score is {score_path(path):.2f}.')
 for _ in range(3):
for ids in tqdm(triplets):
i, j, k = sorted(path_index[ids])
 head, tail = path[i-1], path[k+1]
chunks = [path[i:i+1], path[i+1:j], path[j:j+1], path[j+1:k], path[k:k+1]]
chunks = [chunk for chunk in chunks if len(chunk)]
scores = [chunk_scores(chunk)for chunk in chunks]
default_score = score_compound_chunk(i-1, head, chunks, tail, scores)
 best_score = default_score
for indexes_permutation in not_trivial_indexes_permutations(len(chunks)) :
score = score_compound_chunk(i-1, head, chunks, tail, scores, indexes_permutation)
 if score < best_score:
permutation = [chunks[i] for i in indexes_permutation]
best_chunk = np.concatenate([[head], np.concatenate(permutation), [tail]])
 best_score = score
if best_score < default_score:
path[i-1:k+2] = best_chunk
path_index = np.argsort(path[:-1])
 print(f'New total score is {score_path(path):.2f}.Permutating path at indexes {i}, {j}, {k}.')
 triplets = triplets[:10**6]
inp = Input(shape=(maxlen,))
x = Embedding(max_features, embed_size, weights=[embedding_matrix] )(inp)
 x = Bidirectional(CuDNNGRU(64, return_sequences=True))(x)
 x = GlobalMaxPool1D()(x)
 x = Dense(16, activation="relu" )(x)
 x = Dropout(0.1 )(x)
 x = Dense(1, activation="sigmoid" )(x)
 model = Model(inputs=inp, outputs=x)
 model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
 print(model.summary() )<train_model>
print(f'Final score is {score_path(path):.2f}.' )
model.fit(train_X, train_y, batch_size=512, epochs=3, validation_data=(val_X, val_y))<predict_on_test>
def make_submission(name, path):
pd.DataFrame({'Path': path} ).to_csv(f'{name}.csv', index=False )
<find_best_params><EOS> 
make_submission(score_path(path), path )