def go_to_search_page(): """Sets up search page and redirect user there.""" try: genres = get_genres() keys = get_key_list() modes = get_modes() return render_template("search.html", genres=genres, keys=keys, modes=modes) # A KeyError occurs if genres, keys, or modes aren't populated lists; these cannot be retrieved from the Spotify API unless authenticated except KeyError: return redirect('/')
def remove_playlist(): """Removes selected playlist from user's Spotify account""" try: delete_playlist(session['playlist_id']) message = "Playlist deleted from Spotify" genres = get_genres() keys = get_key_list() modes = get_modes() return render_template("search.html", genres=genres, keys=keys, modes=modes, message=message) except KeyError: redirect('/')
def test_batch(model, samples, labels, pad_id=0, batch_size=1, mode_concat=True): y_pred = [] y_test = labels lens = [len(s) for s in samples] lens_samples_labels = list(zip(lens, samples, labels)) model.eval() with torch.no_grad(): for batch_lens_samples_labels in utils.get_batch( lens_samples_labels, batch_size=batch_size): batch_lens_samples_labels = sorted(batch_lens_samples_labels, reverse=True) batch_lens, sents, labels = zip(*batch_lens_samples_labels) batch_lens = list(batch_lens) max_sent_len = batch_lens[0] if mode_concat: del batch_lens modes = utils.get_modes(sents) sents = [s + [modes[i]] for i, s in enumerate(sents)] batch_lens = [len(s) for s in sents] max_sent_len = batch_lens[0] sents = [ utils.pad_token_ids(s, pad_id, max_len=max_sent_len) for s in sents ] sents = torch.tensor(sents, device=device, dtype=torch.long) labels = torch.tensor(labels, device=device, dtype=torch.long) hidden = model.initHidden(batch_size=len(labels), bi=bi) logprobs = model(sents, batch_lens, hidden, batch_first=True) topv, topi = logprobs.topk(1) topi = topi.squeeze().detach() # detach from history as input y_hat = topi.item() y_pred.append(y_hat) acc = accuracy_score(y_test, y_pred) f1 = f1_score(y_test, y_pred, average='macro') return acc, f1
def train(samples, labels, embeddings, n_epochs=2, vocab_size=-1, lr=0.01, use_pretrained_wv=False, pad_id=0, batch_size=1, test_dict=None, test_every=0, use_wt_loss=True, mode_concat=True): lens = [len(s) for s in samples] lens_samples_labels = list(zip(lens, samples, labels)) n_classes = len(set(labels)) model = rnn_model_batch.rnn_model(device, word_embedding=embeddings, n_classes=n_classes, vocab_size=vocab_size, use_pretrained_wv=use_pretrained_wv, bi=bi, n_layers=2) model = model.cuda() print(f' created RNN (GRU) model: {model}') if use_wt_loss: label_freq_counts = Counter(labels) print('class freq dist: ', sorted(label_freq_counts.items())) total_labels_count = len(labels) label_probs = { label: count / total_labels_count for label, count in label_freq_counts.items() } # wts = [label_probs[label] for label in sorted(label_probs.keys())] wts = [ 1. / label_freq_counts[label] for label in sorted(label_probs.keys()) ] wts = torch.tensor(wts, device=device, dtype=torch.float) print('weights for loss function: ', wts) criterion = nn.CrossEntropyLoss(weight=wts, reduction='sum') else: criterion = nn.CrossEntropyLoss() # optimizer = optim.SGD(model.parameters(), lr=lr) optimizer = optim.Adam(model.parameters(), lr=lr) # optimizer = optim.RMSprop(model.parameters(), lr=lr) for e in range(1, n_epochs + 1): model.train() t0 = time() losses = [] shuffle(lens_samples_labels) for batch_lens_samples_labels in utils.get_batch( lens_samples_labels, batch_size=batch_size): batch_lens_samples_labels = sorted(batch_lens_samples_labels, reverse=True) batch_lens, sents, labels = zip(*batch_lens_samples_labels) batch_lens = list(batch_lens) max_sent_len = batch_lens[0] if mode_concat: del batch_lens modes = utils.get_modes(sents) sents = [s + [modes[i]] for i, s in enumerate(sents)] batch_lens = [len(s) for s in sents] max_sent_len = batch_lens[0] sents = [ utils.pad_token_ids(s, pad_id, max_len=max_sent_len) for s in sents ] sents = torch.tensor(sents, device=device, dtype=torch.long) labels = torch.tensor(labels, device=device, dtype=torch.long) optimizer.zero_grad() hidden = model.initHidden(batch_size=len(labels), bi=bi) logprobs = model(sents, batch_lens, hidden, batch_first=True) loss = criterion(logprobs, labels) losses.append(loss.item()) loss.backward() optimizer.step() epoch_loss = sum(losses) / len(losses) epoch_time = round(time() - t0, 2) print(f'epoch: {e}, time: {epoch_time}, loss: {epoch_loss}') if e % test_every == 0: if test_dict: X_test = test_dict['X_test'] y_test = test_dict['y_test'] pad_id = test_dict['pad_id'] a, f = test_batch(model, X_test, y_test, pad_id, batch_size=1) print('*' * 80) print(f'epoch: {e}, on TEST SET acc: {a}, f1: {f}') print('*' * 80) return model
def show_recommendations(): """Processes search data against Spotify's API and gets the user to this results page.""" try: headers = {'Authorization': 'Bearer ' + session['token']} payload = {} # gets a list of artists to be searched for, if any if request.form.get('artist'): artist_list = "" for artist in request.form.getlist('artist'): artist_list += f"{artist}," payload['seed_artists'] = artist_list # gets a list of tracks to be searched for, if any if request.form.get('track'): track_list = "" for track in request.form.getlist('track'): track_list += f"{track}," payload['seed_tracks'] = track_list # gets the genre to be searched for, if any if request.form.get('seed_genre'): payload['seed_genres'] = request.form.get('seed_genre') # this series of seed inputs all aim to maximize that attribute (1.0 is 100%) but are 'target' values rather than 'maximum' values which would reduce the amount of results we get if request.form.get('acousticness'): payload['target_acousticness'] = 1.0 if request.form.get('danceability'): payload['target_danceability'] = 1.0 if request.form.get('energy'): payload['target_energy'] = 1.0 if request.form.get('instrumentalness'): payload['target_instrumentalness'] = 1.0 if request.form.get('liveness'): payload['target_liveness'] = 1.0 if request.form.get('speechiness'): payload['target_speechiness'] = 1.0 if request.form.get('valence'): payload['target_valence'] = 1.0 # these seed inputs include either ranges or select fields if request.form.get('include_min_duration'): payload['min_duration_ms'] = int(request.form.get('min_duration')) if request.form.get('include_max_duration'): payload['max_duration_ms'] = int(request.form.get('max_duration')) if request.form.get('key'): payload['target_key'] = int(request.form.get('key')) if request.form.get('include_loudness'): payload['target_loudness'] = float(request.form.get('loudness')) if request.form.get('mode'): payload['target_mode'] = int(request.form.get('mode')) if request.form.get('include_popularity'): payload['target_popularity'] = int(request.form.get('popularity')) if request.form.get('include_tempo'): payload['target_tempo'] = float(request.form.get('tempo')) if request.form.get('include_time_sig'): payload['target_time_signature'] = int( request.form.get('time_sig')) resp = requests.get('https://api.spotify.com/v1/recommendations', params=payload, headers=headers).json() # used in the case of app level authentication track_id_list = [] for track in resp['tracks']: track_id_list.append(track['id']) # used in the case of user level authentication track_uris = "" for track_uri in resp['tracks']: track_uris += track_uri['uri'] + ',' # necessary in the case of app authentication as this data is necessary rendered in the returned template playlist_id = None if session.get('user_id'): session['playlist_id'] = create_playlist(session['user_id']) playlist_id = session['playlist_id'] add_songs_to_playlist(session['playlist_id'], track_uris) return render_template("results.html", resp=resp, track_id_list=track_id_list, playlist_id=playlist_id) # a KeyError occurs when no artist, track, or genre is included in the seed search except KeyError: message = "Please enter at least an artist, song, or genre" genres = get_genres() keys = get_key_list() modes = get_modes() return render_template("search.html", genres=genres, keys=keys, modes=modes, message=message)