pyGrFNN documentation¶
pyGrFNN (pronounced “pie-griffin”) is a pure Python implementation of a Gradient Frequency Neural Network (GrFNN), introduced by Large, Almonte and Velasco in
Edward W. Large, Felix V. Almonte, and Marc J. Velasco. A canonical model for gradient frequency neural networks. Physica D: Nonlinear Phenomena, 239(12):905-911, 2010.
These networks are perceptual models that can be used to compute a time-frequency representation (TFR) of an input signal (e.g. audio or an onset signal). Unlike other TFRs, GrFNNs can generate energy at frequencies not present in the input signal via mode-locking.
LICENCE¶
Copyright (c) 2014--2015, Jorge Herrera (jorgeh@ccrma.stanford.edu)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Examples¶
- A single layer (single GrFNN) model responding to an external stimulus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | """
Mimic GrFNN-Toobox1.0 example1.m
A one layer network driven with a sinusoidal input. Several parameter
sets are provided for experimentation with different types of intrinsic
oscillator dynamics.
"""
import sys
# needed to run the examples from within the package folder
sys.path.append('../')
import matplotlib
matplotlib.use('TkAgg')
import numpy as np
import matplotlib.pyplot as plt
from pygrfnn import Zparam, GrFNN, Model, make_connections
from pygrfnn.vis import plot_connections
from pygrfnn.vis import tf_detail
from pygrfnn.vis import GrFNN_RT_plot
# GrFNN params
# params = Zparam(-1, 0, 0, 0, 0, 1) # Linear
params = Zparam(0, -1, -1, 0, 0, 1) # Critical
# params = Zparam( 0, -1, -1, 1, 0, 1) # Critical with detuning
# params = Zparam( 1, -1, -1, 0, 0, 1) # Limit Cycle
# params = Zparam(-1, -3, -1, 0, 0, 1) # Double Limit-cycle
# Stimulus: Complex sinusoid
sr = 40.0 # sample rate
dt = 1.0 / sr
t = np.arange(0, 50, dt)
fc = 1.0 # frequency
A = 0.25 # amplitude
s = A * np.exp(1j * 2 * np.pi * fc * t)
# ramp signal linearly up/down
ramp_dur = 0.02 # in secs
ramp = np.arange(0, 1, dt / ramp_dur)
env = np.ones(s.shape, dtype=float)
env[0:len(ramp)] = ramp
env[-len(ramp):] = ramp[::-1]
# apply envelope
s = s * env
# plt.plot(t, np.real(s))
# Create a GrFNN layer
layer = GrFNN(
params,
frequency_range=(0.5, 2),
num_oscs=200,
stimulus_conn_type='linear')
# store layer's states
layer.save_states = True # True by default, but it can be disabled to save memory
print(layer)
# create the model and add the layer
model = Model()
model.add_layer(layer, input_channel=0)
# setup real-time plot
GrFNN_RT_plot(layer, update_interval=0.2, title='Single Layer')
# run the model
model.run(s, t, dt)
# plot time-frequency representation (magnitude and phase)
tf_detail(
layer.Z, t, layer.f, t_detail=[np.max(t) / 2, np.max(t)], x=np.real(s))
tf_detail(layer.Z, t, layer.f, x=np.real(s), display_op=np.angle)
plt.show()
|
2. A double layer model responding to an external stimulus. One layer is visible (i.e. received the stimulus directly) and the other one is hidden. They are connected via afferent and efferent connections
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | # 0. Preliminares
import sys
sys.path.append('../') # needed to run the examples from within the package folder
import numpy as np
from pygrfnn import Zparam, GrFNN, Model, make_connections
from pygrfnn.vis import plot_connections
from pygrfnn.vis import tf_detail
from pygrfnn.vis import GrFNN_RT_plot
# 1. Create Stimulus: Complex sinusoid
sr = 4000.0 # sample rate
dt = 1.0/sr
t = np.arange(0, 1, dt)
fc = 100.0 # frequency
A = 0.025 # amplitude
s = A * np.exp(1j * 2 * np.pi * fc * t)
# ramp signal linearly up/down
ramp_dur = 0.01 # in secs
ramp = np.arange(0, 1, dt / ramp_dur)
env = np.ones(s.shape, dtype=float)
env[0:len(ramp)] = ramp
env[-len(ramp):] = ramp[::-1]
# apply envelope
s = s * env
# plot stimulus
import matplotlib.pyplot as plt
plt.ion()
plt.plot(t, np.real(s))
plt.plot(t, np.imag(s))
plt.title('Stimulus')
# 2. Make the GrFNN model
# Explore different parameter sets
params1 = Zparam(0.01,-1.,-10., 0., 0., 1.) # Linear
params2 = Zparam( -1., 4., -3., 0., 0., 1.) # Critical
# Create the GrFNNs
layer1 = GrFNN(params1,
frequency_range=(50,200),
num_oscs=200,
stimulus_conn_type='active')
layer2 = GrFNN(params2,
frequency_range=(50,200),
num_oscs=200)
# create a connection matrix
# C = make_connections(layer1, layer2, 1, 1.005, self_connect=True)
C = np.eye(len(layer2.f), len(layer1.f))
# Make the model
model = Model()
model.add_layer(layer1, input_channel=0) # layer one will receive the external stimulus
model.add_layer(layer2) # layer 2 is a hidden layer (no external input)
# connect the layers
conn = model.connect_layers(layer1, layer2, C, '1freq', self_connect=True)
plot_connections(conn, title='Connection matrix (abs)')
# prepare real-time plots
GrFNN_RT_plot(layer1, update_interval=0.005, title='First Layer')
GrFNN_RT_plot(layer2, update_interval=0.005, title='Second Layer')
# 3. Run the model
model.run(s, t, dt)
## Profile
# cmd = "model.run(s, t, dt)"
# import cProfile
# results = cProfile.run(cmd)
|