In [1]:
Plot = require 'itorch.Plot'
In [2]:
-- Implements MATLAB's convmtx.
function convmtx (h, n)
local m = h:size()[1] - 1
local c = torch.Tensor(n, n+m):fill(0)
for i = 1, n do
c[{ i, {i, i+m} }] = h
end
return c
end
In [22]:
convmtx(torch.Tensor({1, -1}), 5)
Out[22]:
In [3]:
-- Implements bruges's ricker.
function ricker (f, length, dt)
-- Defaults.
f = f or 25
length = length or 0.128
dt = dt or 0.001
-- Time basis.
local t = torch.range(0, length, dt) - length/2
-- Amplitudes.
local x = 1 - 2 * math.pi * f^2 * torch.pow(t, 2)
local y = torch.exp(-math.pi^2 * f^2 * torch.pow(t, 2))
local a = torch.cmul(x, y)
return t, a
end
In [4]:
-- VP RHO
imp = torch.ones(51, 1) * 2550 * 2650
imp[{{11, 15}, {}}] = 2700 * 2750
imp[{{16, 27}, {}}] = 2400 * 2450
imp[{{28, 35}, {}}] = 2800 * 3000
In [5]:
x = torch.range(1, imp:size(1))
plot = Plot():line(x, imp[{{},1}])
:title('Impedance')
:draw()
In [6]:
numerator = imp[{{2, imp:size(1)}}] - imp[{{1, imp:size(1) - 1}}]
denominator = imp[{{2, imp:size(1)}}] + imp[{{1, imp:size(1) - 1}}]
m = torch.cdiv(numerator, denominator)
In [7]:
x = torch.range(1, m:size(1))
plot = Plot():line(x, m[{{}, 1}], 'blue')
:title('Reflectivity')
:draw()
In [35]:
t, wavelet = ricker(100, 0.02, 0.001)
In [36]:
plot = Plot():line(t, wavelet)
:title('Wavelet')
:draw()
In [89]:
G_ = convmtx(wavelet, m:size(1))[{{}, {11,60}}]
In [83]:
-- If anyone knows a better way to get every other row of G,
-- I'd love to hear it!
G = torch.Tensor(G_:size(1)/2, G_:size(2))
for i = 1, G_:size(1) do
if i % 2 == 1 then
G[{(i+1)/2}] = G_[{i}]
end
end
In [84]:
d = G * m
In [85]:
x = torch.range(1, d:size(1))
plot = Plot():circle(x, d[{{}, 1}])
:title('Data d')
:draw()
In [86]:
m_est = G:t() * torch.inverse(G * G:t()) * d
d_pred = G * m_est
In [87]:
x = torch.range(1, m_est:size(1))
plot = Plot():line(x, m_est[{{}, 1}])
:title('Predicted model m_est')
:draw()
In [46]:
x = torch.range(1, d_pred:size(1))
plot = Plot():circle(x, d_pred[{{}, 1}])
:title('Predicted data d_pred')
:draw()
In [90]:
-- Use torch.gels()
m_est = torch.gels(d, G)
d_pred = G * m_est
-- Plot
x = torch.range(1,d_pred:size(1))
plot = Plot():circle(x, d[{{},1}], 'blue')
:circle(x, d_pred[{{},1}], 'red')
:title('blue:d red:d_pred')
:draw()
In [93]:
x = torch.range(1, m_est:size(1))
plot = Plot():line(x, m_est[{{}, 1}])
:title('Predicted model m_est')
:draw()
In [91]:
d:dist(d_pred)
Out[91]:
This is the L2 norm; Mauricio used the square of this as the misfit:
In [92]:
(d_pred - d):t() * (d_pred - d)
Out[92]:
In [ ]:
q, r = torch.qr(G)
p = q:t() * d
m_est = torch.inverse(r) * p
d_pred = G * m_est
-- Plot
x = torch.range(1,d_pred:size(1))
plot = Plot():circle(x, d[{{},1}], 'blue')
:circle(x, d_pred[{{},1}], 'red')
:title('blue:d red:d_pred')
:draw()
In [ ]:
d:dist(d_pred)
In [52]:
-- Add noise
dc = G * m
s = 0.025
d = dc + s * (torch.DoubleTensor(d:size()):uniform(0,1) - 0.5)
In [53]:
-- Compute using Mauricio's second form
I = torch.eye(G:size(1))
mu = 2.5
m_est = G:t() * torch.inverse(G*G:t() + mu*I) * d
d_pred = G * m_est
In [54]:
-- Plot
x = torch.range(1,d_pred:size(1))
plot = Plot():line(x, d[{{},1}], 'blue'):circle(x, d[{{},1}], 'blue')
:line(x, d_pred[{{},1}]):circle(x, d_pred[{{},1}])
:title('blue:d red:d_pred')
:draw()
It's not a good idea to use the matrix inverse. So let's try factorization:
In [55]:
chol = torch.potrf(G * G:t() + mu * I)
In [56]:
m_est = torch.potrs(G:t() * d, chol)
In [57]:
d_pred = G * m_est
In [58]:
-- Plot
x = torch.range(1,d_pred:size(1))
plot = Plot():line(x, d[{{},1}], 'blue'):circle(x, d[{{},1}], 'blue')
:line(x, d_pred[{{},1}]):circle(x, d_pred[{{},1}])
:title('blue:d red:d_pred')
:draw()
In [59]:
h = torch.Tensor({1,-1})
cols = G:size(1) + h:size()[1] - 1
W = convmtx(h, G:size(1))[{ {},{1, cols-1} }]
Now we solve:
$$ \hat{\mathbf{m}} = (\mathbf{G}^\mathrm{T} \mathbf{G} + \mu \mathbf{W}^\mathrm{T} \mathbf{W})^{-1} \mathbf{G}^\mathrm{T} \mathbf{d} \ \ $$
In [60]:
m_est = torch.inverse(G:t()*G + mu*W:t()*W) * G:t() * d
d_pred = G * m_est
In [61]:
-- Plot
x = torch.range(1,d_pred:size(1))
plot = Plot():line(x, d[{{},1}], 'blue'):circle(x, d[{{},1}], 'blue')
:line(x, d_pred[{{},1}]):circle(x, d_pred[{{},1}])
:title('blue:d red:d_pred')
:draw()
In [62]:
-- Plot
x = torch.range(1,m_est:size(1))
plot = Plot():line(x, m[{{},1}], 'blue', 'blue')
:line(x, m_est[{{},1}]):title('blue:m red:m_est')
:draw()
In [63]:
h = torch.Tensor({1,-2, 1})
W = convmtx(h, G:size(1))[{{}, {2, G:size(1)+1}}]
Q = torch.inverse(W * W:t())
m_est = Q * G:t() * torch.inverse(G * Q * G:t()) * d
d_pred = G * m_est
-- Plot
x = torch.range(1, m_est:size(1))
plot = Plot():line(x, m[{{}, 1}], 'blue', 'blue')
:line(x, m_est[{{}, 1}]):title('blue:m red:m_est')
:draw()
In [ ]: