Module note_seq.pianoroll_encoder_decoder
Classes for converting between pianoroll input and model input/output.
Expand source code
# Copyright 2021 The Magenta Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Classes for converting between pianoroll input and model input/output."""
from note_seq import encoder_decoder
import numpy as np
class PianorollEncoderDecoder(encoder_decoder.EventSequenceEncoderDecoder):
"""An EventSequenceEncoderDecoder that produces a pianoroll encoding.
Inputs are binary arrays with active pitches (with some offset) at each step
set to 1 and inactive pitches set to 0.
Events are PianorollSequence events, which are tuples of active pitches
(with some offset) at each step.
"""
def __init__(self, input_size=88):
"""Initialize a PianorollEncoderDecoder object.
Args:
input_size: The size of the input vector.
"""
self._input_size = input_size
@property
def input_size(self):
return self._input_size
@property
def num_classes(self):
return 2 ** self.input_size
@property
def default_event_label(self):
return 0
def _event_to_label(self, event):
label = 0
for pitch in event:
label += 2**pitch
return label
def _event_to_input(self, event):
input_ = np.zeros(self.input_size, np.float32)
input_[list(event)] = 1
return input_
def events_to_input(self, events, position):
"""Returns the input vector for the given position in the event sequence.
Args:
events: A list-like sequence of PianorollSequence events.
position: An integer event position in the event sequence.
Returns:
An input vector, a list of floats.
"""
return self._event_to_input(events[position])
def events_to_label(self, events, position):
"""Returns the label for the given position in the event sequence.
Args:
events: A list-like sequence of PianorollSequence events.
position: An integer event position in the event sequence.
Returns:
A label, an integer.
"""
return self._event_to_label(events[position])
def class_index_to_event(self, class_index, events):
"""Returns the event for the given class index.
This is the reverse process of the self.events_to_label method.
Args:
class_index: An integer in the range [0, self.num_classes).
events: A list-like sequence of events. This object is not used in this
implementation.
Returns:
An PianorollSequence event value.
"""
assert class_index < self.num_classes
event = []
for i in range(self.input_size):
if class_index % 2:
event.append(i)
class_index >>= 1
assert class_index == 0
return tuple(event)
def extend_event_sequences(self, event_sequences, softmax):
"""Extends the event sequences by adding the new samples.
Args:
event_sequences: A collection of PianorollSequences to append `samples`
to.
softmax: A collection of binary arrays with active pitches set to 1 and
inactive pitches set to 0, which will be added to the corresponding
`pianoroll_seqs`.
Raises:
ValueError: if inputs are not of equal length.
"""
pianoroll_seqs = event_sequences
samples = softmax
if len(pianoroll_seqs) != len(samples):
raise ValueError(
'`pianoroll_seqs` and `samples` must have equal lengths.')
for pianoroll_seq, sample in zip(pianoroll_seqs, samples):
event = tuple(np.where(sample)[0])
pianoroll_seq.append(event)
Classes
class PianorollEncoderDecoder (input_size=88)
-
An EventSequenceEncoderDecoder that produces a pianoroll encoding.
Inputs are binary arrays with active pitches (with some offset) at each step set to 1 and inactive pitches set to 0.
Events are PianorollSequence events, which are tuples of active pitches (with some offset) at each step.
Initialize a PianorollEncoderDecoder object.
Args
input_size
- The size of the input vector.
Expand source code
class PianorollEncoderDecoder(encoder_decoder.EventSequenceEncoderDecoder): """An EventSequenceEncoderDecoder that produces a pianoroll encoding. Inputs are binary arrays with active pitches (with some offset) at each step set to 1 and inactive pitches set to 0. Events are PianorollSequence events, which are tuples of active pitches (with some offset) at each step. """ def __init__(self, input_size=88): """Initialize a PianorollEncoderDecoder object. Args: input_size: The size of the input vector. """ self._input_size = input_size @property def input_size(self): return self._input_size @property def num_classes(self): return 2 ** self.input_size @property def default_event_label(self): return 0 def _event_to_label(self, event): label = 0 for pitch in event: label += 2**pitch return label def _event_to_input(self, event): input_ = np.zeros(self.input_size, np.float32) input_[list(event)] = 1 return input_ def events_to_input(self, events, position): """Returns the input vector for the given position in the event sequence. Args: events: A list-like sequence of PianorollSequence events. position: An integer event position in the event sequence. Returns: An input vector, a list of floats. """ return self._event_to_input(events[position]) def events_to_label(self, events, position): """Returns the label for the given position in the event sequence. Args: events: A list-like sequence of PianorollSequence events. position: An integer event position in the event sequence. Returns: A label, an integer. """ return self._event_to_label(events[position]) def class_index_to_event(self, class_index, events): """Returns the event for the given class index. This is the reverse process of the self.events_to_label method. Args: class_index: An integer in the range [0, self.num_classes). events: A list-like sequence of events. This object is not used in this implementation. Returns: An PianorollSequence event value. """ assert class_index < self.num_classes event = [] for i in range(self.input_size): if class_index % 2: event.append(i) class_index >>= 1 assert class_index == 0 return tuple(event) def extend_event_sequences(self, event_sequences, softmax): """Extends the event sequences by adding the new samples. Args: event_sequences: A collection of PianorollSequences to append `samples` to. softmax: A collection of binary arrays with active pitches set to 1 and inactive pitches set to 0, which will be added to the corresponding `pianoroll_seqs`. Raises: ValueError: if inputs are not of equal length. """ pianoroll_seqs = event_sequences samples = softmax if len(pianoroll_seqs) != len(samples): raise ValueError( '`pianoroll_seqs` and `samples` must have equal lengths.') for pianoroll_seq, sample in zip(pianoroll_seqs, samples): event = tuple(np.where(sample)[0]) pianoroll_seq.append(event)
Ancestors
Methods
def class_index_to_event(self, class_index, events)
-
Returns the event for the given class index.
This is the reverse process of the self.events_to_label method.
Args
class_index
- An integer in the range [0, self.num_classes).
events
- A list-like sequence of events. This object is not used in this implementation.
Returns
An PianorollSequence event value.
Expand source code
def class_index_to_event(self, class_index, events): """Returns the event for the given class index. This is the reverse process of the self.events_to_label method. Args: class_index: An integer in the range [0, self.num_classes). events: A list-like sequence of events. This object is not used in this implementation. Returns: An PianorollSequence event value. """ assert class_index < self.num_classes event = [] for i in range(self.input_size): if class_index % 2: event.append(i) class_index >>= 1 assert class_index == 0 return tuple(event)
def events_to_input(self, events, position)
-
Returns the input vector for the given position in the event sequence.
Args
events
- A list-like sequence of PianorollSequence events.
position
- An integer event position in the event sequence.
Returns
An input vector, a list of floats.
Expand source code
def events_to_input(self, events, position): """Returns the input vector for the given position in the event sequence. Args: events: A list-like sequence of PianorollSequence events. position: An integer event position in the event sequence. Returns: An input vector, a list of floats. """ return self._event_to_input(events[position])
def events_to_label(self, events, position)
-
Returns the label for the given position in the event sequence.
Args
events
- A list-like sequence of PianorollSequence events.
position
- An integer event position in the event sequence.
Returns
A label, an integer.
Expand source code
def events_to_label(self, events, position): """Returns the label for the given position in the event sequence. Args: events: A list-like sequence of PianorollSequence events. position: An integer event position in the event sequence. Returns: A label, an integer. """ return self._event_to_label(events[position])
def extend_event_sequences(self, event_sequences, softmax)
-
Extends the event sequences by adding the new samples.
Args
event_sequences
- A collection of PianorollSequences to append
samples
to. softmax
- A collection of binary arrays with active pitches set to 1 and
inactive pitches set to 0, which will be added to the corresponding
pianoroll_seqs
.
Raises
ValueError
- if inputs are not of equal length.
Expand source code
def extend_event_sequences(self, event_sequences, softmax): """Extends the event sequences by adding the new samples. Args: event_sequences: A collection of PianorollSequences to append `samples` to. softmax: A collection of binary arrays with active pitches set to 1 and inactive pitches set to 0, which will be added to the corresponding `pianoroll_seqs`. Raises: ValueError: if inputs are not of equal length. """ pianoroll_seqs = event_sequences samples = softmax if len(pianoroll_seqs) != len(samples): raise ValueError( '`pianoroll_seqs` and `samples` must have equal lengths.') for pianoroll_seq, sample in zip(pianoroll_seqs, samples): event = tuple(np.where(sample)[0]) pianoroll_seq.append(event)
Inherited members