def test_can_multiply_by_frequency_weighting_linear_scale(self): frequency = Seconds(1) duration = Seconds(1) scale = LinearScale(FrequencyBand(20, 22050), 100) td = TimeDimension(frequency, duration) fd = FrequencyDimension(scale) tf = ArrayWithUnits(np.ones((30, 100)), [td, fd]) result = tf * AWeighting() self.assertIsInstance(result, ArrayWithUnits) peak_frequency_band = FrequencyBand(9000, 11000) lower_band = FrequencyBand(100, 300) peak_slice = np.abs(result[:, peak_frequency_band]).max() lower_slice = np.abs(result[:, lower_band]).max() self.assertGreater(peak_slice, lower_slice)
def test_array_with_units(self): r = Reservoir(100) frequency_dimension = FrequencyDimension( LinearScale(FrequencyBand(100, 1000), 100)) samples = ArrayWithUnits(np.ones( (20, 100)), [TimeDimension(frequency=Seconds(1)), frequency_dimension]) r.add(samples) mixed = r.get() self.assertIsInstance(mixed, ArrayWithUnits) self.assertEqual(100, mixed.shape[1]) self.assertIsInstance(mixed.dimensions[0], IdentityDimension) self.assertIsInstance(mixed.dimensions[1], FrequencyDimension)
def test_can_sample_from_one_dimensional_feature(self): sampler = ReservoirSampler(nsamples=10) frequency_dimension = FrequencyDimension( LinearScale(FrequencyBand(100, 1000), 100)) samples = ArrayWithUnits(np.ones( (20, 100)), [TimeDimension(frequency=Seconds(1)), frequency_dimension]) sampler._enqueue(samples, pusher=None) reservoir = sampler._r self.assertEqual((10, 100), reservoir.shape) self.assertIsInstance(reservoir, ArrayWithUnits) self.assertEqual(reservoir.dimensions[0], IdentityDimension()) self.assertEqual(reservoir.dimensions[1], frequency_dimension)
def test_can_round_trip_2d_constant_rate_time_series(self): dim1 = TimeDimension(Seconds(1), Milliseconds(500)) scale = LinearScale(FrequencyBand(20, 20000), 100) dim2 = FrequencyDimension(scale) raw = np.random.random_sample((10, 100)) ts = ArrayWithUnits(raw, (dim1, dim2)) decoded = self._roundtrip(ts) self.assertIsInstance(decoded, ArrayWithUnits) self.assertEqual(2, len(decoded.dimensions)) self.assertIsInstance(decoded.dimensions[0], TimeDimension) td = decoded.dimensions[0] self.assertIsInstance(td, TimeDimension) self.assertEqual(Seconds(1), td.frequency) self.assertEqual(Milliseconds(500), td.duration) fd = decoded.dimensions[1] self.assertIsInstance(fd, FrequencyDimension) self.assertEqual(scale, fd.scale) np.testing.assert_allclose(decoded, raw)
def test_sliding_window_maintains_dtype(self): band = FrequencyBand(0, 22000) scale = LinearScale(band, 100) arr = ArrayWithUnits( np.zeros((200, 100), dtype=np.uint8), [TimeDimension(Seconds(1)), FrequencyDimension(scale)]) sw = SampleRate(Seconds(2), Seconds(2)) @simple_in_memory_settings class Document(BaseModel): windowed = ArrayWithUnitsFeature(SlidingWindow, wscheme=sw, store=True) _id = Document.process(windowed=arr) result = Document(_id).windowed self.assertEqual(np.uint8, result.dtype)
def test_can_iterate_after_packbits(self): tf = ArrayWithUnits(np.random.binomial(1, 0.5, (10, 256)).astype(np.uint8), dimensions=[ TimeDimension(Seconds(1), Seconds(1)), IdentityDimension() ]) tf = tf.packbits(axis=1) self.assertIsInstance(tf, ArrayWithUnits) self.assertEqual((10, 32), tf.shape) self.assertIsInstance(tf.dimensions[0], TimeDimension) self.assertIsInstance(tf.dimensions[1], IdentityDimension) rows = [row for row in tf] self.assertEqual(10, len(rows)) for row in rows: self.assertIsInstance(row, ArrayWithUnits) self.assertIsInstance(row.dimensions[0], IdentityDimension) self.assertEqual((32, ), row.shape)
def test_iter_slices_yields_evenly_spaced_time_slices(self): raw = np.random.random_sample((10, 3)) arr = ArrayWithUnits(raw, dimensions=[ TimeDimension(frequency=Milliseconds(500), duration=Seconds(1)), IdentityDimension() ]) crts = ConstantRateTimeSeries(arr) slices = list(crts.iter_slices()) self.assertEqual(10, len(slices)) ts1, d1 = slices[0] self.assertEqual(TimeSlice(start=Seconds(0), duration=Seconds(1)), ts1) np.testing.assert_allclose(raw[0], d1) ts2, d2 = slices[1] self.assertEqual( TimeSlice(start=Milliseconds(500), duration=Seconds(1)), ts2) np.testing.assert_allclose(raw[1], d2)
def test_forward_transform_returns_array_with_units_where_possible(self): # train the model on random data training = np.random.random_sample((100, 30)) Model = self.get_model() _id = Model.process(unitnorm=training) model = Model(_id) # create a time-frequency representation scale = LinearScale(FrequencyBand(20, 20000), 30) data = ArrayWithUnits(np.random.random_sample( (10, 30)), [TimeDimension(Seconds(1)), FrequencyDimension(scale)]) # do a forward pass transformed = model.pipeline.transform(data).data self.assertIsInstance(transformed, ArrayWithUnits) self.assertEqual(2, len(transformed.dimensions)) self.assertIsInstance(transformed.dimensions[0], TimeDimension) self.assertIsInstance(transformed.dimensions[1], IdentityDimension)
def test_square_form_no_overlap_do_overlap_add(self): td = TimeDimension(duration=Seconds(1), frequency=Seconds(1)) scale = GeometricScale(20, 5000, 0.05, 120) arrs = [np.zeros((10, x)) for x in xrange(1, 121)] fa = FrequencyAdaptive(arrs, td, scale) square = fa.square(50, do_overlap_add=True) self.assertEqual(2, square.ndim) self.assertEqual(500, square.shape[0]) self.assertEqual(120, square.shape[1]) self.assertIsInstance(square, ArrayWithUnits) self.assertIsInstance(square.dimensions[0], TimeDimension) self.assertEqual(Seconds(10), square.dimensions[0].end) self.assertEqual(Milliseconds(20), square.dimensions[0].frequency) self.assertEqual(Milliseconds(20), square.dimensions[0].duration) self.assertIsInstance(square.dimensions[1], FrequencyDimension) self.assertEqual(scale, square.dimensions[1].scale)
def fir_filter_bank(scale, taps, samplerate, window): basis = np.zeros((len(scale), taps)) basis = ArrayWithUnits( basis, [FrequencyDimension(scale), TimeDimension(*samplerate)]) nyq = samplerate.nyquist if window.ndim == 1: window = repeat(window, len(scale)) for i, band, win in zip(range(len(scale)), scale, window): start_hz = max(0, band.start_hz) stop_hz = min(nyq, band.stop_hz) freqs = np.linspace(start_hz / nyq, stop_hz / nyq, len(win)) freqs = [0] + list(freqs) + [1] gains = [0] + list(win) + [0] basis[i] = firwin2(taps, freqs, gains) return basis
def transform(self, samples, pooling_kernel_size, pooling_stride): # convert the raw audio samples to a PyTorch tensor tensor_samples = torch.from_numpy(samples).float() \ .to(self.filter_bank.device) # compute the transform spectral = self.convolve(tensor_samples) log_magnitude = self.log_magnitude(spectral) pooled = self.temporal_pooling(log_magnitude, pooling_kernel_size, pooling_stride) # convert back to an ArrayWithUnits instance samplerate = samples.samplerate time_frequency = pooled.data.cpu().numpy().squeeze().T time_frequency = ArrayWithUnits(time_frequency, [ TimeDimension(frequency=samplerate.frequency * pooling_stride, duration=samplerate.frequency * pooling_kernel_size), FrequencyDimension(self.scale) ]) return time_frequency
def test_can_apply_sliding_window_to_constant_rate_time_series(self): arr = ArrayWithUnits(np.zeros(100), [TimeDimension(Seconds(1))]) sw = SampleRate(Seconds(2), Seconds(2)) @simple_in_memory_settings class Document(BaseModel): windowed = ArrayWithUnitsFeature(SlidingWindow, wscheme=sw, store=True) _id = Document.process(windowed=arr) result = Document(_id).windowed self.assertIsInstance(result, ArrayWithUnits) self.assertEqual((50, 2), result.shape) self.assertEqual(2, len(result.dimensions)) self.assertIsInstance(result.dimensions[0], TimeDimension) self.assertEqual(Seconds(2), result.dimensions[0].frequency) self.assertIsInstance(result.dimensions[1], TimeDimension) self.assertEqual(Seconds(1), result.dimensions[1].frequency)
def stft(x, window_sample_rate=HalfLapped(), window=HanningWindowingFunc()): duration = TimeSlice(window_sample_rate.duration) frequency = TimeSlice(window_sample_rate.frequency) if x.ndim == 1: _, arr = x.sliding_window_with_leftovers(duration, frequency, dopad=True) elif x.ndim == 2 and isinstance(x.dimensions[0], IdentityDimension): arr = x.sliding_window((1, duration), (1, frequency)) td = x.dimensions[-1] dims = [IdentityDimension(), TimeDimension(*window_sample_rate), td] arr = ArrayWithUnits(arr.reshape((len(x), -1, arr.shape[-1])), dims) else: raise ValueError('x must either have a single TimeDimension, or ' '(IdentityDimension, TimeDimension)') window = window or IdentityWindowingFunc() windowed = arr * window._wdata(arr.shape[-1]) return fft(windowed)
def test_can_invert_pipeline_that_takes_frequency_adaptive_transform(self): td = TimeDimension(frequency=Seconds(1)) scale = GeometricScale(20, 5000, 0.05, 10) arrs = [np.zeros((10, x)) for x in xrange(1, 11)] fa = FrequencyAdaptive(arrs, td, scale) @simple_in_memory_settings class Model(featureflow.BaseModel): log = featureflow.PickleFeature(Log, store=False) meanstd = featureflow.PickleFeature(MeanStdNormalization, needs=log, store=False) pipeline = featureflow.PickleFeature(PreprocessingPipeline, needs=(log, meanstd), store=True) _id = Model.process(log=fa) model = Model(_id) result = model.pipeline.transform(fa) recon = result.inverse_transform() self.assertIsInstance(recon, FrequencyAdaptive) self.assertEqual(fa.shape, recon.shape)
def test_can_maintain_array_dimensions_with_supervised_learning(self): trainer = SupervisedTrainer( model=SupervisedNetwork(), loss=nn.BCELoss(), optimizer=lambda model: SGD(model.parameters(), lr=0.2), epochs=1, batch_size=64, data_preprocessor=lambda x: x.astype(np.float32), label_preprocessor=lambda x: x.astype(np.float32)) @simple_in_memory_settings class Pipeline(ff.BaseModel): inp = ff.PickleFeature(ff.IteratorNode, store=False) samples = ff.PickleFeature(ShuffledSamples, nsamples=500, multiplexed=True, dtype=np.float32, needs=inp, store=False) unitnorm = ff.PickleFeature(UnitNorm, needs=samples.aspect('data'), store=False) hard_labels = ff.PickleFeature(Binarize, needs=samples.aspect('labels'), store=False) network = ff.PickleFeature(PyTorchNetwork, trainer=trainer, needs=dict(data=unitnorm, labels=hard_labels), store=False) pipeline = ff.PickleFeature(PreprocessingPipeline, needs=(unitnorm, network), store=True) # Produce some random points on the unit circle samples = np.random.random_sample((1000, 2)) samples /= np.linalg.norm(samples, axis=1, keepdims=True) # a line extending from the origin to (1, 1) origin = np.array([0, 0]) unit = np.array([1, 1]) # which side of the plane is each sample on? labels = np.sign(np.cross(unit - origin, origin - samples)) labels[labels < 0] = 0 # scale each sample randomly, forcing the pipeline to normalize data factors = np.random.randint(1, 1000, (len(samples), 1)) scaled_samples = samples * factors scaled_samples = scaled_samples # fuzz the labels, forcing the pipeline to binarize these (i.e., force # them to be 0 or 1) fuzzed_labels = labels + np.random.normal(0, 0.1, labels.shape) fuzzed_labels = fuzzed_labels[..., None] def gen(chunksize, s, l): for i in xrange(0, len(s), chunksize): sl = slice(i, i + chunksize) yield dict(data=s[sl], labels=l[sl]) _id = Pipeline.process(inp=gen(100, scaled_samples, fuzzed_labels)) pipe = Pipeline(_id) # produce some new samples new_samples = np.random.random_sample((1000, 2)) new_samples /= np.linalg.norm(samples, axis=1, keepdims=True) # scale each example randomly, so the pipeline must give it unit norm # to arrive at the correct answer new_factors = np.random.randint(1, 1000, (len(samples), 1)) new_scaled_samples = new_factors * new_samples arr = ArrayWithUnits(new_scaled_samples, dimensions=[ TimeDimension(Seconds(1)), FrequencyDimension( LinearScale(FrequencyBand(100, 1000), 2)) ]) result = pipe.pipeline.transform(arr.astype(np.float32)) self.assertIsInstance(result.data, ArrayWithUnits) self.assertIsInstance(result.data.dimensions[0], TimeDimension)
def test_can_decompose_audio_samples(self): samples = AudioSamples.silence(SR22050(), Seconds(1)) bands = frequency_decomposition(samples, [64, 128, 256, 512, 1024]) expected_td = TimeDimension(samples.end, samples.end) self.assertEqual(expected_td, bands.dimensions[0]) self.assertIsInstance(bands.dimensions[1], ExplicitFrequencyDimension)
def test_cannot_multiply_when_array_does_not_have_expected_dimensions(self): td = TimeDimension(Seconds(1), Seconds(1)) tf = ArrayWithUnits(np.ones((90, 100)), [td, IdentityDimension()]) weighting = AWeighting() self.assertRaises(ValueError, lambda: tf * weighting)
def _process(self, data): for i in xrange(0, self.total_frames, self.increments_of): size = min(self.increments_of, self.total_frames - i) td = TimeDimension(frequency=Milliseconds(500)) yield ArrayWithUnits(np.zeros((size, self.features)), [td, IdentityDimension()])