Consider a setup with a 1 kHz acoustic source at 1 km depth that sends a broadband pulse once every week. A receiver 10 km away at a depth of 800 m measures the impulse response from the received broadband pulse. We assume that we have an initial sound speed profile measurement with a CTD at the start of the experiment. The sound speed profile changes over the weeks of the experiment, and we wish to track the changes using the measured impulse response every week.
Key idea
Since the sound speed profile is an unknown function of depth, we model it using a small 3-layer neural network. We initialize the parameters by training the neural network on the known/estimated sound speed profile from the previous week. We use the neural network to provide sound speed estimates to RaySolver, thus effectively creating a model that combines a numerical physics-based differential equation solver with a data-driven neural network. The hybrid model returns a vector of predicted delays of the first few multipath arrivals in the impulse response. We minimize a loss function that measures the difference between the predictions and measurements using gradient descent and automatic differentiation. This essentially trains the neural network to approximate the sound speed profile via a loss function that utilizes the propagation model. At the end of each week’s training, we get a revised estimate of the sound speed profile.
Dataset
To illustrate this idea, let us generate a synthetic dataset:
usingUnderwaterAcousticsusingAcousticRayTracers# define Munk sound speed profilestruct MunkSSP <: UnderwaterAcoustics.DepthDependent endfunction (ssp::MunkSSP)(pos) ϵ =0.00737 z̃ =2.0* (-pos.z -1300.0) /1300.01500.0* (1.0+ ϵ * (z̃ -1+exp(-z̃)))end# simulate acoustic propagation using RaySolver to generate impulse responsefunctionmodel(h, r, d1, d2, c, n) env =UnderwaterEnvironment(bathymetry=h, seabed=Rock, soundspeed=c) pm =RaySolver(env) tx =AcousticSource(0.0, -d1, 1000.0) rx =AcousticReceiver(r, -d2) arr =arrivals(pm, tx, rx) t =getfield.(arr, :t) # get a.t for each arrival a in arr (t[2:n] .- t[1]) .*1000# relative time in millisecondsend# estimated sound speed profile from previous weekprev_depths = [0, 500.0, 1000.0, 2000.0, 3000.0, 4000.0, 5000.0]prev_soundspeeds = [1518.6, 1494.5, 1490.6, 1505.8, 1530.3, 1556.7, 1583.6]# generate data with first 6 multipath delaysdata =model(5000.0, 10000.0, 1000.0, 1800.0, MunkSSP(), 7)
Now we define a loss function that computes the difference between the predictions of RaySolver using the sound speed given by the NeuralSSP, and the measured impulse response:
# compute loss using predictions of RaySolver using the NeuralSSPfunctionloss(ps) ssp1 =NeuralSSP(ssp.model, ps, 5000.0, 1450.0, 1600.0) pred =model(5000.0, 10000.0, 1000.0, 1800.0, ssp1, length(data)+1)sum(abs2, pred - data)end
and perform gradient descent to minimize the loss function:
importForwardDiffη =1e-6# learning rateps =copy(ssp.ps) # start with the previous week’s parameters# this will take a few minutes to run...for i ∈1:20 g = ForwardDiff.gradient(loss, ps) ps .-= η .* g # gradient descentend
We plot the trained neural sound speed profile against the ground truth: