# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

from src.features.build_features import get_roast_classification_dataset
from sklearn.model_selection import train_test_split, RandomizedSearchCV, learning_curve
from gensim.utils import simple_preprocess
from gensim.models.doc2vec import TaggedDocument, Doc2Vec
from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt
import numpy as np

X, y = get_roast_classification_dataset()

X_tokenized = []
for i, doc in enumerate(X):
    tokens = simple_preprocess(doc)
    tagged_doc = TaggedDocument(tokens, [i])
    X_tokenized.append(tagged_doc)

X_tokenized[1]

# Split into test and train datasets
X_train, X_test, y_train, y_test = train_test_split(X_tokenized, y, test_size=0.2, random_state=25)

# create model
model = Doc2Vec(vector_size=50, min_count=2, epochs=40)

# build a vocabulary
model.build_vocab(X_train)

# view the vocab
model.wv.index_to_key

# vocab size
model.corpus_count

# train model on corpus
model.train(X_train, total_examples=model.corpus_count, epochs=model.epochs)

# look at document vector for example sentence
model.infer_vector(X_tokenized[1].words)

# ## Sanity Check the Model

# It looks like almost all documents are most similar to themselves, which is good.

X_train[1]

inferred_vector = model.infer_vector(X_train[1].words)
model.dv.most_similar([inferred_vector], topn=len(model.dv))

ranks = []
second_ranks = []
for idx in range(len(X_train)):
    doc_id = X_train[idx].tags[0]
    inferred_vector = model.infer_vector(X_train[idx].words)
    sims = model.dv.most_similar([inferred_vector], topn=len(model.dv))
    rank = [docid for docid, sim in sims].index(doc_id)
    ranks.append(rank)
    
    second_ranks.append(sims[1])

# +
import collections

counter = collections.Counter(ranks)
print(counter)
# -

# ## Classifier

X_train_doc2vec = []
for idx in range(len(X_train)):
    inferred_vector = model.infer_vector(X_train[idx].words)
    X_train_doc2vec.append(inferred_vector)

X_train_doc2vec[0].shape

# Fit model, and make predictions
rnd_clf = RandomForestClassifier(n_estimators=500, max_depth=32, max_features=50, n_jobs=-1, oob_score=True, random_state=23)
rnd_clf.fit(X_train_doc2vec, y_train)
rnd_clf.oob_score_

rnd_clf = RandomForestClassifier(n_jobs=-1, oob_score=True, random_state=21)
param_dist = {"max_depth": [5, 10, 25, 50, 100, 200],
              "n_estimators": [500],
              "max_features": [10, 20, 30, 40, 50],
              "min_samples_split": [2, 3, 5, 7, 9],
              "bootstrap": [True]}
n_iter_search = 10
random_search = RandomizedSearchCV(rnd_clf, param_distributions=param_dist,
                                   n_iter=n_iter_search, random_state=25,
                                  return_train_score=True)
random_search.fit(X_train_doc2vec, y_train)


# +
# Utility function to report best scores
def report(results, n_top=3):
    for i in range(1, n_top + 1):
        candidates = np.flatnonzero(results['rank_test_score'] == i)
        for candidate in candidates:
            print("Model with rank: {0}".format(i))
            print("Mean validation score: {0:.3f} (std: {1:.3f})"
                  .format(results['mean_test_score'][candidate],
                          results['std_test_score'][candidate]))
            print("Parameters: {0}".format(results['params'][candidate]))
            print("")
            
report(random_search.cv_results_)
# -

# ## Bigger Doc2Vec Vector

# +
# create model
model = Doc2Vec(vector_size=100, min_count=2, epochs=40)
# build a vocabulary
model.build_vocab(X_train)
# train model on corpus
model.train(X_train, total_examples=model.corpus_count, epochs=model.epochs)

# classifier
X_train_doc2vec = []
for idx in range(len(X_train)):
    inferred_vector = model.infer_vector(X_train[idx].words)
    X_train_doc2vec.append(inferred_vector)
    
# Fit model, and make predictions
rnd_clf = RandomForestClassifier(n_estimators=500, max_depth=32, max_features=50, n_jobs=-1, oob_score=True, random_state=23)
rnd_clf.fit(X_train_doc2vec, y_train)
rnd_clf.oob_score_

# +
# create model
model = Doc2Vec(vector_size=25, min_count=2, epochs=40)
# build a vocabulary
model.build_vocab(X_train)
# train model on corpus
model.train(X_train, total_examples=model.corpus_count, epochs=model.epochs)

# classifier
X_train_doc2vec = []
for idx in range(len(X_train)):
    inferred_vector = model.infer_vector(X_train[idx].words)
    X_train_doc2vec.append(inferred_vector)
    
# Fit model, and make predictions
rnd_clf = RandomForestClassifier(n_estimators=500, max_depth=32, max_features=25, n_jobs=-1, oob_score=True, random_state=23)
rnd_clf.fit(X_train_doc2vec, y_train)
rnd_clf.oob_score_
# -

# ## Learning Curves

# +
training_set_size = [1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 250, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, 1300, 1400, 1600, 1800, 2000, 2500, 3000, 3500]


train_sizes, train_scores, test_scores, fit_times, _  = learning_curve(
    estimator=RandomForestClassifier(n_estimators=500, max_depth=10, max_features=25, n_jobs=-1, oob_score=True, random_state=21),
    X=X_train_doc2vec,
    y=y_train,
    train_sizes=training_set_size,
    cv=5,
    shuffle=True,
    n_jobs=-1,
    random_state=21,
    return_times=True)
# -

train_scores_mean = np.mean(train_scores, axis=1)
train_scores_std = np.std(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)
test_scores_std = np.std(test_scores, axis=1)
fit_times_mean = np.mean(fit_times, axis=1)
fit_times_std = np.std(fit_times, axis=1)

# +
# Plot learning curve
_, axes = plt.subplots(1, 3, figsize=(20, 20))

if axes is None:
        _, axes = plt.subplots(1, 3, figsize=(20, 20))

axes[0].set_title("Learning Curves Random Forest")
axes[0].set_ylim(*(0.20, 1.01))
axes[0].set_xlabel("Training examples")
axes[0].set_ylabel("Score")

axes[0].grid()
axes[0].fill_between(train_sizes, train_scores_mean - train_scores_std,
                     train_scores_mean + train_scores_std, alpha=0.1,
                     color="r")
axes[0].fill_between(train_sizes, test_scores_mean - test_scores_std,
                     test_scores_mean + test_scores_std, alpha=0.1,
                     color="g")
axes[0].plot(train_sizes, train_scores_mean, 'o-', color="r",
             label="Training score")
axes[0].plot(train_sizes, test_scores_mean, 'o-', color="g",
             label="Cross-validation score")
axes[0].legend(loc="best")

# Plot n_samples vs fit_times
axes[1].grid()
axes[1].plot(train_sizes, fit_times_mean, 'o-')
axes[1].fill_between(train_sizes, fit_times_mean - fit_times_std,
                     fit_times_mean + fit_times_std, alpha=0.1)
axes[1].set_xlabel("Training examples")
axes[1].set_ylabel("fit_times")
axes[1].set_title("Scalability of the model")

# Plot fit_time vs score
axes[2].grid()
axes[2].plot(fit_times_mean, test_scores_mean, 'o-')
axes[2].fill_between(fit_times_mean, test_scores_mean - test_scores_std,
                     test_scores_mean + test_scores_std, alpha=0.1)
axes[2].set_xlabel("fit_times")
axes[2].set_ylabel("Score")
axes[2].set_title("Performance of the model")

StarcoderdataJupyterScriptsDedupFiltered