Пример #1
0
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('/')
Пример #2
0
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('/')
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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)