# What can I do when my test and validation scores are good, but the submission is terrible?

This is a very broad question, I understand and I'm totally fine if someone believes it's not appropriate to do it. But it's killing me not to understand this...

Here's the thing, I'm doing a machine learning model to predict the tweet topic. I'm participating in this competition. So this is what I've done in order to ensure I'm not overfitting: I separated 10% of my training data and I called validation set, and I used the rest (90%) to prepare my model. So 90% of my data was divided into train and test set. So basically I had two datasets to test my model, the test set and the validation set. All results are great! Both the test and the validation set got me great results. I also did a Stratified K-Fold, which also showed me great results. However, the submission set is returning me 73% of accuracy. What can be happening? Why do I get good results in the test and validation set, but no so good in the submission? Is there any explanation? Is there any data leakage happening in here? I find it very weird to have any leakage, since the validation set is not used at all. But idk what can be happening anymore...

This is part of what I've done and where might lead to some leakage (I simplified a little):

# load training data

# leave 10% for validation
train = train_set.loc[:35685, ["Tweet_ID", "tweet", "type"]]
validation = train_set.loc[35685:, ["Tweet_ID", "tweet"]]

def preprocess_text(text):
STOPWORDS = stopwords.words("english")

# Check characters to see if they are in punctuation
nopunc = [char for char in text if char not in string.punctuation]

# Join the characters again to form the string.
nopunc = "".join(nopunc)

# Now just remove any stopwords
return " ".join([word for word in nopunc.split() if word.lower() not in STOPWORDS])

X = train["tweet"]
y = train["type"]

X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.15, random_state=42
)

pipe = Pipeline([
("vect", CountVectorizer(analyzer=preprocess_text)),
("clf", RandomForestClassifier(class_weight='balanced'))
])

pipe.fit(X_train, y_train)
y_pred = pipe.predict(X_test)