def METHOD_NAME(self, predictions, num_tags, labels, transitions):
    low_score = -1000
    b_s = np.array(
        [[low_score] * num_tags + [0, low_score]]
    ).astype(np.float32)
    e_s = np.array(
        [[low_score] * num_tags + [low_score, 0]]
    ).astype(np.float32)
    predictions = np.concatenate(
        [predictions, low_score * np.ones((predictions.shape[0], 2))],
        axis=1
    )
    predictions = np.concatenate(
        [b_s, predictions, e_s],
        axis=0
    )
    b_id = np.array([num_tags], dtype=np.int32)
    e_id = np.array([num_tags + 1], dtype=np.int32)
    labels = np.concatenate(
        [b_id, labels, e_id],
        axis=0
    )
    curr_state = predictions[0]
    input_states = predictions[1:]
    for input_state in input_states:
        prev = np.expand_dims(curr_state, axis=1)
        curr_input = np.expand_dims(input_state, axis=0)
        curr_state = logsumexp(prev + curr_input + transitions, axis=0)
    total_score = logsumexp(curr_state, axis=0)
    # Compute best path score
    unary_scores = sum(w[labels[i]] for i, w in enumerate(predictions))
    binary_scores = sum(
        transitions[a][b] for a, b in zip(labels[:-1], labels[1:])
    )
    loss = total_score - (binary_scores + unary_scores)
    return loss