<jupyter_start><jupyter_text><jupyter_code>from google.colab import drive
drive.mount('/content/drive')
import pandas as pd
import numpy as np
# CONSTANTS
LIKE, DISLIKE = 1, 0
N_TRACKS = 100<jupyter_output><empty_output><jupyter_text>**Importing the dataset and extracting features**In this part, the aim is to import the dataset and extract the features in it.<jupyter_code>DATASET_PATH = '/content/drive/MyDrive/datasets/data.csv'
data_df = pd.read_csv(DATASET_PATH)
data_df.head()
features = data_df.drop(labels=['artists', 'id', 'name', 'year', 'release_date'], axis=1).to_numpy()
features[:5]
features.shape<jupyter_output><empty_output><jupyter_text>**Normalizing the features of the dataset.**In this part, the aim is to normalize the features using standard score formula.<jupyter_code>def normalize_features(arr):
  # standard score
  cols_mean, cols_stdev = arr.mean(axis=0), arr.std(axis=0)
  output = (arr - cols_mean) / cols_stdev
  return output
normalized_features = normalize_features(features)<jupyter_output><empty_output><jupyter_text>**Importing the user input.**In this part, the aim is to import the user input.<jupyter_code>import json
USER_FAVORITES_INPUT = '/content/drive/MyDrive/datasets/oldies-but-goldies-00s.json'
USER_DISLIKES_INPUT = '/content/drive/MyDrive/datasets/rock-classics.json'
user_favorites_ids, user_dislikes_ids = None, None
with open(USER_FAVORITES_INPUT, 'r') as f:
  user_favorites_ids = json.load(f)

with open(USER_DISLIKES_INPUT, 'r') as f:
  user_dislikes_ids = json.load(f)
def get_track_features(idx_arr):
  track_features = []
  for idx in idx_arr['trackIds']:
    track = normalized_features[data_df['id'].str.contains(idx, na=False)]
    if len(track) > 0:
      track_features.append(track)
  return np.array(track_features)
user_favorites = get_track_features(user_favorites_ids)
user_dislikes = get_track_features(user_dislikes_ids)
len(user_favorites), len(user_dislikes)
# extracting samples and its labels
samples = np.concatenate((user_favorites, user_dislikes), axis=0)
samples = samples.reshape(samples.shape[0], -1)
labels = np.array([LIKE for _ in range(len(user_favorites))] + [DISLIKE for _ in range(len(user_dislikes))])<jupyter_output><empty_output><jupyter_text>**Naive Bayes Classifier**Simple implementation of the Naive Bayes Classifier.<jupyter_code>import math

class NaiveBayesClassifier:
    def __init__(self, features, labels):
        self.means, self.std = [], []
        self.features, self.labels = features, labels
        self.classes = np.unique(labels)
        cls_idx, cls_features = [0] * len(self.classes), [0] * len(self.classes)
        label, counts = np.unique(labels, return_counts=True)
        self.prior = dict(zip(label, counts))
        for c in self.classes:
            cls_idx[c] = np.argwhere(labels == c)
            cls_features[c] = features[cls_idx[c], :]
            self.prior[c] = self.prior[c] / sum(list(self.prior.values()))
        n_features = features.shape[1]
        self.means = [np.mean(cls_features[c], axis=0).reshape(n_features,)
                      for c in self.classes]
        self.std = [np.std(cls_features[c], axis=0)[0]
                    for c in self.classes]

    def _calc_likelihood(self, x, mean, stdev):
        exponent = math.exp(-((x - mean) ** 2 / (2 * stdev ** 2)))
        return (1 / (math.sqrt(2 * math.pi) * stdev)) * exponent
    
    def _predict(self, sample):
        self.posterior = {label: math.log(
            self.prior[label], math.e) for label in self.classes}
        for c in self.classes:
            # calculate likelihood for each feature
            for i in range(len(self.means)):
                # log(prior) += log(feature_1 | class) + log(feature_2 | class) + ...
                self.posterior[c] += math.log(self._calc_likelihood(
                    sample[i], self.means[c][i], self.std[c][i]), math.e)
        
        evidence = 0 #math.log(sum([math.e ** val for val in self.posterior.values()]), math.e)
        # posterior = prior * likelihood / evidence
        self.posterior = {c: (math.e ** (self.posterior[c] - evidence)) for c in self.posterior}
                          
        return self.posterior

    def predict(self, samples):
        predictions = []
        for sample in samples:
            predicted_c, max_p = None, 0
            for c, p in self._predict(sample).items():
                if p > max_p:
                    max_p, predicted_c = p, c
            predictions.append((max_p, predicted_c))
        return predictions<jupyter_output><empty_output><jupyter_text>**Testing**In this part, the aim is to test the algorithm.<jupyter_code>nb = NaiveBayesClassifier(samples, list(labels))
predictions = nb.predict(normalized_features)
highest_probabilities = sorted(enumerate(predictions), key=lambda tup: tup[1], reverse=True)
like_predictions = sorted(highest_probabilities, key=lambda tup: list(tup[1])[1], reverse=True)[:N_TRACKS]

for idx, (p, c) in like_predictions:
  print("probability: \t{}\n{}\n".format(p, data_df.iloc[idx]))
nb.means
ftrs = []
for idx, (p, c) in like_predictions:
  if c == LIKE:
    ftrs.append(normalized_features[idx])  
ftrs = np.array(ftrs)
print(ftrs.mean(axis=0))<jupyter_output>[-1.11137104  0.87568602 -0.08450858  0.59581325  0.60269263 -0.48398487
  0.02975732 -0.10800547  0.45709759 -0.15831627  0.47441011  0.33663959
  0.05511222  0.51076199]<jupyter_text>**Sklearn Naive Bayes**In this part, the aim is to run the NB algorithm of Sklearn on the dataset.<jupyter_code>from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()
clf.fit(samples, labels)
predictions = clf.predict_proba(normalized_features)
count = 0
for idx, p in enumerate(predictions):
  if p[1] >= p[0]:
    count += 1
count<jupyter_output><empty_output><jupyter_text>**Preprocessing and labelling the data.**In this part, the aim is to label the data by preprocessing it.<jupyter_code># preprocess the data and extract the data
#fav_mean = user_favorites.mean(axis=0)
#fav_mean.reshape(14,1)
#cosine_similarities = [dot(fav_mean, sample)/(norm(fav_mean)*norm(sample)) for sample in normalized_features]
#zipped_similarities = zip(cosine_similarities, enumerate(normalized_features))
#sorted_similarities = sorted(zipped_similarities, reverse=True, key = lambda x: x[0])
#for _similarity,(idx,_features) in sorted_similarities[len(sorted_similarities)-5:]:
#  print("Similarity:\t{}\nFeatures:\n{}\n".format(_similarity,data_df.iloc[idx]))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1279445727482679, 'fraction_numerical': 0.02617397998460354, 'mean_word_length': 4.094901960784314, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '624184', 'license': 'MIT', 'n_tokens_mistral': 2366, 'n_tokens_neox': 2217, 'n_words': 484, 'path': 'main.ipynb', 'repo_name': 'alpgokcek/music-recommendation', 'size': '6495'}